From 108d7693a443435e39d2278d5dbf842a80c6260c Mon Sep 17 00:00:00 2001 From: Eric Hu Date: Fri, 3 Dec 2010 10:23:45 -0800 Subject: Preparing for axTLS. Actual SSL API functions are only stubbed. Added axTLS to autotool files and glue code to misc other files. axtls.h maps SSL API functions, but may change. axtls.c is just a stub file and will definitely change. --- lib/axtls.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 lib/axtls.c (limited to 'lib/axtls.c') diff --git a/lib/axtls.c b/lib/axtls.c new file mode 100644 index 000000000..9a253bc1e --- /dev/null +++ b/lib/axtls.c @@ -0,0 +1,139 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2010, DirecTV + * contact: Eric Hu + * + * 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 axTLS-specific code for the TLS/SSL layer. No code + * but sslgen.c should ever call or use these functions. + */ + +#include "setup.h" +#ifdef USE_AXTLS +#include +#include "axtls.h" + +#include +#include +#include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#include "sendf.h" +#include "inet_pton.h" +#include "sslgen.h" +#include "parsedate.h" +#include "connect.h" /* for the connect timeout */ +#include "select.h" +#define _MPRINTF_REPLACE /* use our functions only */ +#include +#include "memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* Global axTLS init, called from Curl_ssl_init() */ +int Curl_axtls_init(void) +{ + return 1; +} + +int Curl_axtls_cleanup(void) +{ + return 1; +} + +/* + * This function is called after the TCP connect has completed. Setup the TLS + * layer and do all necessary magic. + */ +CURLcode +Curl_axtls_connect(struct connectdata *conn, + int sockindex) + +{ + return CURLE_OK; +} + + +/* return number of sent (non-SSL) bytes */ +ssize_t Curl_axtls_send(struct connectdata *conn, + int sockindex, + const void *mem, + size_t len) +{ + return 0; +} + +void Curl_axtls_close_all(struct SessionHandle *data) +{ +} + +void Curl_axtls_close(struct connectdata *conn, int sockindex) +{ +} + +/* + * This function is called to shut down the SSL layer but keep the + * socket open (CCC - Clear Command Channel) + */ +int Curl_axtls_shutdown(struct connectdata *conn, int sockindex) +{ + return 0; +} + +/* + * If the read would block we return -1 and set 'wouldblock' to TRUE. + * Otherwise we return the amount of data read. Other errors should return -1 + * and set 'wouldblock' to FALSE. + */ +ssize_t Curl_axtls_recv(struct connectdata *conn, /* connection data */ + int num, /* socketindex */ + char *buf, /* store read data here */ + size_t buffersize, /* max amount to read */ + bool *wouldblock) +{ + return 0; +} + +/* + * This function uses SSL_peek to determine connection status. + * + * Return codes: + * 1 means the connection is still in place + * 0 means the connection has been closed + * -1 means the connection status is unknown + */ +int Curl_axtls_check_cxn(struct connectdata *conn) +{ + return 0; +} + +void Curl_axtls_session_free(void *ptr) +{ +} + +size_t Curl_axtls_version(char *buffer, size_t size) +{ + return snprintf(buffer, size, "axTLS/1.2.7"); +} + +#endif /* USE_AXTLS */ -- cgit v1.2.1 From be312336f6014b707fe9ec26ab75f8712c21d611 Mon Sep 17 00:00:00 2001 From: Eric Hu Date: Mon, 6 Dec 2010 16:18:35 -0800 Subject: Initial axTLS integration. Connections can be made and some tests pass. Failed HTTPS tests: 301, 306, 311, 312, 313, 560 311, 312 need more detailed error reporting from axTLS. 313 relates to CRL, which hasn't been implemented yet. --- lib/axtls.c | 376 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 362 insertions(+), 14 deletions(-) (limited to 'lib/axtls.c') diff --git a/lib/axtls.c b/lib/axtls.c index 9a253bc1e..ff4ff2b15 100644 --- a/lib/axtls.c +++ b/lib/axtls.c @@ -50,17 +50,93 @@ /* The last #include file should be: */ #include "memdebug.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) { +/* axTLS has no global init. Everything is done through SSL and SSL_CTX + * structs stored in connectdata structure. Perhaps can move to axtls.h. + */ return 1; } int Curl_axtls_cleanup(void) { + /* axTLS has no global cleanup. Perhaps can move this to axtls.h. */ return 1; } +static CURLcode map_error_to_curl(int axtls_err) +{ + switch (axtls_err) + { + case SSL_ERROR_NOT_SUPPORTED: + case SSL_ERROR_INVALID_VERSION: + case -70: /* protocol version alert from server */ + return CURLE_UNSUPPORTED_PROTOCOL; + break; + case SSL_ERROR_NO_CIPHER: + return CURLE_SSL_CIPHER; + break; + case SSL_ERROR_BAD_CERTIFICATE: /* this may be bad server cert too */ + case SSL_ERROR_NO_CERT_DEFINED: + case -42: /* bad certificate alert from server */ + case -43: /* unsupported cert alert from server */ + case -44: /* cert revoked alert from server */ + case -45: /* cert expired alert from server */ + case -46: /* cert unknown alert from server */ + return CURLE_SSL_CERTPROBLEM; + break; + case SSL_X509_ERROR(X509_NOT_OK): + case SSL_X509_ERROR(X509_VFY_ERROR_NO_TRUSTED_CERT): + case SSL_X509_ERROR(X509_VFY_ERROR_BAD_SIGNATURE): + case SSL_X509_ERROR(X509_VFY_ERROR_NOT_YET_VALID): + case SSL_X509_ERROR(X509_VFY_ERROR_EXPIRED): + case SSL_X509_ERROR(X509_VFY_ERROR_SELF_SIGNED): + case SSL_X509_ERROR(X509_VFY_ERROR_INVALID_CHAIN): + case SSL_X509_ERROR(X509_VFY_ERROR_UNSUPPORTED_DIGEST): + case SSL_X509_ERROR(X509_INVALID_PRIV_KEY): + return CURLE_PEER_FAILED_VERIFICATION; + break; + case -48: /* unknown ca alert from server */ + return CURLE_SSL_CACERT; + break; + case -49: /* access denied alert from server */ + return CURLE_REMOTE_ACCESS_DENIED; + break; + case SSL_ERROR_CONN_LOST: + case SSL_ERROR_SOCK_SETUP_FAILURE: + case SSL_ERROR_INVALID_HANDSHAKE: + case SSL_ERROR_INVALID_PROT_MSG: + case SSL_ERROR_INVALID_HMAC: + case SSL_ERROR_INVALID_SESSION: + case SSL_ERROR_INVALID_KEY: /* it's too bad this doesn't map better */ + case SSL_ERROR_FINISHED_INVALID: + case SSL_ERROR_NO_CLIENT_RENOG: + default: + return CURLE_SSL_CONNECT_ERROR; + break; + } + return CURLE_SSL_CONNECT_ERROR; /* catch-all for non-easily-mapped errors */ +} + +static Curl_recv axtls_recv; +static Curl_send axtls_send; + /* * This function is called after the TCP connect has completed. Setup the TLS * layer and do all necessary magic. @@ -70,25 +146,232 @@ Curl_axtls_connect(struct connectdata *conn, int sockindex) { + struct SessionHandle *data = conn->data; + SSL_CTX *ssl_ctx; + SSL *ssl; + int cert_types[] = {SSL_OBJ_X509_CERT, SSL_OBJ_PKCS12, 0}; + int key_types[] = {SSL_OBJ_RSA_KEY, SSL_OBJ_PKCS8, SSL_OBJ_PKCS12, 0}; + int i, ssl_fcn_return; + const uint8_t *ssl_sessionid; + size_t ssl_idsize; + const char *x509; + + /* Assuming users will not compile in custom key/cert to axTLS */ + uint32_t client_option = SSL_NO_DEFAULT_KEY; + + if(conn->ssl[sockindex].state == ssl_connection_complete) + /* to make us tolerant against being called more than once for the + same connection */ + return CURLE_OK; + + /* axTLS only supports TLSv1 */ + if(data->set.ssl.version != CURL_SSLVERSION_TLSv1) { + failf(data, "axTLS only supports TLSv1"); + return CURLE_SSL_CONNECT_ERROR; + } + +#ifdef AXTLSDEBUG + client_option |= SSL_DISPLAY_STATES | SSL_DISPLAY_RSA | SSL_DISPLAY_CERTS; +#endif /* AXTLSDEBUG */ + + /* Allocate an SSL_CTX struct */ + ssl_ctx = ssl_ctx_new(client_option, SSL_DEFAULT_CLNT_SESS); + if(ssl_ctx == NULL) { + failf(data, "unable to create client SSL context"); + return CURLE_SSL_CONNECT_ERROR; + } + + /* 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) \ + != SSL_OK){ + infof(data, "error reading ca cert file %s \n", + data->set.ssl.CAfile); + if(data->set.ssl.verifypeer){ + Curl_axtls_close(conn, sockindex); + return CURLE_SSL_CACERT_BADFILE; + } + } + else + infof(data, "found certificates in %s\n", data->set.ssl.CAfile); + } + + /* gtls.c tasks we're skipping for now: + * 1) certificate revocation list checking + * 2) dns name assignment to host + * 3) set protocol priority. axTLS is TLSv1 only, so can probably ignore + * 4) set certificate priority. axTLS ignores type and sends certs in + * order added. can probably ignore this. + */ + + /* Load client certificate */ + if(data->set.str[STRING_CERT]){ + i=0; + /* Instead of trying to analyze cert type here, let axTLS try them all. */ + while(cert_types[i] != 0){ + ssl_fcn_return = ssl_obj_load(ssl_ctx, cert_types[i], \ + data->set.str[STRING_CERT], NULL); + if(ssl_fcn_return == SSL_OK){ + infof(data, "successfully read cert file %s \n", \ + data->set.str[STRING_CERT]); + break; + } + i++; + } + /* Tried all cert types, none worked. */ + if(cert_types[i] == 0){ + failf(data, "%s is not x509 or pkcs12 format", \ + data->set.str[STRING_CERT]); + Curl_axtls_close(conn, sockindex); + return CURLE_SSL_CERTPROBLEM; + } + } + + /* Load client key. + If a pkcs12 file successfully loaded a cert, then there's nothing to do + because the key has already been loaded. */ + if(data->set.str[STRING_KEY] && cert_types[i] != SSL_OBJ_PKCS12){ + i=0; + /* Instead of trying to analyze key type here, let axTLS try them all. */ + while(key_types[i] != 0){ + ssl_fcn_return = ssl_obj_load(ssl_ctx, key_types[i], \ + data->set.str[STRING_KEY], NULL); + if(ssl_fcn_return == SSL_OK){ + infof(data, "successfully read key file %s \n", \ + data->set.str[STRING_KEY]); + break; + } + i++; + } + /* Tried all key types, none worked. */ + 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); + return CURLE_SSL_CONNECT_ERROR; + } + } + + /* gtls.c does more here that is being left out for now + * 1) set session credentials. can probably ignore since axtls puts this + * info in the ssl_ctx struct + * 2) setting up callbacks. these seem gnutls specific + */ + + /* In axTLS, handshaking happens inside ssl_client_new. */ + if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize)){ + /* we got a session id, use it! */ + infof (data, "SSL re-using session ID\n"); + ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], \ + ssl_sessionid, ssl_idsize); + } + 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); + ssl_display_error(ssl_fcn_return); /* goes to stdout. */ + return map_error_to_curl(ssl_fcn_return); + } + infof (data, "handshake completed successfully\n"); + + /* 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? + */ + + /* Verify server's certificate */ + if(data->set.ssl.verifypeer){ + if(ssl_verify_cert(ssl) != SSL_OK){ + Curl_axtls_close(conn, sockindex); + failf(data, "server cert verify failed"); + return CURLE_SSL_CONNECT_ERROR; + } + } + else + infof(data, "\t server certificate verification SKIPPED\n"); + + /* Here, gtls.c does issuer verfication. axTLS has no straightforward + * equivalent, so omitting for now.*/ + + /* See if common name was set in server certificate */ + x509 = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME); + if(x509 == NULL) + infof(data, "error fetching CN from cert\n"); + + /* Here, gtls.c does the following + * 1) x509 hostname checking per RFC2818. axTLS doesn't support this, but + * it seems useful. Omitting for now. + * 2) checks cert validity based on time. axTLS does this in ssl_verify_cert + * 3) displays a bunch of cert information. axTLS doesn't support most of + * this, but a couple fields are available. + */ + + /* 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; + + /* Put our freshly minted SSL session in cache */ + ssl_idsize = ssl_get_session_id_size(ssl); + ssl_sessionid = ssl_get_session_id(ssl); + if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize) \ + != CURLE_OK) + infof (data, "failed to add session to cache\n"); + return CURLE_OK; } /* return number of sent (non-SSL) bytes */ -ssize_t Curl_axtls_send(struct connectdata *conn, - int sockindex, - const void *mem, - size_t len) +static ssize_t axtls_send(struct connectdata *conn, + int sockindex, + const void *mem, + size_t len, + CURLcode *err) { - return 0; + /* ssl_write() returns 'int' while write() and send() returns + 'size_t' */ + char error_buffer[120]; /* Comply with OpenSSL, which documents that this + must be at least 120 bytes long. */ + int rc = ssl_write(conn->ssl[sockindex].ssl, mem, (int)len); + + if(rc < 0 ) { + *err = map_error_to_curl(rc); + rc = -1; /* generic error code for send failure */ + } + + *err = CURLE_OK; + return rc; } void Curl_axtls_close_all(struct SessionHandle *data) { + (void)data; } void Curl_axtls_close(struct connectdata *conn, int sockindex) { + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + if(connssl->ssl) { + /* line from ssluse.c: (void)SSL_shutdown(connssl->ssl); + axTLS compat layer does nothing for SSL_shutdown */ + + /* The following line is from ssluse.c. There seems to be no axTLS + 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; + } } /* @@ -97,7 +380,54 @@ void Curl_axtls_close(struct connectdata *conn, int sockindex) */ int Curl_axtls_shutdown(struct connectdata *conn, int sockindex) { - return 0; + /* Outline taken from ssluse.c since functions are in axTLS compat layer. + axTLS's error set is much smaller, so a lot of error-handling was removed. + */ + 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. */ + ssize_t nread; + + /* This has only been tested on the proftpd server, and the mod_tls code + sends a close notify alert without waiting for a close notify alert in + response. Thus we wait for a close notify alert from the server, but + we do not send one. Let's hope other servers do the same... */ + + /* axTLS compat layer does nothing for SSL_shutdown, so we do nothing too + if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE) + (void)SSL_shutdown(connssl->ssl); + */ + + if(connssl->ssl) { + int what = Curl_socket_ready(conn->sock[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)); + + if (nread < SSL_OK){ + failf(data, "close notify alert not received during shutdown"); + retval = -1; + } + } + else if(0 == what) { + /* timeout */ + failf(data, "SSL shutdown timeout"); + } + else { + /* anything that gets here is fatally bad */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + retval = -1; + } + + ssl_free (connssl->ssl); + connssl->ssl = NULL; + } + return retval; } /* @@ -105,13 +435,24 @@ int Curl_axtls_shutdown(struct connectdata *conn, int sockindex) * Otherwise we return the amount of data read. Other errors should return -1 * and set 'wouldblock' to FALSE. */ -ssize_t Curl_axtls_recv(struct connectdata *conn, /* connection data */ - int num, /* socketindex */ - char *buf, /* store read data here */ - size_t buffersize, /* max amount to read */ - bool *wouldblock) +static ssize_t axtls_recv(struct connectdata *conn, /* connection data */ + int num, /* socketindex */ + char *buf, /* store read data here */ + size_t buffersize, /* max amount to read */ + CURLcode *err) { - return 0; + ssize_t ret = (ssize_t)SSL_read(conn->ssl[num].ssl, buf, + (int)buffersize); + + /* axTLS isn't terribly generous about error reporting */ + if(ret < 0) { + failf(conn->data, "axTLS recv error (%d)", (int)ret); + *err = map_error_to_curl(ret); + return -1; + } + + *err = CURLE_OK; + return ret; } /* @@ -124,16 +465,23 @@ ssize_t Curl_axtls_recv(struct connectdata *conn, /* connection data */ */ int Curl_axtls_check_cxn(struct connectdata *conn) { - return 0; + /* ssluse.c line: rc = SSL_peek(conn->ssl[FIRSTSOCKET].ssl, (void*)&buf, 1); + axTLS compat layer always returns the last argument, so connection is + always alive? */ + + return 1; /* connection still in place */ } void Curl_axtls_session_free(void *ptr) { + /* free the ID */ + /* both ssluse.c and gtls.c do something here, but axTLS's OpenSSL + compatibility layer does nothing, so we do nothing too. */ } size_t Curl_axtls_version(char *buffer, size_t size) { - return snprintf(buffer, size, "axTLS/1.2.7"); + return snprintf(buffer, size, "axTLS/%s", ssl_version()); } #endif /* USE_AXTLS */ -- cgit v1.2.1 From a7cf30f8081f98bdcd3f999a13c619374792f4c6 Mon Sep 17 00:00:00 2001 From: Eric Hu Date: Thu, 9 Dec 2010 16:29:39 -0800 Subject: Minor fixes to pass tests 301 and 306 with a patched axTLS. --- lib/axtls.c | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) (limited to 'lib/axtls.c') diff --git a/lib/axtls.c b/lib/axtls.c index ff4ff2b15..82a0ddcc6 100644 --- a/lib/axtls.c +++ b/lib/axtls.c @@ -131,7 +131,6 @@ static CURLcode map_error_to_curl(int axtls_err) return CURLE_SSL_CONNECT_ERROR; break; } - return CURLE_SSL_CONNECT_ERROR; /* catch-all for non-easily-mapped errors */ } static Curl_recv axtls_recv; @@ -339,6 +338,8 @@ static ssize_t axtls_send(struct connectdata *conn, must be at least 120 bytes long. */ int rc = ssl_write(conn->ssl[sockindex].ssl, mem, (int)len); + infof(conn->data, " axtls_send\n"); + if(rc < 0 ) { *err = map_error_to_curl(rc); rc = -1; /* generic error code for send failure */ @@ -351,12 +352,14 @@ static ssize_t axtls_send(struct connectdata *conn, void Curl_axtls_close_all(struct SessionHandle *data) { (void)data; + infof(data, " Curl_axtls_close_all\n"); } 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 */ @@ -390,6 +393,8 @@ int Curl_axtls_shutdown(struct connectdata *conn, int sockindex) to be at least 120 bytes long. */ ssize_t nread; + infof(conn->data, " Curl_axtls_shutdown\n"); + /* This has only been tested on the proftpd server, and the mod_tls code sends a close notify alert without waiting for a close notify alert in response. Thus we wait for a close notify alert from the server, but @@ -430,25 +435,31 @@ int Curl_axtls_shutdown(struct connectdata *conn, int sockindex) return retval; } -/* - * If the read would block we return -1 and set 'wouldblock' to TRUE. - * Otherwise we return the amount of data read. Other errors should return -1 - * and set 'wouldblock' to FALSE. - */ static ssize_t axtls_recv(struct connectdata *conn, /* connection data */ int num, /* socketindex */ char *buf, /* store read data here */ size_t buffersize, /* max amount to read */ CURLcode *err) { - ssize_t ret = (ssize_t)SSL_read(conn->ssl[num].ssl, buf, - (int)buffersize); - - /* axTLS isn't terribly generous about error reporting */ - if(ret < 0) { - failf(conn->data, "axTLS recv error (%d)", (int)ret); - *err = map_error_to_curl(ret); - return -1; + struct ssl_connect_data *connssl = &conn->ssl[num]; + ssize_t ret = 0; + + infof(conn->data, " axtls_recv\n"); + + if(connssl){ + ret = (ssize_t)SSL_read(conn->ssl[num].ssl, buf, (int)buffersize); + + /* axTLS isn't terribly generous about error reporting */ + /* 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); + *err = map_error_to_curl(ret); + return -1; + } } *err = CURLE_OK; @@ -456,8 +467,6 @@ static ssize_t axtls_recv(struct connectdata *conn, /* connection data */ } /* - * This function uses SSL_peek to determine connection status. - * * Return codes: * 1 means the connection is still in place * 0 means the connection has been closed @@ -469,6 +478,7 @@ int Curl_axtls_check_cxn(struct connectdata *conn) axTLS compat layer always returns the last argument, so connection is always alive? */ + infof(conn->data, " Curl_axtls_check_cxn\n"); return 1; /* connection still in place */ } -- cgit v1.2.1 From b88ead62e72813d24888efea3d45d56ceb7f3947 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 11 Dec 2010 00:55:06 +0100 Subject: axtls.c: cleanup Removed trailing whitespace Removed several compiler warnings Removed odd backslashes at some line endings --- lib/axtls.c | 96 ++++++++++++++++++++++++++++++------------------------------- 1 file changed, 47 insertions(+), 49 deletions(-) (limited to 'lib/axtls.c') diff --git a/lib/axtls.c b/lib/axtls.c index 82a0ddcc6..80c3554ee 100644 --- a/lib/axtls.c +++ b/lib/axtls.c @@ -55,7 +55,7 @@ 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){ @@ -182,13 +182,13 @@ Curl_axtls_connect(struct connectdata *conn, /* 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) \ + if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, data->set.ssl.CAfile, NULL) != SSL_OK){ infof(data, "error reading ca cert file %s \n", - data->set.ssl.CAfile); + data->set.ssl.CAfile); if(data->set.ssl.verifypeer){ - Curl_axtls_close(conn, sockindex); - return CURLE_SSL_CACERT_BADFILE; + Curl_axtls_close(conn, sockindex); + return CURLE_SSL_CACERT_BADFILE; } } else @@ -199,7 +199,7 @@ Curl_axtls_connect(struct connectdata *conn, * 1) certificate revocation list checking * 2) dns name assignment to host * 3) set protocol priority. axTLS is TLSv1 only, so can probably ignore - * 4) set certificate priority. axTLS ignores type and sends certs in + * 4) set certificate priority. axTLS ignores type and sends certs in * order added. can probably ignore this. */ @@ -208,20 +208,20 @@ Curl_axtls_connect(struct connectdata *conn, i=0; /* Instead of trying to analyze cert type here, let axTLS try them all. */ while(cert_types[i] != 0){ - ssl_fcn_return = ssl_obj_load(ssl_ctx, cert_types[i], \ - data->set.str[STRING_CERT], NULL); + ssl_fcn_return = ssl_obj_load(ssl_ctx, cert_types[i], + data->set.str[STRING_CERT], NULL); if(ssl_fcn_return == SSL_OK){ - infof(data, "successfully read cert file %s \n", \ - data->set.str[STRING_CERT]); - break; + infof(data, "successfully read cert file %s \n", + data->set.str[STRING_CERT]); + break; } i++; } /* Tried all cert types, none worked. */ if(cert_types[i] == 0){ - failf(data, "%s is not x509 or pkcs12 format", \ - data->set.str[STRING_CERT]); - Curl_axtls_close(conn, sockindex); + failf(data, "%s is not x509 or pkcs12 format", + data->set.str[STRING_CERT]); + Curl_axtls_close(conn, sockindex); return CURLE_SSL_CERTPROBLEM; } } @@ -233,20 +233,20 @@ Curl_axtls_connect(struct connectdata *conn, i=0; /* Instead of trying to analyze key type here, let axTLS try them all. */ while(key_types[i] != 0){ - ssl_fcn_return = ssl_obj_load(ssl_ctx, key_types[i], \ - data->set.str[STRING_KEY], NULL); + ssl_fcn_return = ssl_obj_load(ssl_ctx, key_types[i], + data->set.str[STRING_KEY], NULL); if(ssl_fcn_return == SSL_OK){ - infof(data, "successfully read key file %s \n", \ - data->set.str[STRING_KEY]); - break; + infof(data, "successfully read key file %s \n", + data->set.str[STRING_KEY]); + break; } i++; } /* Tried all key types, none worked. */ 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); + failf(data, "Failure: %s is not a supported key file", + data->set.str[STRING_KEY]); + Curl_axtls_close(conn, sockindex); return CURLE_SSL_CONNECT_ERROR; } } @@ -258,11 +258,11 @@ Curl_axtls_connect(struct connectdata *conn, */ /* In axTLS, handshaking happens inside ssl_client_new. */ - if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize)){ + if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize)) { /* we got a session id, use it! */ infof (data, "SSL re-using session ID\n"); - ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], \ - ssl_sessionid, ssl_idsize); + ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], + ssl_sessionid, (uint8_t)ssl_idsize); } else ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0); @@ -270,20 +270,20 @@ Curl_axtls_connect(struct connectdata *conn, /* 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); + Curl_axtls_close(conn, sockindex); ssl_display_error(ssl_fcn_return); /* goes to stdout. */ return map_error_to_curl(ssl_fcn_return); } infof (data, "handshake completed successfully\n"); - /* Here, gtls.c gets the peer certificates and fails out depending on + /* 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? */ /* Verify server's certificate */ if(data->set.ssl.verifypeer){ if(ssl_verify_cert(ssl) != SSL_OK){ - Curl_axtls_close(conn, sockindex); + Curl_axtls_close(conn, sockindex); failf(data, "server cert verify failed"); return CURLE_SSL_CONNECT_ERROR; } @@ -296,11 +296,11 @@ Curl_axtls_connect(struct connectdata *conn, /* See if common name was set in server certificate */ x509 = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME); - if(x509 == NULL) + if(x509 == NULL) infof(data, "error fetching CN from cert\n"); /* Here, gtls.c does the following - * 1) x509 hostname checking per RFC2818. axTLS doesn't support this, but + * 1) x509 hostname checking per RFC2818. axTLS doesn't support this, but * it seems useful. Omitting for now. * 2) checks cert validity based on time. axTLS does this in ssl_verify_cert * 3) displays a bunch of cert information. axTLS doesn't support most of @@ -317,7 +317,7 @@ Curl_axtls_connect(struct connectdata *conn, /* Put our freshly minted SSL session in cache */ ssl_idsize = ssl_get_session_id_size(ssl); ssl_sessionid = ssl_get_session_id(ssl); - if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize) \ + if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize) != CURLE_OK) infof (data, "failed to add session to cache\n"); @@ -327,15 +327,12 @@ Curl_axtls_connect(struct connectdata *conn, /* return number of sent (non-SSL) bytes */ static ssize_t axtls_send(struct connectdata *conn, - int sockindex, - const void *mem, - size_t len, - CURLcode *err) + int sockindex, + const void *mem, + size_t len, + CURLcode *err) { - /* ssl_write() returns 'int' while write() and send() returns - 'size_t' */ - char error_buffer[120]; /* Comply with OpenSSL, which documents that this - must be at least 120 bytes long. */ + /* ssl_write() returns 'int' while write() and send() returns 'size_t' */ int rc = ssl_write(conn->ssl[sockindex].ssl, mem, (int)len); infof(conn->data, " axtls_send\n"); @@ -407,16 +404,16 @@ int Curl_axtls_shutdown(struct connectdata *conn, int sockindex) if(connssl->ssl) { int what = Curl_socket_ready(conn->sock[sockindex], - CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT); + 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 */ + notify alert from the server */ nread = (ssize_t)SSL_read(conn->ssl[sockindex].ssl, buf, - sizeof(buf)); + sizeof(buf)); if (nread < SSL_OK){ - failf(data, "close notify alert not received during shutdown"); - retval = -1; + failf(data, "close notify alert not received during shutdown"); + retval = -1; } } else if(0 == what) { @@ -436,10 +433,10 @@ int Curl_axtls_shutdown(struct connectdata *conn, int sockindex) } static ssize_t axtls_recv(struct connectdata *conn, /* connection data */ - int num, /* socketindex */ - char *buf, /* store read data here */ - size_t buffersize, /* max amount to read */ - CURLcode *err) + int num, /* socketindex */ + char *buf, /* store read data here */ + size_t buffersize, /* max amount to read */ + CURLcode *err) { struct ssl_connect_data *connssl = &conn->ssl[num]; ssize_t ret = 0; @@ -475,7 +472,7 @@ static ssize_t axtls_recv(struct connectdata *conn, /* connection data */ int Curl_axtls_check_cxn(struct connectdata *conn) { /* ssluse.c line: rc = SSL_peek(conn->ssl[FIRSTSOCKET].ssl, (void*)&buf, 1); - axTLS compat layer always returns the last argument, so connection is + axTLS compat layer always returns the last argument, so connection is always alive? */ infof(conn->data, " Curl_axtls_check_cxn\n"); @@ -484,6 +481,7 @@ int Curl_axtls_check_cxn(struct connectdata *conn) void Curl_axtls_session_free(void *ptr) { + (void)ptr; /* free the ID */ /* both ssluse.c and gtls.c do something here, but axTLS's OpenSSL compatibility layer does nothing, so we do nothing too. */ -- cgit v1.2.1 From 9035709e25232b0a256684626405e0d0b4c15099 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 15 Dec 2010 10:23:19 +0100 Subject: axTLS: allow "default" SSL version as well When no explicit version is selected we should try to use whatever is best for us, and in the axTLS case that means TLSv1. --- lib/axtls.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'lib/axtls.c') diff --git a/lib/axtls.c b/lib/axtls.c index 80c3554ee..855b554b4 100644 --- a/lib/axtls.c +++ b/lib/axtls.c @@ -164,7 +164,12 @@ Curl_axtls_connect(struct connectdata *conn, return CURLE_OK; /* axTLS only supports TLSv1 */ - if(data->set.ssl.version != CURL_SSLVERSION_TLSv1) { + /* check to see if we've been told to use an explicit SSL/TLS version */ + switch(data->set.ssl.version) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + break; + default: failf(data, "axTLS only supports TLSv1"); return CURLE_SSL_CONNECT_ERROR; } -- cgit v1.2.1 From c75a9fef592a412de707b45ea1a6f814cf65a23f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 15 Dec 2010 11:11:20 +0100 Subject: axtls_connect: allow connect without peer verification The SSL_SERVER_VERIFY_LATER bit in the ssl_ctx_new() call allows the code to verify the peer certificate explicitly after the handshake and then the "data->set.ssl.verifypeer" option works. --- lib/axtls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/axtls.c') diff --git a/lib/axtls.c b/lib/axtls.c index 855b554b4..152de6f2c 100644 --- a/lib/axtls.c +++ b/lib/axtls.c @@ -156,7 +156,7 @@ Curl_axtls_connect(struct connectdata *conn, const char *x509; /* Assuming users will not compile in custom key/cert to axTLS */ - uint32_t client_option = SSL_NO_DEFAULT_KEY; + uint32_t client_option = SSL_NO_DEFAULT_KEY|SSL_SERVER_VERIFY_LATER; if(conn->ssl[sockindex].state == ssl_connection_complete) /* to make us tolerant against being called more than once for the -- cgit v1.2.1 From a834e004544cff32f933b899a1f6d29963bef0e1 Mon Sep 17 00:00:00 2001 From: Guenter Knauf Date: Wed, 22 Dec 2010 03:34:13 +0100 Subject: Fixed include: memory.h -> curl_memory.h. --- lib/axtls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/axtls.c') diff --git a/lib/axtls.c b/lib/axtls.c index 152de6f2c..892b8c3a5 100644 --- a/lib/axtls.c +++ b/lib/axtls.c @@ -46,7 +46,7 @@ #include "select.h" #define _MPRINTF_REPLACE /* use our functions only */ #include -#include "memory.h" +#include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" -- cgit v1.2.1 From 1702a2c08d3a0ed5945f34e6cd38436611f65164 Mon Sep 17 00:00:00 2001 From: Fabian Keil Date: Tue, 19 Apr 2011 15:54:13 +0200 Subject: Fix a couple of spelling errors in lib/ Found with codespell. --- lib/axtls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/axtls.c') diff --git a/lib/axtls.c b/lib/axtls.c index 892b8c3a5..b6d93e909 100644 --- a/lib/axtls.c +++ b/lib/axtls.c @@ -296,7 +296,7 @@ Curl_axtls_connect(struct connectdata *conn, else infof(data, "\t server certificate verification SKIPPED\n"); - /* Here, gtls.c does issuer verfication. axTLS has no straightforward + /* Here, gtls.c does issuer verification. axTLS has no straightforward * equivalent, so omitting for now.*/ /* See if common name was set in server certificate */ -- 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/axtls.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'lib/axtls.c') diff --git a/lib/axtls.c b/lib/axtls.c index b6d93e909..ffbd1d4f3 100644 --- a/lib/axtls.c +++ b/lib/axtls.c @@ -82,8 +82,7 @@ int Curl_axtls_cleanup(void) static CURLcode map_error_to_curl(int axtls_err) { - switch (axtls_err) - { + switch (axtls_err) { case SSL_ERROR_NOT_SUPPORTED: case SSL_ERROR_INVALID_VERSION: case -70: /* protocol version alert from server */ @@ -416,7 +415,7 @@ int Curl_axtls_shutdown(struct connectdata *conn, int sockindex) nread = (ssize_t)SSL_read(conn->ssl[sockindex].ssl, buf, sizeof(buf)); - if (nread < SSL_OK){ + if(nread < SSL_OK){ failf(data, "close notify alert not received during shutdown"); retval = -1; } -- cgit v1.2.1 From b680fd180bf31dd29d84f43d91b6ee56e62d452f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 4 Jul 2011 22:10:32 +0200 Subject: code style: space between close paren and open brace --- lib/axtls.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'lib/axtls.c') diff --git a/lib/axtls.c b/lib/axtls.c index ffbd1d4f3..990264b93 100644 --- a/lib/axtls.c +++ b/lib/axtls.c @@ -58,7 +58,7 @@ static int SSL_read(SSL *ssl, void *buf, int num) while((ret = ssl_read(ssl, &read_buf)) == SSL_OK); - if(ret > SSL_OK){ + if(ret > SSL_OK) { memcpy(buf, read_buf, ret > num ? num : ret); } @@ -187,10 +187,10 @@ Curl_axtls_connect(struct connectdata *conn, /* 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) - != SSL_OK){ + != SSL_OK) { infof(data, "error reading ca cert file %s \n", data->set.ssl.CAfile); - if(data->set.ssl.verifypeer){ + if(data->set.ssl.verifypeer) { Curl_axtls_close(conn, sockindex); return CURLE_SSL_CACERT_BADFILE; } @@ -208,13 +208,13 @@ Curl_axtls_connect(struct connectdata *conn, */ /* Load client certificate */ - if(data->set.str[STRING_CERT]){ + if(data->set.str[STRING_CERT]) { i=0; /* Instead of trying to analyze cert type here, let axTLS try them all. */ - while(cert_types[i] != 0){ + while(cert_types[i] != 0) { ssl_fcn_return = ssl_obj_load(ssl_ctx, cert_types[i], data->set.str[STRING_CERT], NULL); - if(ssl_fcn_return == SSL_OK){ + if(ssl_fcn_return == SSL_OK) { infof(data, "successfully read cert file %s \n", data->set.str[STRING_CERT]); break; @@ -222,7 +222,7 @@ Curl_axtls_connect(struct connectdata *conn, i++; } /* Tried all cert types, none worked. */ - if(cert_types[i] == 0){ + if(cert_types[i] == 0) { failf(data, "%s is not x509 or pkcs12 format", data->set.str[STRING_CERT]); Curl_axtls_close(conn, sockindex); @@ -233,13 +233,13 @@ Curl_axtls_connect(struct connectdata *conn, /* Load client key. If a pkcs12 file successfully loaded a cert, then there's nothing to do because the key has already been loaded. */ - if(data->set.str[STRING_KEY] && cert_types[i] != SSL_OBJ_PKCS12){ + if(data->set.str[STRING_KEY] && cert_types[i] != SSL_OBJ_PKCS12) { i=0; /* Instead of trying to analyze key type here, let axTLS try them all. */ - while(key_types[i] != 0){ + while(key_types[i] != 0) { ssl_fcn_return = ssl_obj_load(ssl_ctx, key_types[i], data->set.str[STRING_KEY], NULL); - if(ssl_fcn_return == SSL_OK){ + if(ssl_fcn_return == SSL_OK) { infof(data, "successfully read key file %s \n", data->set.str[STRING_KEY]); break; @@ -247,7 +247,7 @@ Curl_axtls_connect(struct connectdata *conn, i++; } /* Tried all key types, none worked. */ - if(key_types[i] == 0){ + 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); @@ -273,7 +273,7 @@ Curl_axtls_connect(struct connectdata *conn, /* Check to make sure handshake was ok. */ ssl_fcn_return = ssl_handshake_status(ssl); - if(ssl_fcn_return != SSL_OK){ + if(ssl_fcn_return != SSL_OK) { Curl_axtls_close(conn, sockindex); ssl_display_error(ssl_fcn_return); /* goes to stdout. */ return map_error_to_curl(ssl_fcn_return); @@ -285,8 +285,8 @@ Curl_axtls_connect(struct connectdata *conn, */ /* Verify server's certificate */ - if(data->set.ssl.verifypeer){ - if(ssl_verify_cert(ssl) != SSL_OK){ + if(data->set.ssl.verifypeer) { + if(ssl_verify_cert(ssl) != SSL_OK) { Curl_axtls_close(conn, sockindex); failf(data, "server cert verify failed"); return CURLE_SSL_CONNECT_ERROR; @@ -415,7 +415,7 @@ int Curl_axtls_shutdown(struct connectdata *conn, int sockindex) nread = (ssize_t)SSL_read(conn->ssl[sockindex].ssl, buf, sizeof(buf)); - if(nread < SSL_OK){ + if(nread < SSL_OK) { failf(data, "close notify alert not received during shutdown"); retval = -1; } @@ -447,13 +447,13 @@ static ssize_t axtls_recv(struct connectdata *conn, /* connection data */ infof(conn->data, " axtls_recv\n"); - if(connssl){ + if(connssl) { ret = (ssize_t)SSL_read(conn->ssl[num].ssl, buf, (int)buffersize); /* axTLS isn't terribly generous about error reporting */ /* With patched axTLS, SSL_CLOSE_NOTIFY=-3. Hard-coding until axTLS team approves proposed fix. */ - if(ret == -3 ){ + if(ret == -3 ) { Curl_axtls_close(conn, num); } else if(ret < 0) { -- 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/axtls.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'lib/axtls.c') diff --git a/lib/axtls.c b/lib/axtls.c index 990264b93..e37aed50a 100644 --- a/lib/axtls.c +++ b/lib/axtls.c @@ -27,13 +27,11 @@ */ #include "setup.h" + #ifdef USE_AXTLS #include #include "axtls.h" -#include -#include -#include #ifdef HAVE_SYS_SOCKET_H #include #endif -- 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/axtls.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 59 insertions(+), 7 deletions(-) (limited to 'lib/axtls.c') diff --git a/lib/axtls.c b/lib/axtls.c index e37aed50a..ea94c6cf9 100644 --- a/lib/axtls.c +++ b/lib/axtls.c @@ -47,6 +47,8 @@ #include "curl_memory.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) @@ -150,7 +152,11 @@ Curl_axtls_connect(struct connectdata *conn, int i, ssl_fcn_return; const uint8_t *ssl_sessionid; size_t ssl_idsize; - const char *x509; + 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; @@ -296,19 +302,65 @@ Curl_axtls_connect(struct connectdata *conn, /* Here, gtls.c does issuer verification. axTLS has no straightforward * equivalent, so omitting for now.*/ - /* See if common name was set in server certificate */ - x509 = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME); - if(x509 == NULL) - infof(data, "error fetching CN from cert\n"); - /* Here, gtls.c does the following * 1) x509 hostname checking per RFC2818. axTLS doesn't support this, but - * it seems useful. Omitting for now. + * it seems useful. This is now implemented, by Oscar Koeroo * 2) checks cert validity based on time. axTLS does this in ssl_verify_cert * 3) displays a bunch of cert information. axTLS doesn't support most of * 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++) { + dns_altname = ssl_get_cert_subject_alt_dnsname(ssl, dns_altname_index); + if(dns_altname == NULL) { + break; + } + found_subject_alt_names = 1; + + infof(data, "\tComparing subject alt name DNS with hostname: %s <-> %s\n", + dns_altname, conn->host.name); + if(Curl_cert_hostcheck(dns_altname, conn->host.name)) { + found_subject_alt_name_matching_conn = 1; + break; + } + } + + /* RFC2818 checks */ + if(found_subject_alt_names && !found_subject_alt_name_matching_conn) { + /* Break connection ! */ + Curl_axtls_close(conn, sockindex); + failf(data, "\tsubjectAltName(s) do not match %s\n", conn->host.dispname); + return CURLE_PEER_FAILED_VERIFICATION; + } + else if(found_subject_alt_names == 0) { + /* Per RFC2818, when no Subject Alt Names were available, examine the peer + CN as a legacy fallback */ + peer_CN = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME); + if(peer_CN == NULL) { + /* Similar behaviour to the OpenSSL interface */ + Curl_axtls_close(conn, sockindex); + failf(data, "unable to obtain common name from peer certificate"); + return CURLE_PEER_FAILED_VERIFICATION; + } + else { + if(!Curl_cert_hostcheck((const char *)peer_CN, conn->host.name)) { + if(data->set.ssl.verifyhost) { + /* Break connection ! */ + Curl_axtls_close(conn, sockindex); + failf(data, "\tcommon name \"%s\" does not match \"%s\"\n", + peer_CN, conn->host.dispname); + return CURLE_PEER_FAILED_VERIFICATION; + } + else + infof(data, "\tcommon name \"%s\" does not match \"%s\"\n", + peer_CN, conn->host.dispname); + } + } + } + /* General housekeeping */ conn->ssl[sockindex].state = ssl_connection_complete; conn->ssl[sockindex].ssl = ssl; -- cgit v1.2.1