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
9 changes: 5 additions & 4 deletions apps/wolfsshd/auth.c
Comment thread
ejohnstown marked this conversation as resolved.
Resolved
Original file line number Diff line number Diff line change
Expand Up @@ -2961,7 +2961,8 @@ static int RequestAuthentication(WS_UserAuthData* authData,
wolfSSHD_ConfigGetPubKeyAuth(usrConf) != 1) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Public key authentication not "
"allowed by configuration!");
ret = WOLFSSH_USERAUTH_REJECTED;
/* FAILURE, not REJECTED, so the client can try another method. */
ret = WOLFSSH_USERAUTH_FAILURE;
}

if (ret == WOLFSSH_USERAUTH_SUCCESS &&
Expand All @@ -2970,7 +2971,7 @@ static int RequestAuthentication(WS_UserAuthData* authData,
/* Forced command required. */
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Public key login for root requires "
"a forced command by configuration!");
ret = WOLFSSH_USERAUTH_REJECTED;
ret = WOLFSSH_USERAUTH_FAILURE;
}

#if defined(WOLFSSH_CERTS) && (defined(WOLFSSL_FPKI) || defined(_WIN32))
Expand Down Expand Up @@ -3093,7 +3094,7 @@ static int RequestAuthentication(WS_UserAuthData* authData,
"[SSHD] Per-user TrustedUserCAKeys override is not enforced "
"for certificate authentication; rejecting (user=%.32s)",
usr);
ret = WOLFSSH_USERAUTH_REJECTED;
ret = WOLFSSH_USERAUTH_FAILURE;
}
else {
#if defined(WOLFSSH_CERTS) && defined(_WIN32)
Expand Down Expand Up @@ -3131,7 +3132,7 @@ static int RequestAuthentication(WS_UserAuthData* authData,
"[SSHD] Certificate authentication cannot bind the requested "
"user without FPKI or AuthorizedKeysFile; rejecting "
"(user=%.32s)", usr);
ret = WOLFSSH_USERAUTH_REJECTED;
ret = WOLFSSH_USERAUTH_FAILURE;
#endif
}
}
Expand Down
5 changes: 4 additions & 1 deletion apps/wolfsshd/test/sshd_permitroot_prohibit_password.sh
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,11 @@ fi

TEST_CLIENT="../../../examples/client/client"

# Attempt password login as root, which should be rejected
# Attempt password login as root, which should be rejected. The client
# tries a key first, so offer one root does not authorize.
timeout 10 $TEST_CLIENT -u "$USER" -P "somepassword" -c 'true' \
-i $PWD/../../../keys/gretel-key-ecc.der \
-j $PWD/../../../keys/gretel-key-ecc.pub \
-h "$TEST_HOST" -p "$TEST_PORT" > /dev/null 2>&1
PASS_RESULT=$?

Expand Down
4 changes: 1 addition & 3 deletions examples/client/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -533,9 +533,7 @@ int ClientUserAuth(byte authType,
WS_UserAuthData_PublicKey* pk = &authData->sf.publicKey;

if (userPublicKeyType == NULL || userPublicKeySz == 0) {
/* Nothing to sign with. SendUserAuthRequest() turns this
* into WS_FATAL_ERROR rather than putting an untyped
* publickey request on the wire. */
/* Nothing to sign with; the library tries another method. */
return WOLFSSH_USERAUTH_FAILURE;
}

Expand Down
5 changes: 4 additions & 1 deletion examples/portfwd/portfwd.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,10 @@ static int wsUserAuth(byte authType,
word32 passwordSz = 0;
int ret = WOLFSSH_USERAUTH_SUCCESS;

(void)authType;
/* Password only, so it is asked for once. */
if (authType != WOLFSSH_USERAUTH_PASSWORD)
return WOLFSSH_USERAUTH_INVALID_AUTHTYPE;

if (defaultPassword != NULL) {
passwordSz = (word32)strlen(defaultPassword);
if (passwordSz > (word32)sizeof(userPassword))
Expand Down
209 changes: 111 additions & 98 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -12442,20 +12442,24 @@ static int DoUserAuthFailure(WOLFSSH* ssh,
for (j = 0; j < sizeof(ssh->supportedAuth); j++) {
if (authList[i] == ssh->supportedAuth[j]) {
switch(authList[i]) {
/* As OpenSSH: the key once, the others thrice. */
case ID_USERAUTH_PASSWORD:
authType |= WOLFSSH_USERAUTH_PASSWORD;
if (ssh->pwAuthAttempts < 3) {
authType |= WOLFSSH_USERAUTH_PASSWORD;
}
break;
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
case ID_USERAUTH_KEYBOARD:
/* try a different auth method if failing */
if (ssh->kbAuthAttempts < 3) {
authType |= WOLFSSH_USERAUTH_KEYBOARD;
}
break;
#endif
#ifndef WOLFSSH_NO_PUBKEY_AUTH
case ID_USERAUTH_PUBLICKEY:
authType |= WOLFSSH_USERAUTH_PUBLICKEY;
if (!ssh->userAuthPkDone) {
authType |= WOLFSSH_USERAUTH_PUBLICKEY;
}
break;
#endif
default:
Expand All @@ -12465,9 +12469,9 @@ static int DoUserAuthFailure(WOLFSSH* ssh,
}
}

/* the auth type attempted was not in the list */
/* nothing in the list is supported or left to try */
if (authType == 0) {
WLOG(WS_LOG_DEBUG, "Did not match any auth IDs in peers list");
WLOG(WS_LOG_DEBUG, "No untried auth method in peer's list");
ret = WS_USER_AUTH_E;
}
}
Expand Down Expand Up @@ -22863,6 +22867,43 @@ static int BuildUserAuthRequestMlDsa(WOLFSSH* ssh,


#ifndef WOLFSSH_NO_PUBKEY_AUTH
/* Returns the signature algorithm for keyId, or ID_UNKNOWN if the peer
* accepts none. */
static byte UserAuthSigId(WOLFSSH* ssh, byte keyId)
{
byte algoId[4];
word32 algoIdSz = 0;

/* Typically a 1:1 match of key type to signature type. RSA uses
* a key type of ssh-rsa, but different signature types. */
if (keyId == ID_SSH_RSA) {
#ifndef WOLFSSH_NO_RSA_SHA2_512
algoId[algoIdSz++] = ID_RSA_SHA2_512;
#endif
#ifndef WOLFSSH_NO_RSA_SHA2_256
algoId[algoIdSz++] = ID_RSA_SHA2_256;
#endif
#if !defined(WOLFSSH_NO_SSH_RSA_SHA1) \
&& defined(WOLFSSH_NO_SHA1_SOFT_DISABLE)
algoId[algoIdSz++] = ID_SSH_RSA;
#endif
}
else {
algoId[algoIdSz++] = keyId;
}

/* Is that in the peerSigId list? With no server-sig-algs, RFC 8308
* section 2.2, use the canned order, which prefers rsa-sha2-* to
* ssh-rsa; RFC 8332 section 3.3 allows either. */
if (ssh->peerSigAlgsSeen) {
return MatchIdLists(WOLFSSH_ENDPOINT_CLIENT, algoId, algoIdSz,
ssh->peerSigId, ssh->peerSigIdSz);
}
return MatchIdLists(WOLFSSH_ENDPOINT_CLIENT, algoId, algoIdSz,
cannedKeyAlgoClient, cannedKeyAlgoClientSz);
}


static int PrepareUserAuthRequestPublicKey(WOLFSSH* ssh, word32* payloadSz,
WS_UserAuthData* authData, WS_KeySignature* keySig)
{
Expand All @@ -22875,43 +22916,14 @@ static int PrepareUserAuthRequestPublicKey(WOLFSSH* ssh, word32* payloadSz,
}

if (ret == WS_SUCCESS) {
byte matchId, algoId[4];
word32 algoIdSz = 0;
byte matchId;

keySig->keyId = NameToId(
(const char*)authData->sf.publicKey.publicKeyType,
authData->sf.publicKey.publicKeyTypeSz);
keySig->keyName = (const char*)authData->sf.publicKey.publicKeyType;
keySig->keyNameSz = authData->sf.publicKey.publicKeyTypeSz;
/* Typically a 1:1 match of key type to signature type. RSA uses
* a key type of ssh-rsa, but different signature types. */
if (keySig->keyId == ID_SSH_RSA) {
#ifndef WOLFSSH_NO_RSA_SHA2_512
algoId[algoIdSz++] = ID_RSA_SHA2_512;
#endif
#ifndef WOLFSSH_NO_RSA_SHA2_256
algoId[algoIdSz++] = ID_RSA_SHA2_256;
#endif
#if !defined(WOLFSSH_NO_SSH_RSA_SHA1) \
&& defined(WOLFSSH_NO_SHA1_SOFT_DISABLE)
algoId[algoIdSz++] = ID_SSH_RSA;
#endif
}
else {
algoId[algoIdSz++] = keySig->keyId;
}

/* Is that in the peerSigId list? With no server-sig-algs, RFC 8308
* section 2.2, use the canned order, which prefers rsa-sha2-* to
* ssh-rsa; RFC 8332 section 3.3 allows either. */
if (ssh->peerSigAlgsSeen) {
matchId = MatchIdLists(WOLFSSH_ENDPOINT_CLIENT, algoId, algoIdSz,
ssh->peerSigId, ssh->peerSigIdSz);
}
else {
matchId = MatchIdLists(WOLFSSH_ENDPOINT_CLIENT, algoId, algoIdSz,
cannedKeyAlgoClient, cannedKeyAlgoClientSz);
}
matchId = UserAuthSigId(ssh, keySig->keyId);
if (matchId == ID_UNKNOWN) {
ret = WS_MATCH_KEY_ALGO_E;
}
Expand Down Expand Up @@ -23390,80 +23402,80 @@ int SendUserAuthRequest(WOLFSSH* ssh, byte authType, int addSig)
keySig_ptr->sigId = ID_NONE;
keySig_ptr->heap = ssh->ctx->heap;

#ifdef WOLFSSH_TPM
/* When the client has a TPM key configured, prefer publickey auth so
* the TPM key is used even if the server also offers password or
* keyboard-interactive. Only strip the other methods on the first
* attempt; once publickey has been tried and rejected, allow fallback
* to password/keyboard on the next DoUserAuthFailure() retry. */
if (ssh->ctx->tpmKey != NULL && !ssh->tpmPubkeyTried
&& (authType & WOLFSSH_USERAUTH_PUBLICKEY)) {
ssh->tpmPubkeyTried = 1;
authType &= ~WOLFSSH_USERAUTH_PASSWORD;
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
authType &= ~WOLFSSH_USERAUTH_KEYBOARD;
authData.type = authType;
authData.username = (const byte*)ssh->userName;
authData.usernameSz = ssh->userNameSz;

/* The client's order, as OpenSSH: publickey,
* keyboard-interactive, then password. */
if ((authType & WOLFSSH_USERAUTH_PUBLICKEY)
&& ssh->ctx->userAuthCb != NULL) {
WLOG(WS_LOG_DEBUG, "SUAR: Calling the userauth callback for key");
/* Success without a key is a decline. */
if (ssh->ctx->userAuthCb(WOLFSSH_USERAUTH_PUBLICKEY,
&authData, ssh->userAuthCtx)
== WOLFSSH_USERAUTH_SUCCESS
&& authData.sf.publicKey.publicKeyType != NULL
&& authData.sf.publicKey.publicKeyTypeSz != 0
&& authData.sf.publicKey.publicKey != NULL
&& authData.sf.publicKey.publicKeySz != 0) {
WLOG(WS_LOG_DEBUG, "SUAR: Callback successful public key");
authId = ID_USERAUTH_PUBLICKEY;
}
else {
WLOG(WS_LOG_DEBUG, "SUAR: Couldn't get key");
ssh->userAuthPkDone = 1; /* a decline is the one key try */
}
#ifndef WOLFSSH_NO_PUBKEY_AUTH
/* Skip a key the peer has no signature algorithm for. */
if (authId == ID_USERAUTH_PUBLICKEY
&& UserAuthSigId(ssh, NameToId(
(const char*)authData.sf.publicKey.publicKeyType,
authData.sf.publicKey.publicKeyTypeSz))
== ID_UNKNOWN) {
WLOG(WS_LOG_DEBUG, "SUAR: No signature algorithm for key");
authId = ID_NONE;
ssh->userAuthPkDone = 1;
}
#endif
if (authId == ID_USERAUTH_PUBLICKEY) {
authData.type = WOLFSSH_USERAUTH_PUBLICKEY;
}
else {
WMEMSET(&authData.sf, 0, sizeof(authData.sf));
authData.type = (byte)(authType & ~WOLFSSH_USERAUTH_PUBLICKEY);
}
}
Comment thread
ejohnstown marked this conversation as resolved.
Resolved
#endif

#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
/* Callback happens later for keyboard auth */
if (authType & WOLFSSH_USERAUTH_KEYBOARD) {
authId = ID_USERAUTH_KEYBOARD;
if (authId == ID_NONE && (authType & WOLFSSH_USERAUTH_KEYBOARD)) {
authId = ID_USERAUTH_KEYBOARD;
}
else
#endif
if (ssh->ctx->userAuthCb != NULL) {
WLOG(WS_LOG_DEBUG, "SUAR: Calling the userauth callback");

authData.type = authType;
authData.username = (const byte*)ssh->userName;
authData.usernameSz = ssh->userNameSz;

if (authType & WOLFSSH_USERAUTH_PASSWORD) {
ret = ssh->ctx->userAuthCb(WOLFSSH_USERAUTH_PASSWORD,
&authData, ssh->userAuthCtx);
if (ret != WOLFSSH_USERAUTH_SUCCESS) {
WLOG(WS_LOG_DEBUG, "SUAR: Couldn't get password");
ret = WS_FATAL_ERROR;
authType &= ~WOLFSSH_USERAUTH_PASSWORD;
}
else {
WLOG(WS_LOG_DEBUG, "SUAR: Callback successful password");
authId = ID_USERAUTH_PASSWORD;
authType = WOLFSSH_USERAUTH_PASSWORD;
authData.type = authType;
}
if (authId == ID_NONE && (authType & WOLFSSH_USERAUTH_PASSWORD)
&& ssh->ctx->userAuthCb != NULL) {
WLOG(WS_LOG_DEBUG, "SUAR: Calling the userauth callback for "
"password");
if (ssh->ctx->userAuthCb(WOLFSSH_USERAUTH_PASSWORD,
&authData, ssh->userAuthCtx)
== WOLFSSH_USERAUTH_SUCCESS) {
WLOG(WS_LOG_DEBUG, "SUAR: Callback successful password");
authId = ID_USERAUTH_PASSWORD;
authData.type = WOLFSSH_USERAUTH_PASSWORD;
}
/* fall into public key case if keyboard or password case was not
* successful */
if ((ret == WS_FATAL_ERROR ||

#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
(!(authType & WOLFSSH_USERAUTH_PASSWORD) &&
!(authType & WOLFSSH_USERAUTH_KEYBOARD))) &&
#else
!(authType & WOLFSSH_USERAUTH_PASSWORD)) &&
#endif
(authType & WOLFSSH_USERAUTH_PUBLICKEY)) {
ret = ssh->ctx->userAuthCb(WOLFSSH_USERAUTH_PUBLICKEY,
&authData, ssh->userAuthCtx);
if (ret != WOLFSSH_USERAUTH_SUCCESS) {
WLOG(WS_LOG_DEBUG, "SUAR: Couldn't get key");
ret = WS_FATAL_ERROR;
}
else {
WLOG(WS_LOG_DEBUG, "SUAR: Callback successful public key");
authData.type = WOLFSSH_USERAUTH_PUBLICKEY;
authId = ID_USERAUTH_PUBLICKEY;
}
else {
WLOG(WS_LOG_DEBUG, "SUAR: Couldn't get password");
}

}
else {
/* authType 0 is the opening "none" probe. */
if (ssh->ctx->userAuthCb == NULL && authId == ID_NONE) {
WLOG(WS_LOG_DEBUG, "SUAR: No user auth callback");
ret = WS_FATAL_ERROR;
}
else if (authId == ID_NONE && authType != 0) {
WLOG(WS_LOG_DEBUG, "SUAR: Callback declined every method");
ret = WS_USER_AUTH_E;
}
}

if (ret == WS_SUCCESS) {
Expand Down Expand Up @@ -23524,6 +23536,7 @@ int SendUserAuthRequest(WOLFSSH* ssh, byte authType, int addSig)
WOLFSSH_UNUSED(sigStartIdx);

ret = BuildUserAuthRequestPassword(ssh, output, &idx, &authData);
ssh->pwAuthAttempts++;
}
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
else if (authId == ID_USERAUTH_KEYBOARD) {
Expand Down
Loading
Loading