diff --git a/examples/client/client.c b/examples/client/client.c index f60a7b8b..af282892 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -179,8 +179,10 @@ static void ShowUsage(void) static byte userPassword[256]; -static byte userPublicKey[512]; +static byte userPublicKeyBuf[512]; +static byte* userPublicKey = userPublicKeyBuf; static const byte* userPublicKeyType = NULL; +static const char* pubKeyName = NULL; static byte userPrivateKeyBuf[1191]; /* Size equal to hanselPrivateRsaSz. */ static byte* userPrivateKey = userPrivateKeyBuf; static const byte* userPrivateKeyType = NULL; @@ -377,16 +379,20 @@ static int wsUserAuth(byte authType, printf("wolfSSH requesting to use type %d\n", authType); #endif - /* We know hansel has a key, wait for request of public key */ + /* Wait for request of public key on names known to have one */ if ((authData->type & WOLFSSH_USERAUTH_PUBLICKEY) && authData->username != NULL && - authData->usernameSz > 0 && - (XSTRNCMP((char*)authData->username, "hansel", - authData->usernameSz) == 0)) { - if (authType == WOLFSSH_USERAUTH_PASSWORD) { - printf("rejecting password type with %s in favor of pub key\n", + authData->usernameSz > 0) { + + /* in the case that the name is hansel or in the case that the user + * passed in a public key file, use public key auth */ + if ((XSTRNCMP((char*)authData->username, "hansel", + authData->usernameSz) == 0) || pubKeyName != NULL) { + if (authType == WOLFSSH_USERAUTH_PASSWORD) { + printf("rejecting password type with %s in favor of pub key\n", (char*)authData->username); - return WOLFSSH_USERAUTH_FAILURE; + return WOLFSSH_USERAUTH_FAILURE; + } } } @@ -809,7 +815,6 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args) const char* password = NULL; const char* cmd = NULL; const char* privKeyName = NULL; - const char* pubKeyName = NULL; byte imExit = 0; byte nonBlock = 0; byte keepOpen = 0; @@ -945,6 +950,7 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args) } else { #ifndef NO_FILESYSTEM + userPrivateKey = NULL; /* create new buffer based on parsed input */ ret = wolfSSH_ReadKey_file(privKeyName, (byte**)&userPrivateKey, &userPrivateKeySz, (const byte**)&userPrivateKeyType, &userPrivateKeyTypeSz, @@ -958,7 +964,7 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args) if (pubKeyName == NULL) { byte* p = userPublicKey; - userPublicKeySz = sizeof(userPublicKey); + userPublicKeySz = sizeof(userPublicKeyBuf); if (userEcc) { #ifdef HAVE_ECC @@ -981,11 +987,9 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args) } else { #ifndef NO_FILESYSTEM - byte* p = userPublicKey; - userPublicKeySz = sizeof(userPublicKey); - + userPublicKey = NULL; /* create new buffer based on parsed input */ ret = wolfSSH_ReadKey_file(pubKeyName, - &p, &userPublicKeySz, + &userPublicKey, &userPublicKeySz, (const byte**)&userPublicKeyType, &userPublicKeyTypeSz, &isPrivate, NULL); #else @@ -1143,6 +1147,13 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args) if (ret != WS_SUCCESS) err_sys("Closing client stream failed. Connection could have been closed by peer"); + if (pubKeyName != NULL && userPublicKey != NULL) { + WFREE(userPublicKey, NULL, DYNTYPE_PRIVKEY); + } + + if (privKeyName != NULL && userPrivateKey != NULL) { + WFREE(userPrivateKey, NULL, DYNTYPE_PRIVKEY); + } #if defined(HAVE_ECC) && defined(FP_ECC) && defined(HAVE_THREAD_LS) wc_ecc_fp_free(); /* free per thread cache */ #endif diff --git a/examples/echoserver/echoserver.c b/examples/echoserver/echoserver.c index 052e3c69..21ba0fde 100644 --- a/examples/echoserver/echoserver.c +++ b/examples/echoserver/echoserver.c @@ -1074,7 +1074,8 @@ static THREAD_RETURN WOLFSSH_THREAD server_worker(void* vArgs) } #ifndef NO_FILESYSTEM -static int load_file(const char* fileName, byte* buf, word32 bufSz) +/* set bufSz to size wanted if too small and buf is null */ +static int load_file(const char* fileName, byte* buf, word32* bufSz) { FILE* file; word32 fileSz; @@ -1088,7 +1089,9 @@ static int load_file(const char* fileName, byte* buf, word32 bufSz) fileSz = (word32)ftell(file); rewind(file); - if (fileSz > bufSz) { + if (fileSz > *bufSz) { + if (buf == NULL) + *bufSz = fileSz; fclose(file); return 0; } @@ -1119,7 +1122,7 @@ static int load_key(byte isEcc, byte* buf, word32 bufSz) #ifndef NO_FILESYSTEM const char* bufName; bufName = isEcc ? ECC_PATH : "./keys/server-key-rsa.der" ; - sz = load_file(bufName, buf, bufSz); + sz = load_file(bufName, buf, &bufSz); #else /* using buffers instead */ if (isEcc) { @@ -1336,7 +1339,7 @@ static int LoadPublicKeyBuffer(byte* buf, word32 bufSz, PwMapList* list) word32 publicKey64Sz; byte* username; word32 usernameSz; - byte publicKey[300]; + byte* publicKey; word32 publicKeySz; /* Each line of passwd.txt is in the format @@ -1371,20 +1374,35 @@ static int LoadPublicKeyBuffer(byte* buf, word32 bufSz, PwMapList* list) *delimiter = 0; usernameSz = (word32)(delimiter - str); str = delimiter + 1; - publicKeySz = sizeof(publicKey); + + /* more than enough space for base64 decode + * not using WMALLOC because internal.h is not included for DYNTYPE_* */ + publicKey = (byte*)malloc(publicKey64Sz); + if (publicKey == NULL) { + fprintf(stderr, "error with malloc\n"); + return -1; + } + publicKeySz = publicKey64Sz; if (Base64_Decode(publicKey64, publicKey64Sz, publicKey, &publicKeySz) != 0) { + free(publicKey); return -1; } + #ifdef DEBUG_WOLFSSH + printf("Adding public key for user : %s\n", username); + #endif + if (PwMapNew(list, WOLFSSH_USERAUTH_PUBLICKEY, username, usernameSz, publicKey, publicKeySz) == NULL ) { + free(publicKey); return -1; } + free(publicKey); } return 0; @@ -1504,6 +1522,7 @@ static void ShowUsage(void) #ifdef WOLFSSH_SFTP printf(" -d set the home directory for SFTP connections\n"); #endif + printf(" -j load in a public key to accept from peer\n"); } @@ -1540,13 +1559,14 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) char* readyFile = NULL; const char* defaultSftpPath = NULL; char nonBlock = 0; + char* userPubKey = NULL; int argc = serverArgs->argc; char** argv = serverArgs->argv; serverArgs->return_code = 0; if (argc > 0) { - while ((ch = mygetopt(argc, argv, "?1d:efEp:R:N")) != -1) { + while ((ch = mygetopt(argc, argv, "?1d:efEp:R:Nj:")) != -1) { switch (ch) { case '?' : ShowUsage(); @@ -1590,6 +1610,10 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) defaultSftpPath = myoptarg; break; + case 'j': + userPubKey = myoptarg; + break; + default: ShowUsage(); exit(MY_EX_USAGE); @@ -1653,6 +1677,28 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) exit(EXIT_FAILURE); } + if (userPubKey) { + byte* userBuf = NULL; + word32 userBufSz = 0; + + /* get the files size */ + load_file(userPubKey, NULL, &userBufSz); + + /* create temp buffer and load in file */ + if (userBufSz == 0) { + fprintf(stderr, "Couldn't find size of file %s.\n", userPubKey); + exit(EXIT_FAILURE); + } + + userBuf = (byte*)malloc(userBufSz); + if (userBuf == NULL) { + fprintf(stderr, "malloc failed\n"); + exit(EXIT_FAILURE); + } + load_file(userPubKey, userBuf, &userBufSz); + LoadPublicKeyBuffer(userBuf, userBufSz, &pwMapList); + } + bufSz = (word32)strlen(samplePasswordBuffer); memcpy(buf, samplePasswordBuffer, bufSz); buf[bufSz] = 0; diff --git a/src/ssh.c b/src/ssh.c index 6fc289f5..00f2f27f 100644 --- a/src/ssh.c +++ b/src/ssh.c @@ -1415,6 +1415,7 @@ int wolfSSH_ReadKey_buffer(const byte* in, word32 inSz, int format, void* heap) { int ret = WS_SUCCESS; + byte* newKey = NULL; (void)heap; @@ -1448,6 +1449,17 @@ int wolfSSH_ReadKey_buffer(const byte* in, word32 inSz, int format, *outType = (const byte*)name; *outTypeSz = typeSz; + if (*out == NULL) { + /* set size based on sanity check in wolfSSL base64 decode + * function */ + *outSz = ((word32)WSTRLEN(key) * 3 + 3) / 4; + newKey = (byte*)WMALLOC(*outSz, heap, DYNTYPE_PRIVKEY); + if (newKey == NULL) { + return WS_MEMORY_E; + } + *out = newKey; + } + ret = Base64_Decode((byte*)key, (word32)WSTRLEN(key), *out, outSz); } @@ -1457,7 +1469,6 @@ int wolfSSH_ReadKey_buffer(const byte* in, word32 inSz, int format, WFREE(c, heap, DYNTYPE_STRING); } else if (format == WOLFSSH_FORMAT_ASN1) { - byte* newKey; word32 scratch = 0; union wolfSSH_key *key_ptr;