From 5abeeff9198f60bab823067830e7ad80bf09363d Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Fri, 22 Apr 2016 13:46:54 -0600 Subject: [PATCH 1/2] add STARTTLS support to example client --- examples/client/client.c | 106 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 105 insertions(+), 1 deletion(-) diff --git a/examples/client/client.c b/examples/client/client.c index 275c92f95..65fdde9d9 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -364,6 +364,7 @@ static void Usage(void) printf("-N Use Non-blocking sockets\n"); printf("-r Resume session\n"); printf("-w Wait for bidirectional shutdown\n"); + printf("-M Use STARTTLS, using protocol (smtp)\n"); #ifdef HAVE_SECURE_RENEGOTIATION printf("-R Allow Secure Renegotiation\n"); printf("-i Force client Initiated Secure Renegotiation\n"); @@ -465,6 +466,9 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) const char* ourCert = cliCert; const char* ourKey = cliKey; + int doSTARTTLS = 0; + char* starttlsProt = NULL; + #ifdef WOLFSSL_TRUST_PEER_CERT const char* trustCert = NULL; #endif @@ -489,6 +493,17 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) char* ocspUrl = NULL; #endif + /* STARTTLS */ + char recvBuffer[256]; + const char* starttlsCmd[6] = { + "220", + "EHLO mail.example.com\r\n", + "250", + "STARTTLS\r\n", + "220", + "QUIT\r\n", + }; + int argc = ((func_args*)args)->argc; char** argv = ((func_args*)args)->argv; @@ -521,7 +536,8 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifndef WOLFSSL_VXWORKS while ((ch = mygetopt(argc, argv, - "?gdeDusmNrwRitfxXUPCVh:p:v:l:A:c:k:Z:b:zS:F:L:ToO:aB:W:E:")) != -1) { + "?gdeDusmNrwRitfxXUPCVh:p:v:l:A:c:k:Z:b:zS:F:L:ToO:aB:W:E:M:")) + != -1) { switch (ch) { case '?' : Usage(); @@ -762,6 +778,17 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif break; + case 'M' : + doSTARTTLS = 1; + starttlsProt = myoptarg; + + if (XSTRNCMP(starttlsProt, "smtp", 4) != 0) { + Usage(); + exit(MY_EX_USAGE); + } + + break; + default: Usage(); exit(MY_EX_USAGE); @@ -1163,6 +1190,55 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if (wolfSSL_set_fd(ssl, sockfd) != SSL_SUCCESS) { err_sys("error in setting fd"); } + + /* STARTTLS */ + if (doSTARTTLS) { + + /* S: 220 SMTP service ready */ + if (read(sockfd, recvBuffer, sizeof(recvBuffer)) < 0) + err_sys("failed to read STARTTLS command\n"); + + if (!XSTRNCMP(recvBuffer, starttlsCmd[0], 3)) { + printf("%s\n", recvBuffer); + XMEMSET(recvBuffer, 0, sizeof(recvBuffer)); + } else { + err_sys("incorrect STARTTLS command received"); + } + + /* C: EHLO mail.example.com */ + if (write(sockfd, starttlsCmd[1], XSTRLEN(starttlsCmd[1])) != + (int)XSTRLEN(starttlsCmd[1])) + err_sys("failed to send STARTTLS EHLO command\n"); + + /* S: 250 offers a warm hug of welcome */ + if (read(sockfd, recvBuffer, sizeof(recvBuffer)) < 0) + err_sys("failed to read STARTTLS command\n"); + + if (!XSTRNCMP(recvBuffer, starttlsCmd[2], 3)) { + printf("%s\n", recvBuffer); + XMEMSET(recvBuffer, 0, sizeof(recvBuffer)); + } else { + err_sys("incorrect STARTTLS command received"); + } + + /* C: STARTTLS */ + if (write(sockfd, starttlsCmd[3], XSTRLEN(starttlsCmd[3])) != + (int)XSTRLEN(starttlsCmd[3])) { + err_sys("failed to send STARTTLS command\n"); + } + + /* S: 220 Go ahead */ + if (read(sockfd, recvBuffer, sizeof(recvBuffer)) < 0) + err_sys("failed to read STARTTLS command\n"); + + if (!XSTRNCMP(recvBuffer, starttlsCmd[4], 3)) { + printf("%s\n", recvBuffer); + XMEMSET(recvBuffer, 0, sizeof(recvBuffer)); + } else { + err_sys("incorrect STARTTLS command received, expected 220"); + } + } + #ifdef HAVE_CRL if (disableCRL == 0) { if (wolfSSL_EnableCRL(ssl, WOLFSSL_CRL_CHECKALL) != SSL_SUCCESS) @@ -1225,6 +1301,34 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif showPeer(ssl); + if (doSTARTTLS) { + printf("\nwolfSSL client shutting down SMTP connection\n"); + + /* C: QUIT */ + if (wolfSSL_write(ssl, starttlsCmd[5], (int)XSTRLEN(starttlsCmd[5])) != + (int)XSTRLEN(starttlsCmd[5])) + err_sys("failed to send STARTTLS EHLO command\n"); + + /* S: 221 2.0.0 Service closing transmission channel */ + if (wolfSSL_read(ssl, recvBuffer, sizeof(recvBuffer)) < 0) + err_sys("failed to read STARTTLS command\n"); + + printf("%s\n", recvBuffer); + XMEMSET(recvBuffer, 0, sizeof(recvBuffer)); + + ret = wolfSSL_shutdown(ssl); + if (wc_shutdown && ret == SSL_SHUTDOWN_NOT_DONE) + wolfSSL_shutdown(ssl); /* bidirectional shutdown */ + + wolfSSL_free(ssl); + CloseSocket(sockfd); + + wolfSSL_CTX_free(ctx); + + ((func_args*)args)->return_code = 0; + return 0; + } + #ifdef HAVE_ALPN if (alpnList != NULL) { char *protocol_name = NULL; From 46addfb1306474274c7be6e4c739da64df2aa064 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 28 Apr 2016 14:21:33 -0600 Subject: [PATCH 2/2] move example client STARTTLS into separate funcs --- examples/client/client.c | 171 +++++++++++++++++++++++---------------- examples/client/client.h | 6 ++ 2 files changed, 106 insertions(+), 71 deletions(-) diff --git a/examples/client/client.c b/examples/client/client.c index 65fdde9d9..ab4436341 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -328,6 +328,99 @@ int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, return EXIT_SUCCESS; } +const char* starttlsCmd[6] = { + "220", + "EHLO mail.example.com\r\n", + "250", + "STARTTLS\r\n", + "220", + "QUIT\r\n", +}; + +int StartTLS_Init(SOCKET_T* sockfd) +{ + char tmpBuf[256]; + + if (sockfd == NULL) + return BAD_FUNC_ARG; + + /* S: 220 SMTP service ready */ + if (read(*sockfd, tmpBuf, sizeof(tmpBuf)) < 0) + err_sys("failed to read STARTTLS command\n"); + + if (!XSTRNCMP(tmpBuf, starttlsCmd[0], XSTRLEN(starttlsCmd[0]))) { + printf("%s\n", tmpBuf); + XMEMSET(tmpBuf, 0, sizeof(tmpBuf)); + } else { + err_sys("incorrect STARTTLS command received"); + } + + /* C: EHLO mail.example.com */ + if (write(*sockfd, starttlsCmd[1], XSTRLEN(starttlsCmd[1])) != + (int)XSTRLEN(starttlsCmd[1])) + err_sys("failed to send STARTTLS EHLO command\n"); + + /* S: 250 offers a warm hug of welcome */ + if (read(*sockfd, tmpBuf, sizeof(tmpBuf)) < 0) + err_sys("failed to read STARTTLS command\n"); + + if (!XSTRNCMP(tmpBuf, starttlsCmd[2], XSTRLEN(starttlsCmd[2]))) { + printf("%s\n", tmpBuf); + XMEMSET(tmpBuf, 0, sizeof(tmpBuf)); + } else { + err_sys("incorrect STARTTLS command received"); + } + + /* C: STARTTLS */ + if (write(*sockfd, starttlsCmd[3], XSTRLEN(starttlsCmd[3])) != + (int)XSTRLEN(starttlsCmd[3])) { + err_sys("failed to send STARTTLS command\n"); + } + + /* S: 220 Go ahead */ + if (read(*sockfd, tmpBuf, sizeof(tmpBuf)) < 0) + err_sys("failed to read STARTTLS command\n"); + + if (!XSTRNCMP(tmpBuf, starttlsCmd[4], XSTRLEN(starttlsCmd[4]))) { + printf("%s\n", tmpBuf); + XMEMSET(tmpBuf, 0, sizeof(tmpBuf)); + } else { + err_sys("incorrect STARTTLS command received, expected 220"); + } + + return SSL_SUCCESS; +} + +int SMTP_Shutdown(WOLFSSL* ssl, int wc_shutdown) +{ + int ret; + char tmpBuf[256]; + + if (ssl == NULL) + return BAD_FUNC_ARG; + + printf("\nwolfSSL client shutting down SMTP connection\n"); + + XMEMSET(tmpBuf, 0, sizeof(tmpBuf)); + + /* C: QUIT */ + if (wolfSSL_write(ssl, starttlsCmd[5], (int)XSTRLEN(starttlsCmd[5])) != + (int)XSTRLEN(starttlsCmd[5])) + err_sys("failed to send SMTP QUIT command\n"); + + /* S: 221 2.0.0 Service closing transmission channel */ + if (wolfSSL_read(ssl, tmpBuf, sizeof(tmpBuf)) < 0) + err_sys("failed to read SMTP closing down response\n"); + + printf("%s\n", tmpBuf); + + ret = wolfSSL_shutdown(ssl); + if (wc_shutdown && ret == SSL_SHUTDOWN_NOT_DONE) + wolfSSL_shutdown(ssl); /* bidirectional shutdown */ + + return SSL_SUCCESS; +} + static void Usage(void) { @@ -493,17 +586,6 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) char* ocspUrl = NULL; #endif - /* STARTTLS */ - char recvBuffer[256]; - const char* starttlsCmd[6] = { - "220", - "EHLO mail.example.com\r\n", - "250", - "STARTTLS\r\n", - "220", - "QUIT\r\n", - }; - int argc = ((func_args*)args)->argc; char** argv = ((func_args*)args)->argv; @@ -1193,49 +1275,8 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) /* STARTTLS */ if (doSTARTTLS) { - - /* S: 220 SMTP service ready */ - if (read(sockfd, recvBuffer, sizeof(recvBuffer)) < 0) - err_sys("failed to read STARTTLS command\n"); - - if (!XSTRNCMP(recvBuffer, starttlsCmd[0], 3)) { - printf("%s\n", recvBuffer); - XMEMSET(recvBuffer, 0, sizeof(recvBuffer)); - } else { - err_sys("incorrect STARTTLS command received"); - } - - /* C: EHLO mail.example.com */ - if (write(sockfd, starttlsCmd[1], XSTRLEN(starttlsCmd[1])) != - (int)XSTRLEN(starttlsCmd[1])) - err_sys("failed to send STARTTLS EHLO command\n"); - - /* S: 250 offers a warm hug of welcome */ - if (read(sockfd, recvBuffer, sizeof(recvBuffer)) < 0) - err_sys("failed to read STARTTLS command\n"); - - if (!XSTRNCMP(recvBuffer, starttlsCmd[2], 3)) { - printf("%s\n", recvBuffer); - XMEMSET(recvBuffer, 0, sizeof(recvBuffer)); - } else { - err_sys("incorrect STARTTLS command received"); - } - - /* C: STARTTLS */ - if (write(sockfd, starttlsCmd[3], XSTRLEN(starttlsCmd[3])) != - (int)XSTRLEN(starttlsCmd[3])) { - err_sys("failed to send STARTTLS command\n"); - } - - /* S: 220 Go ahead */ - if (read(sockfd, recvBuffer, sizeof(recvBuffer)) < 0) - err_sys("failed to read STARTTLS command\n"); - - if (!XSTRNCMP(recvBuffer, starttlsCmd[4], 3)) { - printf("%s\n", recvBuffer); - XMEMSET(recvBuffer, 0, sizeof(recvBuffer)); - } else { - err_sys("incorrect STARTTLS command received, expected 220"); + if (StartTLS_Init(&sockfd) != SSL_SUCCESS) { + err_sys("error during STARTTLS protocol"); } } @@ -1302,23 +1343,11 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) showPeer(ssl); if (doSTARTTLS) { - printf("\nwolfSSL client shutting down SMTP connection\n"); - - /* C: QUIT */ - if (wolfSSL_write(ssl, starttlsCmd[5], (int)XSTRLEN(starttlsCmd[5])) != - (int)XSTRLEN(starttlsCmd[5])) - err_sys("failed to send STARTTLS EHLO command\n"); - - /* S: 221 2.0.0 Service closing transmission channel */ - if (wolfSSL_read(ssl, recvBuffer, sizeof(recvBuffer)) < 0) - err_sys("failed to read STARTTLS command\n"); - - printf("%s\n", recvBuffer); - XMEMSET(recvBuffer, 0, sizeof(recvBuffer)); - - ret = wolfSSL_shutdown(ssl); - if (wc_shutdown && ret == SSL_SHUTDOWN_NOT_DONE) - wolfSSL_shutdown(ssl); /* bidirectional shutdown */ + if (XSTRNCMP(starttlsProt, "smtp", 4) == 0) { + if (SMTP_Shutdown(ssl, wc_shutdown) != SSL_SUCCESS) { + err_sys("error closing STARTTLS connection"); + } + } wolfSSL_free(ssl); CloseSocket(sockfd); diff --git a/examples/client/client.h b/examples/client/client.h index 6b5bd27e4..913339ac0 100644 --- a/examples/client/client.h +++ b/examples/client/client.h @@ -35,6 +35,12 @@ int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, int doDTLS, int throughput); +/* Initiates the STARTTLS command sequence over TCP */ +int StartTLS_Init(SOCKET_T* sockfd); + +/* Closes down the SMTP connection */ +int SMTP_Shutdown(WOLFSSL* ssl, int wc_shutdown); + #endif /* WOLFSSL_CLIENT_H */