From 56616d3416633fac25c3802b1af715c149d5d220 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 6 Jun 2019 11:59:35 -0700 Subject: [PATCH] Public key authentication 1. Cleanup some debug printouts. 2. Add option to the echoserver and wolfSFTP client to use ECC keys or RSA keys for user authentication. 3. Add option to the echoserver to use ECC keys for peer authentication. Note, the user authentication type is still hardcoded in the library as password. To use public key, need to update the authId in SendUserAuthFailure(). --- examples/client/client.c | 20 +++++---- examples/echoserver/echoserver.c | 17 +++++--- examples/sftpclient/sftpclient.c | 70 ++++++++++++++++++++++++-------- src/internal.c | 3 +- 4 files changed, 79 insertions(+), 31 deletions(-) diff --git a/examples/client/client.c b/examples/client/client.c index b4e9e05..9aaf11a 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -184,7 +184,7 @@ static int wsUserAuth(byte authType, } } else if (authType == WOLFSSH_USERAUTH_PUBLICKEY) { - fprintf(stderr, "username = %p\n", authData->username); + ret = WOLFSSH_USERAUTH_INVALID_AUTHTYPE; } return ret; @@ -193,10 +193,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); + #ifdef DEBUG_WOLFSSH + printf("Sample public key check callback\n" + " public key = %p\n" + " public key size = %u\n" + " ctx = %s\n", pubKey, pubKeySz, (const char*)ctx); + #else + (void)pubKey; + (void)pubKeySz; + (void)ctx; + #endif return 0; } @@ -525,10 +531,8 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args) ret = wolfSSH_connect(ssh); else ret = NonBlockSSH_connect(ssh); - if (ret != WS_SUCCESS) { - printf("err = %s\n", wolfSSH_get_error_name(ssh)); + if (ret != WS_SUCCESS) err_sys("Couldn't connect SSH stream."); - } #if !defined(SINGLE_THREADED) && !defined(WOLFSSL_NUCLEUS) if (keepOpen) /* set up for psuedo-terminal */ diff --git a/examples/echoserver/echoserver.c b/examples/echoserver/echoserver.c index 9acad9f..5b40522 100644 --- a/examples/echoserver/echoserver.c +++ b/examples/echoserver/echoserver.c @@ -720,7 +720,8 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) word32 defaultHighwater = EXAMPLE_HIGHWATER_MARK; word32 threadCount = 0; int multipleConnections = 1; - int useEcc = 0; + int userEcc = 0; + int peerEcc = 0; int ch; word16 port = wolfSshPort; char* readyFile = NULL; @@ -732,7 +733,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) serverArgs->return_code = 0; if (argc > 0) { - while ((ch = mygetopt(argc, argv, "?1d:ep:R:N")) != -1) { + while ((ch = mygetopt(argc, argv, "?1d:eEp:R:N")) != -1) { switch (ch) { case '?' : ShowUsage(); @@ -743,7 +744,11 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) break; case 'e' : - useEcc = 1; + userEcc = 1; + break; + + case 'E': + peerEcc = 1; break; case 'p': @@ -804,7 +809,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) byte buf[SCRATCH_BUFFER_SZ]; word32 bufSz; - bufSz = load_key(useEcc, buf, SCRATCH_BUFFER_SZ); + bufSz = load_key(peerEcc, buf, SCRATCH_BUFFER_SZ); if (bufSz == 0) { fprintf(stderr, "Couldn't load key file.\n"); exit(EXIT_FAILURE); @@ -820,8 +825,8 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) buf[bufSz] = 0; LoadPasswordBuffer(buf, bufSz, &pwMapList); - bufName = useEcc ? samplePublicKeyEccBuffer : - samplePublicKeyRsaBuffer; + bufName = userEcc ? samplePublicKeyEccBuffer : + samplePublicKeyRsaBuffer; bufSz = (word32)strlen(bufName); memcpy(buf, bufName, bufSz); buf[bufSz] = 0; diff --git a/examples/sftpclient/sftpclient.c b/examples/sftpclient/sftpclient.c index 640c3cc..97db63f 100644 --- a/examples/sftpclient/sftpclient.c +++ b/examples/sftpclient/sftpclient.c @@ -280,6 +280,8 @@ static void ShowUsage(void) printf(" -P password for username, prompted if omitted\n"); printf(" -d set the default local path\n"); printf(" -N use non blocking sockets\n"); + printf(" -e use ECC user authentication\n"); + /*printf(" -E use ECC server authentication\n");*/ ShowCommands(); } @@ -289,6 +291,8 @@ byte userPassword[256]; byte userPublicKeyType[32]; byte userPublicKey[512]; word32 userPublicKeySz; +const byte* userPrivateKey; +word32 userPrivateKeySz; const char hanselPublicRsa[] = "AAAAB3NzaC1yc2EAAAADAQABAAABAQC9P3ZFowOsONXHD5MwWiCciXytBRZGho" @@ -443,7 +447,8 @@ static int wsUserAuth(byte authType, else { printf("Password: "); SetEcho(0); - if (WFGETS((char*)userPassword, sizeof(userPassword), stdin) == NULL) { + if (WFGETS((char*)userPassword, sizeof(userPassword), + stdin) == NULL) { printf("Getting password failed.\n"); ret = WOLFSSH_USERAUTH_FAILURE; } @@ -467,20 +472,12 @@ static int wsUserAuth(byte authType, else if (authType == WOLFSSH_USERAUTH_PUBLICKEY) { WS_UserAuthData_PublicKey* pk = &authData->sf.publicKey; - userPublicKeySz = (word32)sizeof(userPublicKey); - - Base64_Decode((byte*)hanselPublicRsa, - (word32)WSTRLEN(hanselPublicRsa), - (byte*)userPublicKey, &userPublicKeySz); - - strncpy((char*)userPublicKeyType, "ssh-rsa", - sizeof(userPublicKeyType)); pk->publicKeyType = userPublicKeyType; pk->publicKeyTypeSz = (word32)WSTRLEN((char*)userPublicKeyType); pk->publicKey = userPublicKey; pk->publicKeySz = userPublicKeySz; - pk->privateKey = hanselPrivateRsa; - pk->privateKeySz = hanselPrivateRsaSz; + pk->privateKey = userPrivateKey; + pk->privateKeySz = userPrivateKeySz; ret = WOLFSSH_USERAUTH_SUCCESS; } @@ -490,10 +487,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); + #ifdef DEBUG_WOLFSSH + printf("Sample public key check callback\n" + " public key = %p\n" + " public key size = %u\n" + " ctx = %s\n", pubKey, pubKeySz, (const char*)ctx); + #else + (void)pubKey; + (void)pubKeySz; + (void)ctx; + #endif return 0; } @@ -1146,6 +1149,8 @@ THREAD_RETURN WOLFSSH_THREAD sftpclient_test(void* args) socklen_t clientAddrSz = sizeof(clientAddr); int ret; int ch; + int userEcc = 0; + /* int peerEcc = 0; */ word16 port = wolfSshPort; char* host = (char*)wolfSshIp; const char* username = NULL; @@ -1157,12 +1162,22 @@ THREAD_RETURN WOLFSSH_THREAD sftpclient_test(void* args) char** argv = ((func_args*)args)->argv; ((func_args*)args)->return_code = 0; - while ((ch = mygetopt(argc, argv, "?d:h:p:u:P:N")) != -1) { + while ((ch = mygetopt(argc, argv, "?d:eEh:p:u:P:N")) != -1) { switch (ch) { case 'd': defaultSftpPath = myoptarg; break; + case 'e': + userEcc = 1; + break; + + case 'E': + /* peerEcc = 1; */ + err_sys("wolfSFTP ECC server authentication " + "not yet supported."); + break; + case 'h': host = myoptarg; break; @@ -1208,6 +1223,29 @@ THREAD_RETURN WOLFSSH_THREAD sftpclient_test(void* args) } #endif + if (userEcc) { + userPublicKeySz = (word32)sizeof(userPublicKey); + Base64_Decode((byte*)hanselPublicEcc, + (word32)WSTRLEN(hanselPublicEcc), + (byte*)userPublicKey, &userPublicKeySz); + + strncpy((char*)userPublicKeyType, "ecdsa-sha2-nistp256", + sizeof(userPublicKeyType)); + userPrivateKey = hanselPrivateEcc; + userPrivateKeySz = hanselPrivateEccSz; + } + else { + userPublicKeySz = (word32)sizeof(userPublicKey); + Base64_Decode((byte*)hanselPublicRsa, + (word32)WSTRLEN(hanselPublicRsa), + (byte*)userPublicKey, &userPublicKeySz); + + strncpy((char*)userPublicKeyType, "ssh-rsa", + sizeof(userPublicKeyType)); + userPrivateKey = hanselPrivateRsa; + userPrivateKeySz = hanselPrivateRsaSz; + } + ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_CLIENT, NULL); if (ctx == NULL) err_sys("Couldn't create wolfSSH client context."); diff --git a/src/internal.c b/src/internal.c index 2158b1b..865e200 100644 --- a/src/internal.c +++ b/src/internal.c @@ -3703,7 +3703,8 @@ static int DoUserAuthFailure(WOLFSSH* ssh, byte authList[3]; /* Should only ever be password, publickey, hostname */ word32 authListSz = 3; byte partialSuccess; - byte authId = ID_USERAUTH_PUBLICKEY; + byte authId = ID_USERAUTH_PASSWORD; + /* To use public key authentication, change authId. */ int ret = WS_SUCCESS; WLOG(WS_LOG_DEBUG, "Entering DoUserAuthFailure()");