From eccf4fb7eee33c0d011bd90449ff1c162dc87c1b Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 17 Dec 2013 23:05:37 +0100 Subject: vtls: created subdir, moved sslgen.[ch] there, updated all include lines --- lib/Makefile.am | 13 +- lib/Makefile.inc | 4 +- lib/connect.c | 2 +- lib/curl_ntlm_msgs.c | 2 +- lib/curl_sasl.c | 2 +- lib/easy.c | 2 +- lib/formdata.c | 2 +- lib/ftp.c | 2 +- lib/getinfo.c | 2 +- lib/http.c | 2 +- lib/http_digest.c | 2 +- lib/imap.c | 2 +- lib/openldap.c | 4 +- lib/pingpong.c | 2 +- lib/pop3.c | 2 +- lib/sendf.c | 2 +- lib/share.c | 4 +- lib/smtp.c | 2 +- lib/ssh.c | 2 +- lib/sslgen.c | 689 --------------------------------------------------- lib/sslgen.h | 126 ---------- lib/ssluse.c | 2 +- lib/transfer.c | 2 +- lib/url.c | 2 +- lib/version.c | 2 +- lib/vtls/sslgen.c | 689 +++++++++++++++++++++++++++++++++++++++++++++++++++ lib/vtls/sslgen.h | 126 ++++++++++ 27 files changed, 844 insertions(+), 849 deletions(-) delete mode 100644 lib/sslgen.c delete mode 100644 lib/sslgen.h create mode 100644 lib/vtls/sslgen.c create mode 100644 lib/vtls/sslgen.h (limited to 'lib') diff --git a/lib/Makefile.am b/lib/Makefile.am index 4477cc25f..6dffbd9c9 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -60,20 +60,15 @@ CFLAGS += @CURL_CFLAG_EXTRAS@ # $(top_builddir)/ares is for in-tree c-ares's generated ares_build.h file # $(top_srcdir)/ares is for in-tree c-ares's external include files -if USE_EMBEDDED_ARES -AM_CPPFLAGS = -I$(top_builddir)/include/curl \ - -I$(top_builddir)/include \ - -I$(top_srcdir)/include \ - -I$(top_builddir)/lib \ - -I$(top_srcdir)/lib \ - -I$(top_builddir)/ares \ - -I$(top_srcdir)/ares -else AM_CPPFLAGS = -I$(top_builddir)/include/curl \ -I$(top_builddir)/include \ -I$(top_srcdir)/include \ -I$(top_builddir)/lib \ -I$(top_srcdir)/lib + +if USE_EMBEDDED_ARES +AM_CPPFLAGS += -I$(top_builddir)/ares \ + -I$(top_srcdir)/ares endif # Prevent LIBS from being used for all link targets diff --git a/lib/Makefile.inc b/lib/Makefile.inc index 62bc0b3d5..3c5885d09 100644 --- a/lib/Makefile.inc +++ b/lib/Makefile.inc @@ -16,7 +16,7 @@ CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c \ content_encoding.c share.c http_digest.c md4.c md5.c \ http_negotiate.c inet_pton.c strtoofft.c strerror.c amigaos.c \ hostasyn.c hostip4.c hostip6.c hostsyn.c inet_ntop.c parsedate.c \ - select.c gtls.c sslgen.c tftp.c splay.c strdup.c socks.c ssh.c nss.c \ + select.c gtls.c vtls/sslgen.c tftp.c splay.c strdup.c socks.c ssh.c nss.c \ qssl.c rawstr.c curl_addrinfo.c socks_gssapi.c socks_sspi.c \ curl_sspi.c slist.c nonblock.c curl_memrchr.c imap.c pop3.c smtp.c \ pingpong.c rtsp.c curl_threads.c warnless.c hmac.c polarssl.c \ @@ -36,7 +36,7 @@ HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.h \ connect.h llist.h hash.h content_encoding.h share.h curl_md4.h \ curl_md5.h http_digest.h http_negotiate.h inet_pton.h amigaos.h \ strtoofft.h strerror.h inet_ntop.h curlx.h curl_memory.h curl_setup.h \ - transfer.h select.h easyif.h multiif.h parsedate.h sslgen.h gtls.h \ + transfer.h select.h easyif.h multiif.h parsedate.h vtls/sslgen.h gtls.h \ tftp.h sockaddr.h splay.h strdup.h socks.h ssh.h nssg.h curl_base64.h \ rawstr.h curl_addrinfo.h curl_sspi.h slist.h nonblock.h \ curl_memrchr.h imap.h pop3.h smtp.h pingpong.h rtsp.h curl_threads.h \ diff --git a/lib/connect.c b/lib/connect.c index a39699ba7..c85c7c783 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -71,7 +71,7 @@ #include "sockaddr.h" /* required for Curl_sockaddr_storage */ #include "inet_ntop.h" #include "inet_pton.h" -#include "sslgen.h" /* for Curl_ssl_check_cxn() */ +#include "vtls/sslgen.h" /* for Curl_ssl_check_cxn() */ #include "progress.h" #include "warnless.h" #include "conncache.h" diff --git a/lib/curl_ntlm_msgs.c b/lib/curl_ntlm_msgs.c index 125ce6e49..07c427f89 100644 --- a/lib/curl_ntlm_msgs.c +++ b/lib/curl_ntlm_msgs.c @@ -47,7 +47,7 @@ # include "curl_sspi.h" #endif -#include "sslgen.h" +#include "vtls/sslgen.h" #define BUILDING_CURL_NTLM_MSGS_C #include "curl_ntlm_msgs.h" diff --git a/lib/curl_sasl.c b/lib/curl_sasl.c index 240537283..e6a528abb 100644 --- a/lib/curl_sasl.c +++ b/lib/curl_sasl.c @@ -34,7 +34,7 @@ #include "curl_base64.h" #include "curl_md5.h" -#include "sslgen.h" +#include "vtls/sslgen.h" #include "curl_hmac.h" #include "curl_ntlm_msgs.h" #include "curl_sasl.h" diff --git a/lib/easy.c b/lib/easy.c index 1dbdcb768..0bd99ebdf 100644 --- a/lib/easy.c +++ b/lib/easy.c @@ -54,7 +54,7 @@ #include "urldata.h" #include #include "transfer.h" -#include "sslgen.h" +#include "vtls/sslgen.h" #include "url.h" #include "getinfo.h" #include "hostip.h" diff --git a/lib/formdata.c b/lib/formdata.c index f718a3e4e..4fbe92143 100644 --- a/lib/formdata.c +++ b/lib/formdata.c @@ -32,7 +32,7 @@ #include "urldata.h" /* for struct SessionHandle */ #include "formdata.h" -#include "sslgen.h" +#include "vtls/sslgen.h" #include "strequal.h" #include "curl_memory.h" #include "sendf.h" diff --git a/lib/ftp.c b/lib/ftp.c index abd70e070..07c000dbd 100644 --- a/lib/ftp.c +++ b/lib/ftp.c @@ -62,7 +62,7 @@ #include "curl_sec.h" #include "strtoofft.h" #include "strequal.h" -#include "sslgen.h" +#include "vtls/sslgen.h" #include "connect.h" #include "strerror.h" #include "inet_ntop.h" diff --git a/lib/getinfo.c b/lib/getinfo.c index c5c00e048..5db824da2 100644 --- a/lib/getinfo.c +++ b/lib/getinfo.c @@ -28,7 +28,7 @@ #include "getinfo.h" #include "curl_memory.h" -#include "sslgen.h" +#include "vtls/sslgen.h" #include "connect.h" /* Curl_getconnectinfo() */ #include "progress.h" diff --git a/lib/http.c b/lib/http.c index 459b98bca..510f4bbc5 100644 --- a/lib/http.c +++ b/lib/http.c @@ -54,7 +54,7 @@ #include "curl_base64.h" #include "cookie.h" #include "strequal.h" -#include "sslgen.h" +#include "vtls/sslgen.h" #include "http_digest.h" #include "curl_ntlm.h" #include "curl_ntlm_wb.h" diff --git a/lib/http_digest.c b/lib/http_digest.c index 581049dd3..cd26d5a2b 100644 --- a/lib/http_digest.c +++ b/lib/http_digest.c @@ -31,7 +31,7 @@ #include "http_digest.h" #include "strtok.h" #include "curl_memory.h" -#include "sslgen.h" /* for Curl_rand() */ +#include "vtls/sslgen.h" /* for Curl_rand() */ #include "non-ascii.h" /* included for Curl_convert_... prototypes */ #include "warnless.h" diff --git a/lib/imap.c b/lib/imap.c index bd03c76cd..d45751b79 100644 --- a/lib/imap.c +++ b/lib/imap.c @@ -71,7 +71,7 @@ #include "strtoofft.h" #include "strequal.h" -#include "sslgen.h" +#include "vtls/sslgen.h" #include "connect.h" #include "strerror.h" #include "select.h" diff --git a/lib/openldap.c b/lib/openldap.c index 98793b306..72e134160 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2010, Howard Chu, + * Copyright (C) 2010, 2013, Howard Chu, * Copyright (C) 2011 - 2013, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which @@ -41,7 +41,7 @@ #include "urldata.h" #include #include "sendf.h" -#include "sslgen.h" +#include "vtls/sslgen.h" #include "transfer.h" #include "curl_ldap.h" #include "curl_memory.h" diff --git a/lib/pingpong.c b/lib/pingpong.c index 3ebeabe53..420197e69 100644 --- a/lib/pingpong.c +++ b/lib/pingpong.c @@ -33,7 +33,7 @@ #include "pingpong.h" #include "multiif.h" #include "non-ascii.h" -#include "sslgen.h" +#include "vtls/sslgen.h" #define _MPRINTF_REPLACE /* use our functions only */ #include diff --git a/lib/pop3.c b/lib/pop3.c index eb0164862..40a2b2fdb 100644 --- a/lib/pop3.c +++ b/lib/pop3.c @@ -73,7 +73,7 @@ #include "strtoofft.h" #include "strequal.h" -#include "sslgen.h" +#include "vtls/sslgen.h" #include "connect.h" #include "strerror.h" #include "select.h" diff --git a/lib/sendf.c b/lib/sendf.c index 7b6fca610..70a65de4e 100644 --- a/lib/sendf.c +++ b/lib/sendf.c @@ -27,7 +27,7 @@ #include "urldata.h" #include "sendf.h" #include "connect.h" -#include "sslgen.h" +#include "vtls/sslgen.h" #include "ssh.h" #include "multiif.h" #include "non-ascii.h" diff --git a/lib/share.c b/lib/share.c index b21c9f685..a71a26908 100644 --- a/lib/share.c +++ b/lib/share.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2013, 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 @@ -25,7 +25,7 @@ #include #include "urldata.h" #include "share.h" -#include "sslgen.h" +#include "vtls/sslgen.h" #include "curl_memory.h" /* The last #include file should be: */ diff --git a/lib/smtp.c b/lib/smtp.c index f35f7537e..e7e8bf1cc 100644 --- a/lib/smtp.c +++ b/lib/smtp.c @@ -72,7 +72,7 @@ #include "strtoofft.h" #include "strequal.h" -#include "sslgen.h" +#include "vtls/sslgen.h" #include "connect.h" #include "strerror.h" #include "select.h" diff --git a/lib/ssh.c b/lib/ssh.c index 35cb20193..fb3255e9d 100644 --- a/lib/ssh.c +++ b/lib/ssh.c @@ -73,7 +73,7 @@ #include "getinfo.h" #include "strequal.h" -#include "sslgen.h" +#include "vtls/sslgen.h" #include "connect.h" #include "strerror.h" #include "inet_ntop.h" diff --git a/lib/sslgen.c b/lib/sslgen.c deleted file mode 100644 index 887b95ff4..000000000 --- a/lib/sslgen.c +++ /dev/null @@ -1,689 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2013, 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 - * 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. - * - ***************************************************************************/ - -/* This file is for implementing all "generic" SSL functions that all libcurl - internals should use. It is then responsible for calling the proper - "backend" function. - - SSL-functions in libcurl should call functions in this source file, and not - to any specific SSL-layer. - - Curl_ssl_ - prefix for generic ones - Curl_ossl_ - prefix for OpenSSL ones - Curl_gtls_ - prefix for GnuTLS ones - Curl_nss_ - prefix for NSS ones - Curl_qssl_ - prefix for QsoSSL ones - Curl_gskit_ - prefix for GSKit ones - Curl_polarssl_ - prefix for PolarSSL ones - Curl_cyassl_ - prefix for CyaSSL ones - Curl_schannel_ - prefix for Schannel SSPI ones - Curl_darwinssl_ - prefix for SecureTransport (Darwin) ones - - Note that this source code uses curlssl_* functions, and they are all - defines/macros #defined by the lib-specific header files. - - "SSL/TLS Strong Encryption: An Introduction" - http://httpd.apache.org/docs-2.0/ssl/ssl_intro.html -*/ - -#include "curl_setup.h" - -#ifdef HAVE_SYS_TYPES_H -#include -#endif -#ifdef HAVE_SYS_STAT_H -#include -#endif -#ifdef HAVE_FCNTL_H -#include -#endif - -#include "urldata.h" -#define SSLGEN_C -#include "sslgen.h" /* generic SSL protos etc */ -#include "ssluse.h" /* OpenSSL versions */ -#include "gtls.h" /* GnuTLS versions */ -#include "nssg.h" /* NSS versions */ -#include "qssl.h" /* QSOSSL versions */ -#include "gskit.h" /* Global Secure ToolKit versions */ -#include "polarssl.h" /* PolarSSL versions */ -#include "axtls.h" /* axTLS versions */ -#include "cyassl.h" /* CyaSSL versions */ -#include "curl_schannel.h" /* Schannel SSPI version */ -#include "curl_darwinssl.h" /* SecureTransport (Darwin) version */ -#include "slist.h" -#include "sendf.h" -#include "rawstr.h" -#include "url.h" -#include "curl_memory.h" -#include "progress.h" -#include "share.h" -#include "timeval.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -/* The last #include file should be: */ -#include "memdebug.h" - -/* convenience macro to check if this handle is using a shared SSL session */ -#define SSLSESSION_SHARED(data) (data->share && \ - (data->share->specifier & \ - (1<version == needle->version) && - (data->verifypeer == needle->verifypeer) && - (data->verifyhost == needle->verifyhost) && - safe_strequal(data->CApath, needle->CApath) && - safe_strequal(data->CAfile, needle->CAfile) && - safe_strequal(data->random_file, needle->random_file) && - safe_strequal(data->egdsocket, needle->egdsocket) && - safe_strequal(data->cipher_list, needle->cipher_list)) - return TRUE; - - return FALSE; -} - -bool -Curl_clone_ssl_config(struct ssl_config_data *source, - struct ssl_config_data *dest) -{ - dest->sessionid = source->sessionid; - dest->verifyhost = source->verifyhost; - dest->verifypeer = source->verifypeer; - dest->version = source->version; - - if(source->CAfile) { - dest->CAfile = strdup(source->CAfile); - if(!dest->CAfile) - return FALSE; - } - else - dest->CAfile = NULL; - - if(source->CApath) { - dest->CApath = strdup(source->CApath); - if(!dest->CApath) - return FALSE; - } - else - dest->CApath = NULL; - - if(source->cipher_list) { - dest->cipher_list = strdup(source->cipher_list); - if(!dest->cipher_list) - return FALSE; - } - else - dest->cipher_list = NULL; - - if(source->egdsocket) { - dest->egdsocket = strdup(source->egdsocket); - if(!dest->egdsocket) - return FALSE; - } - else - dest->egdsocket = NULL; - - if(source->random_file) { - dest->random_file = strdup(source->random_file); - if(!dest->random_file) - return FALSE; - } - else - dest->random_file = NULL; - - return TRUE; -} - -void Curl_free_ssl_config(struct ssl_config_data* sslc) -{ - Curl_safefree(sslc->CAfile); - Curl_safefree(sslc->CApath); - Curl_safefree(sslc->cipher_list); - Curl_safefree(sslc->egdsocket); - Curl_safefree(sslc->random_file); -} - - -/* - * Curl_rand() returns a random unsigned integer, 32bit. - * - * This non-SSL function is put here only because this file is the only one - * with knowledge of what the underlying SSL libraries provide in terms of - * randomizers. - * - * NOTE: 'data' may be passed in as NULL when coming from external API without - * easy handle! - * - */ - -unsigned int Curl_rand(struct SessionHandle *data) -{ - unsigned int r; - static unsigned int randseed; - static bool seeded = FALSE; - -#ifndef have_curlssl_random - (void)data; -#else - if(data) { - Curl_ssl_random(data, (unsigned char *)&r, sizeof(r)); - return r; - } -#endif - -#ifdef RANDOM_FILE - if(!seeded) { - /* if there's a random file to read a seed from, use it */ - int fd = open(RANDOM_FILE, O_RDONLY); - if(fd > -1) { - /* read random data into the randseed variable */ - ssize_t nread = read(fd, &randseed, sizeof(randseed)); - if(nread == sizeof(randseed)) - seeded = TRUE; - close(fd); - } - } -#endif - - if(!seeded) { - struct timeval now = curlx_tvnow(); - randseed += (unsigned int)now.tv_usec + (unsigned int)now.tv_sec; - randseed = randseed * 1103515245 + 12345; - randseed = randseed * 1103515245 + 12345; - randseed = randseed * 1103515245 + 12345; - seeded = TRUE; - } - - /* Return an unsigned 32-bit pseudo-random number. */ - r = randseed = randseed * 1103515245 + 12345; - return (r << 16) | ((r >> 16) & 0xFFFF); -} - -#ifdef USE_SSL - -/* "global" init done? */ -static bool init_ssl=FALSE; - -/** - * Global SSL init - * - * @retval 0 error initializing SSL - * @retval 1 SSL initialized successfully - */ -int Curl_ssl_init(void) -{ - /* make sure this is only done once */ - if(init_ssl) - return 1; - init_ssl = TRUE; /* never again */ - - return curlssl_init(); -} - - -/* Global cleanup */ -void Curl_ssl_cleanup(void) -{ - if(init_ssl) { - /* only cleanup if we did a previous init */ - curlssl_cleanup(); - init_ssl = FALSE; - } -} - -CURLcode -Curl_ssl_connect(struct connectdata *conn, int sockindex) -{ - CURLcode res; - /* mark this is being ssl-enabled from here on. */ - conn->ssl[sockindex].use = TRUE; - conn->ssl[sockindex].state = ssl_connection_negotiating; - - res = curlssl_connect(conn, sockindex); - - if(!res) - Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */ - - return res; -} - -CURLcode -Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex, - bool *done) -{ - CURLcode res; - /* mark this is being ssl requested from here on. */ - conn->ssl[sockindex].use = TRUE; -#ifdef curlssl_connect_nonblocking - res = curlssl_connect_nonblocking(conn, sockindex, done); -#else - *done = TRUE; /* fallback to BLOCKING */ - res = curlssl_connect(conn, sockindex); -#endif /* non-blocking connect support */ - if(!res && *done) - Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */ - return res; -} - -/* - * Check if there's a session ID for the given connection in the cache, and if - * there's one suitable, it is provided. Returns TRUE when no entry matched. - */ -int Curl_ssl_getsessionid(struct connectdata *conn, - void **ssl_sessionid, - size_t *idsize) /* set 0 if unknown */ -{ - struct curl_ssl_session *check; - struct SessionHandle *data = conn->data; - size_t i; - long *general_age; - bool no_match = TRUE; - - *ssl_sessionid = NULL; - - if(!conn->ssl_config.sessionid) - /* session ID re-use is disabled */ - return TRUE; - - /* Lock if shared */ - if(SSLSESSION_SHARED(data)) { - Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE); - general_age = &data->share->sessionage; - } - else - general_age = &data->state.sessionage; - - for(i = 0; i < data->set.ssl.max_ssl_sessions; i++) { - check = &data->state.session[i]; - if(!check->sessionid) - /* not session ID means blank entry */ - continue; - if(Curl_raw_equal(conn->host.name, check->name) && - (conn->remote_port == check->remote_port) && - Curl_ssl_config_matches(&conn->ssl_config, &check->ssl_config)) { - /* yes, we have a session ID! */ - (*general_age)++; /* increase general age */ - check->age = *general_age; /* set this as used in this age */ - *ssl_sessionid = check->sessionid; - if(idsize) - *idsize = check->idsize; - no_match = FALSE; - break; - } - } - - /* Unlock */ - if(SSLSESSION_SHARED(data)) - Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION); - - return no_match; -} - -/* - * Kill a single session ID entry in the cache. - */ -void Curl_ssl_kill_session(struct curl_ssl_session *session) -{ - if(session->sessionid) { - /* defensive check */ - - /* free the ID the SSL-layer specific way */ - curlssl_session_free(session->sessionid); - - session->sessionid = NULL; - session->age = 0; /* fresh */ - - Curl_free_ssl_config(&session->ssl_config); - - Curl_safefree(session->name); - } -} - -/* - * Delete the given session ID from the cache. - */ -void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid) -{ - size_t i; - struct SessionHandle *data=conn->data; - - if(SSLSESSION_SHARED(data)) - Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE); - - for(i = 0; i < data->set.ssl.max_ssl_sessions; i++) { - struct curl_ssl_session *check = &data->state.session[i]; - - if(check->sessionid == ssl_sessionid) { - Curl_ssl_kill_session(check); - break; - } - } - - if(SSLSESSION_SHARED(data)) - Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION); -} - -/* - * Store session id in the session cache. The ID passed on to this function - * must already have been extracted and allocated the proper way for the SSL - * layer. Curl_XXXX_session_free() will be called to free/kill the session ID - * later on. - */ -CURLcode Curl_ssl_addsessionid(struct connectdata *conn, - void *ssl_sessionid, - size_t idsize) -{ - size_t i; - struct SessionHandle *data=conn->data; /* the mother of all structs */ - struct curl_ssl_session *store = &data->state.session[0]; - long oldest_age=data->state.session[0].age; /* zero if unused */ - char *clone_host; - long *general_age; - - /* Even though session ID re-use might be disabled, that only disables USING - IT. We still store it here in case the re-using is again enabled for an - upcoming transfer */ - - clone_host = strdup(conn->host.name); - if(!clone_host) - return CURLE_OUT_OF_MEMORY; /* bail out */ - - /* Now we should add the session ID and the host name to the cache, (remove - the oldest if necessary) */ - - /* If using shared SSL session, lock! */ - if(SSLSESSION_SHARED(data)) { - Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE); - general_age = &data->share->sessionage; - } - else { - general_age = &data->state.sessionage; - } - - /* find an empty slot for us, or find the oldest */ - for(i = 1; (i < data->set.ssl.max_ssl_sessions) && - data->state.session[i].sessionid; i++) { - if(data->state.session[i].age < oldest_age) { - oldest_age = data->state.session[i].age; - store = &data->state.session[i]; - } - } - if(i == data->set.ssl.max_ssl_sessions) - /* cache is full, we must "kill" the oldest entry! */ - Curl_ssl_kill_session(store); - else - store = &data->state.session[i]; /* use this slot */ - - /* now init the session struct wisely */ - store->sessionid = ssl_sessionid; - store->idsize = idsize; - store->age = *general_age; /* set current age */ - if(store->name) - /* free it if there's one already present */ - free(store->name); - store->name = clone_host; /* clone host name */ - store->remote_port = conn->remote_port; /* port number */ - - - /* Unlock */ - if(SSLSESSION_SHARED(data)) - Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION); - - if(!Curl_clone_ssl_config(&conn->ssl_config, &store->ssl_config)) { - store->sessionid = NULL; /* let caller free sessionid */ - free(clone_host); - return CURLE_OUT_OF_MEMORY; - } - - return CURLE_OK; -} - - -void Curl_ssl_close_all(struct SessionHandle *data) -{ - size_t i; - /* kill the session ID cache if not shared */ - if(data->state.session && !SSLSESSION_SHARED(data)) { - for(i = 0; i < data->set.ssl.max_ssl_sessions; i++) - /* the single-killer function handles empty table slots */ - Curl_ssl_kill_session(&data->state.session[i]); - - /* free the cache data */ - Curl_safefree(data->state.session); - } - - curlssl_close_all(data); -} - -void Curl_ssl_close(struct connectdata *conn, int sockindex) -{ - DEBUGASSERT((sockindex <= 1) && (sockindex >= -1)); - curlssl_close(conn, sockindex); -} - -CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex) -{ - if(curlssl_shutdown(conn, sockindex)) - return CURLE_SSL_SHUTDOWN_FAILED; - - conn->ssl[sockindex].use = FALSE; /* get back to ordinary socket usage */ - conn->ssl[sockindex].state = ssl_connection_none; - - conn->recv[sockindex] = Curl_recv_plain; - conn->send[sockindex] = Curl_send_plain; - - return CURLE_OK; -} - -/* Selects an SSL crypto engine - */ -CURLcode Curl_ssl_set_engine(struct SessionHandle *data, const char *engine) -{ - return curlssl_set_engine(data, engine); -} - -/* Selects the default SSL crypto engine - */ -CURLcode Curl_ssl_set_engine_default(struct SessionHandle *data) -{ - return curlssl_set_engine_default(data); -} - -/* Return list of OpenSSL crypto engine names. */ -struct curl_slist *Curl_ssl_engines_list(struct SessionHandle *data) -{ - return curlssl_engines_list(data); -} - -/* - * This sets up a session ID cache to the specified size. Make sure this code - * is agnostic to what underlying SSL technology we use. - */ -CURLcode Curl_ssl_initsessions(struct SessionHandle *data, size_t amount) -{ - struct curl_ssl_session *session; - - if(data->state.session) - /* this is just a precaution to prevent multiple inits */ - return CURLE_OK; - - session = calloc(amount, sizeof(struct curl_ssl_session)); - if(!session) - return CURLE_OUT_OF_MEMORY; - - /* store the info in the SSL section */ - data->set.ssl.max_ssl_sessions = amount; - data->state.session = session; - data->state.sessionage = 1; /* this is brand new */ - return CURLE_OK; -} - -size_t Curl_ssl_version(char *buffer, size_t size) -{ - return curlssl_version(buffer, size); -} - -/* - * This function tries 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_ssl_check_cxn(struct connectdata *conn) -{ - return curlssl_check_cxn(conn); -} - -bool Curl_ssl_data_pending(const struct connectdata *conn, - int connindex) -{ - return curlssl_data_pending(conn, connindex); -} - -void Curl_ssl_free_certinfo(struct SessionHandle *data) -{ - int i; - struct curl_certinfo *ci = &data->info.certs; - if(ci->num_of_certs) { - /* free all individual lists used */ - for(i=0; inum_of_certs; i++) { - curl_slist_free_all(ci->certinfo[i]); - ci->certinfo[i] = NULL; - } - free(ci->certinfo); /* free the actual array too */ - ci->certinfo = NULL; - ci->num_of_certs = 0; - } -} - -int Curl_ssl_init_certinfo(struct SessionHandle * data, - int num) -{ - struct curl_certinfo * ci = &data->info.certs; - struct curl_slist * * table; - - /* Initialize the certificate information structures. Return 0 if OK, else 1. - */ - Curl_ssl_free_certinfo(data); - ci->num_of_certs = num; - table = calloc((size_t) num, sizeof(struct curl_slist *)); - if(!table) - return 1; - - ci->certinfo = table; - return 0; -} - -/* - * 'value' is NOT a zero terminated string - */ -CURLcode Curl_ssl_push_certinfo_len(struct SessionHandle *data, - int certnum, - const char *label, - const char *value, - size_t valuelen) -{ - struct curl_certinfo * ci = &data->info.certs; - char * output; - struct curl_slist * nl; - CURLcode res = CURLE_OK; - size_t labellen = strlen(label); - size_t outlen = labellen + 1 + valuelen + 1; /* label:value\0 */ - - output = malloc(outlen); - if(!output) - return CURLE_OUT_OF_MEMORY; - - /* sprintf the label and colon */ - snprintf(output, outlen, "%s:", label); - - /* memcpy the value (it might not be zero terminated) */ - memcpy(&output[labellen+1], value, valuelen); - - /* zero terminate the output */ - output[labellen + 1 + valuelen] = 0; - - nl = Curl_slist_append_nodup(ci->certinfo[certnum], output); - if(!nl) { - free(output); - curl_slist_free_all(ci->certinfo[certnum]); - res = CURLE_OUT_OF_MEMORY; - } - - ci->certinfo[certnum] = nl; - return res; -} - -/* - * This is a convenience function for push_certinfo_len that takes a zero - * terminated value. - */ -CURLcode Curl_ssl_push_certinfo(struct SessionHandle *data, - int certnum, - const char *label, - const char *value) -{ - size_t valuelen = strlen(value); - - return Curl_ssl_push_certinfo_len(data, certnum, label, value, valuelen); -} - -/* these functions are only provided by some SSL backends */ - -#ifdef have_curlssl_random -void Curl_ssl_random(struct SessionHandle *data, - unsigned char *entropy, - size_t length) -{ - curlssl_random(data, entropy, length); -} -#endif - -#ifdef have_curlssl_md5sum -void Curl_ssl_md5sum(unsigned char *tmp, /* input */ - size_t tmplen, - unsigned char *md5sum, /* output */ - size_t md5len) -{ - curlssl_md5sum(tmp, tmplen, md5sum, md5len); -} -#endif - -#endif /* USE_SSL */ diff --git a/lib/sslgen.h b/lib/sslgen.h deleted file mode 100644 index c7f5f0092..000000000 --- a/lib/sslgen.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef HEADER_CURL_SSLGEN_H -#define HEADER_CURL_SSLGEN_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 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 - * 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. - * - ***************************************************************************/ -#include "curl_setup.h" - -#ifndef MD5_DIGEST_LENGTH -#define MD5_DIGEST_LENGTH 16 /* fixed size */ -#endif - -bool Curl_ssl_config_matches(struct ssl_config_data* data, - struct ssl_config_data* needle); -bool Curl_clone_ssl_config(struct ssl_config_data* source, - struct ssl_config_data* dest); -void Curl_free_ssl_config(struct ssl_config_data* sslc); - -unsigned int Curl_rand(struct SessionHandle *); - -#ifdef USE_SSL -int Curl_ssl_init(void); -void Curl_ssl_cleanup(void); -CURLcode Curl_ssl_connect(struct connectdata *conn, int sockindex); -CURLcode Curl_ssl_connect_nonblocking(struct connectdata *conn, - int sockindex, - bool *done); -/* tell the SSL stuff to close down all open information regarding - connections (and thus session ID caching etc) */ -void Curl_ssl_close_all(struct SessionHandle *data); -void Curl_ssl_close(struct connectdata *conn, int sockindex); -CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex); -CURLcode Curl_ssl_set_engine(struct SessionHandle *data, const char *engine); -/* Sets engine as default for all SSL operations */ -CURLcode Curl_ssl_set_engine_default(struct SessionHandle *data); -struct curl_slist *Curl_ssl_engines_list(struct SessionHandle *data); - -/* init the SSL session ID cache */ -CURLcode Curl_ssl_initsessions(struct SessionHandle *, size_t); -size_t Curl_ssl_version(char *buffer, size_t size); -bool Curl_ssl_data_pending(const struct connectdata *conn, - int connindex); -int Curl_ssl_check_cxn(struct connectdata *conn); - -/* Certificate information list handling. */ - -void Curl_ssl_free_certinfo(struct SessionHandle *data); -int Curl_ssl_init_certinfo(struct SessionHandle * data, int num); -CURLcode Curl_ssl_push_certinfo_len(struct SessionHandle * data, int certnum, - const char * label, const char * value, - size_t valuelen); -CURLcode Curl_ssl_push_certinfo(struct SessionHandle * data, int certnum, - const char * label, const char * value); - -/* Functions to be used by SSL library adaptation functions */ - -/* extract a session ID */ -int Curl_ssl_getsessionid(struct connectdata *conn, - void **ssl_sessionid, - size_t *idsize) /* set 0 if unknown */; -/* add a new session ID */ -CURLcode Curl_ssl_addsessionid(struct connectdata *conn, - void *ssl_sessionid, - size_t idsize); -/* Kill a single session ID entry in the cache */ -void Curl_ssl_kill_session(struct curl_ssl_session *session); -/* delete a session from the cache */ -void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid); - -/* get N random bytes into the buffer */ -void Curl_ssl_random(struct SessionHandle *data, unsigned char *buffer, - size_t length); -void Curl_ssl_md5sum(unsigned char *tmp, /* input */ - size_t tmplen, - unsigned char *md5sum, /* output */ - size_t md5len); - -#define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */ - -#ifdef have_curlssl_random -#define HAVE_CURL_SSL_RANDOM -#endif -#ifdef have_curlssl_md5sum -#define HAVE_CURL_SSL_MD5SUM -#endif - -#else -/* When SSL support is not present, just define away these function calls */ -#define Curl_ssl_init() 1 -#define Curl_ssl_cleanup() Curl_nop_stmt -#define Curl_ssl_connect(x,y) CURLE_NOT_BUILT_IN -#define Curl_ssl_close_all(x) Curl_nop_stmt -#define Curl_ssl_close(x,y) Curl_nop_stmt -#define Curl_ssl_shutdown(x,y) CURLE_NOT_BUILT_IN -#define Curl_ssl_set_engine(x,y) CURLE_NOT_BUILT_IN -#define Curl_ssl_set_engine_default(x) CURLE_NOT_BUILT_IN -#define Curl_ssl_engines_list(x) NULL -#define Curl_ssl_send(a,b,c,d,e) -1 -#define Curl_ssl_recv(a,b,c,d,e) -1 -#define Curl_ssl_initsessions(x,y) CURLE_OK -#define Curl_ssl_version(x,y) 0 -#define Curl_ssl_data_pending(x,y) 0 -#define Curl_ssl_check_cxn(x) 0 -#define Curl_ssl_free_certinfo(x) Curl_nop_stmt -#define Curl_ssl_connect_nonblocking(x,y,z) CURLE_NOT_BUILT_IN -#define Curl_ssl_kill_session(x) Curl_nop_stmt -#endif - -#endif /* HEADER_CURL_SSLGEN_H */ diff --git a/lib/ssluse.c b/lib/ssluse.c index d0a83f740..3743170a9 100644 --- a/lib/ssluse.c +++ b/lib/ssluse.c @@ -46,7 +46,7 @@ #include "slist.h" #include "strequal.h" #include "select.h" -#include "sslgen.h" +#include "vtls/sslgen.h" #include "rawstr.h" #include "hostcheck.h" diff --git a/lib/transfer.c b/lib/transfer.c index e3194415b..c199b4f67 100644 --- a/lib/transfer.c +++ b/lib/transfer.c @@ -70,7 +70,7 @@ #include "http.h" #include "url.h" #include "getinfo.h" -#include "sslgen.h" +#include "vtls/sslgen.h" #include "http_digest.h" #include "curl_ntlm.h" #include "http_negotiate.h" diff --git a/lib/url.c b/lib/url.c index 5903628c9..5a70c9241 100644 --- a/lib/url.c +++ b/lib/url.c @@ -78,7 +78,7 @@ int curl_win32_idn_to_ascii(const char *in, char **out); #include "netrc.h" #include "formdata.h" -#include "sslgen.h" +#include "vtls/sslgen.h" #include "hostip.h" #include "transfer.h" #include "sendf.h" diff --git a/lib/version.c b/lib/version.c index 1f62131eb..e82698e4e 100644 --- a/lib/version.c +++ b/lib/version.c @@ -24,7 +24,7 @@ #include #include "urldata.h" -#include "sslgen.h" +#include "vtls/sslgen.h" #include "http2.h" #define _MPRINTF_REPLACE /* use the internal *printf() functions */ diff --git a/lib/vtls/sslgen.c b/lib/vtls/sslgen.c new file mode 100644 index 000000000..887b95ff4 --- /dev/null +++ b/lib/vtls/sslgen.c @@ -0,0 +1,689 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2013, 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 + * 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. + * + ***************************************************************************/ + +/* This file is for implementing all "generic" SSL functions that all libcurl + internals should use. It is then responsible for calling the proper + "backend" function. + + SSL-functions in libcurl should call functions in this source file, and not + to any specific SSL-layer. + + Curl_ssl_ - prefix for generic ones + Curl_ossl_ - prefix for OpenSSL ones + Curl_gtls_ - prefix for GnuTLS ones + Curl_nss_ - prefix for NSS ones + Curl_qssl_ - prefix for QsoSSL ones + Curl_gskit_ - prefix for GSKit ones + Curl_polarssl_ - prefix for PolarSSL ones + Curl_cyassl_ - prefix for CyaSSL ones + Curl_schannel_ - prefix for Schannel SSPI ones + Curl_darwinssl_ - prefix for SecureTransport (Darwin) ones + + Note that this source code uses curlssl_* functions, and they are all + defines/macros #defined by the lib-specific header files. + + "SSL/TLS Strong Encryption: An Introduction" + http://httpd.apache.org/docs-2.0/ssl/ssl_intro.html +*/ + +#include "curl_setup.h" + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif + +#include "urldata.h" +#define SSLGEN_C +#include "sslgen.h" /* generic SSL protos etc */ +#include "ssluse.h" /* OpenSSL versions */ +#include "gtls.h" /* GnuTLS versions */ +#include "nssg.h" /* NSS versions */ +#include "qssl.h" /* QSOSSL versions */ +#include "gskit.h" /* Global Secure ToolKit versions */ +#include "polarssl.h" /* PolarSSL versions */ +#include "axtls.h" /* axTLS versions */ +#include "cyassl.h" /* CyaSSL versions */ +#include "curl_schannel.h" /* Schannel SSPI version */ +#include "curl_darwinssl.h" /* SecureTransport (Darwin) version */ +#include "slist.h" +#include "sendf.h" +#include "rawstr.h" +#include "url.h" +#include "curl_memory.h" +#include "progress.h" +#include "share.h" +#include "timeval.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include + +/* The last #include file should be: */ +#include "memdebug.h" + +/* convenience macro to check if this handle is using a shared SSL session */ +#define SSLSESSION_SHARED(data) (data->share && \ + (data->share->specifier & \ + (1<version == needle->version) && + (data->verifypeer == needle->verifypeer) && + (data->verifyhost == needle->verifyhost) && + safe_strequal(data->CApath, needle->CApath) && + safe_strequal(data->CAfile, needle->CAfile) && + safe_strequal(data->random_file, needle->random_file) && + safe_strequal(data->egdsocket, needle->egdsocket) && + safe_strequal(data->cipher_list, needle->cipher_list)) + return TRUE; + + return FALSE; +} + +bool +Curl_clone_ssl_config(struct ssl_config_data *source, + struct ssl_config_data *dest) +{ + dest->sessionid = source->sessionid; + dest->verifyhost = source->verifyhost; + dest->verifypeer = source->verifypeer; + dest->version = source->version; + + if(source->CAfile) { + dest->CAfile = strdup(source->CAfile); + if(!dest->CAfile) + return FALSE; + } + else + dest->CAfile = NULL; + + if(source->CApath) { + dest->CApath = strdup(source->CApath); + if(!dest->CApath) + return FALSE; + } + else + dest->CApath = NULL; + + if(source->cipher_list) { + dest->cipher_list = strdup(source->cipher_list); + if(!dest->cipher_list) + return FALSE; + } + else + dest->cipher_list = NULL; + + if(source->egdsocket) { + dest->egdsocket = strdup(source->egdsocket); + if(!dest->egdsocket) + return FALSE; + } + else + dest->egdsocket = NULL; + + if(source->random_file) { + dest->random_file = strdup(source->random_file); + if(!dest->random_file) + return FALSE; + } + else + dest->random_file = NULL; + + return TRUE; +} + +void Curl_free_ssl_config(struct ssl_config_data* sslc) +{ + Curl_safefree(sslc->CAfile); + Curl_safefree(sslc->CApath); + Curl_safefree(sslc->cipher_list); + Curl_safefree(sslc->egdsocket); + Curl_safefree(sslc->random_file); +} + + +/* + * Curl_rand() returns a random unsigned integer, 32bit. + * + * This non-SSL function is put here only because this file is the only one + * with knowledge of what the underlying SSL libraries provide in terms of + * randomizers. + * + * NOTE: 'data' may be passed in as NULL when coming from external API without + * easy handle! + * + */ + +unsigned int Curl_rand(struct SessionHandle *data) +{ + unsigned int r; + static unsigned int randseed; + static bool seeded = FALSE; + +#ifndef have_curlssl_random + (void)data; +#else + if(data) { + Curl_ssl_random(data, (unsigned char *)&r, sizeof(r)); + return r; + } +#endif + +#ifdef RANDOM_FILE + if(!seeded) { + /* if there's a random file to read a seed from, use it */ + int fd = open(RANDOM_FILE, O_RDONLY); + if(fd > -1) { + /* read random data into the randseed variable */ + ssize_t nread = read(fd, &randseed, sizeof(randseed)); + if(nread == sizeof(randseed)) + seeded = TRUE; + close(fd); + } + } +#endif + + if(!seeded) { + struct timeval now = curlx_tvnow(); + randseed += (unsigned int)now.tv_usec + (unsigned int)now.tv_sec; + randseed = randseed * 1103515245 + 12345; + randseed = randseed * 1103515245 + 12345; + randseed = randseed * 1103515245 + 12345; + seeded = TRUE; + } + + /* Return an unsigned 32-bit pseudo-random number. */ + r = randseed = randseed * 1103515245 + 12345; + return (r << 16) | ((r >> 16) & 0xFFFF); +} + +#ifdef USE_SSL + +/* "global" init done? */ +static bool init_ssl=FALSE; + +/** + * Global SSL init + * + * @retval 0 error initializing SSL + * @retval 1 SSL initialized successfully + */ +int Curl_ssl_init(void) +{ + /* make sure this is only done once */ + if(init_ssl) + return 1; + init_ssl = TRUE; /* never again */ + + return curlssl_init(); +} + + +/* Global cleanup */ +void Curl_ssl_cleanup(void) +{ + if(init_ssl) { + /* only cleanup if we did a previous init */ + curlssl_cleanup(); + init_ssl = FALSE; + } +} + +CURLcode +Curl_ssl_connect(struct connectdata *conn, int sockindex) +{ + CURLcode res; + /* mark this is being ssl-enabled from here on. */ + conn->ssl[sockindex].use = TRUE; + conn->ssl[sockindex].state = ssl_connection_negotiating; + + res = curlssl_connect(conn, sockindex); + + if(!res) + Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */ + + return res; +} + +CURLcode +Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex, + bool *done) +{ + CURLcode res; + /* mark this is being ssl requested from here on. */ + conn->ssl[sockindex].use = TRUE; +#ifdef curlssl_connect_nonblocking + res = curlssl_connect_nonblocking(conn, sockindex, done); +#else + *done = TRUE; /* fallback to BLOCKING */ + res = curlssl_connect(conn, sockindex); +#endif /* non-blocking connect support */ + if(!res && *done) + Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */ + return res; +} + +/* + * Check if there's a session ID for the given connection in the cache, and if + * there's one suitable, it is provided. Returns TRUE when no entry matched. + */ +int Curl_ssl_getsessionid(struct connectdata *conn, + void **ssl_sessionid, + size_t *idsize) /* set 0 if unknown */ +{ + struct curl_ssl_session *check; + struct SessionHandle *data = conn->data; + size_t i; + long *general_age; + bool no_match = TRUE; + + *ssl_sessionid = NULL; + + if(!conn->ssl_config.sessionid) + /* session ID re-use is disabled */ + return TRUE; + + /* Lock if shared */ + if(SSLSESSION_SHARED(data)) { + Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE); + general_age = &data->share->sessionage; + } + else + general_age = &data->state.sessionage; + + for(i = 0; i < data->set.ssl.max_ssl_sessions; i++) { + check = &data->state.session[i]; + if(!check->sessionid) + /* not session ID means blank entry */ + continue; + if(Curl_raw_equal(conn->host.name, check->name) && + (conn->remote_port == check->remote_port) && + Curl_ssl_config_matches(&conn->ssl_config, &check->ssl_config)) { + /* yes, we have a session ID! */ + (*general_age)++; /* increase general age */ + check->age = *general_age; /* set this as used in this age */ + *ssl_sessionid = check->sessionid; + if(idsize) + *idsize = check->idsize; + no_match = FALSE; + break; + } + } + + /* Unlock */ + if(SSLSESSION_SHARED(data)) + Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION); + + return no_match; +} + +/* + * Kill a single session ID entry in the cache. + */ +void Curl_ssl_kill_session(struct curl_ssl_session *session) +{ + if(session->sessionid) { + /* defensive check */ + + /* free the ID the SSL-layer specific way */ + curlssl_session_free(session->sessionid); + + session->sessionid = NULL; + session->age = 0; /* fresh */ + + Curl_free_ssl_config(&session->ssl_config); + + Curl_safefree(session->name); + } +} + +/* + * Delete the given session ID from the cache. + */ +void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid) +{ + size_t i; + struct SessionHandle *data=conn->data; + + if(SSLSESSION_SHARED(data)) + Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE); + + for(i = 0; i < data->set.ssl.max_ssl_sessions; i++) { + struct curl_ssl_session *check = &data->state.session[i]; + + if(check->sessionid == ssl_sessionid) { + Curl_ssl_kill_session(check); + break; + } + } + + if(SSLSESSION_SHARED(data)) + Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION); +} + +/* + * Store session id in the session cache. The ID passed on to this function + * must already have been extracted and allocated the proper way for the SSL + * layer. Curl_XXXX_session_free() will be called to free/kill the session ID + * later on. + */ +CURLcode Curl_ssl_addsessionid(struct connectdata *conn, + void *ssl_sessionid, + size_t idsize) +{ + size_t i; + struct SessionHandle *data=conn->data; /* the mother of all structs */ + struct curl_ssl_session *store = &data->state.session[0]; + long oldest_age=data->state.session[0].age; /* zero if unused */ + char *clone_host; + long *general_age; + + /* Even though session ID re-use might be disabled, that only disables USING + IT. We still store it here in case the re-using is again enabled for an + upcoming transfer */ + + clone_host = strdup(conn->host.name); + if(!clone_host) + return CURLE_OUT_OF_MEMORY; /* bail out */ + + /* Now we should add the session ID and the host name to the cache, (remove + the oldest if necessary) */ + + /* If using shared SSL session, lock! */ + if(SSLSESSION_SHARED(data)) { + Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE); + general_age = &data->share->sessionage; + } + else { + general_age = &data->state.sessionage; + } + + /* find an empty slot for us, or find the oldest */ + for(i = 1; (i < data->set.ssl.max_ssl_sessions) && + data->state.session[i].sessionid; i++) { + if(data->state.session[i].age < oldest_age) { + oldest_age = data->state.session[i].age; + store = &data->state.session[i]; + } + } + if(i == data->set.ssl.max_ssl_sessions) + /* cache is full, we must "kill" the oldest entry! */ + Curl_ssl_kill_session(store); + else + store = &data->state.session[i]; /* use this slot */ + + /* now init the session struct wisely */ + store->sessionid = ssl_sessionid; + store->idsize = idsize; + store->age = *general_age; /* set current age */ + if(store->name) + /* free it if there's one already present */ + free(store->name); + store->name = clone_host; /* clone host name */ + store->remote_port = conn->remote_port; /* port number */ + + + /* Unlock */ + if(SSLSESSION_SHARED(data)) + Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION); + + if(!Curl_clone_ssl_config(&conn->ssl_config, &store->ssl_config)) { + store->sessionid = NULL; /* let caller free sessionid */ + free(clone_host); + return CURLE_OUT_OF_MEMORY; + } + + return CURLE_OK; +} + + +void Curl_ssl_close_all(struct SessionHandle *data) +{ + size_t i; + /* kill the session ID cache if not shared */ + if(data->state.session && !SSLSESSION_SHARED(data)) { + for(i = 0; i < data->set.ssl.max_ssl_sessions; i++) + /* the single-killer function handles empty table slots */ + Curl_ssl_kill_session(&data->state.session[i]); + + /* free the cache data */ + Curl_safefree(data->state.session); + } + + curlssl_close_all(data); +} + +void Curl_ssl_close(struct connectdata *conn, int sockindex) +{ + DEBUGASSERT((sockindex <= 1) && (sockindex >= -1)); + curlssl_close(conn, sockindex); +} + +CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex) +{ + if(curlssl_shutdown(conn, sockindex)) + return CURLE_SSL_SHUTDOWN_FAILED; + + conn->ssl[sockindex].use = FALSE; /* get back to ordinary socket usage */ + conn->ssl[sockindex].state = ssl_connection_none; + + conn->recv[sockindex] = Curl_recv_plain; + conn->send[sockindex] = Curl_send_plain; + + return CURLE_OK; +} + +/* Selects an SSL crypto engine + */ +CURLcode Curl_ssl_set_engine(struct SessionHandle *data, const char *engine) +{ + return curlssl_set_engine(data, engine); +} + +/* Selects the default SSL crypto engine + */ +CURLcode Curl_ssl_set_engine_default(struct SessionHandle *data) +{ + return curlssl_set_engine_default(data); +} + +/* Return list of OpenSSL crypto engine names. */ +struct curl_slist *Curl_ssl_engines_list(struct SessionHandle *data) +{ + return curlssl_engines_list(data); +} + +/* + * This sets up a session ID cache to the specified size. Make sure this code + * is agnostic to what underlying SSL technology we use. + */ +CURLcode Curl_ssl_initsessions(struct SessionHandle *data, size_t amount) +{ + struct curl_ssl_session *session; + + if(data->state.session) + /* this is just a precaution to prevent multiple inits */ + return CURLE_OK; + + session = calloc(amount, sizeof(struct curl_ssl_session)); + if(!session) + return CURLE_OUT_OF_MEMORY; + + /* store the info in the SSL section */ + data->set.ssl.max_ssl_sessions = amount; + data->state.session = session; + data->state.sessionage = 1; /* this is brand new */ + return CURLE_OK; +} + +size_t Curl_ssl_version(char *buffer, size_t size) +{ + return curlssl_version(buffer, size); +} + +/* + * This function tries 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_ssl_check_cxn(struct connectdata *conn) +{ + return curlssl_check_cxn(conn); +} + +bool Curl_ssl_data_pending(const struct connectdata *conn, + int connindex) +{ + return curlssl_data_pending(conn, connindex); +} + +void Curl_ssl_free_certinfo(struct SessionHandle *data) +{ + int i; + struct curl_certinfo *ci = &data->info.certs; + if(ci->num_of_certs) { + /* free all individual lists used */ + for(i=0; inum_of_certs; i++) { + curl_slist_free_all(ci->certinfo[i]); + ci->certinfo[i] = NULL; + } + free(ci->certinfo); /* free the actual array too */ + ci->certinfo = NULL; + ci->num_of_certs = 0; + } +} + +int Curl_ssl_init_certinfo(struct SessionHandle * data, + int num) +{ + struct curl_certinfo * ci = &data->info.certs; + struct curl_slist * * table; + + /* Initialize the certificate information structures. Return 0 if OK, else 1. + */ + Curl_ssl_free_certinfo(data); + ci->num_of_certs = num; + table = calloc((size_t) num, sizeof(struct curl_slist *)); + if(!table) + return 1; + + ci->certinfo = table; + return 0; +} + +/* + * 'value' is NOT a zero terminated string + */ +CURLcode Curl_ssl_push_certinfo_len(struct SessionHandle *data, + int certnum, + const char *label, + const char *value, + size_t valuelen) +{ + struct curl_certinfo * ci = &data->info.certs; + char * output; + struct curl_slist * nl; + CURLcode res = CURLE_OK; + size_t labellen = strlen(label); + size_t outlen = labellen + 1 + valuelen + 1; /* label:value\0 */ + + output = malloc(outlen); + if(!output) + return CURLE_OUT_OF_MEMORY; + + /* sprintf the label and colon */ + snprintf(output, outlen, "%s:", label); + + /* memcpy the value (it might not be zero terminated) */ + memcpy(&output[labellen+1], value, valuelen); + + /* zero terminate the output */ + output[labellen + 1 + valuelen] = 0; + + nl = Curl_slist_append_nodup(ci->certinfo[certnum], output); + if(!nl) { + free(output); + curl_slist_free_all(ci->certinfo[certnum]); + res = CURLE_OUT_OF_MEMORY; + } + + ci->certinfo[certnum] = nl; + return res; +} + +/* + * This is a convenience function for push_certinfo_len that takes a zero + * terminated value. + */ +CURLcode Curl_ssl_push_certinfo(struct SessionHandle *data, + int certnum, + const char *label, + const char *value) +{ + size_t valuelen = strlen(value); + + return Curl_ssl_push_certinfo_len(data, certnum, label, value, valuelen); +} + +/* these functions are only provided by some SSL backends */ + +#ifdef have_curlssl_random +void Curl_ssl_random(struct SessionHandle *data, + unsigned char *entropy, + size_t length) +{ + curlssl_random(data, entropy, length); +} +#endif + +#ifdef have_curlssl_md5sum +void Curl_ssl_md5sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *md5sum, /* output */ + size_t md5len) +{ + curlssl_md5sum(tmp, tmplen, md5sum, md5len); +} +#endif + +#endif /* USE_SSL */ diff --git a/lib/vtls/sslgen.h b/lib/vtls/sslgen.h new file mode 100644 index 000000000..c7f5f0092 --- /dev/null +++ b/lib/vtls/sslgen.h @@ -0,0 +1,126 @@ +#ifndef HEADER_CURL_SSLGEN_H +#define HEADER_CURL_SSLGEN_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 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 + * 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. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifndef MD5_DIGEST_LENGTH +#define MD5_DIGEST_LENGTH 16 /* fixed size */ +#endif + +bool Curl_ssl_config_matches(struct ssl_config_data* data, + struct ssl_config_data* needle); +bool Curl_clone_ssl_config(struct ssl_config_data* source, + struct ssl_config_data* dest); +void Curl_free_ssl_config(struct ssl_config_data* sslc); + +unsigned int Curl_rand(struct SessionHandle *); + +#ifdef USE_SSL +int Curl_ssl_init(void); +void Curl_ssl_cleanup(void); +CURLcode Curl_ssl_connect(struct connectdata *conn, int sockindex); +CURLcode Curl_ssl_connect_nonblocking(struct connectdata *conn, + int sockindex, + bool *done); +/* tell the SSL stuff to close down all open information regarding + connections (and thus session ID caching etc) */ +void Curl_ssl_close_all(struct SessionHandle *data); +void Curl_ssl_close(struct connectdata *conn, int sockindex); +CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex); +CURLcode Curl_ssl_set_engine(struct SessionHandle *data, const char *engine); +/* Sets engine as default for all SSL operations */ +CURLcode Curl_ssl_set_engine_default(struct SessionHandle *data); +struct curl_slist *Curl_ssl_engines_list(struct SessionHandle *data); + +/* init the SSL session ID cache */ +CURLcode Curl_ssl_initsessions(struct SessionHandle *, size_t); +size_t Curl_ssl_version(char *buffer, size_t size); +bool Curl_ssl_data_pending(const struct connectdata *conn, + int connindex); +int Curl_ssl_check_cxn(struct connectdata *conn); + +/* Certificate information list handling. */ + +void Curl_ssl_free_certinfo(struct SessionHandle *data); +int Curl_ssl_init_certinfo(struct SessionHandle * data, int num); +CURLcode Curl_ssl_push_certinfo_len(struct SessionHandle * data, int certnum, + const char * label, const char * value, + size_t valuelen); +CURLcode Curl_ssl_push_certinfo(struct SessionHandle * data, int certnum, + const char * label, const char * value); + +/* Functions to be used by SSL library adaptation functions */ + +/* extract a session ID */ +int Curl_ssl_getsessionid(struct connectdata *conn, + void **ssl_sessionid, + size_t *idsize) /* set 0 if unknown */; +/* add a new session ID */ +CURLcode Curl_ssl_addsessionid(struct connectdata *conn, + void *ssl_sessionid, + size_t idsize); +/* Kill a single session ID entry in the cache */ +void Curl_ssl_kill_session(struct curl_ssl_session *session); +/* delete a session from the cache */ +void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid); + +/* get N random bytes into the buffer */ +void Curl_ssl_random(struct SessionHandle *data, unsigned char *buffer, + size_t length); +void Curl_ssl_md5sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *md5sum, /* output */ + size_t md5len); + +#define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */ + +#ifdef have_curlssl_random +#define HAVE_CURL_SSL_RANDOM +#endif +#ifdef have_curlssl_md5sum +#define HAVE_CURL_SSL_MD5SUM +#endif + +#else +/* When SSL support is not present, just define away these function calls */ +#define Curl_ssl_init() 1 +#define Curl_ssl_cleanup() Curl_nop_stmt +#define Curl_ssl_connect(x,y) CURLE_NOT_BUILT_IN +#define Curl_ssl_close_all(x) Curl_nop_stmt +#define Curl_ssl_close(x,y) Curl_nop_stmt +#define Curl_ssl_shutdown(x,y) CURLE_NOT_BUILT_IN +#define Curl_ssl_set_engine(x,y) CURLE_NOT_BUILT_IN +#define Curl_ssl_set_engine_default(x) CURLE_NOT_BUILT_IN +#define Curl_ssl_engines_list(x) NULL +#define Curl_ssl_send(a,b,c,d,e) -1 +#define Curl_ssl_recv(a,b,c,d,e) -1 +#define Curl_ssl_initsessions(x,y) CURLE_OK +#define Curl_ssl_version(x,y) 0 +#define Curl_ssl_data_pending(x,y) 0 +#define Curl_ssl_check_cxn(x) 0 +#define Curl_ssl_free_certinfo(x) Curl_nop_stmt +#define Curl_ssl_connect_nonblocking(x,y,z) CURLE_NOT_BUILT_IN +#define Curl_ssl_kill_session(x) Curl_nop_stmt +#endif + +#endif /* HEADER_CURL_SSLGEN_H */ -- cgit v1.2.3