diff --git a/examples/client/client.c b/examples/client/client.c index 9bc6d31..9a265c4 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -152,6 +152,16 @@ static int wsUserAuth(byte authType, } +static int wsPublicKeyCheck(const byte* pubKey, word32 pubKeySz, void* ctx) +{ + printf("Sample public key check callback\n" + " public key = %p\n" + " public key size = %u\n" + " ctx = %s\n", pubKey, pubKeySz, (const char*)ctx); + return 0; +} + + static int NonBlockSSH_connect(WOLFSSH* ssh) { int ret; @@ -269,6 +279,9 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args) if (password != NULL) wolfSSH_SetUserAuthCtx(ssh, (void*)password); + wolfSSH_CTX_SetPublicKeyCheck(ctx, wsPublicKeyCheck); + wolfSSH_SetPublicKeyCheckCtx(ssh, (void*)"You've been sampled!"); + ret = wolfSSH_SetUsername(ssh, username); if (ret != WS_SUCCESS) err_sys("Couldn't set the username."); diff --git a/examples/portfwd/portfwd.c b/examples/portfwd/portfwd.c index 7ef5264..4d42b9e 100644 --- a/examples/portfwd/portfwd.c +++ b/examples/portfwd/portfwd.c @@ -180,6 +180,16 @@ static int wsUserAuth(byte authType, } +static int wsPublicKeyCheck(const byte* pubKey, word32 pubKeySz, void* ctx) +{ + printf("Sample public key check callback\n" + " public key = %p\n" + " public key size = %u\n" + " ctx = %s\n", pubKey, pubKeySz, (const char*)ctx); + return 0; +} + + /* * fwdFromHost - address to bind the local listener socket to (default: any) * fwdFromHostPort - port number to bind the local listener socket to @@ -312,6 +322,9 @@ THREAD_RETURN WOLFSSH_THREAD portfwd_worker(void* args) if (password != NULL) wolfSSH_SetUserAuthCtx(ssh, (void*)password); + wolfSSH_CTX_SetPublicKeyCheck(ctx, wsPublicKeyCheck); + wolfSSH_SetPublicKeyCheckCtx(ssh, (void*)"You've been sampled."); + ret = wolfSSH_SetUsername(ssh, username); if (ret != WS_SUCCESS) err_sys("Couldn't set the username."); diff --git a/examples/sftpclient/sftpclient.c b/examples/sftpclient/sftpclient.c index 98b5b32..67c6a14 100644 --- a/examples/sftpclient/sftpclient.c +++ b/examples/sftpclient/sftpclient.c @@ -326,6 +326,16 @@ static int wsUserAuth(byte authType, } +static int wsPublicKeyCheck(const byte* pubKey, word32 pubKeySz, void* ctx) +{ + printf("Sample public key check callback\n" + " public key = %p\n" + " public key size = %u\n" + " ctx = %s\n", pubKey, pubKeySz, (const char*)ctx); + return 0; +} + + /* returns 0 on success */ static INLINE int SFTP_FPUTS(func_args* args, const char* msg) { @@ -1065,6 +1075,9 @@ THREAD_RETURN WOLFSSH_THREAD sftpclient_test(void* args) if (password != NULL) wolfSSH_SetUserAuthCtx(ssh, (void*)password); + wolfSSH_CTX_SetPublicKeyCheck(ctx, wsPublicKeyCheck); + wolfSSH_SetPublicKeyCheckCtx(ssh, (void*)"You've been sampled!"); + ret = wolfSSH_SetUsername(ssh, username); if (ret != WS_SUCCESS) err_sys("Couldn't set the username."); diff --git a/src/internal.c b/src/internal.c index fdcaa73..f782846 100644 --- a/src/internal.c +++ b/src/internal.c @@ -266,6 +266,9 @@ const char* GetErrorString(int err) case WS_CLOSE_FILE_E: return "Unable to close local file"; + case WS_PUBKEY_REJECTED_E: + return "server's public key is rejected"; + default: return "Unknown error code"; } @@ -2342,7 +2345,26 @@ static int DoKexDhReply(WOLFSSH* ssh, byte* buf, word32 len, word32* idx) if (ret == WS_SUCCESS && (pubKeySz > len - LENGTH_SZ - begin )) { ret = WS_BUFFER_E; } + } + if (ret == WS_SUCCESS) { + if (ssh->ctx->publicKeyCheckCb != NULL) { + WLOG(WS_LOG_DEBUG, "DKDR: Calling the public key check callback"); + ret = ssh->ctx->publicKeyCheckCb(pubKey, pubKeySz, + ssh->publicKeyCheckCtx); + if (ret == 0) { + WLOG(WS_LOG_DEBUG, "DKDR: public key accepted"); + ret = WS_SUCCESS; + } + else { + WLOG(WS_LOG_DEBUG, "DKDR: public key rejected"); + ret = WS_PUBKEY_REJECTED_E; + } + } + else { + WLOG(WS_LOG_DEBUG, "DKDR: no public key check callback, accepted"); + ret = WS_SUCCESS; + } } if (ret == WS_SUCCESS) diff --git a/src/ssh.c b/src/ssh.c index acdd1c6..6246bad 100644 --- a/src/ssh.c +++ b/src/ssh.c @@ -924,6 +924,32 @@ void* wolfSSH_GetUserAuthCtx(WOLFSSH* ssh) } +void wolfSSH_CTX_SetPublicKeyCheck(WOLFSSH_CTX* ctx, + WS_CallbackPublicKeyCheck cb) +{ + if (ctx != NULL) { + ctx->publicKeyCheckCb = cb; + } +} + + +void wolfSSH_SetPublicKeyCheckCtx(WOLFSSH* ssh, void* publicKeyCheckCtx) +{ + if (ssh != NULL) { + ssh->publicKeyCheckCtx = publicKeyCheckCtx; + } +} + + +void* wolfSSH_GetPublicKeyCheckCtx(WOLFSSH* ssh) +{ + if (ssh != NULL) { + return ssh->publicKeyCheckCtx; + } + return NULL; +} + + /* Used to set the channel request type sent in wolfSSH connect. The default * type set is shell if this function is not called. * diff --git a/wolfssh/error.h b/wolfssh/error.h index bd0fb3d..ffe4a35 100644 --- a/wolfssh/error.h +++ b/wolfssh/error.h @@ -103,8 +103,9 @@ enum WS_ErrorCodes { WS_SFTP_FILE_DNE = -63, /* SFTP File Does Not Exist */ WS_SIZE_ONLY = -64, /* Only getting the size of buffer needed */ WS_CLOSE_FILE_E = -65, /* Unable to close local file */ + WS_PUBKEY_REJECTED_E = -66, /* Server public key rejected */ - WS_LAST_E = -65 /* Update this to indicate last error */ + WS_LAST_E = -66 /* Update this to indicate last error */ }; diff --git a/wolfssh/internal.h b/wolfssh/internal.h index 7f740b6..a67cff2 100644 --- a/wolfssh/internal.h +++ b/wolfssh/internal.h @@ -181,6 +181,8 @@ struct WOLFSSH_CTX { WS_CallbackScpRecv scpRecvCb; /* SCP receive callback */ WS_CallbackScpSend scpSendCb; /* SCP send callback */ #endif + WS_CallbackPublicKeyCheck publicKeyCheckCb; + /* Check server's public key callback */ byte* privateKey; /* Owned by CTX */ word32 privateKeySz; @@ -388,6 +390,7 @@ struct WOLFSSH { word32 pkBlobSz; byte* peerProtoId; /* Save for rekey */ word32 peerProtoIdSz; + void* publicKeyCheckCtx; #ifdef WOLFSSH_SFTP word32 reqId; diff --git a/wolfssh/ssh.h b/wolfssh/ssh.h index f3d1b96..cbdddd4 100644 --- a/wolfssh/ssh.h +++ b/wolfssh/ssh.h @@ -148,6 +148,13 @@ WOLFSSH_API void wolfSSH_SetUserAuth(WOLFSSH_CTX*, WS_CallbackUserAuth); WOLFSSH_API void wolfSSH_SetUserAuthCtx(WOLFSSH*, void*); WOLFSSH_API void* wolfSSH_GetUserAuthCtx(WOLFSSH*); +/* Public Key Check Callback */ +typedef int (*WS_CallbackPublicKeyCheck)(const byte*, word32, void*); +WOLFSSH_API void wolfSSH_CTX_SetPublicKeyCheck(WOLFSSH_CTX*, + WS_CallbackPublicKeyCheck); +WOLFSSH_API void wolfSSH_SetPublicKeyCheckCtx(WOLFSSH*, void*); +WOLFSSH_API void* wolfSSH_GetPublicKeyCheckCtx(WOLFSSH*); + WOLFSSH_API int wolfSSH_SetUsername(WOLFSSH*, const char*); WOLFSSH_API int wolfSSH_CTX_SetBanner(WOLFSSH_CTX*, const char*);