Loading lib/axtls.c +171 −81 Original line number Diff line number Diff line Loading @@ -41,26 +41,12 @@ #define _MPRINTF_REPLACE /* use our functions only */ #include <curl/mprintf.h> #include "curl_memory.h" #include <unistd.h> /* The last #include file should be: */ #include "memdebug.h" #include "hostcheck.h" /* SSL_read is opied from axTLS compat layer */ static int SSL_read(SSL *ssl, void *buf, int num) { uint8_t *read_buf; int ret; while((ret = ssl_read(ssl, &read_buf)) == SSL_OK); if(ret > SSL_OK) { memcpy(buf, read_buf, ret > num ? num : ret); } return ret; } /* Global axTLS init, called from Curl_ssl_init() */ int Curl_axtls_init(void) { Loading Loading @@ -131,24 +117,24 @@ static CURLcode map_error_to_curl(int axtls_err) static Curl_recv axtls_recv; static Curl_send axtls_send; static void free_ssl_structs(SSL_CTX *ssl_ctx, SSL *ssl) static void free_ssl_structs(struct ssl_connect_data *connssl) { if(ssl) { ssl_free (ssl); if(connssl->ssl) { ssl_free (connssl->ssl); connssl->ssl = NULL; } if(ssl_ctx) { ssl_ctx_free(ssl_ctx); if(connssl->ssl_ctx) { ssl_ctx_free(connssl->ssl_ctx); connssl->ssl_ctx = NULL; } } /* * This function is called after the TCP connect has completed. Setup the TLS * layer and do all necessary magic. * For both blocking and non-blocking connects, this function sets up the * ssl context and state. This function is called after the TCP connect * has completed. */ CURLcode Curl_axtls_connect(struct connectdata *conn, int sockindex) static CURLcode connect_prep(struct connectdata *conn, int sockindex) { struct SessionHandle *data = conn->data; SSL_CTX *ssl_ctx; Loading @@ -158,14 +144,13 @@ Curl_axtls_connect(struct connectdata *conn, int i, ssl_fcn_return; const uint8_t *ssl_sessionid; size_t ssl_idsize; const char *peer_CN; uint32_t dns_altname_index; const char *dns_altname; int8_t found_subject_alt_names = 0; int8_t found_subject_alt_name_matching_conn = 0; /* Assuming users will not compile in custom key/cert to axTLS */ uint32_t client_option = SSL_NO_DEFAULT_KEY|SSL_SERVER_VERIFY_LATER; /* Assuming users will not compile in custom key/cert to axTLS. * Also, even for blocking connects, use axTLS non-blocking feature. */ uint32_t client_option = SSL_NO_DEFAULT_KEY | SSL_SERVER_VERIFY_LATER | SSL_CONNECT_IN_PARTS; if(conn->ssl[sockindex].state == ssl_connection_complete) /* to make us tolerant against being called more than once for the Loading Loading @@ -194,6 +179,9 @@ Curl_axtls_connect(struct connectdata *conn, return CURLE_SSL_CONNECT_ERROR; } conn->ssl[sockindex].ssl_ctx = ssl_ctx; conn->ssl[sockindex].ssl = NULL; /* Load the trusted CA cert bundle file */ if(data->set.ssl.CAfile) { if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, data->set.ssl.CAfile, NULL) Loading @@ -201,8 +189,6 @@ Curl_axtls_connect(struct connectdata *conn, infof(data, "error reading ca cert file %s \n", data->set.ssl.CAfile); if(data->set.ssl.verifypeer) { Curl_axtls_close(conn, sockindex); free_ssl_structs(ssl_ctx, ssl); return CURLE_SSL_CACERT_BADFILE; } } Loading Loading @@ -236,8 +222,6 @@ Curl_axtls_connect(struct connectdata *conn, if(cert_types[i] == 0) { failf(data, "%s is not x509 or pkcs12 format", data->set.str[STRING_CERT]); Curl_axtls_close(conn, sockindex); free_ssl_structs(ssl_ctx, ssl); return CURLE_SSL_CERTPROBLEM; } } Loading @@ -262,8 +246,6 @@ Curl_axtls_connect(struct connectdata *conn, if(key_types[i] == 0) { failf(data, "Failure: %s is not a supported key file", data->set.str[STRING_KEY]); Curl_axtls_close(conn, sockindex); free_ssl_structs(ssl_ctx, ssl); return CURLE_SSL_CONNECT_ERROR; } } Loading @@ -284,15 +266,25 @@ Curl_axtls_connect(struct connectdata *conn, else ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0); /* Check to make sure handshake was ok. */ ssl_fcn_return = ssl_handshake_status(ssl); if(ssl_fcn_return != SSL_OK) { Curl_axtls_close(conn, sockindex); free_ssl_structs(ssl_ctx, ssl); ssl_display_error(ssl_fcn_return); /* goes to stdout. */ return map_error_to_curl(ssl_fcn_return); conn->ssl[sockindex].ssl = ssl; return CURLE_OK; } infof (data, "handshake completed successfully\n"); /* * For both blocking and non-blocking connects, this function finalizes the * SSL connection. */ static CURLcode connect_finish(struct connectdata *conn, int sockindex) { struct SessionHandle *data = conn->data; SSL *ssl = conn->ssl[sockindex].ssl; const uint8_t *ssl_sessionid; size_t ssl_idsize; const char *peer_CN; uint32_t dns_altname_index; const char *dns_altname; int8_t found_subject_alt_names = 0; int8_t found_subject_alt_name_matching_conn = 0; /* Here, gtls.c gets the peer certificates and fails out depending on * settings in "data." axTLS api doesn't have get cert chain fcn, so omit? Loading @@ -302,9 +294,8 @@ Curl_axtls_connect(struct connectdata *conn, if(data->set.ssl.verifypeer) { if(ssl_verify_cert(ssl) != SSL_OK) { Curl_axtls_close(conn, sockindex); free_ssl_structs(ssl_ctx, ssl); failf(data, "server cert verify failed"); return CURLE_SSL_CONNECT_ERROR; return CURLE_PEER_FAILED_VERIFICATION; } } else Loading @@ -321,7 +312,6 @@ Curl_axtls_connect(struct connectdata *conn, * this, but a couple fields are available. */ /* There is no (DNS) Altnames count in the version 1.4.8 API. There is a risk of an inifite loop */ for(dns_altname_index = 0; ; dns_altname_index++) { Loading @@ -344,13 +334,13 @@ Curl_axtls_connect(struct connectdata *conn, if(data->set.ssl.verifyhost) { /* Break connection ! */ Curl_axtls_close(conn, sockindex); free_ssl_structs(ssl_ctx, ssl); failf(data, "\tsubjectAltName(s) do not match %s\n", conn->host.dispname); return CURLE_PEER_FAILED_VERIFICATION; } else infof(data, "\tsubjectAltName(s) do not match %s\n", conn->host.dispname); } else if(found_subject_alt_names == 0) { /* Per RFC2818, when no Subject Alt Names were available, examine the peer Loading @@ -359,7 +349,6 @@ Curl_axtls_connect(struct connectdata *conn, if(peer_CN == NULL) { if(data->set.ssl.verifyhost) { Curl_axtls_close(conn, sockindex); free_ssl_structs(ssl_ctx, ssl); failf(data, "unable to obtain common name from peer certificate"); return CURLE_PEER_FAILED_VERIFICATION; } Loading @@ -371,7 +360,6 @@ Curl_axtls_connect(struct connectdata *conn, if(data->set.ssl.verifyhost) { /* Break connection ! */ Curl_axtls_close(conn, sockindex); free_ssl_structs(ssl_ctx, ssl); failf(data, "\tcommon name \"%s\" does not match \"%s\"\n", peer_CN, conn->host.dispname); return CURLE_PEER_FAILED_VERIFICATION; Loading @@ -385,8 +373,6 @@ Curl_axtls_connect(struct connectdata *conn, /* General housekeeping */ conn->ssl[sockindex].state = ssl_connection_complete; conn->ssl[sockindex].ssl = ssl; conn->ssl[sockindex].ssl_ctx = ssl_ctx; conn->recv[sockindex] = axtls_recv; conn->send[sockindex] = axtls_send; Loading @@ -400,6 +386,107 @@ Curl_axtls_connect(struct connectdata *conn, return CURLE_OK; } /* * Use axTLS's non-blocking connection feature to open an SSL connection. * This is called after a TCP connection is already established. */ CURLcode Curl_axtls_connect_nonblocking( struct connectdata *conn, int sockindex, bool *done) { CURLcode conn_step; int ssl_fcn_return; *done = FALSE; /* connectdata is calloc'd and connecting_state is only changed in this function, so this is safe, as the state is effectively initialized. */ if(conn->ssl[sockindex].connecting_state == ssl_connect_1) { conn_step = connect_prep(conn, sockindex); if(conn_step != CURLE_OK) { Curl_axtls_close(conn, sockindex); return conn_step; } conn->ssl[sockindex].connecting_state = ssl_connect_2; } if(conn->ssl[sockindex].connecting_state == ssl_connect_2) { /* Check to make sure handshake was ok. */ if(ssl_handshake_status(conn->ssl[sockindex].ssl) != SSL_OK) { ssl_fcn_return = ssl_read(conn->ssl[sockindex].ssl, NULL); if(ssl_fcn_return < 0) { Curl_axtls_close(conn, sockindex); ssl_display_error(ssl_fcn_return); /* goes to stdout. */ return map_error_to_curl(ssl_fcn_return); } else { return CURLE_OK; /* Return control to caller for retries */ } } infof (conn->data, "handshake completed successfully\n"); conn->ssl[sockindex].connecting_state = ssl_connect_3; } if(conn->ssl[sockindex].connecting_state == ssl_connect_3) { conn_step = connect_finish(conn, sockindex); if(conn_step != CURLE_OK) { Curl_axtls_close(conn, sockindex); return conn_step; } /* Reset connect state */ conn->ssl[sockindex].connecting_state = ssl_connect_1; *done = TRUE; return CURLE_OK; } /* Unrecognized state. Things are very bad. */ conn->ssl[sockindex].state = ssl_connection_none; conn->ssl[sockindex].connecting_state = ssl_connect_1; /* Return value perhaps not strictly correct, but distinguishes the issue.*/ return CURLE_BAD_FUNCTION_ARGUMENT; } /* * This function is called after the TCP connect has completed. Setup the TLS * layer and do all necessary magic for a blocking connect. */ CURLcode Curl_axtls_connect(struct connectdata *conn, int sockindex) { CURLcode conn_step = connect_prep(conn, sockindex); int ssl_fcn_return; SSL *ssl = conn->ssl[sockindex].ssl; if(conn_step != CURLE_OK) { Curl_axtls_close(conn, sockindex); return conn_step; } /* Check to make sure handshake was ok. */ while(ssl_handshake_status(ssl) != SSL_OK) { ssl_fcn_return = ssl_read(ssl, NULL); if(ssl_fcn_return < 0) { Curl_axtls_close(conn, sockindex); ssl_display_error(ssl_fcn_return); /* goes to stdout. */ return map_error_to_curl(ssl_fcn_return); } usleep(10000); } infof (conn->data, "handshake completed successfully\n"); conn_step = connect_finish(conn, sockindex); if(conn_step != CURLE_OK) { Curl_axtls_close(conn, sockindex); return conn_step; } return CURLE_OK; } /* return number of sent (non-SSL) bytes */ static ssize_t axtls_send(struct connectdata *conn, Loading Loading @@ -433,7 +520,7 @@ void Curl_axtls_close(struct connectdata *conn, int sockindex) struct ssl_connect_data *connssl = &conn->ssl[sockindex]; infof(conn->data, " Curl_axtls_close\n"); if(connssl->ssl) { /* line from ssluse.c: (void)SSL_shutdown(connssl->ssl); axTLS compat layer does nothing for SSL_shutdown */ Loading @@ -441,13 +528,7 @@ void Curl_axtls_close(struct connectdata *conn, int sockindex) equivalent. ssl_free and ssl_ctx_free close things. SSL_set_connect_state(connssl->handle); */ ssl_free (connssl->ssl); connssl->ssl = NULL; } if(connssl->ssl_ctx) { ssl_ctx_free (connssl->ssl_ctx); connssl->ssl_ctx = NULL; } free_ssl_structs(connssl); } /* Loading @@ -462,8 +543,7 @@ int Curl_axtls_shutdown(struct connectdata *conn, int sockindex) int retval = 0; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct SessionHandle *data = conn->data; char buf[120]; /* We will use this for the OpenSSL error buffer, so it has to be at least 120 bytes long. */ uint8_t *buf; ssize_t nread; infof(conn->data, " Curl_axtls_shutdown\n"); Loading @@ -483,9 +563,10 @@ int Curl_axtls_shutdown(struct connectdata *conn, int sockindex) CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT); if(what > 0) { /* Something to read, let's do it and hope that it is the close notify alert from the server */ nread = (ssize_t)SSL_read(conn->ssl[sockindex].ssl, buf, sizeof(buf)); notify alert from the server. buf is managed internally by axTLS and will be released upon calling ssl_free via free_ssl_structs. */ nread = (ssize_t)ssl_read(connssl->ssl, &buf); if(nread < SSL_OK) { failf(data, "close notify alert not received during shutdown"); Loading @@ -502,8 +583,7 @@ int Curl_axtls_shutdown(struct connectdata *conn, int sockindex) retval = -1; } ssl_free (connssl->ssl); connssl->ssl = NULL; free_ssl_structs(connssl); } return retval; } Loading @@ -516,26 +596,36 @@ static ssize_t axtls_recv(struct connectdata *conn, /* connection data */ { struct ssl_connect_data *connssl = &conn->ssl[num]; ssize_t ret = 0; uint8_t *read_buf; infof(conn->data, " axtls_recv\n"); *err = CURLE_OK; if(connssl) { ret = (ssize_t)SSL_read(conn->ssl[num].ssl, buf, (int)buffersize); /* axTLS isn't terribly generous about error reporting */ ret = ssl_read(connssl->ssl, &read_buf); if(ret > SSL_OK) { /* ssl_read returns SSL_OK if there is more data to read, so if it is larger, then all data has been read already. */ memcpy(buf, read_buf, (size_t)ret > buffersize ? buffersize : (size_t)ret); } else if(ret == SSL_OK) { /* more data to be read, signal caller to call again */ *err = CURLE_AGAIN; ret = -1; } else if(ret == -3) { /* With patched axTLS, SSL_CLOSE_NOTIFY=-3. Hard-coding until axTLS team approves proposed fix. */ if(ret == -3 ) { Curl_axtls_close(conn, num); } else if(ret < 0) { failf(conn->data, "axTLS recv error (%d)", (int)ret); else { failf(conn->data, "axTLS recv error (%d)", ret); *err = map_error_to_curl(ret); return -1; ret = -1; } } *err = CURLE_OK; return ret; } Loading lib/axtls.h +5 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,10 @@ int Curl_axtls_init(void); int Curl_axtls_cleanup(void); CURLcode Curl_axtls_connect(struct connectdata *conn, int sockindex); CURLcode Curl_axtls_connect_nonblocking( struct connectdata *conn, int sockindex, bool *done); /* tell axTLS to close down all open information regarding connections (and thus session ID caching etc) */ Loading @@ -47,6 +51,7 @@ int Curl_axtls_check_cxn(struct connectdata *conn); #define curlssl_init Curl_axtls_init #define curlssl_cleanup Curl_axtls_cleanup #define curlssl_connect Curl_axtls_connect #define curlssl_connect_nonblocking Curl_axtls_connect_nonblocking #define curlssl_session_free(x) Curl_axtls_session_free(x) #define curlssl_close_all Curl_axtls_close_all #define curlssl_close Curl_axtls_close Loading lib/urldata.h +1 −0 Original line number Diff line number Diff line Loading @@ -325,6 +325,7 @@ struct ssl_connect_data { #ifdef USE_AXTLS SSL_CTX* ssl_ctx; SSL* ssl; ssl_connect_state connecting_state; #endif /* USE_AXTLS */ #ifdef USE_SCHANNEL struct curl_schannel_cred *cred; Loading Loading
lib/axtls.c +171 −81 Original line number Diff line number Diff line Loading @@ -41,26 +41,12 @@ #define _MPRINTF_REPLACE /* use our functions only */ #include <curl/mprintf.h> #include "curl_memory.h" #include <unistd.h> /* The last #include file should be: */ #include "memdebug.h" #include "hostcheck.h" /* SSL_read is opied from axTLS compat layer */ static int SSL_read(SSL *ssl, void *buf, int num) { uint8_t *read_buf; int ret; while((ret = ssl_read(ssl, &read_buf)) == SSL_OK); if(ret > SSL_OK) { memcpy(buf, read_buf, ret > num ? num : ret); } return ret; } /* Global axTLS init, called from Curl_ssl_init() */ int Curl_axtls_init(void) { Loading Loading @@ -131,24 +117,24 @@ static CURLcode map_error_to_curl(int axtls_err) static Curl_recv axtls_recv; static Curl_send axtls_send; static void free_ssl_structs(SSL_CTX *ssl_ctx, SSL *ssl) static void free_ssl_structs(struct ssl_connect_data *connssl) { if(ssl) { ssl_free (ssl); if(connssl->ssl) { ssl_free (connssl->ssl); connssl->ssl = NULL; } if(ssl_ctx) { ssl_ctx_free(ssl_ctx); if(connssl->ssl_ctx) { ssl_ctx_free(connssl->ssl_ctx); connssl->ssl_ctx = NULL; } } /* * This function is called after the TCP connect has completed. Setup the TLS * layer and do all necessary magic. * For both blocking and non-blocking connects, this function sets up the * ssl context and state. This function is called after the TCP connect * has completed. */ CURLcode Curl_axtls_connect(struct connectdata *conn, int sockindex) static CURLcode connect_prep(struct connectdata *conn, int sockindex) { struct SessionHandle *data = conn->data; SSL_CTX *ssl_ctx; Loading @@ -158,14 +144,13 @@ Curl_axtls_connect(struct connectdata *conn, int i, ssl_fcn_return; const uint8_t *ssl_sessionid; size_t ssl_idsize; const char *peer_CN; uint32_t dns_altname_index; const char *dns_altname; int8_t found_subject_alt_names = 0; int8_t found_subject_alt_name_matching_conn = 0; /* Assuming users will not compile in custom key/cert to axTLS */ uint32_t client_option = SSL_NO_DEFAULT_KEY|SSL_SERVER_VERIFY_LATER; /* Assuming users will not compile in custom key/cert to axTLS. * Also, even for blocking connects, use axTLS non-blocking feature. */ uint32_t client_option = SSL_NO_DEFAULT_KEY | SSL_SERVER_VERIFY_LATER | SSL_CONNECT_IN_PARTS; if(conn->ssl[sockindex].state == ssl_connection_complete) /* to make us tolerant against being called more than once for the Loading Loading @@ -194,6 +179,9 @@ Curl_axtls_connect(struct connectdata *conn, return CURLE_SSL_CONNECT_ERROR; } conn->ssl[sockindex].ssl_ctx = ssl_ctx; conn->ssl[sockindex].ssl = NULL; /* Load the trusted CA cert bundle file */ if(data->set.ssl.CAfile) { if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, data->set.ssl.CAfile, NULL) Loading @@ -201,8 +189,6 @@ Curl_axtls_connect(struct connectdata *conn, infof(data, "error reading ca cert file %s \n", data->set.ssl.CAfile); if(data->set.ssl.verifypeer) { Curl_axtls_close(conn, sockindex); free_ssl_structs(ssl_ctx, ssl); return CURLE_SSL_CACERT_BADFILE; } } Loading Loading @@ -236,8 +222,6 @@ Curl_axtls_connect(struct connectdata *conn, if(cert_types[i] == 0) { failf(data, "%s is not x509 or pkcs12 format", data->set.str[STRING_CERT]); Curl_axtls_close(conn, sockindex); free_ssl_structs(ssl_ctx, ssl); return CURLE_SSL_CERTPROBLEM; } } Loading @@ -262,8 +246,6 @@ Curl_axtls_connect(struct connectdata *conn, if(key_types[i] == 0) { failf(data, "Failure: %s is not a supported key file", data->set.str[STRING_KEY]); Curl_axtls_close(conn, sockindex); free_ssl_structs(ssl_ctx, ssl); return CURLE_SSL_CONNECT_ERROR; } } Loading @@ -284,15 +266,25 @@ Curl_axtls_connect(struct connectdata *conn, else ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0); /* Check to make sure handshake was ok. */ ssl_fcn_return = ssl_handshake_status(ssl); if(ssl_fcn_return != SSL_OK) { Curl_axtls_close(conn, sockindex); free_ssl_structs(ssl_ctx, ssl); ssl_display_error(ssl_fcn_return); /* goes to stdout. */ return map_error_to_curl(ssl_fcn_return); conn->ssl[sockindex].ssl = ssl; return CURLE_OK; } infof (data, "handshake completed successfully\n"); /* * For both blocking and non-blocking connects, this function finalizes the * SSL connection. */ static CURLcode connect_finish(struct connectdata *conn, int sockindex) { struct SessionHandle *data = conn->data; SSL *ssl = conn->ssl[sockindex].ssl; const uint8_t *ssl_sessionid; size_t ssl_idsize; const char *peer_CN; uint32_t dns_altname_index; const char *dns_altname; int8_t found_subject_alt_names = 0; int8_t found_subject_alt_name_matching_conn = 0; /* Here, gtls.c gets the peer certificates and fails out depending on * settings in "data." axTLS api doesn't have get cert chain fcn, so omit? Loading @@ -302,9 +294,8 @@ Curl_axtls_connect(struct connectdata *conn, if(data->set.ssl.verifypeer) { if(ssl_verify_cert(ssl) != SSL_OK) { Curl_axtls_close(conn, sockindex); free_ssl_structs(ssl_ctx, ssl); failf(data, "server cert verify failed"); return CURLE_SSL_CONNECT_ERROR; return CURLE_PEER_FAILED_VERIFICATION; } } else Loading @@ -321,7 +312,6 @@ Curl_axtls_connect(struct connectdata *conn, * this, but a couple fields are available. */ /* There is no (DNS) Altnames count in the version 1.4.8 API. There is a risk of an inifite loop */ for(dns_altname_index = 0; ; dns_altname_index++) { Loading @@ -344,13 +334,13 @@ Curl_axtls_connect(struct connectdata *conn, if(data->set.ssl.verifyhost) { /* Break connection ! */ Curl_axtls_close(conn, sockindex); free_ssl_structs(ssl_ctx, ssl); failf(data, "\tsubjectAltName(s) do not match %s\n", conn->host.dispname); return CURLE_PEER_FAILED_VERIFICATION; } else infof(data, "\tsubjectAltName(s) do not match %s\n", conn->host.dispname); } else if(found_subject_alt_names == 0) { /* Per RFC2818, when no Subject Alt Names were available, examine the peer Loading @@ -359,7 +349,6 @@ Curl_axtls_connect(struct connectdata *conn, if(peer_CN == NULL) { if(data->set.ssl.verifyhost) { Curl_axtls_close(conn, sockindex); free_ssl_structs(ssl_ctx, ssl); failf(data, "unable to obtain common name from peer certificate"); return CURLE_PEER_FAILED_VERIFICATION; } Loading @@ -371,7 +360,6 @@ Curl_axtls_connect(struct connectdata *conn, if(data->set.ssl.verifyhost) { /* Break connection ! */ Curl_axtls_close(conn, sockindex); free_ssl_structs(ssl_ctx, ssl); failf(data, "\tcommon name \"%s\" does not match \"%s\"\n", peer_CN, conn->host.dispname); return CURLE_PEER_FAILED_VERIFICATION; Loading @@ -385,8 +373,6 @@ Curl_axtls_connect(struct connectdata *conn, /* General housekeeping */ conn->ssl[sockindex].state = ssl_connection_complete; conn->ssl[sockindex].ssl = ssl; conn->ssl[sockindex].ssl_ctx = ssl_ctx; conn->recv[sockindex] = axtls_recv; conn->send[sockindex] = axtls_send; Loading @@ -400,6 +386,107 @@ Curl_axtls_connect(struct connectdata *conn, return CURLE_OK; } /* * Use axTLS's non-blocking connection feature to open an SSL connection. * This is called after a TCP connection is already established. */ CURLcode Curl_axtls_connect_nonblocking( struct connectdata *conn, int sockindex, bool *done) { CURLcode conn_step; int ssl_fcn_return; *done = FALSE; /* connectdata is calloc'd and connecting_state is only changed in this function, so this is safe, as the state is effectively initialized. */ if(conn->ssl[sockindex].connecting_state == ssl_connect_1) { conn_step = connect_prep(conn, sockindex); if(conn_step != CURLE_OK) { Curl_axtls_close(conn, sockindex); return conn_step; } conn->ssl[sockindex].connecting_state = ssl_connect_2; } if(conn->ssl[sockindex].connecting_state == ssl_connect_2) { /* Check to make sure handshake was ok. */ if(ssl_handshake_status(conn->ssl[sockindex].ssl) != SSL_OK) { ssl_fcn_return = ssl_read(conn->ssl[sockindex].ssl, NULL); if(ssl_fcn_return < 0) { Curl_axtls_close(conn, sockindex); ssl_display_error(ssl_fcn_return); /* goes to stdout. */ return map_error_to_curl(ssl_fcn_return); } else { return CURLE_OK; /* Return control to caller for retries */ } } infof (conn->data, "handshake completed successfully\n"); conn->ssl[sockindex].connecting_state = ssl_connect_3; } if(conn->ssl[sockindex].connecting_state == ssl_connect_3) { conn_step = connect_finish(conn, sockindex); if(conn_step != CURLE_OK) { Curl_axtls_close(conn, sockindex); return conn_step; } /* Reset connect state */ conn->ssl[sockindex].connecting_state = ssl_connect_1; *done = TRUE; return CURLE_OK; } /* Unrecognized state. Things are very bad. */ conn->ssl[sockindex].state = ssl_connection_none; conn->ssl[sockindex].connecting_state = ssl_connect_1; /* Return value perhaps not strictly correct, but distinguishes the issue.*/ return CURLE_BAD_FUNCTION_ARGUMENT; } /* * This function is called after the TCP connect has completed. Setup the TLS * layer and do all necessary magic for a blocking connect. */ CURLcode Curl_axtls_connect(struct connectdata *conn, int sockindex) { CURLcode conn_step = connect_prep(conn, sockindex); int ssl_fcn_return; SSL *ssl = conn->ssl[sockindex].ssl; if(conn_step != CURLE_OK) { Curl_axtls_close(conn, sockindex); return conn_step; } /* Check to make sure handshake was ok. */ while(ssl_handshake_status(ssl) != SSL_OK) { ssl_fcn_return = ssl_read(ssl, NULL); if(ssl_fcn_return < 0) { Curl_axtls_close(conn, sockindex); ssl_display_error(ssl_fcn_return); /* goes to stdout. */ return map_error_to_curl(ssl_fcn_return); } usleep(10000); } infof (conn->data, "handshake completed successfully\n"); conn_step = connect_finish(conn, sockindex); if(conn_step != CURLE_OK) { Curl_axtls_close(conn, sockindex); return conn_step; } return CURLE_OK; } /* return number of sent (non-SSL) bytes */ static ssize_t axtls_send(struct connectdata *conn, Loading Loading @@ -433,7 +520,7 @@ void Curl_axtls_close(struct connectdata *conn, int sockindex) struct ssl_connect_data *connssl = &conn->ssl[sockindex]; infof(conn->data, " Curl_axtls_close\n"); if(connssl->ssl) { /* line from ssluse.c: (void)SSL_shutdown(connssl->ssl); axTLS compat layer does nothing for SSL_shutdown */ Loading @@ -441,13 +528,7 @@ void Curl_axtls_close(struct connectdata *conn, int sockindex) equivalent. ssl_free and ssl_ctx_free close things. SSL_set_connect_state(connssl->handle); */ ssl_free (connssl->ssl); connssl->ssl = NULL; } if(connssl->ssl_ctx) { ssl_ctx_free (connssl->ssl_ctx); connssl->ssl_ctx = NULL; } free_ssl_structs(connssl); } /* Loading @@ -462,8 +543,7 @@ int Curl_axtls_shutdown(struct connectdata *conn, int sockindex) int retval = 0; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct SessionHandle *data = conn->data; char buf[120]; /* We will use this for the OpenSSL error buffer, so it has to be at least 120 bytes long. */ uint8_t *buf; ssize_t nread; infof(conn->data, " Curl_axtls_shutdown\n"); Loading @@ -483,9 +563,10 @@ int Curl_axtls_shutdown(struct connectdata *conn, int sockindex) CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT); if(what > 0) { /* Something to read, let's do it and hope that it is the close notify alert from the server */ nread = (ssize_t)SSL_read(conn->ssl[sockindex].ssl, buf, sizeof(buf)); notify alert from the server. buf is managed internally by axTLS and will be released upon calling ssl_free via free_ssl_structs. */ nread = (ssize_t)ssl_read(connssl->ssl, &buf); if(nread < SSL_OK) { failf(data, "close notify alert not received during shutdown"); Loading @@ -502,8 +583,7 @@ int Curl_axtls_shutdown(struct connectdata *conn, int sockindex) retval = -1; } ssl_free (connssl->ssl); connssl->ssl = NULL; free_ssl_structs(connssl); } return retval; } Loading @@ -516,26 +596,36 @@ static ssize_t axtls_recv(struct connectdata *conn, /* connection data */ { struct ssl_connect_data *connssl = &conn->ssl[num]; ssize_t ret = 0; uint8_t *read_buf; infof(conn->data, " axtls_recv\n"); *err = CURLE_OK; if(connssl) { ret = (ssize_t)SSL_read(conn->ssl[num].ssl, buf, (int)buffersize); /* axTLS isn't terribly generous about error reporting */ ret = ssl_read(connssl->ssl, &read_buf); if(ret > SSL_OK) { /* ssl_read returns SSL_OK if there is more data to read, so if it is larger, then all data has been read already. */ memcpy(buf, read_buf, (size_t)ret > buffersize ? buffersize : (size_t)ret); } else if(ret == SSL_OK) { /* more data to be read, signal caller to call again */ *err = CURLE_AGAIN; ret = -1; } else if(ret == -3) { /* With patched axTLS, SSL_CLOSE_NOTIFY=-3. Hard-coding until axTLS team approves proposed fix. */ if(ret == -3 ) { Curl_axtls_close(conn, num); } else if(ret < 0) { failf(conn->data, "axTLS recv error (%d)", (int)ret); else { failf(conn->data, "axTLS recv error (%d)", ret); *err = map_error_to_curl(ret); return -1; ret = -1; } } *err = CURLE_OK; return ret; } Loading
lib/axtls.h +5 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,10 @@ int Curl_axtls_init(void); int Curl_axtls_cleanup(void); CURLcode Curl_axtls_connect(struct connectdata *conn, int sockindex); CURLcode Curl_axtls_connect_nonblocking( struct connectdata *conn, int sockindex, bool *done); /* tell axTLS to close down all open information regarding connections (and thus session ID caching etc) */ Loading @@ -47,6 +51,7 @@ int Curl_axtls_check_cxn(struct connectdata *conn); #define curlssl_init Curl_axtls_init #define curlssl_cleanup Curl_axtls_cleanup #define curlssl_connect Curl_axtls_connect #define curlssl_connect_nonblocking Curl_axtls_connect_nonblocking #define curlssl_session_free(x) Curl_axtls_session_free(x) #define curlssl_close_all Curl_axtls_close_all #define curlssl_close Curl_axtls_close Loading
lib/urldata.h +1 −0 Original line number Diff line number Diff line Loading @@ -325,6 +325,7 @@ struct ssl_connect_data { #ifdef USE_AXTLS SSL_CTX* ssl_ctx; SSL* ssl; ssl_connect_state connecting_state; #endif /* USE_AXTLS */ #ifdef USE_SCHANNEL struct curl_schannel_cred *cred; Loading