From 85109e66cff17a3d7ef9ccb6d5615c2126424b5f Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Mon, 25 Jul 2022 09:26:05 -0700 Subject: [PATCH] raise and lower permissions levels --- apps/wolfsshd/auth.c | 83 ++++++++++++++++++++++++++++++++++++++++ apps/wolfsshd/auth.h | 2 + apps/wolfsshd/wolfsshd.c | 36 ++++++++++++++++- 3 files changed, 120 insertions(+), 1 deletion(-) diff --git a/apps/wolfsshd/auth.c b/apps/wolfsshd/auth.c index c216206c..96f90295 100644 --- a/apps/wolfsshd/auth.c +++ b/apps/wolfsshd/auth.c @@ -26,6 +26,7 @@ #ifdef __linux__ #define _XOPEN_SOURCE + #define _GNU_SOURCE #endif #include @@ -57,6 +58,8 @@ struct WOLFSSHD_AUTH { CallbackCheckPassword CheckPasswordCb; CallbackCheckPublicKey CheckPublicKeyCb; WOLFSSHD_CONFIG* conf; + int gid; + int uid; void* heap; }; @@ -653,7 +656,17 @@ static int RequestAuthentication(const char* usr, int type, const byte* data, { int ret; + if (auth == NULL) + return WOLFSSH_USERAUTH_FAILURE; + ret = DoCheckUser(usr, auth); + + /* temporarily elevate permissions */ + if (wolfSSHD_RaisePermissions(auth) != 0) { + wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Failure to raise permissions for auth"); + ret = WOLFSSH_USERAUTH_FAILURE; + } + if (ret == WOLFSSH_USERAUTH_SUCCESS && type == WOLFSSH_USERAUTH_PASSWORD) { int rc; @@ -699,6 +712,11 @@ static int RequestAuthentication(const char* usr, int type, const byte* data, } } + + if (wolfSSHD_ReducePermissions(auth) != 0) { + /* stop everything if not able to reduce permissions level */ + exit(1); + } return ret; } @@ -816,6 +834,8 @@ WOLFSSHD_AUTH * wolfSSHD_CreateUserAuth(void* heap, WOLFSSHD_CONFIG* conf) auth = (WOLFSSHD_AUTH*)WMALLOC(sizeof(WOLFSSHD_AUTH), heap, DYNTYPE_SSHD); if (auth != NULL) { int ret; + struct passwd* pwInfo; + const char* usr = "sshd"; auth->heap = heap; auth->conf = conf; @@ -844,6 +864,20 @@ WOLFSSHD_AUTH * wolfSSHD_CreateUserAuth(void* heap, WOLFSSHD_CONFIG* conf) } } + if (ret == WS_SUCCESS) { + pwInfo = getpwnam(usr); + if (pwInfo == NULL) { + /* user name not found on system */ + wolfSSH_Log(WS_LOG_INFO, "[SSHD] No sshd user found to use"); + ret = WS_FATAL_ERROR; + } + } + + if (ret == WS_SUCCESS) { + auth->gid = pwInfo->pw_gid; + auth->uid = pwInfo->pw_uid; + } + /* error case in setting one of the default callbacks */ if (ret != WS_SUCCESS) { (void)wolfSSHD_FreeUserAuth(auth); @@ -864,4 +898,53 @@ int wolfSSHD_FreeUserAuth(WOLFSSHD_AUTH* auth) } return WS_SUCCESS; } + + +/* return 0 on success */ +int wolfSSHD_RaisePermissions(WOLFSSHD_AUTH* auth) +{ + int ret = 0; + + wolfSSH_Log(WS_LOG_INFO, "[SSHD] Attempting to raise permissions level"); + if (auth) { + if (setegid(0) != 0) { + wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error rasing gid"); + ret = WS_FATAL_ERROR; + } + + if (seteuid(0) != 0) { + wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error rasing uid"); + ret = WS_FATAL_ERROR; + } + } + else { + ret = WS_BAD_ARGUMENT; + } + + return ret; +} + + +/* return 0 on success */ +int wolfSSHD_ReducePermissions(WOLFSSHD_AUTH* auth) +{ + int ret = 0; + + wolfSSH_Log(WS_LOG_INFO, "[SSHD] Lowering permissions level"); + if (auth) { + if (setegid(auth->gid) != 0) { + wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error setting sshd gid"); + ret = WS_FATAL_ERROR; + } + + if (seteuid(auth->uid) != 0) { + wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error setting sshd uid"); + ret = WS_FATAL_ERROR; + } + } + else { + ret = WS_BAD_ARGUMENT; + } + return ret; +} #endif /* WOLFSSH_SSHD */ diff --git a/apps/wolfsshd/auth.h b/apps/wolfsshd/auth.h index f99109e9..8e96c65e 100644 --- a/apps/wolfsshd/auth.h +++ b/apps/wolfsshd/auth.h @@ -56,4 +56,6 @@ typedef int (*CallbackCheckPublicKey)(const char* usr, const byte* key, WOLFSSHD_AUTH * wolfSSHD_CreateUserAuth(void* heap, WOLFSSHD_CONFIG* conf); int wolfSSHD_FreeUserAuth(WOLFSSHD_AUTH* auth); +int wolfSSHD_ReducePermissions(WOLFSSHD_AUTH* auth); +int wolfSSHD_RaisePermissions(WOLFSSHD_AUTH* auth); #endif /* WOLFAUTH_H */ diff --git a/apps/wolfsshd/wolfsshd.c b/apps/wolfsshd/wolfsshd.c index 11091867..8973d42e 100644 --- a/apps/wolfsshd/wolfsshd.c +++ b/apps/wolfsshd/wolfsshd.c @@ -336,13 +336,30 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh) byte channelBuffer[EXAMPLE_BUFFER_SZ]; userName = wolfSSH_GetUsername(ssh); + + /* temporarily elevate permissions to get users information */ + if (wolfSSHD_RaisePermissions(conn->auth) != 0) { + wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Failure to raise permissions for auth"); + 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_ReducePermissions(conn->auth) != 0) { + /* stop everything if not able to reduce permissions level */ + exit(1); + } + return WS_FATAL_ERROR; } + if (wolfSSHD_ReducePermissions(conn->auth) != 0) { + /* stop everything if not able to reduce permissions level */ + exit(1); + } + ChildRunning = 1; childPid = forkpty(&childFd, NULL, NULL, NULL); @@ -354,15 +371,24 @@ static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh) else if (childPid == 0) { /* Child process */ const char *args[] = {"-sh", NULL}; + char cmd[80]; signal(SIGINT, SIG_DFL); + setgid(p_passwd->pw_gid); + setuid(p_passwd->pw_uid); if (system("env") != 0) { printf("0 return value from system call\n"); } setenv("HOME", p_passwd->pw_dir, 1); setenv("LOGNAME", p_passwd->pw_name, 1); + + /* @TODO this needs reworked, can just exit into root */ + WMEMSET(cmd, 0, sizeof(cmd)); + XSNPRINTF(cmd, sizeof(cmd), "su %s", userName); + printf("executing command [%s]\n", cmd); + system(cmd); rc = chdir(p_passwd->pw_dir); if (rc != 0) { return WS_FATAL_ERROR; @@ -609,7 +635,7 @@ static int wolfSSHD_PendingConnection(WS_SOCKET_T fd) else { printf("Found write or error data\n"); ret = 0; /* nothing to read */ - } + } } // printf("Timeout waiting for connection\n"); return ret; @@ -724,6 +750,14 @@ int main(int argc, char** argv) } } + /* seperate privlage permisions */ + if (ret == WS_SUCCESS) { + if (wolfSSHD_ReducePermissions(auth) != 0) { + wolfSSH_Log(WS_LOG_INFO, "[SSHD] Error lowering permissions level"); + ret = WS_FATAL_ERROR; + } + } + if (ret == WS_SUCCESS) { wolfSSH_Log(WS_LOG_INFO, "[SSHD] Starting to listen on port %d", port); tcp_listen(&listenFd, &port, 1);