diff --git a/apps/wolfsshd/auth.c b/apps/wolfsshd/auth.c index 042b214f..fa0a63fe 100644 --- a/apps/wolfsshd/auth.c +++ b/apps/wolfsshd/auth.c @@ -1138,10 +1138,9 @@ static int RequestAuthentication(WS_UserAuthData* authData, } + #ifdef WOLFSSL_FPKI if (ret == WOLFSSH_USERAUTH_SUCCESS && authData->type == WOLFSSH_USERAUTH_PUBLICKEY) { - - #ifdef WOLFSSL_FPKI /* compare user name to UPN in certificate */ if (authData->sf.publicKey.isCert) { DecodedCert* dCert; @@ -1204,8 +1203,11 @@ static int RequestAuthentication(WS_UserAuthData* authData, #endif } } + } #endif + if (ret == WOLFSSH_USERAUTH_SUCCESS && + authData->type == WOLFSSH_USERAUTH_PUBLICKEY) { /* if this is a certificate and no specific authorized keys file has * been set then rely on CA to have verified the cert */ if (authData->sf.publicKey.isCert && diff --git a/examples/echoserver/echoserver.c b/examples/echoserver/echoserver.c index 0219d058..2afa0cbd 100644 --- a/examples/echoserver/echoserver.c +++ b/examples/echoserver/echoserver.c @@ -1299,16 +1299,25 @@ static int sftp_worker(thread_ctx_t* threadCtx) { WOLFSSH* ssh = threadCtx->ssh; WS_SOCKET_T s; - int ret = WS_SUCCESS; + int ret; int error = -1; int selected; unsigned char peek_buf[1]; int timeout = TEST_SFTP_TIMEOUT; s = (WS_SOCKET_T)wolfSSH_get_fd(ssh); + ret = error = wolfSSH_get_error(ssh); + + /* there is an edge case where the last SFTP handshake message sent got a + * WANT_WRITE case, keep trying to send it here. */ + while (error == WS_WANT_WRITE) { + ret = wolfSSH_worker(ssh, NULL); + error = wolfSSH_get_error(ssh); + } do { - if (ret == WS_WANT_WRITE || wolfSSH_SFTP_PendingSend(ssh)) { + if (ret == WS_WANT_WRITE || ret == WS_CHAN_RXD || + wolfSSH_SFTP_PendingSend(ssh)) { /* Yes, process the SFTP data. */ ret = wolfSSH_SFTP_read(ssh); error = wolfSSH_get_error(ssh); @@ -1362,6 +1371,19 @@ static int sftp_worker(thread_ctx_t* threadCtx) break; } if (ret != WS_SUCCESS && ret != WS_CHAN_RXD) { + #ifdef WOLFSSH_TEST_BLOCK + if (error == WS_WANT_READ) { + while (error == WS_WANT_READ) { + /* The socket had data but our test nonblocking code + * returned want read. Loop over wolfSSH_worker here + * until we get the data off the socket that select + * indicated was available. */ + ret = wolfSSH_worker(ssh, NULL); + error = wolfSSH_get_error(ssh); + } + continue; + } + #endif if (ret == WS_WANT_WRITE) { /* recall wolfSSH_worker here because is likely our custom * highwater callback that returned up a WS_WANT_WRITE */ @@ -1433,20 +1455,45 @@ static int NonBlockSSH_accept(WOLFSSH* ssh) printf("... server would read block\n"); else if (error == WS_WANT_WRITE) printf("... server would write block\n"); + else if (error == WS_AUTH_PENDING) + printf("... server auth pending\n"); select_ret = tcp_select(sockfd, 1); - if (select_ret == WS_SELECT_RECV_READY || - select_ret == WS_SELECT_ERROR_READY || - error == WS_WANT_WRITE || - error == WS_AUTH_PENDING) - { + if (select_ret == WS_SELECT_RECV_READY) { ret = wolfSSH_accept(ssh); error = wolfSSH_get_error(ssh); + + #ifdef WOLFSSH_TEST_BLOCK + if (error == WS_WANT_READ) { + /* The socket had data but our test nonblocking code + * returned want read. Loop over wolfSSH_accept here until + * we get the data off the socket that select indicated was + * available. */ + while (error == WS_WANT_READ) { + ret = wolfSSH_accept(ssh); + error = wolfSSH_get_error(ssh); + } + } + #endif + } + else if (select_ret == WS_SELECT_TIMEOUT) { + if (error == WS_WANT_WRITE || error == WS_AUTH_PENDING + #ifdef WOLFSSH_TEST_BLOCK + || error == WS_WANT_READ + #endif + ) { + /* For write or auth pending, we need to try again */ + ret = wolfSSH_accept(ssh); + error = wolfSSH_get_error(ssh); + } + else { + error = WS_WANT_READ; + } + } + else { + ret = WS_FATAL_ERROR; + break; } - else if (select_ret == WS_SELECT_TIMEOUT) - error = WS_WANT_READ; - else - error = WS_FATAL_ERROR; } return ret; @@ -1709,7 +1756,7 @@ static void StrListFree(StrList* list) } -/* Map user names to passwords */ +/* Map user names to passwords and keyboard auth prompts */ /* Use arrays for username and p. The password or public key can * be hashed and the hash stored here. Then I won't need the type. */ typedef struct PwMap { @@ -1717,6 +1764,9 @@ typedef struct PwMap { byte username[32]; word32 usernameSz; byte p[WC_SHA256_DIGEST_SIZE]; +#ifdef WOLFSSH_KEYBOARD_INTERACTIVE + WS_UserAuthData_Keyboard* keyboard; +#endif struct PwMap* next; } PwMap; @@ -1752,6 +1802,24 @@ static PwMap* PwMapNew(PwMapList* list, byte type, const byte* username, } +#ifdef WOLFSSH_KEYBOARD_INTERACTIVE +/* Create new node for list of auths, adding keyboard auth prompts */ +static PwMap* PwMapKeyboardNew(PwMapList* list, byte type, const byte* username, + word32 usernameSz, const byte* p, word32 pSz, + WS_UserAuthData_Keyboard* keyboard) +{ + PwMap* map; + + map = PwMapNew(list, type, username, usernameSz, p, pSz); + if (map) { + map->keyboard = keyboard; + } + + return map; +} +#endif + + static void PwMapListDelete(PwMapList* list) { if (list != NULL) { @@ -2013,7 +2081,8 @@ static int LoadPasswdList(StrList* strList, PwMapList* mapList) return count; } #ifdef WOLFSSH_KEYBOARD_INTERACTIVE -static int LoadKeyboardList(StrList* strList, PwMapList* mapList) +static int LoadKeyboardList(StrList* strList, PwMapList* mapList, + WS_UserAuthData_Keyboard* kbAuthData) { char names[256]; char* passwd; @@ -2026,9 +2095,10 @@ static int LoadKeyboardList(StrList* strList, PwMapList* mapList) *passwd = 0; passwd++; - PwMapNew(mapList, WOLFSSH_USERAUTH_KEYBOARD, + PwMapKeyboardNew(mapList, WOLFSSH_USERAUTH_KEYBOARD, (byte*)names, (word32)WSTRLEN(names), - (byte*)passwd, (word32)WSTRLEN(passwd)); + (byte*)passwd, (word32)WSTRLEN(passwd), + kbAuthData); } else { fprintf(stderr, "Ignoring password: %s\n", names); @@ -2192,6 +2262,7 @@ static int wsUserAuth(byte authType, #endif #ifdef WOLFSSH_KEYBOARD_INTERACTIVE authType != WOLFSSH_USERAUTH_KEYBOARD && + authType != WOLFSSH_USERAUTH_KEYBOARD_SETUP && #endif authType != WOLFSSH_USERAUTH_PUBLICKEY) { @@ -2315,6 +2386,14 @@ static int wsUserAuth(byte authType, } #ifdef WOLFSSH_KEYBOARD_INTERACTIVE else if (authData->type == WOLFSSH_USERAUTH_KEYBOARD) { + if (authType == WOLFSSH_USERAUTH_KEYBOARD_SETUP) { + /* setup the keyboard auth prompts */ + WMEMCPY(&authData->sf.keyboard, map->keyboard, + sizeof(WS_UserAuthData_Keyboard)); + return WS_SUCCESS; + } + + /* do keyboard auth prompts */ if (WMEMCMP(map->p, authHash, WC_SHA256_DIGEST_SIZE) == 0) { return WOLFSSH_USERAUTH_SUCCESS; } @@ -2338,15 +2417,6 @@ static int wsUserAuth(byte authType, return WOLFSSH_USERAUTH_INVALID_USER; } -#ifdef WOLFSSH_KEYBOARD_INTERACTIVE -static int keyboardCallback(WS_UserAuthData_Keyboard *kbAuth, void *ctx) -{ - WS_UserAuthData_Keyboard *kbAuthData = (WS_UserAuthData_Keyboard*) ctx; - WMEMCPY(kbAuth, kbAuthData, sizeof(WS_UserAuthData_Keyboard)); - - return WS_SUCCESS; -} -#endif #ifdef WOLFSSH_SFTP /* @@ -2800,9 +2870,6 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) #ifdef WOLFSSH_KEYBOARD_INTERACTIVE if (keyboardList) { - LoadKeyboardList(keyboardList, &pwMapList); - StrListFree(keyboardList); - keyboardList = NULL; kbAuthData.promptCount = 1; kbAuthData.promptName = NULL; kbAuthData.promptNameSz = 0; @@ -2825,7 +2892,9 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) ES_ERROR("Error allocating promptEcho"); } kbAuthData.promptEcho[0] = 0; - wolfSSH_SetKeyboardAuthPrompts(ctx, keyboardCallback); + LoadKeyboardList(keyboardList, &pwMapList, &kbAuthData); + StrListFree(keyboardList); + keyboardList = NULL; } #endif @@ -3035,9 +3104,6 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) #endif wolfSSH_SetUserAuthCtx(ssh, &pwMapList); wolfSSH_SetKeyingCompletionCbCtx(ssh, (void*)ssh); - #ifdef WOLFSSH_KEYBOARD_INTERACTIVE - wolfSSH_SetKeyboardAuthCtx(ssh, &kbAuthData); - #endif /* Use the session object for its own highwater callback ctx */ if (defaultHighwater > 0) { diff --git a/examples/sftpclient/sftpclient.c b/examples/sftpclient/sftpclient.c index c1baba67..4a8de510 100644 --- a/examples/sftpclient/sftpclient.c +++ b/examples/sftpclient/sftpclient.c @@ -205,7 +205,8 @@ static int NonBlockSSH_connect(void) sockfd = (SOCKET_T)wolfSSH_get_fd(ssh); while (ret != WS_SUCCESS && - (error == WS_WANT_READ || error == WS_WANT_WRITE)) + (error == WS_WANT_READ || error == WS_WANT_WRITE || + error == WS_REKEYING || error == WS_AUTH_PENDING)) { if (error == WS_WANT_READ) printf("... client would read block\n"); @@ -219,6 +220,19 @@ static int NonBlockSSH_connect(void) { ret = wolfSSH_SFTP_connect(ssh); error = wolfSSH_get_error(ssh); + + #ifdef WOLFSSH_TEST_BLOCK + if (select_ret == WS_SELECT_RECV_READY && error == WS_WANT_READ) { + /* The socket has data to be read but the non blocking test + * code returned want read. Loop over wolfSSH_SFTP_connect here + * until we get the data off the socket that select indicated + * was available. */ + while (error == WS_WANT_READ) { + ret = wolfSSH_SFTP_connect(ssh); + error = wolfSSH_get_error(ssh); + } + } + #endif } else if (select_ret == WS_SELECT_TIMEOUT) error = WS_WANT_READ; @@ -1146,7 +1160,8 @@ static int doAutopilot(int cmd, char* local, char* remote) } err = wolfSSH_get_error(ssh); } while ((err == WS_WANT_READ || err == WS_WANT_WRITE || - err == WS_CHAN_RXD) && ret == WS_FATAL_ERROR); + err == WS_CHAN_RXD || err == WS_REKEYING) && + ret == WS_FATAL_ERROR); if (ret != WS_SUCCESS) { if (cmd == AUTOPILOT_PUT) { @@ -1409,6 +1424,7 @@ THREAD_RETURN WOLFSSH_THREAD sftpclient_test(void* args) ret = wolfSSH_get_error(ssh); } while (ret == WS_WANT_READ || ret == WS_WANT_WRITE); if (n == NULL) { + printf("Error [%d] when getting real path\n", ret); err_sys("Unable to get real path for working directory"); } diff --git a/src/internal.c b/src/internal.c index 60f802ce..d6caa820 100644 --- a/src/internal.c +++ b/src/internal.c @@ -877,9 +877,6 @@ WOLFSSH_CTX* CtxInit(WOLFSSH_CTX* ctx, byte side, void* heap) ctx->algoListCipher = cannedEncAlgoNames; ctx->algoListMac = cannedMacAlgoNames; ctx->algoListKeyAccepted = cannedKeyAlgoNames; -#ifdef WOLFSSH_KEYBOARD_INTERACTIVE - ctx->keyboardAuthCb = NULL; -#endif count = (word32)(sizeof(ctx->privateKey) / sizeof(ctx->privateKey[0])); @@ -7881,7 +7878,10 @@ static int DoUserAuthFailure(WOLFSSH* ssh, break; #ifdef WOLFSSH_KEYBOARD_INTERACTIVE case ID_USERAUTH_KEYBOARD: - authType |= WOLFSSH_USERAUTH_KEYBOARD; + /* try a different auth method if failing */ + if (ssh->kbAuthAttempts < 3) { + authType |= WOLFSSH_USERAUTH_KEYBOARD; + } break; #endif #if !defined(WOLFSSH_NO_RSA) || !defined(WOLFSSH_NO_ECDSA) @@ -13369,19 +13369,27 @@ int SendUserAuthKeyboardRequest(WOLFSSH* ssh, WS_UserAuthData* authData) WLOG(WS_LOG_DEBUG, "Entering SendUserAuthKeyboardRequest()"); - if (ssh == NULL || authData == NULL) { ret = WS_BAD_ARGUMENT; } - if (ssh->ctx->keyboardAuthCb == NULL) { + if (ssh->ctx->userAuthCb == NULL) { WLOG(WS_LOG_DEBUG, "SendUserAuthKeyboardRequest called with no Cb set"); ret = WS_BAD_USAGE; } if (ret == WS_SUCCESS) { - ret = ssh->ctx->keyboardAuthCb(&authData->sf.keyboard, - ssh->keyboardAuthCtx); + authData->type = WOLFSSH_USERAUTH_KEYBOARD; + ret = ssh->ctx->userAuthCb(WOLFSSH_USERAUTH_KEYBOARD_SETUP, authData, + ssh->userAuthCtx); + if (ret == WOLFSSH_USERAUTH_SUCCESS) { + ret = WS_SUCCESS; + } + else { + WLOG(WS_LOG_DEBUG, "Issue with keyboard auth setup, try another " + "auth type"); + return SendUserAuthFailure(ssh, 0); + } } if (authData->sf.keyboard.promptCount > 0 && @@ -13407,10 +13415,12 @@ int SendUserAuthKeyboardRequest(WOLFSSH* ssh, WS_UserAuthData* authData) ret = PreparePacket(ssh, payloadSz); } - output = ssh->outputBuffer.buffer; - idx = ssh->outputBuffer.length; + if (ret == WS_SUCCESS) { + output = ssh->outputBuffer.buffer; + idx = ssh->outputBuffer.length; - output[idx++] = MSGID_USERAUTH_INFO_REQUEST; + output[idx++] = MSGID_USERAUTH_INFO_REQUEST; + } if (ret == WS_SUCCESS) { ret = BuildUserAuthRequestKeyboard(ssh, output, &idx, authData); @@ -14946,6 +14956,7 @@ int SendUserAuthRequest(WOLFSSH* ssh, byte authType, int addSig) WMEMSET(keySig_ptr, 0, sizeof(WS_KeySignature)); keySig_ptr->keySigId = ID_NONE; keySig_ptr->heap = ssh->ctx->heap; + #ifdef WOLFSSH_KEYBOARD_INTERACTIVE /* Callback happens later for keyboard auth */ if (authType & WOLFSSH_USERAUTH_KEYBOARD) { @@ -15074,6 +15085,7 @@ int SendUserAuthRequest(WOLFSSH* ssh, byte authType, int addSig) /* submethods */ c32toa(0, output + idx); idx += LENGTH_SZ; + ssh->kbAuthAttempts++; } #endif else if (authId == ID_USERAUTH_PUBLICKEY) @@ -15117,9 +15129,7 @@ static int GetAllowedAuth(WOLFSSH* ssh, char* authStr) typeAllowed |= WOLFSSH_USERAUTH_PASSWORD; #ifdef WOLFSSH_KEYBOARD_INTERACTIVE - if (ssh->ctx->keyboardAuthCb != NULL) { - typeAllowed |= WOLFSSH_USERAUTH_KEYBOARD; - } + typeAllowed |= WOLFSSH_USERAUTH_KEYBOARD; #endif #if !defined(WOLFSSH_NO_RSA) || !defined(WOLFSSH_NO_ECDSA) typeAllowed |= WOLFSSH_USERAUTH_PUBLICKEY; diff --git a/src/ssh.c b/src/ssh.c index 6d2012ad..6f7e1c1a 100644 --- a/src/ssh.c +++ b/src/ssh.c @@ -1046,6 +1046,10 @@ int wolfSSH_shutdown(WOLFSSH* ssh) * response to SendChannelClose */ if (channel != NULL && ret == WS_SUCCESS) { ret = wolfSSH_worker(ssh, NULL); + if (ret == WS_CHAN_RXD) { + /* received response */ + ret = WS_SUCCESS; + } } if (ssh != NULL && ssh->channelList == NULL) { @@ -1338,23 +1342,6 @@ int wolfSSH_SendDisconnect(WOLFSSH *ssh, word32 reason) return SendDisconnect(ssh, reason); } -#ifdef WOLFSSH_KEYBOARD_INTERACTIVE -void wolfSSH_SetKeyboardAuthPrompts(WOLFSSH_CTX* ctx, - WS_CallbackKeyboardAuthPrompts cb) -{ - if (ctx != NULL) { - ctx->keyboardAuthCb = cb; - } -} - -void wolfSSH_SetKeyboardAuthCtx(WOLFSSH* ssh, void* keyboardAuthCtx) -{ - if (ssh != NULL) { - ssh->keyboardAuthCtx = keyboardAuthCtx; - } -} -#endif - void wolfSSH_SetUserAuth(WOLFSSH_CTX* ctx, WS_CallbackUserAuth cb) { if (ctx != NULL) { diff --git a/src/wolfsftp.c b/src/wolfsftp.c index 7554da53..594990cd 100644 --- a/src/wolfsftp.c +++ b/src/wolfsftp.c @@ -515,6 +515,7 @@ static void wolfSSH_SFTP_buffer_rewind(WS_SFTP_BUFFER* buffer) static int wolfSSH_SFTP_buffer_send(WOLFSSH* ssh, WS_SFTP_BUFFER* buffer) { int ret = WS_SUCCESS; + int err; if (buffer == NULL) { return WS_BAD_ARGUMENT; @@ -524,6 +525,12 @@ static int wolfSSH_SFTP_buffer_send(WOLFSSH* ssh, WS_SFTP_BUFFER* buffer) return WS_BUFFER_E; } + /* Call wolfSSH worker if rekeying or adjusting window size */ + err = wolfSSH_get_error(ssh); + if (err == WS_WINDOW_FULL || err == WS_REKEYING) { + (void)wolfSSH_worker(ssh, NULL); + } + if (buffer->idx < buffer->sz) { ret = wolfSSH_stream_send(ssh, buffer->data + buffer->idx, buffer->sz - buffer->idx); @@ -543,6 +550,7 @@ static int wolfSSH_SFTP_buffer_read(WOLFSSH* ssh, WS_SFTP_BUFFER* buffer, int readSz) { int ret; + byte peekBuf[1]; if (buffer == NULL || ssh == NULL) { return WS_FATAL_ERROR; @@ -563,8 +571,18 @@ static int wolfSSH_SFTP_buffer_read(WOLFSSH* ssh, WS_SFTP_BUFFER* buffer, } do { - ret = wolfSSH_stream_read(ssh, buffer->data + buffer->idx, + if (!wolfSSH_stream_peek(ssh, peekBuf, 1)) { + /* poll more data off the wire */ + ret = wolfSSH_worker(ssh, NULL); + } + else { + ret = WS_CHAN_RXD; /* existing data found with peek */ + } + + if (ret == WS_CHAN_RXD) { + ret = wolfSSH_stream_read(ssh, buffer->data + buffer->idx, buffer->sz - buffer->idx); + } if (ret < 0) { return WS_FATAL_ERROR; } @@ -1400,8 +1418,9 @@ int wolfSSH_SFTP_read(WOLFSSH* ssh) ret = wolfSSH_SFTP_buffer_read(ssh, &state->buffer, state->buffer.sz); if (ret < 0) { - if (ssh->error != WS_WANT_READ && ssh->error != WS_WANT_WRITE) - wolfSSH_SFTP_ClearState(ssh, STATE_ID_RECV); + if (!NoticeError(ssh)) { + wolfSSH_SFTP_ClearState(ssh, STATE_ID_RECV); + } return ret; } @@ -5661,7 +5680,7 @@ int wolfSSH_SFTP_RecvFSetSTAT(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) * returns WS_SUCCESS on success */ static int SFTP_ClientRecvInit(WOLFSSH* ssh) { - int len; + int len, ret; byte id; word32 sz = 0; word32 version = 0; @@ -5669,6 +5688,11 @@ static int SFTP_ClientRecvInit(WOLFSSH* ssh) { switch (ssh->sftpState) { case SFTP_RECV: + ret = wolfSSH_worker(ssh,NULL); + if (ret != WS_CHAN_RXD) { + return ret; + } + if ((len = wolfSSH_stream_read(ssh, buf, sizeof(buf))) != sizeof(buf)) { /* @TODO partial read on small packet */ @@ -5780,7 +5804,7 @@ int wolfSSH_SFTP_connect(WOLFSSH* ssh) switch (ssh->sftpState) { case SFTP_BEGIN: - if ((ssh->error = SFTP_ClientSendInit(ssh)) != WS_SUCCESS) { + if (SFTP_ClientSendInit(ssh) != WS_SUCCESS) { return WS_FATAL_ERROR; } ssh->sftpState = SFTP_RECV; @@ -5903,14 +5927,7 @@ int SendPacketType(WOLFSSH* ssh, byte type, byte* buf, word32 bufSz) * because channel could have restrictions on how much * state->data can be sent at one time */ do { - int err; ret = wolfSSH_SFTP_buffer_send(ssh, &state->buffer); - - /* check for adjust window packet */ - err = wolfSSH_get_error(ssh); - if (err == WS_WINDOW_FULL || err == WS_REKEYING) - ret = wolfSSH_worker(ssh, NULL); - ssh->error = err; /* don't save potential want read here */ } while (ret > 0 && wolfSSH_SFTP_buffer_idx(&state->buffer) < wolfSSH_SFTP_buffer_size(&state->buffer)); @@ -6544,8 +6561,7 @@ static int wolfSSH_SFTP_GetHandle(WOLFSSH* ssh, byte* handle, word32* handleSz) WLOG(WS_LOG_SFTP, "SFTP GET HANDLE STATE: GET_HEADER"); ret = SFTP_GetHeader(ssh, &state->reqId, &type, &state->buffer); if (ret <= 0) { - if (ssh->error == WS_WANT_READ || - ssh->error == WS_WANT_WRITE) { + if (NoticeError(ssh)) { return WS_FATAL_ERROR; } else { @@ -8066,9 +8082,8 @@ int wolfSSH_SFTP_Close(WOLFSSH* ssh, byte* handle, word32 handleSz) case STATE_CLOSE_SEND: WLOG(WS_LOG_SFTP, "SFTP CLOSE STATE: SEND"); ret = SendPacketType(ssh, WOLFSSH_FTP_CLOSE, handle, handleSz); - if (ssh->error == WS_WANT_WRITE || ssh->error == WS_WANT_READ) - { - return ret; + if (NoticeError(ssh)) { + return WS_FATAL_ERROR; } if (ret != WS_SUCCESS) { @@ -8081,10 +8096,9 @@ int wolfSSH_SFTP_Close(WOLFSSH* ssh, byte* handle, word32 handleSz) case STATE_CLOSE_GET_HEADER: WLOG(WS_LOG_SFTP, "SFTP CLOSE STATE: GET_HEADER"); ret = SFTP_GetHeader(ssh, &state->reqId, &type, &state->buffer); - if (ret <= 0 && - (ssh->error == WS_WANT_WRITE || - ssh->error == WS_WANT_READ)) - return ret; + if (ret <= 0 && NoticeError(ssh)) { + return WS_FATAL_ERROR; + } if (type != WOLFSSH_FTP_STATUS || ret <= 0) { WLOG(WS_LOG_SFTP, "Unexpected packet type"); @@ -8169,7 +8183,7 @@ WS_SFTPNAME* wolfSSH_SFTP_RealPath(WOLFSSH* ssh, char* dir) case SFTP_REAL_GET_PACKET: /* read name response from Real Path packet */ ret = wolfSSH_SFTP_DoName(ssh); - if (ret != NULL || (ret == NULL && ssh->error != WS_WANT_READ)) { + if (ret != NULL || (ret == NULL && !NoticeError(ssh))) { wolfSSH_SFTP_ClearState(ssh, STATE_ID_NAME); ssh->realState = SFTP_REAL_SEND_PACKET; } @@ -9188,9 +9202,7 @@ int wolfSSH_SFTP_Put(WOLFSSH* ssh, char* from, char* to, byte resume, ret = wolfSSH_SFTP_Close(ssh, state->handle, state->handleSz); if (ret != WS_SUCCESS) { - if (ssh->error == WS_WANT_READ || - ssh->error == WS_WANT_WRITE || - ssh->error == WS_REKEYING) { + if (NoticeError(ssh)) { return WS_FATAL_ERROR; } WLOG(WS_LOG_SFTP, "Error closing handle"); diff --git a/tests/auth.c b/tests/auth.c index cf57a3c1..6f374eaf 100644 --- a/tests/auth.c +++ b/tests/auth.c @@ -222,11 +222,23 @@ static int load_key(byte isEcc, byte* buf, word32 bufSz) static int serverUserAuth(byte authType, WS_UserAuthData* authData, void* ctx) { - (void) ctx; - if (authType != WOLFSSH_USERAUTH_KEYBOARD) { + WS_UserAuthData_Keyboard* prompts = (WS_UserAuthData_Keyboard*)ctx; + + if (ctx == NULL) { return WOLFSSH_USERAUTH_FAILURE; } + if (authType != WOLFSSH_USERAUTH_KEYBOARD && + authType != WOLFSSH_USERAUTH_KEYBOARD_SETUP) { + return WOLFSSH_USERAUTH_FAILURE; + } + + if (authType == WOLFSSH_USERAUTH_KEYBOARD_SETUP) { + WMEMCPY(&authData->sf.keyboard, prompts, + sizeof(WS_UserAuthData_Keyboard)); + return WS_SUCCESS; + } + if (authData->sf.keyboard.responseCount != kbResponseCount) { return WOLFSSH_USERAUTH_FAILURE; } @@ -237,8 +249,9 @@ static int serverUserAuth(byte authType, WS_UserAuthData* authData, void* ctx) return WOLFSSH_USERAUTH_FAILURE; } - if (WSTRCMP((const char*)authData->sf.keyboard.responses[resp], - (const char*)kbResponses[resp]) != 0) { + if (WSTRNCMP((const char*)authData->sf.keyboard.responses[resp], + (const char*)kbResponses[resp], + kbResponseLengths[resp]) != 0) { return WOLFSSH_USERAUTH_FAILURE; } } @@ -251,14 +264,6 @@ static int serverUserAuth(byte authType, WS_UserAuthData* authData, void* ctx) return WOLFSSH_USERAUTH_SUCCESS; } -static int serverKeyboardCallback(WS_UserAuthData_Keyboard *kbAuth, void *ctx) -{ - (void) ctx; - WMEMCPY(kbAuth, &promptData, sizeof(WS_UserAuthData_Keyboard)); - - return WS_SUCCESS; -} - static INLINE void SignalTcpReady(tcp_ready* ready, word16 port) { pthread_mutex_lock(&ready->mutex); @@ -332,13 +337,13 @@ static THREAD_RETURN WOLFSSH_THREAD server_thread(void* args) } wolfSSH_SetUserAuth(ctx, serverUserAuth); - wolfSSH_SetKeyboardAuthPrompts(ctx, serverKeyboardCallback); ssh = wolfSSH_new(ctx); if (ssh == NULL) { ES_ERROR("Couldn't allocate SSH data.\n"); } keyLoadBuf = buf; bufSz = EXAMPLE_KEYLOAD_BUFFER_SZ; + wolfSSH_SetUserAuthCtx(ssh, &promptData); bufSz = load_key(peerEcc, keyLoadBuf, bufSz); if (bufSz == 0) { diff --git a/wolfssh/internal.h b/wolfssh/internal.h index 1b60139a..2cd7b97b 100644 --- a/wolfssh/internal.h +++ b/wolfssh/internal.h @@ -529,9 +529,6 @@ struct WOLFSSH_CTX { WS_CallbackUserAuth userAuthCb; /* User Authentication Callback */ WS_CallbackUserAuthTypes userAuthTypesCb; /* Authentication Types Allowed */ WS_CallbackUserAuthResult userAuthResultCb; /* User Authentication Result */ -#ifdef WOLFSSH_KEYBOARD_INTERACTIVE - WS_CallbackKeyboardAuthPrompts keyboardAuthCb; /* Keyboard auth prompts */ -#endif WS_CallbackHighwater highwaterCb; /* Data Highwater Mark Callback */ WS_CallbackGlobalReq globalReqCb; /* Global Request Callback */ WS_CallbackReqSuccess reqSuccessCb; /* Global Request Success Callback */ @@ -922,6 +919,7 @@ struct WOLFSSH { void* keyingCompletionCtx; #ifdef WOLFSSH_KEYBOARD_INTERACTIVE WS_UserAuthData_Keyboard kbAuth; + byte kbAuthAttempts; #endif }; diff --git a/wolfssh/ssh.h b/wolfssh/ssh.h index 9a49b440..fb2324ab 100644 --- a/wolfssh/ssh.h +++ b/wolfssh/ssh.h @@ -368,13 +368,6 @@ WOLFSSH_API void wolfSSH_SetUserAuthTypes(WOLFSSH_CTX*, WOLFSSH_API void wolfSSH_SetUserAuthCtx(WOLFSSH*, void*); WOLFSSH_API void* wolfSSH_GetUserAuthCtx(WOLFSSH*); -#ifdef WOLFSSH_KEYBOARD_INTERACTIVE -typedef int (*WS_CallbackKeyboardAuthPrompts)(WS_UserAuthData_Keyboard*, void*); -WOLFSSH_API void wolfSSH_SetKeyboardAuthPrompts(WOLFSSH_CTX*, - WS_CallbackKeyboardAuthPrompts); -WOLFSSH_API void wolfSSH_SetKeyboardAuthCtx(WOLFSSH*, void*); -#endif - typedef int (*WS_CallbackUserAuthResult)(byte result, WS_UserAuthData* authData, void* userAuthResultCtx); WOLFSSH_API void wolfSSH_SetUserAuthResult(WOLFSSH_CTX* ctx, @@ -474,6 +467,7 @@ enum WS_FormatTypes { #define WOLFSSH_USERAUTH_PUBLICKEY 0x02 #define WOLFSSH_USERAUTH_KEYBOARD 0x04 #define WOLFSSH_USERAUTH_NONE 0x08 +#define WOLFSSH_USERAUTH_KEYBOARD_SETUP 0x10 enum WS_UserAuthResults {