From 51427e1947ddc07b4ce8ad9dcb04846125170f83 Mon Sep 17 00:00:00 2001 From: Hoi-Ho Chan Date: Wed, 5 May 2010 22:30:46 +0200 Subject: PolarSSL: initial support added This is Hoi-Ho Chan's patch with some minor fixes by me. There are some potential issues in this, but none worse than we can sort out on the list and over time. --- lib/polarssl.c | 391 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 391 insertions(+) create mode 100644 lib/polarssl.c (limited to 'lib/polarssl.c') diff --git a/lib/polarssl.c b/lib/polarssl.c new file mode 100644 index 000000000..95baa1320 --- /dev/null +++ b/lib/polarssl.c @@ -0,0 +1,391 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2010, Hoi-Ho Chan, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Source file for all PolarSSL-specific code for the TLS/SSL layer. No code + * but sslgen.c should ever call or use these functions. + * + */ + +#include "setup.h" +#ifdef USE_POLARSSL + +#include +#include +#include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#include +#include +#include +#include +#include + +#include "urldata.h" +#include "sendf.h" +#include "inet_pton.h" +#include "polarssl.h" +#include "sslgen.h" +#include "parsedate.h" +#include "connect.h" /* for the connect timeout */ +#include "select.h" +#include "rawstr.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* Define this to enable lots of debugging for PolarSSL */ +#undef POLARSSL_DEBUG + +#ifdef POLARSSL_DEBUG +static void polarssl_debug(void *context, int level, char *line) +{ + struct SessionHandle *data = NULL; + + if(!context) + return; + + data = (struct SessionHandle *)context; + + infof(data, "%s", line); +} +#else +#endif + +/* + * This function loads all the client/CA certificates and CRLs. Setup the TLS + * layer and do all necessary magic. + */ +CURLcode +Curl_polarssl_connect(struct connectdata *conn, + int sockindex) +{ + struct SessionHandle *data = conn->data; + bool sni = TRUE; /* default is SNI enabled */ + int ret = -1; +#ifdef ENABLE_IPV6 + struct in6_addr addr; +#else + struct in_addr addr; +#endif + void *old_session = NULL; + size_t old_session_size = 0; +#if defined(HAVE_POLARSSL_GPL) + char buffer[1024]; +#endif + + if(conn->ssl[sockindex].state == ssl_connection_complete) + return CURLE_OK; + + /* PolarSSL only supports SSLv3 and TLSv1 */ + if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) { + failf(data, "PolarSSL does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + } else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3) { + sni = FALSE; /* SSLv3 has no SNI */ + } + + havege_init(&conn->ssl[sockindex].hs); + + /* Load the trusted CA */ + memset(&conn->ssl[sockindex].cacert, 0, sizeof(x509_cert)); + + if(data->set.str[STRING_SSL_CAFILE]) { + ret = x509parse_crtfile(&conn->ssl[sockindex].cacert, + data->set.str[STRING_SSL_CAFILE]); + + if(ret) { + failf(data, "Error reading ca cert file %s: -0x%04X", + data->set.str[STRING_SSL_CAFILE], -ret); + + if(data->set.ssl.verifypeer) + return CURLE_SSL_CACERT_BADFILE; + } + } + + /* Load the client certificate */ + memset(&conn->ssl[sockindex].clicert, 0, sizeof(x509_cert)); + + if(data->set.str[STRING_CERT]) { +#if !defined(HAVE_POLARSSL_GPL) + /* FIXME: PolarSSL has a bug where we need to import it twice */ + ret = x509parse_crtfile(&conn->ssl[sockindex].clicert, + data->set.str[STRING_CERT]); +#endif + ret = x509parse_crtfile(&conn->ssl[sockindex].clicert, + data->set.str[STRING_CERT]); + + if(ret) { + failf(data, "Error reading client cert file %s: -0x%04X", + data->set.str[STRING_CERT], -ret); + return CURLE_SSL_CERTPROBLEM; + } + } + + /* Load the client private key */ + if(data->set.str[STRING_KEY]) { + ret = x509parse_keyfile(&conn->ssl[sockindex].rsa, + data->set.str[STRING_KEY], + data->set.str[STRING_KEY_PASSWD]); + + if(ret) { + failf(data, "Error reading private key %s: -0x%04X", + data->set.str[STRING_KEY], -ret); + return CURLE_SSL_CERTPROBLEM; + } + } + +#if defined(HAVE_POLARSSL_GPL) + /* Load the CRL */ + memset(&conn->ssl[sockindex].crl, 0, sizeof(x509_crl)); + + if(data->set.str[STRING_SSL_CRLFILE]) { + ret = x509parse_crlfile(&conn->ssl[sockindex].crl, + data->set.str[STRING_SSL_CRLFILE]); + + if(ret) { + failf(data, "Error reading CRL file %s: -0x%04X", + data->set.str[STRING_SSL_CRLFILE], -ret); + return CURLE_SSL_CRL_BADFILE; + } + } + +#endif + infof(data, "PolarSSL: Connected to %s:%d\n", + conn->host.name, conn->remote_port); + + havege_init(&conn->ssl[sockindex].hs); + + if(ssl_init(&conn->ssl[sockindex].ssl)) { + failf(data, "PolarSSL: ssl_init failed"); + return CURLE_SSL_CONNECT_ERROR; + } + + ssl_set_endpoint(&conn->ssl[sockindex].ssl, SSL_IS_CLIENT); + ssl_set_authmode(&conn->ssl[sockindex].ssl, SSL_VERIFY_OPTIONAL); + + ssl_set_rng(&conn->ssl[sockindex].ssl, havege_rand, + &conn->ssl[sockindex].hs); + ssl_set_bio(&conn->ssl[sockindex].ssl, + net_recv, &conn->sock[sockindex], + net_send, &conn->sock[sockindex]); + + ssl_set_ciphers(&conn->ssl[sockindex].ssl, ssl_default_ciphers); + + if(!Curl_ssl_getsessionid(conn, &old_session, &old_session_size)) { + memcpy(&conn->ssl[sockindex].ssn, old_session, old_session_size); + infof(data, "PolarSSL re-using session\n"); + } + + ssl_set_session(&conn->ssl[sockindex].ssl, 1, 600, + &conn->ssl[sockindex].ssn); + + ssl_set_ca_chain(&conn->ssl[sockindex].ssl, +#if defined(HAVE_POLARSSL_GPL) + &conn->ssl[sockindex].cacert, + &conn->ssl[sockindex].crl, + conn->host.name); +#else + &conn->ssl[sockindex].cacert, conn->host.name); +#endif + + ssl_set_own_cert(&conn->ssl[sockindex].ssl, + &conn->ssl[sockindex].clicert, &conn->ssl[sockindex].rsa); + + if(!Curl_inet_pton(AF_INET, conn->host.name, &addr) && +#ifdef ENABLE_IPV6 + !Curl_inet_pton(AF_INET6, conn->host.name, &addr) && +#endif + sni && ssl_set_hostname(&conn->ssl[sockindex].ssl, conn->host.name)) { + infof(data, "WARNING: failed to configure " + "server name indication (SNI) TLS extension\n"); + } + + infof(data, "PolarSSL: performing SSL/TLS handshake...\n"); + +#ifdef POLARSSL_DEBUG + ssl_set_dbg(&conn->ssl[sockindex].ssl, polarssl_debug, data); +#endif + + do { + if (!(ret = ssl_handshake(&conn->ssl[sockindex].ssl))) { + break; + } else if(ret != POLARSSL_ERR_NET_TRY_AGAIN) { + failf(data, "ssl_handshake returned -0x%04X", -ret); + return CURLE_SSL_CONNECT_ERROR; + } else { + /* wait for data from server... */ + long timeout_ms = Curl_timeleft(conn, NULL, TRUE); + + if(timeout_ms < 0) { + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + switch(Curl_socket_ready(conn->sock[sockindex], + CURL_SOCKET_BAD, timeout_ms)) { + case 0: + failf(data, "SSL handshake timeout"); + return CURLE_OPERATION_TIMEDOUT; + break; + case CURL_CSELECT_IN: + continue; + break; + default: + return CURLE_SSL_CONNECT_ERROR; + break; + } + } + } while (1); + + infof(data, "PolarSSL: Handshake complete, cipher is %s\n", + ssl_get_cipher(&conn->ssl[sockindex].ssl)); + + ret = ssl_get_verify_result(&conn->ssl[sockindex].ssl); + + if(ret && data->set.ssl.verifypeer) { + if(ret & BADCERT_EXPIRED) + failf(data, "Cert verify failed: BADCERT_EXPIRED\n"); + + if(ret & BADCERT_REVOKED) + failf(data, "Cert verify failed: BADCERT_REVOKED"); + + if(ret & BADCERT_CN_MISMATCH) + failf(data, "Cert verify failed: BADCERT_CN_MISMATCH"); + + if(ret & BADCERT_NOT_TRUSTED) + failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED"); + + return CURLE_SSL_CACERT; + } + + if(conn->ssl[sockindex].ssl.peer_cert) { + /* If the session was resumed, there will be no peer certs */ +#if !defined(HAVE_POLARSSL_GPL) + char *buffer = x509parse_cert_info("* ", conn->ssl[sockindex].ssl.peer_cert); + + if(buffer) +#else + memset(buffer, 0, sizeof(buffer)); + + if(x509parse_cert_info(buffer, sizeof(buffer), (char *)"* ", + conn->ssl[sockindex].ssl.peer_cert) != -1) +#endif + infof(data, "Dumping cert info:\n%s\n", buffer); + } + + conn->ssl[sockindex].state = ssl_connection_complete; + + /* Save the current session data for possible re-use */ + { + void *new_session = malloc(sizeof(conn->ssl[sockindex].ssn)); + + if(new_session) { + memcpy(new_session, &conn->ssl[sockindex].ssn, + sizeof(conn->ssl[sockindex].ssn)); + + if(old_session) + Curl_ssl_delsessionid(conn, old_session); + + return Curl_ssl_addsessionid(conn, new_session, + sizeof(conn->ssl[sockindex].ssn)); + } + } + + return CURLE_OK; +} + +/* for documentation see Curl_ssl_send() in sslgen.h */ +ssize_t Curl_polarssl_send(struct connectdata *conn, + int sockindex, + const void *mem, + size_t len, + int *curlcode) +{ + int ret = -1; + + ret = ssl_write(&conn->ssl[sockindex].ssl, + (unsigned char *)mem, len); + + if(ret < 0) { + *curlcode = (ret == POLARSSL_ERR_NET_TRY_AGAIN) ? -1 : CURLE_SEND_ERROR; + ret = -1; + } + + return ret; +} + +void Curl_polarssl_close_all(struct SessionHandle *data) +{ + (void)data; +} + +void Curl_polarssl_close(struct connectdata *conn, int sockindex) +{ + rsa_free(&conn->ssl[sockindex].rsa); + x509_free(&conn->ssl[sockindex].clicert); + x509_free(&conn->ssl[sockindex].cacert); +#if defined(HAVE_POLARSSL_GPL) + x509_crl_free(&conn->ssl[sockindex].crl); +#endif + ssl_free(&conn->ssl[sockindex].ssl); +} + +/* for documentation see Curl_ssl_recv() in sslgen.h */ +ssize_t Curl_polarssl_recv(struct connectdata *conn, + int num, + char *buf, + size_t buffersize, + int *curlcode) +{ + int ret = -1; + ssize_t len = -1; + + memset(buf, 0, buffersize); + ret = ssl_read(&conn->ssl[num].ssl, (unsigned char *)buf, buffersize); + + if(ret <= 0) { + *curlcode = (ret == POLARSSL_ERR_NET_TRY_AGAIN) ? -1 : CURLE_RECV_ERROR; + return -1; + } + + len = ret; + + return len; +} + +void Curl_polarssl_session_free(void *ptr) +{ + free(ptr); +} + +size_t Curl_polarssl_version(char *buffer, size_t size) +{ + return snprintf(buffer, size, "PolarSSL"); +} + +#endif -- cgit v1.2.1 From d64bd82bdcb169d0647a80f00068cedd761f8163 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Fri, 7 May 2010 15:05:34 +0200 Subject: sendrecv: split the I/O handling into private handler Howard Chu brought the bulk work of this patch that properly moves out the sending and recving of data to the parts of the code that are properly responsible for the various ways of doing so. Daniel Stenberg assisted with polishing a few bits and fixed some minor flaws in the original patch. Another upside of this patch is that we now abuse CURLcodes less with the "magic" -1 return codes and instead use CURLE_AGAIN more consistently. --- lib/polarssl.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) (limited to 'lib/polarssl.c') diff --git a/lib/polarssl.c b/lib/polarssl.c index 95baa1320..0027e31e0 100644 --- a/lib/polarssl.c +++ b/lib/polarssl.c @@ -76,6 +76,9 @@ static void polarssl_debug(void *context, int level, char *line) #else #endif +static Curl_recv polarssl_recv; +static Curl_send polarssl_send; + /* * This function loads all the client/CA certificates and CRLs. Setup the TLS * layer and do all necessary magic. @@ -299,6 +302,8 @@ Curl_polarssl_connect(struct connectdata *conn, } conn->ssl[sockindex].state = ssl_connection_complete; + conn->recv = polarssl_recv; + conn->send = polarssl_send; /* Save the current session data for possible re-use */ { @@ -319,12 +324,11 @@ Curl_polarssl_connect(struct connectdata *conn, return CURLE_OK; } -/* for documentation see Curl_ssl_send() in sslgen.h */ -ssize_t Curl_polarssl_send(struct connectdata *conn, - int sockindex, - const void *mem, - size_t len, - int *curlcode) +static ssize_t polarssl_send(struct connectdata *conn, + int sockindex, + const void *mem, + size_t len, + CURLcode *curlcode) { int ret = -1; @@ -332,7 +336,8 @@ ssize_t Curl_polarssl_send(struct connectdata *conn, (unsigned char *)mem, len); if(ret < 0) { - *curlcode = (ret == POLARSSL_ERR_NET_TRY_AGAIN) ? -1 : CURLE_SEND_ERROR; + *curlcode = (ret == POLARSSL_ERR_NET_TRY_AGAIN) ? + CURLE_AGAIN : CURLE_SEND_ERROR; ret = -1; } @@ -355,12 +360,11 @@ void Curl_polarssl_close(struct connectdata *conn, int sockindex) ssl_free(&conn->ssl[sockindex].ssl); } -/* for documentation see Curl_ssl_recv() in sslgen.h */ -ssize_t Curl_polarssl_recv(struct connectdata *conn, - int num, - char *buf, - size_t buffersize, - int *curlcode) +static ssize_t polarssl_recv(struct connectdata *conn, + int num, + char *buf, + size_t buffersize, + CURLcode *curlcode) { int ret = -1; ssize_t len = -1; @@ -369,7 +373,8 @@ ssize_t Curl_polarssl_recv(struct connectdata *conn, ret = ssl_read(&conn->ssl[num].ssl, (unsigned char *)buf, buffersize); if(ret <= 0) { - *curlcode = (ret == POLARSSL_ERR_NET_TRY_AGAIN) ? -1 : CURLE_RECV_ERROR; + *curlcode = (ret == POLARSSL_ERR_NET_TRY_AGAIN) ? + CURLE_AGAIN : CURLE_RECV_ERROR; return -1; } -- cgit v1.2.1 From bc8fc9803fbd0fa9daf0dba796d42d03faf49120 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Tue, 11 May 2010 22:48:38 +0200 Subject: sendrecv: make them two pairs of send/recv to properly deal with FTPS FTP(S) use two connections that can be set to different recv and send functions independently, so by introducing recv+send pairs in the same manner we already have sockets/connections we can work with FTPS fine. This commit fixes the FTPS regression introduced in change d64bd82. --- lib/polarssl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/polarssl.c') diff --git a/lib/polarssl.c b/lib/polarssl.c index 0027e31e0..285b3ae04 100644 --- a/lib/polarssl.c +++ b/lib/polarssl.c @@ -302,8 +302,8 @@ Curl_polarssl_connect(struct connectdata *conn, } conn->ssl[sockindex].state = ssl_connection_complete; - conn->recv = polarssl_recv; - conn->send = polarssl_send; + conn->recv[sockindex] = polarssl_recv; + conn->send[sockindex] = polarssl_send; /* Save the current session data for possible re-use */ { -- cgit v1.2.1 From 83305cbf9fdc5176dca05b5dd182f115051afd54 Mon Sep 17 00:00:00 2001 From: Hoi-Ho Chan Date: Sun, 9 May 2010 12:44:32 -0500 Subject: Remove support for BSD version of PolarSSL "The BSD version of PolarSSL was made for migratory purposes only and is not maintained. The GPL version of PolarSSL is actually the only actively developed version, so I would be very reluctant to use the BSD version." / Paul Bakker, PolarSSL hacker. Signed-off-by: Hoi-Ho Chan --- lib/polarssl.c | 21 --------------------- 1 file changed, 21 deletions(-) (limited to 'lib/polarssl.c') diff --git a/lib/polarssl.c b/lib/polarssl.c index 285b3ae04..e81e66091 100644 --- a/lib/polarssl.c +++ b/lib/polarssl.c @@ -97,9 +97,7 @@ Curl_polarssl_connect(struct connectdata *conn, #endif void *old_session = NULL; size_t old_session_size = 0; -#if defined(HAVE_POLARSSL_GPL) char buffer[1024]; -#endif if(conn->ssl[sockindex].state == ssl_connection_complete) return CURLE_OK; @@ -134,11 +132,6 @@ Curl_polarssl_connect(struct connectdata *conn, memset(&conn->ssl[sockindex].clicert, 0, sizeof(x509_cert)); if(data->set.str[STRING_CERT]) { -#if !defined(HAVE_POLARSSL_GPL) - /* FIXME: PolarSSL has a bug where we need to import it twice */ - ret = x509parse_crtfile(&conn->ssl[sockindex].clicert, - data->set.str[STRING_CERT]); -#endif ret = x509parse_crtfile(&conn->ssl[sockindex].clicert, data->set.str[STRING_CERT]); @@ -162,7 +155,6 @@ Curl_polarssl_connect(struct connectdata *conn, } } -#if defined(HAVE_POLARSSL_GPL) /* Load the CRL */ memset(&conn->ssl[sockindex].crl, 0, sizeof(x509_crl)); @@ -177,7 +169,6 @@ Curl_polarssl_connect(struct connectdata *conn, } } -#endif infof(data, "PolarSSL: Connected to %s:%d\n", conn->host.name, conn->remote_port); @@ -208,13 +199,9 @@ Curl_polarssl_connect(struct connectdata *conn, &conn->ssl[sockindex].ssn); ssl_set_ca_chain(&conn->ssl[sockindex].ssl, -#if defined(HAVE_POLARSSL_GPL) &conn->ssl[sockindex].cacert, &conn->ssl[sockindex].crl, conn->host.name); -#else - &conn->ssl[sockindex].cacert, conn->host.name); -#endif ssl_set_own_cert(&conn->ssl[sockindex].ssl, &conn->ssl[sockindex].clicert, &conn->ssl[sockindex].rsa); @@ -288,16 +275,10 @@ Curl_polarssl_connect(struct connectdata *conn, if(conn->ssl[sockindex].ssl.peer_cert) { /* If the session was resumed, there will be no peer certs */ -#if !defined(HAVE_POLARSSL_GPL) - char *buffer = x509parse_cert_info("* ", conn->ssl[sockindex].ssl.peer_cert); - - if(buffer) -#else memset(buffer, 0, sizeof(buffer)); if(x509parse_cert_info(buffer, sizeof(buffer), (char *)"* ", conn->ssl[sockindex].ssl.peer_cert) != -1) -#endif infof(data, "Dumping cert info:\n%s\n", buffer); } @@ -354,9 +335,7 @@ void Curl_polarssl_close(struct connectdata *conn, int sockindex) rsa_free(&conn->ssl[sockindex].rsa); x509_free(&conn->ssl[sockindex].clicert); x509_free(&conn->ssl[sockindex].cacert); -#if defined(HAVE_POLARSSL_GPL) x509_crl_free(&conn->ssl[sockindex].crl); -#endif ssl_free(&conn->ssl[sockindex].ssl); } -- cgit v1.2.1 From dc3e7df1c99c2ee9dae06453adbb94fe9584bf75 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Mon, 8 Nov 2010 04:03:11 +0100 Subject: fix compiler warning --- lib/polarssl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/polarssl.c') diff --git a/lib/polarssl.c b/lib/polarssl.c index e81e66091..bed76354a 100644 --- a/lib/polarssl.c +++ b/lib/polarssl.c @@ -221,7 +221,7 @@ Curl_polarssl_connect(struct connectdata *conn, ssl_set_dbg(&conn->ssl[sockindex].ssl, polarssl_debug, data); #endif - do { + for(;;) { if (!(ret = ssl_handshake(&conn->ssl[sockindex].ssl))) { break; } else if(ret != POLARSSL_ERR_NET_TRY_AGAIN) { @@ -250,7 +250,7 @@ Curl_polarssl_connect(struct connectdata *conn, break; } } - } while (1); + } infof(data, "PolarSSL: Handshake complete, cipher is %s\n", ssl_get_cipher(&conn->ssl[sockindex].ssl)); -- cgit v1.2.1 From adb49ad8bb280b586b387ba930c0681afee03923 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 4 Jan 2011 23:07:58 +0100 Subject: Curl_timeleft: s/conn/data in first argument As the function doesn't really use the connectdata struct but only the SessionHanadle struct I modified what argument it wants. --- lib/polarssl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/polarssl.c') diff --git a/lib/polarssl.c b/lib/polarssl.c index bed76354a..272e1183e 100644 --- a/lib/polarssl.c +++ b/lib/polarssl.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2010, Hoi-Ho Chan, + * Copyright (C) 2010, 2011, Hoi-Ho Chan, * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -229,7 +229,7 @@ Curl_polarssl_connect(struct connectdata *conn, return CURLE_SSL_CONNECT_ERROR; } else { /* wait for data from server... */ - long timeout_ms = Curl_timeleft(conn, NULL, TRUE); + long timeout_ms = Curl_timeleft(data, NULL, TRUE); if(timeout_ms < 0) { failf(data, "SSL connection timeout"); -- cgit v1.2.1 From 05895927f59eef2d746a1b70f40f1abd0907a474 Mon Sep 17 00:00:00 2001 From: Hoi-Ho Chan Date: Thu, 17 Feb 2011 21:46:59 -0800 Subject: PolarSSL: Return 0 on receiving TLS CLOSE_NOTIFY alert Signed-off-by: Hoi-Ho Chan --- lib/polarssl.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/polarssl.c') diff --git a/lib/polarssl.c b/lib/polarssl.c index 272e1183e..51e35db87 100644 --- a/lib/polarssl.c +++ b/lib/polarssl.c @@ -352,6 +352,9 @@ static ssize_t polarssl_recv(struct connectdata *conn, ret = ssl_read(&conn->ssl[num].ssl, (unsigned char *)buf, buffersize); if(ret <= 0) { + if(ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY) + return 0; + *curlcode = (ret == POLARSSL_ERR_NET_TRY_AGAIN) ? CURLE_AGAIN : CURLE_RECV_ERROR; return -1; -- cgit v1.2.1 From b903186fa0189ff241d756d25d07fdfe9885ae49 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 20 Apr 2011 15:17:42 +0200 Subject: source cleanup: unify look, style and indent levels By the use of a the new lib/checksrc.pl script that checks that our basic source style rules are followed. --- lib/polarssl.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'lib/polarssl.c') diff --git a/lib/polarssl.c b/lib/polarssl.c index 51e35db87..370b8c64c 100644 --- a/lib/polarssl.c +++ b/lib/polarssl.c @@ -106,9 +106,9 @@ Curl_polarssl_connect(struct connectdata *conn, if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) { failf(data, "PolarSSL does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; - } else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3) { - sni = FALSE; /* SSLv3 has no SNI */ } + else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3) + sni = FALSE; /* SSLv3 has no SNI */ havege_init(&conn->ssl[sockindex].hs); @@ -222,12 +222,13 @@ Curl_polarssl_connect(struct connectdata *conn, #endif for(;;) { - if (!(ret = ssl_handshake(&conn->ssl[sockindex].ssl))) { + if(!(ret = ssl_handshake(&conn->ssl[sockindex].ssl))) break; - } else if(ret != POLARSSL_ERR_NET_TRY_AGAIN) { + else if(ret != POLARSSL_ERR_NET_TRY_AGAIN) { failf(data, "ssl_handshake returned -0x%04X", -ret); return CURLE_SSL_CONNECT_ERROR; - } else { + } + else { /* wait for data from server... */ long timeout_ms = Curl_timeleft(data, NULL, TRUE); -- cgit v1.2.1 From 4f170ee8f9c1d067022300df2da331c30dcda9dd Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 4 Jun 2011 21:19:14 +0200 Subject: Curl_socket_ready: make timeout a 'long' It was mostly typecasted to int all over the code so switching to long instead all over should be a net gain. --- lib/polarssl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/polarssl.c') diff --git a/lib/polarssl.c b/lib/polarssl.c index 370b8c64c..2e70a28d5 100644 --- a/lib/polarssl.c +++ b/lib/polarssl.c @@ -238,7 +238,7 @@ Curl_polarssl_connect(struct connectdata *conn, } switch(Curl_socket_ready(conn->sock[sockindex], - CURL_SOCKET_BAD, timeout_ms)) { + CURL_SOCKET_BAD, timeout_ms)) { case 0: failf(data, "SSL handshake timeout"); return CURLE_OPERATION_TIMEDOUT; -- cgit v1.2.1 From f1586cb4775681810afd8e6626e7842d459f3b85 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 26 Jul 2011 17:23:27 +0200 Subject: stdio.h, stdlib.h, string.h, stdarg.h and ctype.h inclusion done in setup_once.h --- lib/polarssl.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'lib/polarssl.c') diff --git a/lib/polarssl.c b/lib/polarssl.c index 2e70a28d5..023204420 100644 --- a/lib/polarssl.c +++ b/lib/polarssl.c @@ -27,11 +27,9 @@ */ #include "setup.h" + #ifdef USE_POLARSSL -#include -#include -#include #ifdef HAVE_SYS_SOCKET_H #include #endif -- cgit v1.2.1 From 1bac153ea31cdc20f9171bed8142d2fe019ed6df Mon Sep 17 00:00:00 2001 From: Jeff Pohlmeyer Date: Tue, 13 Sep 2011 18:44:41 +0200 Subject: polarssl: build with PolarSSL-1.0.0 With this fix, it should work for PolarSSL-1.0.0 (and SVN-1091 trunk) and retain compatibility with earlier versions. (Tested with 0.14.1) PolarSSL still doesn't play nicely with curl's CA bundle (we discussed this before) but I was at least able to retrieve the https://www.gmail.com/ login page using a modified ca-certificates.crt file with all 3 versions of PolarSSL. --- lib/polarssl.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'lib/polarssl.c') diff --git a/lib/polarssl.c b/lib/polarssl.c index 023204420..006163e76 100644 --- a/lib/polarssl.c +++ b/lib/polarssl.c @@ -39,6 +39,15 @@ #include #include #include +#include + +#if POLARSSL_VERSION_NUMBER<0x01000000 +/* + Earlier versions of polarssl had no WANT_READ or WANT_WRITE, only TRY_AGAIN +*/ +#define POLARSSL_ERR_NET_WANT_READ POLARSSL_ERR_NET_TRY_AGAIN +#define POLARSSL_ERR_NET_WANT_WRITE POLARSSL_ERR_NET_TRY_AGAIN +#endif #include "urldata.h" #include "sendf.h" @@ -186,8 +195,12 @@ Curl_polarssl_connect(struct connectdata *conn, net_recv, &conn->sock[sockindex], net_send, &conn->sock[sockindex]); - ssl_set_ciphers(&conn->ssl[sockindex].ssl, ssl_default_ciphers); +#if POLARSSL_VERSION_NUMBER<0x01000000 + ssl_set_ciphers(&conn->ssl[sockindex].ssl, ssl_default_ciphers); +#else + ssl_set_ciphersuites(&conn->ssl[sockindex].ssl, ssl_default_ciphersuites); +#endif if(!Curl_ssl_getsessionid(conn, &old_session, &old_session_size)) { memcpy(&conn->ssl[sockindex].ssn, old_session, old_session_size); infof(data, "PolarSSL re-using session\n"); @@ -222,7 +235,8 @@ Curl_polarssl_connect(struct connectdata *conn, for(;;) { if(!(ret = ssl_handshake(&conn->ssl[sockindex].ssl))) break; - else if(ret != POLARSSL_ERR_NET_TRY_AGAIN) { + else if( ret != POLARSSL_ERR_NET_WANT_READ && + ret != POLARSSL_ERR_NET_WANT_WRITE ) { failf(data, "ssl_handshake returned -0x%04X", -ret); return CURLE_SSL_CONNECT_ERROR; } @@ -252,7 +266,11 @@ Curl_polarssl_connect(struct connectdata *conn, } infof(data, "PolarSSL: Handshake complete, cipher is %s\n", +#if POLARSSL_VERSION_NUMBER<0x01000000 ssl_get_cipher(&conn->ssl[sockindex].ssl)); +#else + ssl_get_ciphersuite_name(&conn->ssl[sockindex].ssl)); +#endif ret = ssl_get_verify_result(&conn->ssl[sockindex].ssl); @@ -316,7 +334,7 @@ static ssize_t polarssl_send(struct connectdata *conn, (unsigned char *)mem, len); if(ret < 0) { - *curlcode = (ret == POLARSSL_ERR_NET_TRY_AGAIN) ? + *curlcode = (ret == POLARSSL_ERR_NET_WANT_WRITE) ? CURLE_AGAIN : CURLE_SEND_ERROR; ret = -1; } @@ -354,7 +372,7 @@ static ssize_t polarssl_recv(struct connectdata *conn, if(ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY) return 0; - *curlcode = (ret == POLARSSL_ERR_NET_TRY_AGAIN) ? + *curlcode = (ret == POLARSSL_ERR_NET_WANT_READ) ? CURLE_AGAIN : CURLE_RECV_ERROR; return -1; } -- cgit v1.2.1 From 73b18a9d249042d464880e24a79a8c4acf103aed Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 13 Sep 2011 18:46:09 +0200 Subject: codestyle: minor whitespace fix --- lib/polarssl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/polarssl.c') diff --git a/lib/polarssl.c b/lib/polarssl.c index 006163e76..09446f995 100644 --- a/lib/polarssl.c +++ b/lib/polarssl.c @@ -235,8 +235,8 @@ Curl_polarssl_connect(struct connectdata *conn, for(;;) { if(!(ret = ssl_handshake(&conn->ssl[sockindex].ssl))) break; - else if( ret != POLARSSL_ERR_NET_WANT_READ && - ret != POLARSSL_ERR_NET_WANT_WRITE ) { + else if(ret != POLARSSL_ERR_NET_WANT_READ && + ret != POLARSSL_ERR_NET_WANT_WRITE) { failf(data, "ssl_handshake returned -0x%04X", -ret); return CURLE_SSL_CONNECT_ERROR; } -- cgit v1.2.1 From 61d31a3caf8bced6d142c43b10e0887af744f50c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 18 Jan 2012 23:17:54 +0100 Subject: polarssl: havege_rand is not present in version 1.1.0 ... it is now named havege_random! Reported by: Robert Schumann Bug: http://curl.haxx.se/mail/lib-2012-01/0178.html --- lib/polarssl.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'lib/polarssl.c') diff --git a/lib/polarssl.c b/lib/polarssl.c index 09446f995..89da87fcd 100644 --- a/lib/polarssl.c +++ b/lib/polarssl.c @@ -65,6 +65,15 @@ /* The last #include file should be: */ #include "memdebug.h" +/* version dependent differences */ +#if POLARSSL_VERSION_NUMBER < 0x01010000 +/* the old way */ +#define HAVEGE_RANDOM havege_rand +#else +/* from 1.1.0 */ +#define HAVEGE_RANDOM havege_random +#endif + /* Define this to enable lots of debugging for PolarSSL */ #undef POLARSSL_DEBUG @@ -189,7 +198,7 @@ Curl_polarssl_connect(struct connectdata *conn, ssl_set_endpoint(&conn->ssl[sockindex].ssl, SSL_IS_CLIENT); ssl_set_authmode(&conn->ssl[sockindex].ssl, SSL_VERIFY_OPTIONAL); - ssl_set_rng(&conn->ssl[sockindex].ssl, havege_rand, + ssl_set_rng(&conn->ssl[sockindex].ssl, HAVEGE_RANDOM, &conn->ssl[sockindex].hs); ssl_set_bio(&conn->ssl[sockindex].ssl, net_recv, &conn->sock[sockindex], -- cgit v1.2.1 From f55f95d49ce2d18beb519b0befbf4710d66cf51d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 18 Jan 2012 23:19:01 +0100 Subject: polarssl: show error code correctly The value was turned negative when it shouldn't have been --- lib/polarssl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/polarssl.c') diff --git a/lib/polarssl.c b/lib/polarssl.c index 89da87fcd..07c0bf436 100644 --- a/lib/polarssl.c +++ b/lib/polarssl.c @@ -137,7 +137,7 @@ Curl_polarssl_connect(struct connectdata *conn, if(ret) { failf(data, "Error reading ca cert file %s: -0x%04X", - data->set.str[STRING_SSL_CAFILE], -ret); + data->set.str[STRING_SSL_CAFILE], ret); if(data->set.ssl.verifypeer) return CURLE_SSL_CACERT_BADFILE; -- cgit v1.2.1 From d1becc3231ae570be19858491c5c9f2fe48c1fd7 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 18 Jan 2012 23:19:37 +0100 Subject: polarssl: show cipher suite name correctly with 1.1.0 Apparently ssl_get_ciphersuite() is needed to get the name of the used cipher suite. --- lib/polarssl.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'lib/polarssl.c') diff --git a/lib/polarssl.c b/lib/polarssl.c index 07c0bf436..f24c7839b 100644 --- a/lib/polarssl.c +++ b/lib/polarssl.c @@ -276,10 +276,13 @@ Curl_polarssl_connect(struct connectdata *conn, infof(data, "PolarSSL: Handshake complete, cipher is %s\n", #if POLARSSL_VERSION_NUMBER<0x01000000 - ssl_get_cipher(&conn->ssl[sockindex].ssl)); + ssl_get_cipher(&conn->ssl[sockindex].ssl) +#elif POLARSSL_VERSION_NUMBER >= 0x01010000 + ssl_get_ciphersuite(&conn->ssl[sockindex].ssl) #else - ssl_get_ciphersuite_name(&conn->ssl[sockindex].ssl)); + ssl_get_ciphersuite_name(&conn->ssl[sockindex].ssl) #endif + ); ret = ssl_get_verify_result(&conn->ssl[sockindex].ssl); -- cgit v1.2.1 From 5e852ab9d158e8400f3b3ea53828237ed0570730 Mon Sep 17 00:00:00 2001 From: Dag Ekengren Date: Tue, 27 Mar 2012 14:10:32 +0200 Subject: PolarSSL: add support for asynchronous connect --- lib/polarssl.c | 318 +++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 243 insertions(+), 75 deletions(-) (limited to 'lib/polarssl.c') diff --git a/lib/polarssl.c b/lib/polarssl.c index f24c7839b..c890a07db 100644 --- a/lib/polarssl.c +++ b/lib/polarssl.c @@ -41,6 +41,9 @@ #include #include +#include +#include + #if POLARSSL_VERSION_NUMBER<0x01000000 /* Earlier versions of polarssl had no WANT_READ or WANT_WRITE, only TRY_AGAIN @@ -95,15 +98,14 @@ static void polarssl_debug(void *context, int level, char *line) static Curl_recv polarssl_recv; static Curl_send polarssl_send; -/* - * This function loads all the client/CA certificates and CRLs. Setup the TLS - * layer and do all necessary magic. - */ -CURLcode -Curl_polarssl_connect(struct connectdata *conn, - int sockindex) + +static CURLcode +polarssl_connect_step1(struct connectdata *conn, + int sockindex) { struct SessionHandle *data = conn->data; + struct ssl_connect_data* connssl = &conn->ssl[sockindex]; + bool sni = TRUE; /* default is SNI enabled */ int ret = -1; #ifdef ENABLE_IPV6 @@ -113,10 +115,6 @@ Curl_polarssl_connect(struct connectdata *conn, #endif void *old_session = NULL; size_t old_session_size = 0; - char buffer[1024]; - - if(conn->ssl[sockindex].state == ssl_connection_complete) - return CURLE_OK; /* PolarSSL only supports SSLv3 and TLSv1 */ if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) { @@ -126,16 +124,16 @@ Curl_polarssl_connect(struct connectdata *conn, else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3) sni = FALSE; /* SSLv3 has no SNI */ - havege_init(&conn->ssl[sockindex].hs); + havege_init(&connssl->hs); /* Load the trusted CA */ - memset(&conn->ssl[sockindex].cacert, 0, sizeof(x509_cert)); + memset(&connssl->cacert, 0, sizeof(x509_cert)); if(data->set.str[STRING_SSL_CAFILE]) { - ret = x509parse_crtfile(&conn->ssl[sockindex].cacert, + ret = x509parse_crtfile(&connssl->cacert, data->set.str[STRING_SSL_CAFILE]); - if(ret) { + if(ret<0) { failf(data, "Error reading ca cert file %s: -0x%04X", data->set.str[STRING_SSL_CAFILE], ret); @@ -145,10 +143,10 @@ Curl_polarssl_connect(struct connectdata *conn, } /* Load the client certificate */ - memset(&conn->ssl[sockindex].clicert, 0, sizeof(x509_cert)); + memset(&connssl->clicert, 0, sizeof(x509_cert)); if(data->set.str[STRING_CERT]) { - ret = x509parse_crtfile(&conn->ssl[sockindex].clicert, + ret = x509parse_crtfile(&connssl->clicert, data->set.str[STRING_CERT]); if(ret) { @@ -160,7 +158,7 @@ Curl_polarssl_connect(struct connectdata *conn, /* Load the client private key */ if(data->set.str[STRING_KEY]) { - ret = x509parse_keyfile(&conn->ssl[sockindex].rsa, + ret = x509parse_keyfile(&connssl->rsa, data->set.str[STRING_KEY], data->set.str[STRING_KEY_PASSWD]); @@ -172,10 +170,10 @@ Curl_polarssl_connect(struct connectdata *conn, } /* Load the CRL */ - memset(&conn->ssl[sockindex].crl, 0, sizeof(x509_crl)); + memset(&connssl->crl, 0, sizeof(x509_crl)); if(data->set.str[STRING_SSL_CRLFILE]) { - ret = x509parse_crlfile(&conn->ssl[sockindex].crl, + ret = x509parse_crlfile(&connssl->crl, data->set.str[STRING_SSL_CRLFILE]); if(ret) { @@ -185,64 +183,77 @@ Curl_polarssl_connect(struct connectdata *conn, } } - infof(data, "PolarSSL: Connected to %s:%d\n", + infof(data, "PolarSSL: Connecting to %s:%d\n", conn->host.name, conn->remote_port); - havege_init(&conn->ssl[sockindex].hs); - - if(ssl_init(&conn->ssl[sockindex].ssl)) { + if(ssl_init(&connssl->ssl)) { failf(data, "PolarSSL: ssl_init failed"); return CURLE_SSL_CONNECT_ERROR; } - ssl_set_endpoint(&conn->ssl[sockindex].ssl, SSL_IS_CLIENT); - ssl_set_authmode(&conn->ssl[sockindex].ssl, SSL_VERIFY_OPTIONAL); + ssl_set_endpoint(&connssl->ssl, SSL_IS_CLIENT); + ssl_set_authmode(&connssl->ssl, SSL_VERIFY_OPTIONAL); - ssl_set_rng(&conn->ssl[sockindex].ssl, HAVEGE_RANDOM, - &conn->ssl[sockindex].hs); - ssl_set_bio(&conn->ssl[sockindex].ssl, + ssl_set_rng(&connssl->ssl, HAVEGE_RANDOM, + &connssl->hs); + ssl_set_bio(&connssl->ssl, net_recv, &conn->sock[sockindex], net_send, &conn->sock[sockindex]); #if POLARSSL_VERSION_NUMBER<0x01000000 - ssl_set_ciphers(&conn->ssl[sockindex].ssl, ssl_default_ciphers); + ssl_set_ciphers(&connssl->ssl, ssl_default_ciphers); #else - ssl_set_ciphersuites(&conn->ssl[sockindex].ssl, ssl_default_ciphersuites); + ssl_set_ciphersuites(&connssl->ssl, ssl_default_ciphersuites); #endif if(!Curl_ssl_getsessionid(conn, &old_session, &old_session_size)) { - memcpy(&conn->ssl[sockindex].ssn, old_session, old_session_size); + memcpy(&connssl->ssn, old_session, old_session_size); infof(data, "PolarSSL re-using session\n"); } - ssl_set_session(&conn->ssl[sockindex].ssl, 1, 600, - &conn->ssl[sockindex].ssn); + ssl_set_session(&connssl->ssl, 1, 600, + &connssl->ssn); - ssl_set_ca_chain(&conn->ssl[sockindex].ssl, - &conn->ssl[sockindex].cacert, - &conn->ssl[sockindex].crl, + ssl_set_ca_chain(&connssl->ssl, + &connssl->cacert, + &connssl->crl, conn->host.name); - ssl_set_own_cert(&conn->ssl[sockindex].ssl, - &conn->ssl[sockindex].clicert, &conn->ssl[sockindex].rsa); + ssl_set_own_cert(&connssl->ssl, + &connssl->clicert, &connssl->rsa); if(!Curl_inet_pton(AF_INET, conn->host.name, &addr) && #ifdef ENABLE_IPV6 !Curl_inet_pton(AF_INET6, conn->host.name, &addr) && #endif - sni && ssl_set_hostname(&conn->ssl[sockindex].ssl, conn->host.name)) { + sni && ssl_set_hostname(&connssl->ssl, conn->host.name)) { infof(data, "WARNING: failed to configure " "server name indication (SNI) TLS extension\n"); } - infof(data, "PolarSSL: performing SSL/TLS handshake...\n"); - #ifdef POLARSSL_DEBUG - ssl_set_dbg(&conn->ssl[sockindex].ssl, polarssl_debug, data); + ssl_set_dbg(&connssl->ssl, polarssl_debug, data); #endif + connssl->connecting_state = ssl_connect_2; + + return CURLE_OK; +} + +static CURLcode +polarssl_connect_step2(struct connectdata *conn, + int sockindex) +{ + int ret; + struct SessionHandle *data = conn->data; + struct ssl_connect_data* connssl = &conn->ssl[sockindex]; + char buffer[1024]; + + conn->recv[sockindex] = polarssl_recv; + conn->send[sockindex] = polarssl_send; + for(;;) { - if(!(ret = ssl_handshake(&conn->ssl[sockindex].ssl))) + if(!(ret = ssl_handshake(&connssl->ssl))) break; else if(ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE) { @@ -250,27 +261,17 @@ Curl_polarssl_connect(struct connectdata *conn, return CURLE_SSL_CONNECT_ERROR; } else { - /* wait for data from server... */ - long timeout_ms = Curl_timeleft(data, NULL, TRUE); - - if(timeout_ms < 0) { - failf(data, "SSL connection timeout"); - return CURLE_OPERATION_TIMEDOUT; + if(ret == POLARSSL_ERR_NET_WANT_READ) { + connssl->connecting_state = ssl_connect_2_reading; + return CURLE_OK; } - - switch(Curl_socket_ready(conn->sock[sockindex], - CURL_SOCKET_BAD, timeout_ms)) { - case 0: - failf(data, "SSL handshake timeout"); - return CURLE_OPERATION_TIMEDOUT; - break; - case CURL_CSELECT_IN: - continue; - break; - default: - return CURLE_SSL_CONNECT_ERROR; - break; + if(ret == POLARSSL_ERR_NET_WANT_WRITE) { + connssl->connecting_state = ssl_connect_2_writing; + return CURLE_OK; } + failf(data, "SSL_connect failed with error %d.", ret); + return CURLE_SSL_CONNECT_ERROR; + } } @@ -299,7 +300,7 @@ Curl_polarssl_connect(struct connectdata *conn, if(ret & BADCERT_NOT_TRUSTED) failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED"); - return CURLE_SSL_CACERT; + return CURLE_PEER_FAILED_VERIFICATION; } if(conn->ssl[sockindex].ssl.peer_cert) { @@ -311,26 +312,56 @@ Curl_polarssl_connect(struct connectdata *conn, infof(data, "Dumping cert info:\n%s\n", buffer); } - conn->ssl[sockindex].state = ssl_connection_complete; - conn->recv[sockindex] = polarssl_recv; - conn->send[sockindex] = polarssl_send; + connssl->connecting_state = ssl_connect_3; + infof(data, "SSL connected\n"); + + return CURLE_OK; +} + +static CURLcode +polarssl_connect_step3(struct connectdata *conn, + int sockindex) +{ + CURLcode retcode = CURLE_OK; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct SessionHandle *data = conn->data; + void *old_ssl_sessionid = NULL; + ssl_session *our_ssl_sessionid = &conn->ssl[sockindex].ssn ; + int incache; + + DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); /* Save the current session data for possible re-use */ - { - void *new_session = malloc(sizeof(conn->ssl[sockindex].ssn)); + incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL)); + if(incache) { + if(old_ssl_sessionid != our_ssl_sessionid) { + infof(data, "old SSL session ID is stale, removing\n"); + Curl_ssl_delsessionid(conn, old_ssl_sessionid); + incache = FALSE; + } + } + if(!incache) { + void *new_session = malloc(sizeof(ssl_session)); if(new_session) { - memcpy(new_session, &conn->ssl[sockindex].ssn, - sizeof(conn->ssl[sockindex].ssn)); + memcpy(new_session, our_ssl_sessionid, + sizeof(ssl_session)); - if(old_session) - Curl_ssl_delsessionid(conn, old_session); + retcode = Curl_ssl_addsessionid(conn, new_session, + sizeof(ssl_session)); + } + else { + retcode = CURLE_OUT_OF_MEMORY; + } - return Curl_ssl_addsessionid(conn, new_session, - sizeof(conn->ssl[sockindex].ssn)); + if(retcode) { + failf(data, "failed to store ssl session"); + return retcode; } } + connssl->connecting_state = ssl_connect_done; + return CURLE_OK; } @@ -404,4 +435,141 @@ size_t Curl_polarssl_version(char *buffer, size_t size) return snprintf(buffer, size, "PolarSSL"); } +static CURLcode +polarssl_connect_common(struct connectdata *conn, + int sockindex, + bool nonblocking, + bool *done) +{ + CURLcode retcode; + struct SessionHandle *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + curl_socket_t sockfd = conn->sock[sockindex]; + long timeout_ms; + int what; + + /* check if the connection has already been established */ + if(ssl_connection_complete == connssl->state) { + *done = TRUE; + return CURLE_OK; + } + + if(ssl_connect_1==connssl->connecting_state) { + /* Find out how much more time we're allowed */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + retcode = polarssl_connect_step1(conn, sockindex); + if(retcode) + return retcode; + } + + while(ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state) { + + /* check allowed time left */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + /* if ssl is expecting something, check if it's available. */ + if(connssl->connecting_state == ssl_connect_2_reading + || connssl->connecting_state == ssl_connect_2_writing) { + + curl_socket_t writefd = ssl_connect_2_writing== + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + curl_socket_t readfd = ssl_connect_2_reading== + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + + what = Curl_socket_ready(readfd, writefd, nonblocking?0:timeout_ms); + if(what < 0) { + /* fatal error */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + return CURLE_SSL_CONNECT_ERROR; + } + else if(0 == what) { + if(nonblocking) { + *done = FALSE; + return CURLE_OK; + } + else { + /* timeout */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + } + /* socket is readable or writable */ + } + + /* Run transaction, and return to the caller if it failed or if + * this connection is part of a multi handle and this loop would + * execute again. This permits the owner of a multi handle to + * abort a connection attempt before step2 has completed while + * ensuring that a client using select() or epoll() will always + * have a valid fdset to wait on. + */ + retcode = polarssl_connect_step2(conn, sockindex); + if(retcode || (nonblocking && + (ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state))) + return retcode; + + } /* repeat step2 until all transactions are done. */ + + if(ssl_connect_3==connssl->connecting_state) { + retcode = polarssl_connect_step3(conn, sockindex); + if(retcode) + return retcode; + } + + if(ssl_connect_done==connssl->connecting_state) { + connssl->state = ssl_connection_complete; + conn->recv[sockindex] = polarssl_recv; + conn->send[sockindex] = polarssl_send; + *done = TRUE; + } + else + *done = FALSE; + + /* Reset our connect state machine */ + connssl->connecting_state = ssl_connect_1; + + return CURLE_OK; +} + +CURLcode +Curl_polarssl_connect_nonblocking(struct connectdata *conn, + int sockindex, + bool *done) +{ + return polarssl_connect_common(conn, sockindex, TRUE, done); +} + + +CURLcode +Curl_polarssl_connect(struct connectdata *conn, + int sockindex) +{ + CURLcode retcode; + bool done = FALSE; + + retcode = polarssl_connect_common(conn, sockindex, FALSE, &done); + if(retcode) + return retcode; + + DEBUGASSERT(done); + + return CURLE_OK; +} + #endif -- cgit v1.2.1 From 118e73306d142a3146356ebf24e2446a65e9fe6f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 6 Apr 2012 14:44:36 +0200 Subject: PolarSSL: include version number in version string Previously it would say PolarSSL only, now it says PolarSSL/1.1.0 in the same style other libs and components do. --- lib/polarssl.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/polarssl.c') diff --git a/lib/polarssl.c b/lib/polarssl.c index c890a07db..15a3e15b5 100644 --- a/lib/polarssl.c +++ b/lib/polarssl.c @@ -432,7 +432,9 @@ void Curl_polarssl_session_free(void *ptr) size_t Curl_polarssl_version(char *buffer, size_t size) { - return snprintf(buffer, size, "PolarSSL"); + unsigned int version = version_get_number(); + return snprintf(buffer, size, "PolarSSL/%d.%d.%d", version>>24, + (version>>16)&0xff, (version>>8)&0xff); } static CURLcode -- cgit v1.2.1 From 376b4d48feea9da98eda15ddf05c86729d9dc3f1 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 6 Apr 2012 15:10:59 +0200 Subject: PolarSSL: correct return code for CRL matches When a server certificate matches one in the given CRL file, the code now returns CURLE_SSL_CACERT as test case 313 expects and verifies. --- lib/polarssl.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/polarssl.c') diff --git a/lib/polarssl.c b/lib/polarssl.c index 15a3e15b5..39816baf0 100644 --- a/lib/polarssl.c +++ b/lib/polarssl.c @@ -291,8 +291,10 @@ polarssl_connect_step2(struct connectdata *conn, if(ret & BADCERT_EXPIRED) failf(data, "Cert verify failed: BADCERT_EXPIRED\n"); - if(ret & BADCERT_REVOKED) + if(ret & BADCERT_REVOKED) { failf(data, "Cert verify failed: BADCERT_REVOKED"); + return CURLE_SSL_CACERT; + } if(ret & BADCERT_CN_MISMATCH) failf(data, "Cert verify failed: BADCERT_CN_MISMATCH"); -- cgit v1.2.1 From 6085ca2aeddb38e4d5f24c47bd98111b236cf384 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Thu, 14 Jun 2012 13:32:05 +0200 Subject: Fix bad failf() and info() usage Calls to failf() are not supposed to provide trailing newline. Calls to infof() must provide trailing newline. Fixed 30 or so strings. --- lib/polarssl.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lib/polarssl.c') diff --git a/lib/polarssl.c b/lib/polarssl.c index 39816baf0..a2f61d23d 100644 --- a/lib/polarssl.c +++ b/lib/polarssl.c @@ -6,6 +6,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2010, 2011, Hoi-Ho Chan, + * Copyright (C) 2012, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -90,7 +91,7 @@ static void polarssl_debug(void *context, int level, char *line) data = (struct SessionHandle *)context; - infof(data, "%s", line); + infof(data, "%s\n", line); } #else #endif @@ -289,7 +290,7 @@ polarssl_connect_step2(struct connectdata *conn, if(ret && data->set.ssl.verifypeer) { if(ret & BADCERT_EXPIRED) - failf(data, "Cert verify failed: BADCERT_EXPIRED\n"); + failf(data, "Cert verify failed: BADCERT_EXPIRED"); if(ret & BADCERT_REVOKED) { failf(data, "Cert verify failed: BADCERT_REVOKED"); -- cgit v1.2.1 From 1394cad30fcac7eb21adb9158dfcfab10e9f53d4 Mon Sep 17 00:00:00 2001 From: Oscar Koeroo Date: Sat, 3 Nov 2012 02:06:51 +0100 Subject: SSL: Several SSL-backend related fixes axTLS: This will make the axTLS backend perform the RFC2818 checks, honoring the VERIFYHOST setting similar to the OpenSSL backend. Generic for OpenSSL and axTLS: Move the hostcheck and cert_hostcheck functions from the lib/ssluse.c files to make them genericly available for both the OpenSSL, axTLS and other SSL backends. They are now in the new lib/hostcheck.c file. CyaSSL: CyaSSL now also has the RFC2818 checks enabled by default. There is a limitation that the verifyhost can not be enabled exclusively on the Subject CN field comparison. This SSL backend will thus behave like the NSS and the GnuTLS (meaning: RFC2818 ok, or bust). In other words: setting verifyhost to 0 or 1 will disable the Subject Alt Names checks too. Schannel: Updated the schannel information messages: Split the IP address usage message from the verifyhost setting and changed the message about disabling SNI (Server Name Indication, used in HTTP virtual hosting) into a message stating that the Subject Alternative Names checks are being disabled when verifyhost is set to 0 or 1. As a side effect of switching off the RFC2818 related servername checks with SCH_CRED_NO_SERVERNAME_CHECK (http://msdn.microsoft.com/en-us/library/aa923430.aspx) the SNI feature is being disabled. This effect is not documented in MSDN, but Wireshark output clearly shows the effect (details on the libcurl maillist). PolarSSL: Fix the prototype change in PolarSSL of ssl_set_session() and the move of the peer_cert from the ssl_context to the ssl_session. Found this change in the PolarSSL SVN between r1316 and r1317 where the POLARSSL_VERSION_NUMBER was at 0x01010100. But to accommodate the Ubuntu PolarSSL version 1.1.4 the check is to discriminate between lower then PolarSSL version 1.2.0 and 1.2.0 and higher. Note: The PolarSSL SVN trunk jumped from version 1.1.1 to 1.2.0. Generic: All the SSL backends are fixed and checked to work with the ssl.verifyhost as a boolean, which is an internal API change. --- lib/polarssl.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'lib/polarssl.c') diff --git a/lib/polarssl.c b/lib/polarssl.c index a2f61d23d..b20b4a397 100644 --- a/lib/polarssl.c +++ b/lib/polarssl.c @@ -212,8 +212,15 @@ polarssl_connect_step1(struct connectdata *conn, infof(data, "PolarSSL re-using session\n"); } +/* PolarSSL SVN revision r1316 to r1317, matching <1.2.0 is to cover Ubuntu's + 1.1.4 version and the like */ +#if POLARSSL_VERSION_NUMBER<0x01020000 ssl_set_session(&connssl->ssl, 1, 600, &connssl->ssn); +#else + ssl_set_session(&connssl->ssl, + &connssl->ssn); +#endif ssl_set_ca_chain(&connssl->ssl, &connssl->cacert, @@ -306,12 +313,25 @@ polarssl_connect_step2(struct connectdata *conn, return CURLE_PEER_FAILED_VERIFICATION; } +/* PolarSSL SVN revision r1316 to r1317, matching <1.2.0 is to cover Ubuntu's + 1.1.4 version and the like */ +#if POLARSSL_VERSION_NUMBER<0x01020000 if(conn->ssl[sockindex].ssl.peer_cert) { +#else + if(ssl_get_peer_cert(&(connssl->ssl))) { +#endif /* If the session was resumed, there will be no peer certs */ memset(buffer, 0, sizeof(buffer)); +/* PolarSSL SVN revision r1316 to r1317, matching <1.2.0 is to cover Ubuntu's + 1.1.4 version and the like */ +#if POLARSSL_VERSION_NUMBER<0x01020000 if(x509parse_cert_info(buffer, sizeof(buffer), (char *)"* ", conn->ssl[sockindex].ssl.peer_cert) != -1) +#else + if(x509parse_cert_info(buffer, sizeof(buffer), (char *)"* ", + ssl_get_peer_cert(&(connssl->ssl))) != -1) +#endif infof(data, "Dumping cert info:\n%s\n", buffer); } -- cgit v1.2.1