Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 101 additions & 18 deletions apps/wolfsshd/auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,12 @@ struct WOLFSSHD_AUTH {
#endif

#ifndef MAX_LINE_SZ
#define MAX_LINE_SZ 900
/* Sized to hold the largest authorized_keys entry. */
#ifndef WOLFSSH_NO_MLDSA
#define MAX_LINE_SZ ((WC_MLDSA_87_PUB_KEY_SIZE + 2) / 3 * 4 + 640)
#else
#define MAX_LINE_SZ 900
#endif
Comment thread
stenslae marked this conversation as resolved.
#endif
#ifndef MAX_PATH_SZ
#define MAX_PATH_SZ 80
Expand Down Expand Up @@ -174,11 +179,55 @@ static int CheckAuthKeysLine(char* line, word32 lineSz, const byte* key,
char* last = NULL;

enum {
NUM_BASE_TYPES = 5,
#ifdef WOLFSSH_CERTS
NUM_ALLOWED_TYPES = 9
NUM_CERT_TYPES = 4,
#else
NUM_ALLOWED_TYPES = 5
NUM_CERT_TYPES = 0,
#endif
#ifndef WOLFSSH_NO_MLDSA
#ifndef WOLFSSH_NO_MLDSA44
MLDSA44_COUNT = 1,
#else
MLDSA44_COUNT = 0,
#endif
#ifndef WOLFSSH_NO_MLDSA65
MLDSA65_COUNT = 1,
#else
MLDSA65_COUNT = 0,
#endif
#ifndef WOLFSSH_NO_MLDSA87
MLDSA87_COUNT = 1,
#else
MLDSA87_COUNT = 0,
#endif
NUM_MLDSA_TYPES = MLDSA44_COUNT + MLDSA65_COUNT + MLDSA87_COUNT,
#else
NUM_MLDSA_TYPES = 0,
#endif
#if !defined(WOLFSSH_NO_MLDSA) && defined(WOLFSSH_CERTS)
#ifndef WOLFSSH_NO_MLDSA44
MLDSA44_CERT_COUNT = 1,
#else
MLDSA44_CERT_COUNT = 0,
#endif
#ifndef WOLFSSH_NO_MLDSA65
MLDSA65_CERT_COUNT = 1,
#else
MLDSA65_CERT_COUNT = 0,
#endif
#ifndef WOLFSSH_NO_MLDSA87
MLDSA87_CERT_COUNT = 1,
#else
MLDSA87_CERT_COUNT = 0,
#endif
NUM_MLDSA_CERT_TYPES = MLDSA44_CERT_COUNT + MLDSA65_CERT_COUNT +
MLDSA87_CERT_COUNT,
#else
NUM_MLDSA_CERT_TYPES = 0,
#endif
NUM_ALLOWED_TYPES = NUM_BASE_TYPES + NUM_CERT_TYPES +
NUM_MLDSA_TYPES + NUM_MLDSA_CERT_TYPES
};
static const char* allowedTypes[NUM_ALLOWED_TYPES] = {
"ssh-rsa",
Expand All @@ -192,6 +241,28 @@ static int CheckAuthKeysLine(char* line, word32 lineSz, const byte* key,
"x509v3-ecdsa-sha2-nistp384",
"x509v3-ecdsa-sha2-nistp521",
#endif
#ifndef WOLFSSH_NO_MLDSA
#ifndef WOLFSSH_NO_MLDSA44
"ssh-mldsa-44",
#endif
#ifndef WOLFSSH_NO_MLDSA65
"ssh-mldsa-65",
#endif
#ifndef WOLFSSH_NO_MLDSA87
"ssh-mldsa-87",
#endif
#ifdef WOLFSSH_CERTS
#ifndef WOLFSSH_NO_MLDSA44
"x509v3-ssh-mldsa-44",
#endif
#ifndef WOLFSSH_NO_MLDSA65
"x509v3-ssh-mldsa-65",
#endif
#ifndef WOLFSSH_NO_MLDSA87
"x509v3-ssh-mldsa-87",
#endif
#endif
#endif
};
int typeOk = 0;
int i;
Expand Down Expand Up @@ -1377,9 +1448,9 @@ static int RequestAuthentication(WS_UserAuthData* authData,
* closed: require AuthorizedKeysFile (per-user key/cert mapping)
* or a wolfSSL build with FPKI. */
wolfSSH_Log(WS_LOG_ERROR,
"[SSHD] Certificate authentication cannot bind the requested "
"user without FPKI or AuthorizedKeysFile; rejecting "
"(user=%s)", usr);
"[SSHD] Certificate authentication cannot bind "
"the requested user without FPKI or "
"AuthorizedKeysFile; rejecting (user=%s)", usr);
ret = WOLFSSH_USERAUTH_REJECTED;
#endif
}
Expand Down Expand Up @@ -1573,6 +1644,11 @@ static int SetDefualtUserID(WOLFSSHD_AUTH* auth)
struct passwd* pwInfo;
int ret = WS_SUCCESS;

if (wolfSSHD_ConfigGetPrivilegeSeparation(auth->conf) ==
WOLFSSHD_PRIV_OFF) {
return WS_SUCCESS;
}

pwInfo = getpwnam(WOLFSSH_USER_STRING(WOLFSSH_SSHD_USER));
if (pwInfo == NULL) {
/* user name not found on system */
Expand Down Expand Up @@ -1665,24 +1741,31 @@ int wolfSSHD_AuthFreeUser(WOLFSSHD_AUTH* auth)
/* return WS_SUCCESS on success */
int wolfSSHD_AuthRaisePermissions(WOLFSSHD_AUTH* auth)
{
int ret = 0;
int ret = WS_SUCCESS;

wolfSSH_Log(WS_LOG_INFO, "[SSHD] Attempting to raise permissions level");
#ifndef WIN32
if (auth) {
if (setegid(auth->sGid) != 0) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error raising gid");
ret = WS_FATAL_ERROR;
{
byte flag = 0;

if (!auth) {
return WS_BAD_ARGUMENT;
}

if (seteuid(auth->sUid) != 0) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error raising uid");
ret = WS_FATAL_ERROR;
flag = wolfSSHD_ConfigGetPrivilegeSeparation(auth->conf);
if (flag == WOLFSSHD_PRIV_SEPARAT || flag == WOLFSSHD_PRIV_SANDBOX) {
wolfSSH_Log(WS_LOG_INFO,
"[SSHD] Attempting to raise permissions level");
if (setegid(auth->sGid) != 0) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error raising gid");
ret = WS_FATAL_ERROR;
}

if (seteuid(auth->sUid) != 0) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error raising uid");
ret = WS_FATAL_ERROR;
}
}
}
else {
ret = WS_BAD_ARGUMENT;
}
#endif

return ret;
Expand Down
100 changes: 97 additions & 3 deletions examples/echoserver/echoserver.c
Original file line number Diff line number Diff line change
Expand Up @@ -1777,6 +1777,46 @@ static int load_key_ed25519(byte* buf, word32 bufSz)
#endif /* WOLFSSH_NO_ED25519 */


#ifndef WOLFSSH_NO_MLDSA44
static int load_key_mldsa44(byte* buf, word32 bufSz)
{
word32 sz = 0;
#ifndef NO_FILESYSTEM
sz = load_file("./keys/server-key-mldsa44.der", buf, &bufSz);
#else
Comment thread
stenslae marked this conversation as resolved.
(void)buf; (void)bufSz;
#endif
return sz;
}
#endif /* WOLFSSH_NO_MLDSA44 */

#ifndef WOLFSSH_NO_MLDSA65
static int load_key_mldsa65(byte* buf, word32 bufSz)
{
word32 sz = 0;
#ifndef NO_FILESYSTEM
sz = load_file("./keys/server-key-mldsa65.der", buf, &bufSz);
#else
(void)buf; (void)bufSz;
#endif
return sz;
}
#endif /* WOLFSSH_NO_MLDSA65 */

#ifndef WOLFSSH_NO_MLDSA87
static int load_key_mldsa87(byte* buf, word32 bufSz)
{
word32 sz = 0;
#ifndef NO_FILESYSTEM
sz = load_file("./keys/server-key-mldsa87.der", buf, &bufSz);
#else
(void)buf; (void)bufSz;
#endif
return sz;
}
#endif /* WOLFSSH_NO_MLDSA87 */


typedef struct StrList {
const char* str;
struct StrList* next;
Expand Down Expand Up @@ -2410,6 +2450,7 @@ static int wsUserAuth(byte authType,
PwMapList* list;
PwMap* map;
byte authHash[WC_SHA256_DIGEST_SIZE] = {0};
int userFound = 0;

if (ctx == NULL) {
fprintf(stderr, "wsUserAuth: ctx not set");
Expand Down Expand Up @@ -2530,12 +2571,12 @@ static int wsUserAuth(byte authType,
authData->type == map->type) {

if (authData->type == WOLFSSH_USERAUTH_PUBLICKEY) {
userFound = 1;
if (WMEMCMP(map->p, authHash, WC_SHA256_DIGEST_SIZE) == 0) {
return WOLFSSH_USERAUTH_SUCCESS;
}
else {
return WOLFSSH_USERAUTH_INVALID_PUBLICKEY;
}
/* Hash mismatch: continue checking other registered keys
* for this user (a user may have multiple public keys). */
}
else if (authData->type == WOLFSSH_USERAUTH_PASSWORD) {
if (WMEMCMP(map->p, authHash, WC_SHA256_DIGEST_SIZE) == 0) {
Expand Down Expand Up @@ -2578,6 +2619,8 @@ static int wsUserAuth(byte authType,
map = map->next;
}

if (userFound)
return WOLFSSH_USERAUTH_INVALID_PUBLICKEY;
return WOLFSSH_USERAUTH_INVALID_USER;
}

Expand Down Expand Up @@ -3151,6 +3194,57 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
#endif /* WOLFSSH_NO_ED25519 */
}

/* Load only the ML-DSA levels requested in keyList; loading all levels
* unconditionally would force mldsa negotiation on non-mldsa tests. */
#ifndef WOLFSSH_NO_MLDSA
if (keyList != NULL && WSTRSTR(keyList, "mldsa") != NULL) {
#define MLDSA_KEY_LOAD_BUF_SZ MLDSA_MAX_BOTH_KEY_DER_SIZE
byte* mldsaBuf = (byte*)WMALLOC(MLDSA_KEY_LOAD_BUF_SZ, NULL, 0);
if (mldsaBuf == NULL) {
ES_ERROR("Couldn't allocate ML-DSA key load buffer.\n");
}
else {
word32 mldsaSz;

#ifndef WOLFSSH_NO_MLDSA44
if (WSTRSTR(keyList, "mldsa-44") != NULL) {
mldsaSz = load_key_mldsa44(mldsaBuf, MLDSA_KEY_LOAD_BUF_SZ);
if (mldsaSz == 0)
ES_ERROR("Couldn't load ML-DSA-44 key file.\n");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 [Low] mldsaBuf leaked on ML-DSA key load/use error paths · Resource leaks on error paths

ES_ERROR expands to WOLFSSL_RETURN_FROM_THREAD, exiting the thread immediately. Each ML-DSA load/use failure fires ES_ERROR after mldsaBuf (allocated at line 3202) and before the WFREE at line 3242, leaking the buffer.

Fix: Free mldsaBuf before each ES_ERROR in this block (or set a flag and free at a single exit point).

else if (wolfSSH_CTX_UsePrivateKey_buffer(ctx, mldsaBuf,
mldsaSz, WOLFSSH_FORMAT_ASN1) < 0)
ES_ERROR("Couldn't use ML-DSA-44 key buffer.\n");
}
#endif /* WOLFSSH_NO_MLDSA44 */

#ifndef WOLFSSH_NO_MLDSA65
if (WSTRSTR(keyList, "mldsa-65") != NULL) {
mldsaSz = load_key_mldsa65(mldsaBuf, MLDSA_KEY_LOAD_BUF_SZ);
if (mldsaSz == 0)
ES_ERROR("Couldn't load ML-DSA-65 key file.\n");
else if (wolfSSH_CTX_UsePrivateKey_buffer(ctx, mldsaBuf,
mldsaSz, WOLFSSH_FORMAT_ASN1) < 0)
ES_ERROR("Couldn't use ML-DSA-65 key buffer.\n");
}
#endif /* WOLFSSH_NO_MLDSA65 */

#ifndef WOLFSSH_NO_MLDSA87
if (WSTRSTR(keyList, "mldsa-87") != NULL) {
mldsaSz = load_key_mldsa87(mldsaBuf, MLDSA_KEY_LOAD_BUF_SZ);
if (mldsaSz == 0)
ES_ERROR("Couldn't load ML-DSA-87 key file.\n");
else if (wolfSSH_CTX_UsePrivateKey_buffer(ctx, mldsaBuf,
mldsaSz, WOLFSSH_FORMAT_ASN1) < 0)
ES_ERROR("Couldn't use ML-DSA-87 key buffer.\n");
}
#endif /* WOLFSSH_NO_MLDSA87 */

WFREE(mldsaBuf, NULL, 0);
}
#undef MLDSA_KEY_LOAD_BUF_SZ
}
#endif /* WOLFSSH_NO_MLDSA */

#ifndef NO_FILESYSTEM
if (userPubKey) {
byte* userBuf = NULL;
Expand Down
Binary file added keys/server-key-mldsa44.der
Binary file not shown.
Binary file added keys/server-key-mldsa65.der
Binary file not shown.
Binary file added keys/server-key-mldsa87.der
Binary file not shown.
Loading
Loading