add chroot jailing to sshd

pull/441/head
JacobBarthelmeh 2022-08-19 14:32:13 -07:00
parent 82172d0e43
commit e1f0a67c38
6 changed files with 512 additions and 72 deletions

View File

@ -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 */

View File

@ -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 */

View File

@ -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(&current->authKeysFile, heap);
FreeString(&current->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(&currentConfig, 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;

View File

@ -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 */

View File

@ -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) ||

View File

@ -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;
ret = execv(cmd, (char**)args);
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,46 +648,110 @@ static void* HandleConnection(void* arg)
}
if (ret == WS_SUCCESS || ret == WS_SFTP_COMPLETE) {
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);
}
#else
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] Shell support is disabled");
ret = WS_NOT_COMPILED;
#endif
break;
case WOLFSSH_SESSION_SUBSYSTEM:
/* test for known subsystems */
switch (ret) {
case WS_SFTP_COMPLETE:
#ifdef WOLFSSH_SFTP
ret = SFTP_Subsystem(ssh, conn);
#else
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));
ret = WS_NOT_COMPILED;
}
break;
case WOLFSSH_SESSION_UNKNOWN:
case WOLFSSH_SESSION_EXEC:
case WOLFSSH_SESSION_TERMINAL:
default:
"[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] Unknown or build not supporting session type found");
ret = WS_NOT_COMPILED;
"[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) {
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,
"[SSHD] Shell support is disabled");
ret = WS_NOT_COMPILED;
#endif
break;
case WOLFSSH_SESSION_SUBSYSTEM:
/* test for known subsystems */
switch (ret) {
case WS_SFTP_COMPLETE:
#ifdef WOLFSSH_SFTP
ret = SFTP_Subsystem(ssh, conn);
#else
err_sys("SFTP not compiled in. Please use "
"--enable-sftp");
#endif
break;
default:
wolfSSH_Log(WS_LOG_ERROR,
"[SSHD] Unknown or build not supporting sub"
"system found [%s]",
wolfSSH_GetSessionCommand(ssh));
ret = WS_NOT_COMPILED;
}
break;
case WOLFSSH_SESSION_UNKNOWN:
case WOLFSSH_SESSION_EXEC:
case WOLFSSH_SESSION_TERMINAL:
default:
wolfSSH_Log(WS_LOG_ERROR,
"[SSHD] Unknown or build not supporting session type "
"found");
ret = WS_NOT_COMPILED;
}
}
}