mirror of https://github.com/wolfSSL/wolfssh.git
add chroot jailing to sshd
parent
82172d0e43
commit
e1f0a67c38
|
@ -51,6 +51,7 @@
|
|||
#ifndef _WIN32
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
|
@ -937,4 +938,33 @@ long wolfSSHD_AuthGetGraceTime(const WOLFSSHD_AUTH* auth)
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* return the user configuration */
|
||||
WOLFSSHD_CONFIG* wolfSSHD_AuthGetUserConf(const WOLFSSHD_AUTH* auth,
|
||||
const char* usr, const char* host,
|
||||
const char* localAdr, word16* localPort, const char* RDomain,
|
||||
const char* adr)
|
||||
{
|
||||
struct group* g = NULL;
|
||||
WOLFSSHD_CONFIG* ret = NULL;
|
||||
|
||||
if (auth != NULL) {
|
||||
struct passwd *p_passwd;
|
||||
|
||||
p_passwd = getpwnam((const char *)usr);
|
||||
if (p_passwd == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g = getgrgid(p_passwd->pw_gid);
|
||||
if (g == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = wolfSSHD_GetUserConf(auth->conf, usr, g->gr_name, host, localAdr,
|
||||
localPort, RDomain, adr);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif /* WOLFSSH_SSHD */
|
||||
|
|
|
@ -61,4 +61,8 @@ int wolfSSHD_AuthRaisePermissions(WOLFSSHD_AUTH* auth);
|
|||
int wolfSSHD_AuthReducePermissionsUser(WOLFSSHD_AUTH* auth, WUID_T uid,
|
||||
WGID_T gid);
|
||||
long wolfSSHD_AuthGetGraceTime(const WOLFSSHD_AUTH* auth);
|
||||
WOLFSSHD_CONFIG* wolfSSHD_AuthGetUserConf(const WOLFSSHD_AUTH* auth,
|
||||
const char* usr, const char* host,
|
||||
const char* localAdr, word16* localPort, const char* RDomain,
|
||||
const char* adr);
|
||||
#endif /* WOLFAUTH_H */
|
||||
|
|
|
@ -49,6 +49,8 @@
|
|||
|
||||
struct WOLFSSHD_CONFIG {
|
||||
void* heap;
|
||||
char* usrAppliesTo; /* NULL means all users */
|
||||
char* groupAppliesTo; /* NULL means all groups */
|
||||
char* banner;
|
||||
char* chrootDir;
|
||||
char* ciphers;
|
||||
|
@ -57,6 +59,8 @@ struct WOLFSSHD_CONFIG {
|
|||
char* kekAlgos;
|
||||
char* listenAddress;
|
||||
char* authKeysFile;
|
||||
char* forceCmd;
|
||||
WOLFSSHD_CONFIG* next; /* next config in list */
|
||||
long loginTimer;
|
||||
word16 port;
|
||||
byte usePrivilegeSeparation;
|
||||
|
@ -66,6 +70,7 @@ struct WOLFSSHD_CONFIG {
|
|||
byte permitEmptyPasswords:1;
|
||||
};
|
||||
|
||||
int CountWhitespace(const char* in, int inSz, byte inv);
|
||||
|
||||
/* convert a string into seconds, handles if 'm' for minutes follows the string
|
||||
* number, i.e. 2m
|
||||
|
@ -110,11 +115,20 @@ static long GetConfigInt(const char* in, int inSz, int isTime, void* heap)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* returns WS_SUCCESS on success */
|
||||
/* returns WS_SUCCESS on success, removes trailng newlines */
|
||||
static int CreateString(char** out, const char* in, int inSz, void* heap)
|
||||
{
|
||||
int ret = WS_SUCCESS;
|
||||
int idx = 0;
|
||||
int idx = 0, tail, sz = 0;
|
||||
|
||||
if (in == NULL && inSz != 0) {
|
||||
return WS_BAD_ARGUMENT;
|
||||
}
|
||||
|
||||
if (in == NULL) {
|
||||
/* "created" an empty string */
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* remove leading white spaces */
|
||||
while (idx < inSz && in[idx] == ' ') idx++;
|
||||
|
@ -123,15 +137,28 @@ static int CreateString(char** out, const char* in, int inSz, void* heap)
|
|||
ret = WS_BAD_ARGUMENT;
|
||||
}
|
||||
|
||||
if (ret == WS_SUCCESS) {
|
||||
for (tail = inSz - 1; tail > idx; tail--) {
|
||||
if (in[tail] != '\n' && in[tail] != ' ' && in[tail] != '\r') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sz = tail - idx + 1; /* +1 to account for index of 0 */
|
||||
if (sz > inSz - idx) {
|
||||
ret = WS_BAD_ARGUMENT;
|
||||
}
|
||||
}
|
||||
|
||||
/* malloc new string and set it */
|
||||
if (ret == WS_SUCCESS) {
|
||||
*out = (char*)WMALLOC((inSz - idx) + 1, heap, DYNTYPE_SSHD);
|
||||
*out = (char*)WMALLOC(sz + 1, heap, DYNTYPE_SSHD);
|
||||
if (*out == NULL) {
|
||||
ret = WS_MEMORY_E;
|
||||
}
|
||||
else {
|
||||
XMEMCPY(*out, in + idx, inSz - idx);
|
||||
*(*out + (inSz - idx)) = '\0';
|
||||
XMEMCPY(*out, in + idx, sz);
|
||||
*(*out + sz) = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -169,17 +196,101 @@ WOLFSSHD_CONFIG* wolfSSHD_ConfigNew(void* heap)
|
|||
|
||||
}
|
||||
|
||||
|
||||
/* on success return a newly create WOLFSSHD_CONFIG structure that has the
|
||||
* same values set as the input 'conf'. User and group match values are not
|
||||
* copied */
|
||||
static WOLFSSHD_CONFIG* wolfSSHD_ConfigCopy(WOLFSSHD_CONFIG* conf)
|
||||
{
|
||||
int ret = WS_SUCCESS;
|
||||
WOLFSSHD_CONFIG* newConf;
|
||||
|
||||
newConf = wolfSSHD_ConfigNew(conf->heap);
|
||||
if (newConf != NULL) {
|
||||
if (conf->banner) {
|
||||
ret = CreateString(&newConf->banner, conf->banner,
|
||||
(int)WSTRLEN(conf->banner),
|
||||
newConf->heap);
|
||||
}
|
||||
|
||||
if (ret == WS_SUCCESS && conf->chrootDir) {
|
||||
ret = CreateString(&newConf->chrootDir, conf->chrootDir,
|
||||
(int)WSTRLEN(conf->chrootDir),
|
||||
newConf->heap);
|
||||
}
|
||||
|
||||
if (ret == WS_SUCCESS && conf->ciphers) {
|
||||
ret = CreateString(&newConf->ciphers, conf->ciphers,
|
||||
(int)WSTRLEN(conf->ciphers),
|
||||
newConf->heap);
|
||||
}
|
||||
|
||||
if (ret == WS_SUCCESS && conf->hostKeyFile) {
|
||||
ret = CreateString(&newConf->hostKeyFile, conf->hostKeyFile,
|
||||
(int)WSTRLEN(conf->hostKeyFile),
|
||||
newConf->heap);
|
||||
}
|
||||
|
||||
if (ret == WS_SUCCESS && conf->hostKeyAlgos) {
|
||||
ret = CreateString(&newConf->hostKeyAlgos, conf->hostKeyAlgos,
|
||||
(int)WSTRLEN(conf->hostKeyAlgos),
|
||||
newConf->heap);
|
||||
}
|
||||
|
||||
if (ret == WS_SUCCESS && conf->kekAlgos) {
|
||||
ret = CreateString(&newConf->kekAlgos, conf->kekAlgos,
|
||||
(int)WSTRLEN(conf->kekAlgos),
|
||||
newConf->heap);
|
||||
}
|
||||
|
||||
if (ret == WS_SUCCESS && conf->listenAddress) {
|
||||
ret = CreateString(&newConf->listenAddress, conf->listenAddress,
|
||||
(int)WSTRLEN(conf->listenAddress),
|
||||
newConf->heap);
|
||||
}
|
||||
|
||||
if (ret == WS_SUCCESS && conf->authKeysFile) {
|
||||
ret = CreateString(&newConf->authKeysFile, conf->authKeysFile,
|
||||
(int)WSTRLEN(conf->authKeysFile),
|
||||
newConf->heap);
|
||||
}
|
||||
|
||||
if (ret == WS_SUCCESS && conf->chrootDir) {
|
||||
ret = CreateString(&newConf->chrootDir, conf->chrootDir,
|
||||
(int)WSTRLEN(conf->chrootDir),
|
||||
newConf->heap);
|
||||
}
|
||||
|
||||
if (ret == WS_SUCCESS) {
|
||||
newConf->loginTimer = conf->loginTimer;
|
||||
newConf->port = conf->port;
|
||||
newConf->passwordAuth = conf->passwordAuth;
|
||||
newConf->pubKeyAuth = conf->pubKeyAuth;
|
||||
newConf->usePrivilegeSeparation = conf->usePrivilegeSeparation;
|
||||
newConf->permitRootLogin = conf->permitRootLogin;
|
||||
newConf->permitEmptyPasswords = conf->permitEmptyPasswords;
|
||||
}
|
||||
}
|
||||
|
||||
return newConf;
|
||||
}
|
||||
|
||||
|
||||
void wolfSSHD_ConfigFree(WOLFSSHD_CONFIG* conf)
|
||||
{
|
||||
WOLFSSHD_CONFIG* current;
|
||||
void* heap;
|
||||
|
||||
if (conf != NULL) {
|
||||
heap = conf->heap;
|
||||
current = conf;
|
||||
while (current != NULL) {
|
||||
WOLFSSHD_CONFIG* next = current->next;
|
||||
heap = current->heap;
|
||||
|
||||
FreeString(&conf->authKeysFile, heap);
|
||||
FreeString(&conf->hostKeyFile, heap);
|
||||
FreeString(¤t->authKeysFile, heap);
|
||||
FreeString(¤t->hostKeyFile, heap);
|
||||
|
||||
WFREE(conf, heap, DYNTYPE_SSHD);
|
||||
WFREE(current, heap, DYNTYPE_SSHD);
|
||||
current = next;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -207,10 +318,13 @@ enum {
|
|||
OPT_PORT = 13,
|
||||
OPT_PERMIT_ROOT = 14,
|
||||
OPT_USE_DNS = 15,
|
||||
OPT_INCLUDE = 16
|
||||
OPT_INCLUDE = 16,
|
||||
OPT_CHROOT_DIR = 17,
|
||||
OPT_MATCH = 18,
|
||||
OPT_FORCE_CMD = 19,
|
||||
};
|
||||
enum {
|
||||
NUM_OPTIONS = 17
|
||||
NUM_OPTIONS = 20
|
||||
};
|
||||
|
||||
static const CONFIG_OPTION options[NUM_OPTIONS] = {
|
||||
|
@ -230,7 +344,10 @@ static const CONFIG_OPTION options[NUM_OPTIONS] = {
|
|||
{OPT_PORT, "Port"},
|
||||
{OPT_PERMIT_ROOT, "PermitRootLogin"},
|
||||
{OPT_USE_DNS, "UseDNS"},
|
||||
{OPT_INCLUDE, "Include"}
|
||||
{OPT_INCLUDE, "Include"},
|
||||
{OPT_CHROOT_DIR, "ChrootDirectory"},
|
||||
{OPT_MATCH, "Match"},
|
||||
{OPT_FORCE_CMD, "ForceCommand"},
|
||||
};
|
||||
|
||||
/* returns WS_SUCCESS on success */
|
||||
|
@ -567,20 +684,154 @@ static int HandleInclude(WOLFSSHD_CONFIG *conf, const char *value)
|
|||
return WS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* returns WS_SUCCESS on success */
|
||||
static int HandleConfigOption(WOLFSSHD_CONFIG* conf, int opt, const char* value)
|
||||
static int HandleChrootDir(WOLFSSHD_CONFIG* conf, const char* value)
|
||||
{
|
||||
int ret = WS_SUCCESS;
|
||||
|
||||
if (conf == NULL || value == NULL) {
|
||||
ret = WS_BAD_ARGUMENT;
|
||||
}
|
||||
|
||||
if (ret == WS_SUCCESS) {
|
||||
if (conf->chrootDir != NULL) {
|
||||
FreeString(&conf->chrootDir, conf->heap);
|
||||
conf->chrootDir = NULL;
|
||||
}
|
||||
ret = CreateString(&conf->chrootDir, value,
|
||||
(int)WSTRLEN(value), conf->heap);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* returns WS_SUCCESS on success, helps with adding a restricted case to the
|
||||
* config */
|
||||
static int AddRestrictedCase(WOLFSSHD_CONFIG* config, const char* mtch,
|
||||
const char* value, char** out)
|
||||
{
|
||||
int ret = WS_SUCCESS;
|
||||
char* pt;
|
||||
|
||||
pt = XSTRSTR(value, mtch);
|
||||
if (pt != NULL) {
|
||||
int sz, i;
|
||||
|
||||
pt += (int)XSTRLEN(mtch);
|
||||
sz = (int)XSTRLEN(pt);
|
||||
|
||||
/* remove spaces between 'mtch' and the user name */
|
||||
for (i = 0; i < sz; i++) {
|
||||
if (pt[i] != ' ') break;
|
||||
}
|
||||
if (i == sz) {
|
||||
wolfSSH_Log(WS_LOG_ERROR,
|
||||
"[SSHD] No valid input found with Match");
|
||||
ret = WS_FATAL_ERROR;
|
||||
}
|
||||
|
||||
if (ret == WS_SUCCESS) {
|
||||
pt += i;
|
||||
sz -= i;
|
||||
|
||||
/* get the actual size of the user name */
|
||||
for (i = 0; i < sz; i++) {
|
||||
if (pt[i] == ' ' || pt[i] == '\r' || pt[i] == '\n') break;
|
||||
}
|
||||
sz = i;
|
||||
|
||||
ret = CreateString(out, pt, sz, config->heap);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* returns WS_SUCCESS on success, on success it update the conf pointed to
|
||||
* and makes it point to the newly created conf node */
|
||||
static int HandleMatch(WOLFSSHD_CONFIG** conf, const char* value, int valueSz)
|
||||
{
|
||||
WOLFSSHD_CONFIG* newConf;
|
||||
int ret = WS_SUCCESS;
|
||||
|
||||
if (conf == NULL || *conf == NULL || value == NULL) {
|
||||
ret = WS_BAD_ARGUMENT;
|
||||
}
|
||||
|
||||
/* create new configure for altered options specific to the match */
|
||||
if (ret == WS_SUCCESS) {
|
||||
newConf = wolfSSHD_ConfigCopy(*conf);
|
||||
if (newConf == NULL) {
|
||||
ret = WS_MEMORY_E;
|
||||
}
|
||||
}
|
||||
|
||||
/* users the settings apply to */
|
||||
if (ret == WS_SUCCESS) {
|
||||
ret = AddRestrictedCase(newConf, "User", value,
|
||||
&newConf->usrAppliesTo);
|
||||
}
|
||||
|
||||
/* groups the settings apply to */
|
||||
if (ret == WS_SUCCESS) {
|
||||
ret = AddRestrictedCase(newConf, "Group", value,
|
||||
&newConf->groupAppliesTo);
|
||||
}
|
||||
|
||||
/* @TODO handle , seperated user/group list */
|
||||
|
||||
/* update current config being processed */
|
||||
if (ret == WS_SUCCESS) {
|
||||
(*conf)->next = newConf;
|
||||
(*conf) = newConf;
|
||||
}
|
||||
|
||||
(void)valueSz;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* returns WS_SUCCESS on success */
|
||||
static int HandleForcedCommand(WOLFSSHD_CONFIG* conf, const char* value,
|
||||
int valueSz)
|
||||
{
|
||||
int ret = WS_SUCCESS;
|
||||
|
||||
if (conf == NULL || value == NULL) {
|
||||
ret = WS_BAD_ARGUMENT;
|
||||
}
|
||||
|
||||
if (ret == WS_SUCCESS) {
|
||||
if (conf->forceCmd != NULL) {
|
||||
FreeString(&conf->forceCmd, conf->heap);
|
||||
conf->forceCmd = NULL;
|
||||
}
|
||||
|
||||
ret = CreateString(&conf->forceCmd, value, valueSz, conf->heap);
|
||||
}
|
||||
|
||||
|
||||
(void)valueSz;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* returns WS_SUCCESS on success */
|
||||
static int HandleConfigOption(WOLFSSHD_CONFIG** conf, int opt,
|
||||
const char* value, const char* full, int fullSz)
|
||||
{
|
||||
int ret = WS_BAD_ARGUMENT;
|
||||
|
||||
switch (opt) {
|
||||
case OPT_AUTH_KEYS_FILE:
|
||||
ret = wolfSSHD_ConfigSetAuthKeysFile(conf, value);
|
||||
ret = wolfSSHD_ConfigSetAuthKeysFile(*conf, value);
|
||||
break;
|
||||
case OPT_PRIV_SEP:
|
||||
ret = HandlePrivSep(conf, value);
|
||||
ret = HandlePrivSep(*conf, value);
|
||||
break;
|
||||
case OPT_PERMIT_EMPTY_PW:
|
||||
ret = HandlePermitEmptyPw(conf, value);
|
||||
ret = HandlePermitEmptyPw(*conf, value);
|
||||
break;
|
||||
case OPT_SUBSYSTEM:
|
||||
/* TODO */
|
||||
|
@ -608,30 +859,40 @@ static int HandleConfigOption(WOLFSSHD_CONFIG* conf, int opt, const char* value)
|
|||
break;
|
||||
case OPT_PROTOCOL:
|
||||
/* TODO */
|
||||
ret = HandleProtocol(conf, value);
|
||||
ret = HandleProtocol(*conf, value);
|
||||
break;
|
||||
case OPT_LOGIN_GRACE_TIME:
|
||||
ret = HandleLoginGraceTime(conf, value);
|
||||
ret = HandleLoginGraceTime(*conf, value);
|
||||
break;
|
||||
case OPT_HOST_KEY:
|
||||
/* TODO: Add logic to check if file exists? */
|
||||
ret = wolfSSHD_ConfigSetHostKeyFile(conf, value);
|
||||
ret = wolfSSHD_ConfigSetHostKeyFile(*conf, value);
|
||||
break;
|
||||
case OPT_PASSWORD_AUTH:
|
||||
ret = HandlePwAuth(conf, value);
|
||||
ret = HandlePwAuth(*conf, value);
|
||||
break;
|
||||
case OPT_PORT:
|
||||
ret = HandlePort(conf, value);
|
||||
ret = HandlePort(*conf, value);
|
||||
break;
|
||||
case OPT_PERMIT_ROOT:
|
||||
ret = HandlePermitRoot(conf, value);
|
||||
ret = HandlePermitRoot(*conf, value);
|
||||
break;
|
||||
case OPT_USE_DNS:
|
||||
/* TODO */
|
||||
ret = WS_SUCCESS;
|
||||
break;
|
||||
case OPT_INCLUDE:
|
||||
ret = HandleInclude(conf, value);
|
||||
ret = HandleInclude(*conf, value);
|
||||
break;
|
||||
case OPT_CHROOT_DIR:
|
||||
ret = HandleChrootDir(*conf, value);
|
||||
break;
|
||||
case OPT_MATCH:
|
||||
/* makes new config and appends it to the list */
|
||||
ret = HandleMatch(conf, full, fullSz);
|
||||
break;
|
||||
case OPT_FORCE_CMD:
|
||||
ret = HandleForcedCommand(*conf, full, fullSz);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -642,7 +903,7 @@ static int HandleConfigOption(WOLFSSHD_CONFIG* conf, int opt, const char* value)
|
|||
|
||||
/* helper function to count white spaces, returns the number of white spaces on
|
||||
* success */
|
||||
static int CountWhitespace(const char* in, int inSz, byte inv)
|
||||
int CountWhitespace(const char* in, int inSz, byte inv)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
|
@ -666,8 +927,9 @@ static int CountWhitespace(const char* in, int inSz, byte inv)
|
|||
|
||||
/* returns WS_SUCCESS on success
|
||||
* Fails if any option is found that is unknown/unsupported
|
||||
* Match command will create new configs for specific matching cases
|
||||
*/
|
||||
WOLFSSHD_STATIC int ParseConfigLine(WOLFSSHD_CONFIG* conf, const char* l,
|
||||
WOLFSSHD_STATIC int ParseConfigLine(WOLFSSHD_CONFIG** conf, const char* l,
|
||||
int lSz)
|
||||
{
|
||||
int ret = WS_BAD_ARGUMENT;
|
||||
|
@ -699,7 +961,7 @@ WOLFSSHD_STATIC int ParseConfigLine(WOLFSSHD_CONFIG* conf, const char* l,
|
|||
else {
|
||||
WMEMCPY(tmp, l + idx, sz);
|
||||
tmp[sz] = 0;
|
||||
ret = HandleConfigOption(conf, found->tag, tmp);
|
||||
ret = HandleConfigOption(conf, found->tag, tmp, l + idx, lSz - idx);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -717,6 +979,7 @@ WOLFSSHD_STATIC int ParseConfigLine(WOLFSSHD_CONFIG* conf, const char* l,
|
|||
int wolfSSHD_ConfigLoad(WOLFSSHD_CONFIG* conf, const char* filename)
|
||||
{
|
||||
XFILE f;
|
||||
WOLFSSHD_CONFIG* currentConfig;
|
||||
int ret = WS_SUCCESS;
|
||||
char buf[MAX_LINE_SIZE];
|
||||
const char* current;
|
||||
|
@ -732,6 +995,7 @@ int wolfSSHD_ConfigLoad(WOLFSSHD_CONFIG* conf, const char* filename)
|
|||
}
|
||||
wolfSSH_Log(WS_LOG_INFO, "[SSHD] parsing config file %s", filename);
|
||||
|
||||
currentConfig = conf;
|
||||
while ((current = XFGETS(buf, MAX_LINE_SIZE, f)) != NULL) {
|
||||
int currentSz = (int)XSTRLEN(current);
|
||||
|
||||
|
@ -749,7 +1013,7 @@ int wolfSSHD_ConfigLoad(WOLFSSHD_CONFIG* conf, const char* filename)
|
|||
continue; /* commented out line */
|
||||
}
|
||||
|
||||
ret = ParseConfigLine(conf, current, currentSz);
|
||||
ret = ParseConfigLine(¤tConfig, current, currentSz);
|
||||
if (ret != WS_SUCCESS) {
|
||||
fprintf(stderr, "Unable to parse config line : %s\n", current);
|
||||
break;
|
||||
|
@ -762,6 +1026,60 @@ int wolfSSHD_ConfigLoad(WOLFSSHD_CONFIG* conf, const char* filename)
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* returns the config associated with the user */
|
||||
WOLFSSHD_CONFIG* wolfSSHD_GetUserConf(const WOLFSSHD_CONFIG* conf,
|
||||
const char* usr, const char* grp, const char* host,
|
||||
const char* localAdr, word16* localPort, const char* RDomain,
|
||||
const char* adr)
|
||||
{
|
||||
WOLFSSHD_CONFIG* ret;
|
||||
WOLFSSHD_CONFIG* current;
|
||||
|
||||
/* default to return head of list */
|
||||
ret = current = (WOLFSSHD_CONFIG*)conf;
|
||||
while (current != NULL) {
|
||||
/* compare current configs user */
|
||||
if (usr != NULL && current->usrAppliesTo != NULL) {
|
||||
if (XSTRCMP(current->usrAppliesTo, usr) == 0) {
|
||||
ret = current;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* compare current configs group */
|
||||
if (grp != NULL && current->groupAppliesTo != NULL) {
|
||||
if (XSTRCMP(current->groupAppliesTo, grp) == 0) {
|
||||
ret = current;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
/* @TODO */
|
||||
(void)host;
|
||||
(void)localAdr;
|
||||
(void)localPort;
|
||||
(void)RDomain;
|
||||
(void)adr;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
char* wolfSSHD_ConfigGetForcedCmd(const WOLFSSHD_CONFIG* conf)
|
||||
{
|
||||
char* ret = NULL;
|
||||
|
||||
if (conf != NULL) {
|
||||
ret = conf->forceCmd;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
char* wolfSSHD_ConfigGetAuthKeysFile(const WOLFSSHD_CONFIG* conf)
|
||||
{
|
||||
char* ret = NULL;
|
||||
|
@ -807,6 +1125,17 @@ char* wolfSSHD_ConfigGetBanner(const WOLFSSHD_CONFIG* conf)
|
|||
return ret;
|
||||
}
|
||||
|
||||
char* wolfSSHD_ConfigGetChroot(const WOLFSSHD_CONFIG* conf)
|
||||
{
|
||||
char* ret = NULL;
|
||||
|
||||
if (conf != NULL) {
|
||||
ret = conf->chrootDir;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
char* wolfSSHD_ConfigGetHostKeyFile(const WOLFSSHD_CONFIG* conf)
|
||||
{
|
||||
char* ret = NULL;
|
||||
|
|
|
@ -34,7 +34,9 @@ WOLFSSHD_CONFIG* wolfSSHD_ConfigNew(void* heap);
|
|||
void wolfSSHD_ConfigFree(WOLFSSHD_CONFIG* conf);
|
||||
int wolfSSHD_ConfigLoad(WOLFSSHD_CONFIG* conf, const char* filename);
|
||||
|
||||
char* wolfSSHD_ConfigGetForcedCmd(const WOLFSSHD_CONFIG* conf);
|
||||
char* wolfSSHD_ConfigGetBanner(const WOLFSSHD_CONFIG* conf);
|
||||
char* wolfSSHD_ConfigGetChroot(const WOLFSSHD_CONFIG* conf);
|
||||
char* wolfSSHD_ConfigGetHostKeyFile(const WOLFSSHD_CONFIG* conf);
|
||||
int wolfSSHD_ConfigSetHostKeyFile(WOLFSSHD_CONFIG* conf, const char* file);
|
||||
word16 wolfSSHD_ConfigGetPort(const WOLFSSHD_CONFIG* conf);
|
||||
|
@ -45,9 +47,13 @@ byte wolfSSHD_ConfigGetPermitRoot(const WOLFSSHD_CONFIG* conf);
|
|||
byte wolfSSHD_ConfigGetPrivilegeSeparation(const WOLFSSHD_CONFIG* conf);
|
||||
long wolfSSHD_ConfigGetGraceTime(const WOLFSSHD_CONFIG* conf);
|
||||
byte wolfSSHD_ConfigGetPwAuth(const WOLFSSHD_CONFIG* conf);
|
||||
WOLFSSHD_CONFIG* wolfSSHD_GetUserConf(const WOLFSSHD_CONFIG* conf,
|
||||
const char* usr, const char* grp, const char* host,
|
||||
const char* localAdr, word16* localPort, const char* RDomain,
|
||||
const char* adr);
|
||||
|
||||
#ifdef WOLFSSHD_UNIT_TEST
|
||||
int ParseConfigLine(WOLFSSHD_CONFIG* conf, const char* l, int lSz);
|
||||
int ParseConfigLine(WOLFSSHD_CONFIG** conf, const char* l, int lSz);
|
||||
#endif
|
||||
|
||||
#endif /* WOLFSSHD_H */
|
||||
|
|
|
@ -122,7 +122,7 @@ static int test_ParseConfigLine(void)
|
|||
for (i = 0; i < numVectors; ++i) {
|
||||
Log(" Testing scenario: %s.", vectors[i].desc);
|
||||
|
||||
ret = ParseConfigLine(conf, vectors[i].line,
|
||||
ret = ParseConfigLine(&conf, vectors[i].line,
|
||||
(int)WSTRLEN(vectors[i].line));
|
||||
|
||||
if ((ret == WS_SUCCESS && !vectors[i].shouldFail) ||
|
||||
|
|
|
@ -377,7 +377,8 @@ static int SFTP_Subsystem(WOLFSSH* ssh, WOLFSSHD_CONNECTION* conn)
|
|||
#define MAX_COMMAND_SZ 80
|
||||
#endif
|
||||
|
||||
static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh)
|
||||
static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh,
|
||||
char* forcedCmd)
|
||||
{
|
||||
WS_SOCKET_T sshFd = 0;
|
||||
int rc;
|
||||
|
@ -460,9 +461,14 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh)
|
|||
}
|
||||
|
||||
errno = 0;
|
||||
if (forcedCmd) {
|
||||
ret = execv(forcedCmd, NULL);
|
||||
}
|
||||
else {
|
||||
ret = execv(cmd, (char**)args);
|
||||
}
|
||||
if (ret && errno) {
|
||||
perror("error executing shell command ");
|
||||
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Issue opening shell");
|
||||
exit(1);
|
||||
}
|
||||
exit(0); /* exit child process and close down SSH connection */
|
||||
|
@ -633,7 +639,8 @@ static void* HandleConnection(void* arg)
|
|||
error = WS_FATAL_ERROR;
|
||||
}
|
||||
|
||||
if (ret != WS_SUCCESS && ret != WS_SFTP_COMPLETE) {
|
||||
if (ret != WS_SUCCESS && ret != WS_SFTP_COMPLETE &&
|
||||
ret != WS_SCP_COMPLETE) {
|
||||
wolfSSH_Log(WS_LOG_ERROR,
|
||||
"[SSHD] Failed to accept WOLFSSH connection from %s",
|
||||
conn->ip);
|
||||
|
@ -641,12 +648,72 @@ static void* HandleConnection(void* arg)
|
|||
}
|
||||
|
||||
if (ret == WS_SUCCESS || ret == WS_SFTP_COMPLETE) {
|
||||
WOLFSSHD_CONFIG* usrConf;
|
||||
char* cmd;
|
||||
char* usr;
|
||||
|
||||
/* get configuration for user */
|
||||
usr = wolfSSH_GetUsername(ssh);
|
||||
usrConf = wolfSSHD_AuthGetUserConf(conn->auth, usr, NULL, NULL,
|
||||
NULL, NULL, NULL);
|
||||
if (usrConf == NULL) {
|
||||
wolfSSH_Log(WS_LOG_ERROR,
|
||||
"[SSHD] Error getting user configuration");
|
||||
ret = WS_FATAL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
#ifdef WOLFSSH_SFTP
|
||||
/* set starting SFTP directory */
|
||||
if (ret == WS_SFTP_COMPLETE) {
|
||||
struct passwd *p_passwd;
|
||||
p_passwd = getpwnam((const char *)usr);
|
||||
if (p_passwd == NULL || wolfSSH_SFTP_SetDefaultPath(ssh,
|
||||
p_passwd->pw_dir) != WS_SUCCESS) {
|
||||
wolfSSH_Log(WS_LOG_ERROR,
|
||||
"[SSHD] Error setting SFTP default home path");
|
||||
ret = WS_FATAL_ERROR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* check for chroot set */
|
||||
cmd = wolfSSHD_ConfigGetChroot(usrConf);
|
||||
if (cmd != NULL) {
|
||||
if (chroot(cmd) != 0) {
|
||||
wolfSSH_Log(WS_LOG_ERROR,
|
||||
"[SSHD] chroot failed to path %s", cmd);
|
||||
ret = WS_FATAL_ERROR;
|
||||
}
|
||||
|
||||
#ifdef WOLFSSH_SFTP
|
||||
if (ret == WS_SFTP_COMPLETE) {
|
||||
if (wolfSSH_SFTP_SetDefaultPath(ssh, "/") != WS_SUCCESS) {
|
||||
wolfSSH_Log(WS_LOG_ERROR,
|
||||
"[SSHD] Error setting SFTP default path");
|
||||
ret = WS_FATAL_ERROR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ret != WS_FATAL_ERROR) {
|
||||
/* check for any forced command set for the user */
|
||||
cmd = wolfSSHD_ConfigGetForcedCmd(usrConf);
|
||||
switch (wolfSSH_GetSessionType(ssh)) {
|
||||
case WOLFSSH_SESSION_SHELL:
|
||||
#ifdef WOLFSSH_SHELL
|
||||
if (ret == WS_SUCCESS) {
|
||||
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Entering new shell");
|
||||
SHELL_Subsystem(conn, ssh);
|
||||
if (cmd != NULL && XSTRCMP(cmd, "internal-sftp") == 0) {
|
||||
wolfSSH_Log(WS_LOG_ERROR,
|
||||
"[SSHD] Only SFTP connections allowed for user "
|
||||
"%s", usr);
|
||||
ret = WS_FATAL_ERROR;
|
||||
}
|
||||
else {
|
||||
wolfSSH_Log(WS_LOG_INFO,
|
||||
"[SSHD] Entering new shell");
|
||||
SHELL_Subsystem(conn, ssh, cmd);
|
||||
}
|
||||
}
|
||||
#else
|
||||
wolfSSH_Log(WS_LOG_ERROR,
|
||||
|
@ -662,14 +729,16 @@ static void* HandleConnection(void* arg)
|
|||
#ifdef WOLFSSH_SFTP
|
||||
ret = SFTP_Subsystem(ssh, conn);
|
||||
#else
|
||||
err_sys("SFTP not compiled in. Please use --enable-sftp");
|
||||
err_sys("SFTP not compiled in. Please use "
|
||||
"--enable-sftp");
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
wolfSSH_Log(WS_LOG_ERROR,
|
||||
"[SSHD] Unknown or build not supporting subsystem"
|
||||
" found [%s]", wolfSSH_GetSessionCommand(ssh));
|
||||
"[SSHD] Unknown or build not supporting sub"
|
||||
"system found [%s]",
|
||||
wolfSSH_GetSessionCommand(ssh));
|
||||
ret = WS_NOT_COMPILED;
|
||||
}
|
||||
break;
|
||||
|
@ -679,10 +748,12 @@ static void* HandleConnection(void* arg)
|
|||
case WOLFSSH_SESSION_TERMINAL:
|
||||
default:
|
||||
wolfSSH_Log(WS_LOG_ERROR,
|
||||
"[SSHD] Unknown or build not supporting session type found");
|
||||
"[SSHD] Unknown or build not supporting session type "
|
||||
"found");
|
||||
ret = WS_NOT_COMPILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Attempting to close down connection");
|
||||
wolfSSH_shutdown(ssh);
|
||||
|
|
Loading…
Reference in New Issue