-
Notifications
You must be signed in to change notification settings - Fork 114
SSHD/Echoserver: Fix memory leaks and public-key lookup #1071
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1559,6 +1559,266 @@ static int test_AuthReducePermissionsUser_uid_fail(void) | |
| wsshd_setreuid_cb = savedReuid; | ||
| return ret; | ||
| } | ||
|
|
||
| static WGID_T s_setegid_arg; | ||
| static WUID_T s_seteuid_arg; | ||
| static int s_setegid_ret; | ||
| static int s_seteuid_ret; | ||
| static int s_setegid_called; | ||
| static int s_seteuid_called; | ||
|
|
||
| static int stub_setegid(WGID_T egid) | ||
| { | ||
| s_setegid_called = 1; | ||
| s_setegid_arg = egid; | ||
| return s_setegid_ret; | ||
| } | ||
|
|
||
| static int stub_seteuid(WUID_T euid) | ||
| { | ||
| s_seteuid_called = 1; | ||
| s_seteuid_arg = euid; | ||
| return s_seteuid_ret; | ||
| } | ||
|
|
||
| static void InstallPrivRaiseStubs(int egidRet, int euidRet, | ||
| int (**savedEgid)(WGID_T), int (**savedEuid)(WUID_T)) | ||
| { | ||
| *savedEgid = wsshd_setegid_cb; | ||
| *savedEuid = wsshd_seteuid_cb; | ||
| wsshd_setegid_cb = stub_setegid; | ||
| wsshd_seteuid_cb = stub_seteuid; | ||
| s_setegid_ret = egidRet; | ||
| s_seteuid_ret = euidRet; | ||
| s_setegid_called = 0; | ||
| s_seteuid_called = 0; | ||
| s_setegid_arg = 0; | ||
| s_seteuid_arg = 0; | ||
| } | ||
|
|
||
| /* UsePrivilegeSeparation no must let SetDefaultUserID succeed without a | ||
| * configured sshd system user, since no uid/gid switching will ever happen. */ | ||
| static int test_AuthCreateUser_privSepOff(void) | ||
| { | ||
| int ret = WS_SUCCESS; | ||
| WOLFSSHD_CONFIG* conf; | ||
| WOLFSSHD_AUTH* auth; | ||
| static const char line[] = "UsePrivilegeSeparation no"; | ||
|
|
||
| conf = wolfSSHD_ConfigNew(NULL); | ||
| if (conf == NULL) { | ||
| return WS_MEMORY_E; | ||
| } | ||
|
|
||
| if (ParseConfigLine(&conf, line, (int)WSTRLEN(line), 0) != WS_SUCCESS) { | ||
| ret = WS_FATAL_ERROR; | ||
| } | ||
|
|
||
| if (ret == WS_SUCCESS) { | ||
| auth = wolfSSHD_AuthCreateUser(NULL, conf); | ||
| if (auth == NULL) { | ||
| ret = WS_FATAL_ERROR; | ||
| } | ||
| else { | ||
| wolfSSHD_AuthFreeUser(auth); | ||
| } | ||
| } | ||
|
|
||
| wolfSSHD_ConfigFree(conf); | ||
| return ret; | ||
| } | ||
|
|
||
| /* wolfSSHD_AuthRaisePermissions must not touch setegid/seteuid at all when | ||
| * privilege separation is off, since the process never dropped privileges. */ | ||
| static int test_AuthRaisePermissions_offSkipsSyscalls(void) | ||
| { | ||
| int ret = WS_SUCCESS; | ||
| WOLFSSHD_CONFIG* conf; | ||
| WOLFSSHD_AUTH* auth; | ||
| int (*savedEgid)(WGID_T); | ||
| int (*savedEuid)(WUID_T); | ||
| static const char line[] = "UsePrivilegeSeparation no"; | ||
|
|
||
| conf = wolfSSHD_ConfigNew(NULL); | ||
| if (conf == NULL) { | ||
| return WS_MEMORY_E; | ||
| } | ||
|
|
||
| if (ParseConfigLine(&conf, line, (int)WSTRLEN(line), 0) != WS_SUCCESS) { | ||
| ret = WS_FATAL_ERROR; | ||
| } | ||
|
|
||
| if (ret == WS_SUCCESS) { | ||
| auth = wolfSSHD_AuthCreateUser(NULL, conf); | ||
| if (auth == NULL) { | ||
| ret = WS_FATAL_ERROR; | ||
| } | ||
| else { | ||
| InstallPrivRaiseStubs(0, 0, &savedEgid, &savedEuid); | ||
|
|
||
| if (wolfSSHD_AuthRaisePermissions(auth) != WS_SUCCESS) | ||
| ret = WS_FATAL_ERROR; | ||
| if (ret == WS_SUCCESS | ||
| && (s_setegid_called || s_seteuid_called)) | ||
| ret = WS_FATAL_ERROR; | ||
|
|
||
| wsshd_setegid_cb = savedEgid; | ||
| wsshd_seteuid_cb = savedEuid; | ||
| wolfSSHD_AuthFreeUser(auth); | ||
| } | ||
| } | ||
|
|
||
| wolfSSHD_ConfigFree(conf); | ||
| return ret; | ||
| } | ||
|
|
||
| /* With privilege separation on, wolfSSHD_AuthRaisePermissions restores the | ||
| * uid/gid the process started with (captured at AuthCreateUser time). Skipped | ||
| * when the environment has no "sshd" system user, since SetDefaultUserID | ||
| * requires one to succeed for this mode. */ | ||
| static int test_AuthRaisePermissions_separateCallsSyscalls(void) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔵 [Low] New privilege-separation-ON tests silently skip when no "sshd" system user exists · Missing Tests Verified: the guard at test_configuration.c:1687-1691 returns WS_SUCCESS when getpwnam("sshd") is NULL, and the auth.c diff confirms SetDefaultUserID only consults getpwnam() on the privilege-separation-ON path (the PRIV_OFF path now short-circuits to getgid()/getuid()). Three of the six new tests — the only ones that exercise the security-relevant branch where privilege separation is ON and setegid/seteuid are actually invoked — bail out with Fix: Decouple these tests from the host's user database so they always run: either add a |
||
| { | ||
| int ret = WS_SUCCESS; | ||
| WOLFSSHD_CONFIG* conf; | ||
| WOLFSSHD_AUTH* auth; | ||
| int (*savedEgid)(WGID_T); | ||
| int (*savedEuid)(WUID_T); | ||
|
|
||
| if (getpwnam("sshd") == NULL) { | ||
| /* no sshd system user available in this environment to switch to */ | ||
| Log(" No \"sshd\" system user available, skipping.\n"); | ||
| return WS_SUCCESS; | ||
| } | ||
|
|
||
| conf = wolfSSHD_ConfigNew(NULL); | ||
| if (conf == NULL) { | ||
| return WS_MEMORY_E; | ||
| } | ||
|
|
||
| /* privilege separation defaults to on */ | ||
| auth = wolfSSHD_AuthCreateUser(NULL, conf); | ||
| if (auth == NULL) { | ||
| ret = WS_FATAL_ERROR; | ||
| } | ||
| else { | ||
| InstallPrivRaiseStubs(0, 0, &savedEgid, &savedEuid); | ||
|
|
||
| if (wolfSSHD_AuthRaisePermissions(auth) != WS_SUCCESS) | ||
| ret = WS_FATAL_ERROR; | ||
| if (ret == WS_SUCCESS && (!s_setegid_called || !s_seteuid_called)) | ||
| ret = WS_FATAL_ERROR; | ||
| if (ret == WS_SUCCESS && s_setegid_arg != getgid()) | ||
| ret = WS_FATAL_ERROR; | ||
| if (ret == WS_SUCCESS && s_seteuid_arg != getuid()) | ||
| ret = WS_FATAL_ERROR; | ||
|
|
||
| wsshd_setegid_cb = savedEgid; | ||
| wsshd_seteuid_cb = savedEuid; | ||
| wolfSSHD_AuthFreeUser(auth); | ||
| } | ||
|
|
||
| wolfSSHD_ConfigFree(conf); | ||
| return ret; | ||
| } | ||
|
|
||
| /* wolfSSHD_AuthRaisePermissions must reject a NULL auth argument instead of | ||
| * dereferencing it. */ | ||
| static int test_AuthRaisePermissions_nullArg(void) | ||
| { | ||
| if (wolfSSHD_AuthRaisePermissions(NULL) != WS_BAD_ARGUMENT) | ||
| return WS_FATAL_ERROR; | ||
| return WS_SUCCESS; | ||
| } | ||
|
|
||
| /* When setegid fails, wolfSSHD_AuthRaisePermissions must report the failure | ||
| * and short-circuit seteuid rather than attempting it anyway. */ | ||
| static int test_AuthRaisePermissions_gidFailSkipsUid(void) | ||
| { | ||
| int ret = WS_SUCCESS; | ||
| WOLFSSHD_CONFIG* conf; | ||
| WOLFSSHD_AUTH* auth; | ||
| int (*savedEgid)(WGID_T); | ||
| int (*savedEuid)(WUID_T); | ||
|
|
||
| if (getpwnam("sshd") == NULL) { | ||
| /* no sshd system user available in this environment to switch to */ | ||
| Log(" No \"sshd\" system user available, skipping.\n"); | ||
| return WS_SUCCESS; | ||
| } | ||
|
|
||
| conf = wolfSSHD_ConfigNew(NULL); | ||
| if (conf == NULL) { | ||
| return WS_MEMORY_E; | ||
| } | ||
|
|
||
| /* privilege separation defaults to on */ | ||
| auth = wolfSSHD_AuthCreateUser(NULL, conf); | ||
| if (auth == NULL) { | ||
| ret = WS_FATAL_ERROR; | ||
| } | ||
| else { | ||
| InstallPrivRaiseStubs(-1, 0, &savedEgid, &savedEuid); | ||
|
|
||
| if (wolfSSHD_AuthRaisePermissions(auth) != WS_FATAL_ERROR) | ||
| ret = WS_FATAL_ERROR; | ||
| if (ret == WS_SUCCESS && !s_setegid_called) | ||
| ret = WS_FATAL_ERROR; | ||
| if (ret == WS_SUCCESS && s_seteuid_called) | ||
| ret = WS_FATAL_ERROR; | ||
|
|
||
| wsshd_setegid_cb = savedEgid; | ||
| wsshd_seteuid_cb = savedEuid; | ||
| wolfSSHD_AuthFreeUser(auth); | ||
| } | ||
|
|
||
| wolfSSHD_ConfigFree(conf); | ||
| return ret; | ||
| } | ||
|
|
||
| /* When setegid succeeds but seteuid fails, wolfSSHD_AuthRaisePermissions must | ||
| * still report the failure. */ | ||
| static int test_AuthRaisePermissions_uidFail(void) | ||
| { | ||
| int ret = WS_SUCCESS; | ||
| WOLFSSHD_CONFIG* conf; | ||
| WOLFSSHD_AUTH* auth; | ||
| int (*savedEgid)(WGID_T); | ||
| int (*savedEuid)(WUID_T); | ||
|
|
||
| if (getpwnam("sshd") == NULL) { | ||
| /* no sshd system user available in this environment to switch to */ | ||
| Log(" No \"sshd\" system user available, skipping.\n"); | ||
| return WS_SUCCESS; | ||
| } | ||
|
|
||
| conf = wolfSSHD_ConfigNew(NULL); | ||
| if (conf == NULL) { | ||
| return WS_MEMORY_E; | ||
| } | ||
|
|
||
| /* privilege separation defaults to on */ | ||
| auth = wolfSSHD_AuthCreateUser(NULL, conf); | ||
| if (auth == NULL) { | ||
| ret = WS_FATAL_ERROR; | ||
| } | ||
| else { | ||
| InstallPrivRaiseStubs(0, -1, &savedEgid, &savedEuid); | ||
|
|
||
| if (wolfSSHD_AuthRaisePermissions(auth) != WS_FATAL_ERROR) | ||
| ret = WS_FATAL_ERROR; | ||
| if (ret == WS_SUCCESS && !s_setegid_called) | ||
| ret = WS_FATAL_ERROR; | ||
| if (ret == WS_SUCCESS && !s_seteuid_called) | ||
| ret = WS_FATAL_ERROR; | ||
|
|
||
| wsshd_setegid_cb = savedEgid; | ||
| wsshd_seteuid_cb = savedEuid; | ||
| wolfSSHD_AuthFreeUser(auth); | ||
| } | ||
|
|
||
| wolfSSHD_ConfigFree(conf); | ||
| return ret; | ||
| } | ||
| #endif /* !_WIN32 */ | ||
|
|
||
| /* Locks in the NULL-safe comparison used by RequestAuthentication to fail | ||
|
|
@@ -1929,6 +2189,12 @@ const TEST_CASE testCases[] = { | |
| TEST_DECL(test_AuthReducePermissionsUser_ok), | ||
| TEST_DECL(test_AuthReducePermissionsUser_gid_fail), | ||
| TEST_DECL(test_AuthReducePermissionsUser_uid_fail), | ||
| TEST_DECL(test_AuthCreateUser_privSepOff), | ||
| TEST_DECL(test_AuthRaisePermissions_offSkipsSyscalls), | ||
| TEST_DECL(test_AuthRaisePermissions_separateCallsSyscalls), | ||
| TEST_DECL(test_AuthRaisePermissions_nullArg), | ||
| TEST_DECL(test_AuthRaisePermissions_gidFailSkipsUid), | ||
| TEST_DECL(test_AuthRaisePermissions_uidFail), | ||
| #endif | ||
| #if defined(WOLFSSH_HAVE_LIBCRYPT) || defined(WOLFSSH_HAVE_LIBLOGIN) | ||
| TEST_DECL(test_CheckPasswordHashUnix), | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.