mirror of https://github.com/wolfSSL/wolfssh.git
commit
c8bdf7d3d2
|
@ -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 */
|
||||
|
|
|
@ -50,6 +50,8 @@
|
|||
|
||||
struct WOLFSSHD_CONFIG {
|
||||
void* heap;
|
||||
char* usrAppliesTo; /* NULL means all users */
|
||||
char* groupAppliesTo; /* NULL means all groups */
|
||||
char* banner;
|
||||
char* chrootDir;
|
||||
char* ciphers;
|
||||
|
@ -58,6 +60,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:2;
|
||||
|
@ -67,6 +71,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
|
||||
|
@ -111,11 +116,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++;
|
||||
|
@ -124,15 +138,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';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -170,17 +197,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) {
|
||||
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->banner, heap);
|
||||
FreeString(¤t->chrootDir, heap);
|
||||
FreeString(¤t->ciphers, heap);
|
||||
FreeString(¤t->kekAlgos, heap);
|
||||
FreeString(¤t->hostKeyAlgos, heap);
|
||||
FreeString(¤t->listenAddress, heap);
|
||||
FreeString(¤t->authKeysFile, heap);
|
||||
FreeString(¤t->hostKeyFile, heap);
|
||||
|
||||
WFREE(conf, heap, DYNTYPE_SSHD);
|
||||
WFREE(current, heap, DYNTYPE_SSHD);
|
||||
current = next;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -208,10 +319,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] = {
|
||||
|
@ -231,7 +345,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 */
|
||||
|
@ -637,20 +754,154 @@ static int HandleInclude(WOLFSSHD_CONFIG *conf, const char *value)
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* 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 */
|
||||
|
@ -678,30 +929,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;
|
||||
|
@ -712,7 +973,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;
|
||||
|
||||
|
@ -736,8 +997,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;
|
||||
|
@ -769,7 +1031,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 {
|
||||
|
@ -787,6 +1049,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;
|
||||
|
@ -802,6 +1065,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);
|
||||
|
||||
|
@ -819,7 +1083,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;
|
||||
|
@ -832,6 +1096,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;
|
||||
|
@ -877,6 +1195,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 */
|
||||
|
|
|
@ -200,7 +200,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) ||
|
||||
|
|
|
@ -281,27 +281,41 @@ static int SetupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx)
|
|||
}
|
||||
|
||||
|
||||
/* return 1 if set, 0 if not set and negative values on error */
|
||||
static int SetupChroot(WOLFSSHD_CONFIG* usrConf)
|
||||
{
|
||||
int ret = 0;
|
||||
char* chrootPath;
|
||||
|
||||
/* check for chroot set */
|
||||
chrootPath = wolfSSHD_ConfigGetChroot(usrConf);
|
||||
if (chrootPath != NULL) {
|
||||
ret = 1;
|
||||
wolfSSH_Log(WS_LOG_INFO, "[SSHD] chroot to path %s", chrootPath);
|
||||
if (chroot(chrootPath) != 0) {
|
||||
wolfSSH_Log(WS_LOG_ERROR,
|
||||
"[SSHD] chroot failed to path %s", chrootPath);
|
||||
ret = WS_FATAL_ERROR;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#ifdef WOLFSSH_SFTP
|
||||
#define TEST_SFTP_TIMEOUT 1
|
||||
|
||||
/* handle SFTP operations
|
||||
* returns 0 on success
|
||||
* returns WS_SUCCESS on success
|
||||
*/
|
||||
static int SFTP_Subsystem(WOLFSSH* ssh, WOLFSSHD_CONNECTION* conn)
|
||||
static int SFTP_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh,
|
||||
WPASSWD* pPasswd, WOLFSSHD_CONFIG* usrConf)
|
||||
{
|
||||
byte tmp[1];
|
||||
int ret = WS_SUCCESS;
|
||||
int error = WS_SUCCESS;
|
||||
WS_SOCKET_T sockfd;
|
||||
int select_ret = 0;
|
||||
const char *userName;
|
||||
struct passwd *p_passwd;
|
||||
|
||||
userName = wolfSSH_GetUsername(ssh);
|
||||
if (userName == NULL) {
|
||||
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Failure get user name");
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
|
||||
/* temporarily elevate permissions to get users information */
|
||||
if (wolfSSHD_AuthRaisePermissions(conn->auth) != WS_SUCCESS) {
|
||||
|
@ -309,18 +323,39 @@ static int SFTP_Subsystem(WOLFSSH* ssh, WOLFSSHD_CONNECTION* conn)
|
|||
return WS_FATAL_ERROR;
|
||||
}
|
||||
|
||||
p_passwd = getpwnam((const char *)userName);
|
||||
if (p_passwd == NULL) {
|
||||
if (wolfSSHD_AuthReducePermissions(conn->auth) != WS_SUCCESS) {
|
||||
/* stop everything if not able to reduce permissions level */
|
||||
exit(1);
|
||||
if (ret == WS_SUCCESS) {
|
||||
error = SetupChroot(usrConf);
|
||||
if (error == 1) {
|
||||
/* chroot was executed */
|
||||
if (wolfSSH_SFTP_SetDefaultPath(ssh, "/") != WS_SUCCESS) {
|
||||
wolfSSH_Log(WS_LOG_ERROR,
|
||||
"[SSHD] Error setting SFTP default path");
|
||||
ret = WS_FATAL_ERROR;
|
||||
}
|
||||
}
|
||||
else if (error < 0) {
|
||||
ret = error; /* error case with setup chroot */
|
||||
}
|
||||
}
|
||||
|
||||
return WS_FATAL_ERROR;
|
||||
/* set starting SFTP directory */
|
||||
if (ret == WS_SUCCESS) {
|
||||
WDIR dir;
|
||||
|
||||
/* if home directory exists than set it as the default */
|
||||
if (WOPENDIR(NULL, NULL, &dir, pPasswd->pw_dir) == 0) {
|
||||
if (wolfSSH_SFTP_SetDefaultPath(ssh, pPasswd->pw_dir)
|
||||
!= WS_SUCCESS) {
|
||||
wolfSSH_Log(WS_LOG_ERROR,
|
||||
"[SSHD] Error setting SFTP default home path");
|
||||
ret = WS_FATAL_ERROR;
|
||||
}
|
||||
WCLOSEDIR(&dir);
|
||||
}
|
||||
}
|
||||
|
||||
if (wolfSSHD_AuthReducePermissionsUser(conn->auth, p_passwd->pw_uid,
|
||||
p_passwd->pw_gid) != WS_SUCCESS) {
|
||||
if (wolfSSHD_AuthReducePermissionsUser(conn->auth, pPasswd->pw_uid,
|
||||
pPasswd->pw_gid) != WS_SUCCESS) {
|
||||
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error setting user ID");
|
||||
if (wolfSSHD_AuthReducePermissions(conn->auth) != WS_SUCCESS) {
|
||||
/* stop everything if not able to reduce permissions level */
|
||||
|
@ -378,12 +413,14 @@ static int SFTP_Subsystem(WOLFSSH* ssh, WOLFSSHD_CONNECTION* conn)
|
|||
#define MAX_COMMAND_SZ 80
|
||||
#endif
|
||||
|
||||
static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh)
|
||||
/* handles creating a new shell env. and maintains SSH connection for incoming
|
||||
* user input as well as output of the shell.
|
||||
* return WS_SUCCESS on success */
|
||||
static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh,
|
||||
WPASSWD* pPasswd, WOLFSSHD_CONFIG* usrConf)
|
||||
{
|
||||
WS_SOCKET_T sshFd = 0;
|
||||
int rc;
|
||||
const char *userName;
|
||||
struct passwd *p_passwd;
|
||||
WS_SOCKET_T childFd = 0;
|
||||
pid_t childPid;
|
||||
#ifndef EXAMPLE_BUFFER_SZ
|
||||
|
@ -391,10 +428,13 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh)
|
|||
#endif
|
||||
byte shellBuffer[EXAMPLE_BUFFER_SZ];
|
||||
byte channelBuffer[EXAMPLE_BUFFER_SZ];
|
||||
char* forcedCmd;
|
||||
|
||||
userName = wolfSSH_GetUsername(ssh);
|
||||
if (userName == NULL) {
|
||||
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Failure get user name");
|
||||
forcedCmd = wolfSSHD_ConfigGetForcedCmd(usrConf);
|
||||
if (forcedCmd != NULL && XSTRCMP(forcedCmd, "internal-sftp") == 0) {
|
||||
wolfSSH_Log(WS_LOG_ERROR,
|
||||
"[SSHD] Only SFTP connections allowed for user "
|
||||
"%s", wolfSSH_GetUsername(ssh));
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
|
||||
|
@ -404,30 +444,7 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh)
|
|||
return WS_FATAL_ERROR;
|
||||
}
|
||||
|
||||
p_passwd = getpwnam((const char *)userName);
|
||||
if (p_passwd == NULL) {
|
||||
/* Not actually a user on the system. */
|
||||
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Invalid user name found");
|
||||
if (wolfSSHD_AuthReducePermissions(conn->auth) != WS_SUCCESS) {
|
||||
/* stop everything if not able to reduce permissions level */
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
|
||||
ChildRunning = 1;
|
||||
if (wolfSSHD_AuthReducePermissionsUser(conn->auth, p_passwd->pw_uid,
|
||||
p_passwd->pw_gid) != WS_SUCCESS) {
|
||||
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error setting user ID");
|
||||
if (wolfSSHD_AuthReducePermissions(conn->auth) != WS_SUCCESS) {
|
||||
/* stop everything if not able to reduce permissions level */
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
|
||||
childPid = forkpty(&childFd, NULL, NULL, NULL);
|
||||
if (childPid < 0) {
|
||||
/* forkpty failed, so return */
|
||||
|
@ -444,31 +461,85 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh)
|
|||
signal(SIGINT, SIG_DFL);
|
||||
signal(SIGCHLD, SIG_DFL);
|
||||
|
||||
setenv("HOME", p_passwd->pw_dir, 1);
|
||||
setenv("LOGNAME", p_passwd->pw_name, 1);
|
||||
rc = chdir(p_passwd->pw_dir);
|
||||
if (rc != 0) {
|
||||
rc = SetupChroot(usrConf);
|
||||
if (rc < 0) {
|
||||
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error setting chroot");
|
||||
if (wolfSSHD_AuthReducePermissions(conn->auth) != WS_SUCCESS) {
|
||||
/* stop everything if not able to reduce permissions level */
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
else if (rc == 1) {
|
||||
rc = chdir("/");
|
||||
if (rc != 0) {
|
||||
wolfSSH_Log(WS_LOG_ERROR,
|
||||
"[SSHD] Error going to / after chroot");
|
||||
if (wolfSSHD_AuthReducePermissions(conn->auth) != WS_SUCCESS) {
|
||||
/* stop everything if not able to reduce permissions level */
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (wolfSSHD_AuthReducePermissionsUser(conn->auth, pPasswd->pw_uid,
|
||||
pPasswd->pw_gid) != WS_SUCCESS) {
|
||||
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error setting user ID");
|
||||
if (wolfSSHD_AuthReducePermissions(conn->auth) != WS_SUCCESS) {
|
||||
/* stop everything if not able to reduce permissions level */
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
|
||||
setenv("HOME", pPasswd->pw_dir, 1);
|
||||
setenv("LOGNAME", pPasswd->pw_name, 1);
|
||||
|
||||
rc = chdir(pPasswd->pw_dir);
|
||||
if (rc != 0) {
|
||||
/* not error'ing out if unable to find home directory */
|
||||
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error going to user home dir %s",
|
||||
pPasswd->pw_dir);
|
||||
}
|
||||
|
||||
/* default to /bin/sh if user shell is not set */
|
||||
WMEMSET(cmd, 0, sizeof(cmd));
|
||||
if (XSTRLEN(p_passwd->pw_shell) == 0) {
|
||||
if (XSTRLEN(pPasswd->pw_shell) == 0) {
|
||||
XSNPRINTF(cmd, sizeof(cmd), "%s", "/bin/sh");
|
||||
}
|
||||
else {
|
||||
XSNPRINTF(cmd, sizeof(cmd),"%s", p_passwd->pw_shell);
|
||||
XSNPRINTF(cmd, sizeof(cmd),"%s", pPasswd->pw_shell);
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
if (forcedCmd) {
|
||||
args[0] = NULL;
|
||||
ret = execv(forcedCmd, (char**)args);
|
||||
}
|
||||
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 */
|
||||
}
|
||||
|
||||
if (wolfSSHD_AuthReducePermissionsUser(conn->auth, pPasswd->pw_uid,
|
||||
pPasswd->pw_gid) != WS_SUCCESS) {
|
||||
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error setting user ID");
|
||||
if (wolfSSHD_AuthReducePermissions(conn->auth) != WS_SUCCESS) {
|
||||
/* stop everything if not able to reduce permissions level */
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
sshFd = wolfSSH_get_fd(ssh);
|
||||
|
||||
struct termios tios;
|
||||
|
@ -634,7 +705,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);
|
||||
|
@ -642,12 +714,36 @@ static void* HandleConnection(void* arg)
|
|||
}
|
||||
|
||||
if (ret == WS_SUCCESS || ret == WS_SFTP_COMPLETE) {
|
||||
WPASSWD* pPasswd;
|
||||
WOLFSSHD_CONFIG* usrConf;
|
||||
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;
|
||||
}
|
||||
|
||||
if (ret == WS_SUCCESS || ret == WS_SFTP_COMPLETE) {
|
||||
pPasswd = getpwnam((const char *)usr);
|
||||
if (pPasswd == NULL) {
|
||||
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error igetting user info");
|
||||
ret = WS_FATAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret != WS_FATAL_ERROR) {
|
||||
/* check for any forced command set for the user */
|
||||
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);
|
||||
SHELL_Subsystem(conn, ssh, pPasswd, usrConf);
|
||||
}
|
||||
#else
|
||||
wolfSSH_Log(WS_LOG_ERROR,
|
||||
|
@ -661,16 +757,18 @@ static void* HandleConnection(void* arg)
|
|||
switch (ret) {
|
||||
case WS_SFTP_COMPLETE:
|
||||
#ifdef WOLFSSH_SFTP
|
||||
ret = SFTP_Subsystem(ssh, conn);
|
||||
ret = SFTP_Subsystem(conn, ssh, pPasswd, usrConf);
|
||||
#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;
|
||||
|
@ -680,10 +778,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);
|
||||
|
|
|
@ -1230,6 +1230,12 @@ static int wolfSSH_SFTP_RecvRealPath(WOLFSSH* ssh, int reqId, byte* data,
|
|||
rSz -= 1;
|
||||
}
|
||||
|
||||
/* special case of /. */
|
||||
if (rSz == 2 && r[0] == WS_DELIM && r[1] == '.') {
|
||||
r[1] = '\0';
|
||||
rSz -= 1;
|
||||
}
|
||||
|
||||
/* for real path always send '/' chars */
|
||||
for (i = 0; i < rSz; i++) {
|
||||
if (r[i] == WS_DELIM) r[i] = '/';
|
||||
|
|
|
@ -50,6 +50,7 @@ extern "C" {
|
|||
#endif
|
||||
#define WUID_T uid_t
|
||||
#define WGID_T gid_t
|
||||
#define WPASSWD struct passwd
|
||||
#endif
|
||||
|
||||
/* setup memory handling */
|
||||
|
|
Loading…
Reference in New Issue