diff --git a/examples/echoserver/echoserver.c b/examples/echoserver/echoserver.c index 15edb79..6ffd3ce 100644 --- a/examples/echoserver/echoserver.c +++ b/examples/echoserver/echoserver.c @@ -391,6 +391,11 @@ static THREAD_RETURN WOLFSSH_THREAD server_worker(void* vArgs) ret = 0; /* don't break out of loop with version miss match */ printf("Unsupported version error\n"); } + else if (ret == WS_FATAL_ERROR && wolfSSH_get_error(threadCtx->ssh) == + WS_USER_AUTH_E) { + ret = 0; /* don't break out of loop with user auth error */ + printf("User Authentication error\n"); + } if (wolfSSH_shutdown(threadCtx->ssh) != WS_SUCCESS) { fprintf(stderr, "Error with SSH shutdown.\n"); @@ -683,6 +688,8 @@ static int LoadPublicKeyBuffer(byte* buf, word32 bufSz, PwMapList* list) return 0; } +#define MAX_PASSWD_RETRY 3 +static int passwdRetry = MAX_PASSWD_RETRY; static int wsUserAuth(byte authType, WS_UserAuthData* authData, @@ -691,6 +698,7 @@ static int wsUserAuth(byte authType, PwMapList* list; PwMap* map; byte authHash[SHA256_DIGEST_SIZE]; + int ret; if (ctx == NULL) { fprintf(stderr, "wsUserAuth: ctx not set"); @@ -737,9 +745,12 @@ static int wsUserAuth(byte authType, return WOLFSSH_USERAUTH_SUCCESS; } else { - return (authType == WOLFSSH_USERAUTH_PASSWORD ? - WOLFSSH_USERAUTH_INVALID_PASSWORD : - WOLFSSH_USERAUTH_INVALID_PUBLICKEY); + ret = (authType == WOLFSSH_USERAUTH_PASSWORD ? + (--passwdRetry > 0 ? + WOLFSSH_USERAUTH_INVALID_PASSWORD : WOLFSSH_USERAUTH_REJECTED) + : WOLFSSH_USERAUTH_INVALID_PUBLICKEY); + if (passwdRetry == 0)passwdRetry = MAX_PASSWD_RETRY; + return ret; } } else { diff --git a/src/internal.c b/src/internal.c index 3415244..7270d23 100644 --- a/src/internal.c +++ b/src/internal.c @@ -272,6 +272,9 @@ const char* GetErrorString(int err) case WS_EXTDATA: return "Extended Data available to be read"; + case WS_USER_AUTH_E: + return "User authentication error"; + default: return "Unknown error code"; } @@ -3211,7 +3214,7 @@ static int DoUserAuthRequestPassword(WOLFSSH* ssh, WS_UserAuthData* authData, pw->newPassword = NULL; pw->newPasswordSz = 0; } - + if (ssh->ctx->userAuthCb != NULL) { WLOG(WS_LOG_DEBUG, "DUARPW: Calling the userauth callback"); ret = ssh->ctx->userAuthCb(WOLFSSH_USERAUTH_PASSWORD, @@ -3221,14 +3224,22 @@ static int DoUserAuthRequestPassword(WOLFSSH* ssh, WS_UserAuthData* authData, ssh->clientState = CLIENT_USERAUTH_DONE; ret = WS_SUCCESS; } + else if (ret == WOLFSSH_USERAUTH_REJECTED) { + WLOG(WS_LOG_DEBUG, "DUARPW: password rejected"); + ret = SendUserAuthFailure(ssh, 0); + if (ret == WS_SUCCESS) + ret = WS_USER_AUTH_E; + } else { - WLOG(WS_LOG_DEBUG, "DUARPW: password check failed"); + WLOG(WS_LOG_DEBUG, "DUARPW: password check failed, retry"); ret = SendUserAuthFailure(ssh, 0); } } else { WLOG(WS_LOG_DEBUG, "DUARPW: No user auth callback"); ret = SendUserAuthFailure(ssh, 0); + if (ret == WS_SUCCESS) + ret = WS_FATAL_ERROR; } } diff --git a/wolfssh/error.h b/wolfssh/error.h index 4cbd0df..c756e29 100644 --- a/wolfssh/error.h +++ b/wolfssh/error.h @@ -105,8 +105,9 @@ enum WS_ErrorCodes { WS_CLOSE_FILE_E = -1065, /* Unable to close local file */ WS_PUBKEY_REJECTED_E = -1066, /* Server public key rejected */ WS_EXTDATA = -1067, /* Extended Data available to be read */ - - WS_LAST_E = -1067 /* Update this to indicate last error */ + WS_USER_AUTH_E = -1068, /* User authentication error */ + + WS_LAST_E = -1068 /* Update this to indicate last error */ }; diff --git a/wolfssh/ssh.h b/wolfssh/ssh.h index 6ecfc1e..df49c63 100644 --- a/wolfssh/ssh.h +++ b/wolfssh/ssh.h @@ -234,17 +234,17 @@ enum WS_UserAuthTypes { WOLFSSH_USERAUTH_PUBLICKEY }; - -enum WS_UserAuthResults { +enum WS_UserAuthResults +{ WOLFSSH_USERAUTH_SUCCESS, WOLFSSH_USERAUTH_FAILURE, WOLFSSH_USERAUTH_INVALID_AUTHTYPE, WOLFSSH_USERAUTH_INVALID_USER, WOLFSSH_USERAUTH_INVALID_PASSWORD, + WOLFSSH_USERAUTH_REJECTED, WOLFSSH_USERAUTH_INVALID_PUBLICKEY }; - enum WS_DisconnectReasonCodes { WOLFSSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT = 1, WOLFSSH_DISCONNECT_PROTOCOL_ERROR = 2,