1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at http://curl.haxx.se/docs/copyright.html.
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ***************************************************************************/
24 * Source file for all GnuTLS-specific code for the TLS/SSL layer. No code
25 * but sslgen.c should ever call or use these functions.
27 * Note: don't use the GnuTLS' *_t variable type names in this source code,
28 * since they were not present in 1.0.X.
35 #include <gnutls/gnutls.h>
36 #include <gnutls/x509.h>
38 #ifdef USE_GNUTLS_NETTLE
39 #include <gnutls/crypto.h>
40 #include <nettle/md5.h>
47 #include "inet_pton.h"
50 #include "parsedate.h"
51 #include "connect.h" /* for the connect timeout */
55 #define _MPRINTF_REPLACE /* use our functions only */
56 #include <curl/mprintf.h>
57 #include "curl_memory.h"
58 /* The last #include file should be: */
62 Some hackish cast macros based on:
63 http://library.gnome.org/devel/glib/unstable/glib-Type-Conversion-Macros.html
65 #ifndef GNUTLS_POINTER_TO_INT_CAST
66 #define GNUTLS_POINTER_TO_INT_CAST(p) ((int) (long) (p))
68 #ifndef GNUTLS_INT_TO_POINTER_CAST
69 #define GNUTLS_INT_TO_POINTER_CAST(i) ((void*) (long) (i))
72 /* Enable GnuTLS debugging by defining GTLSDEBUG */
73 /*#define GTLSDEBUG */
76 static void tls_log_func(int level, const char *str)
78 fprintf(stderr, "|<%d>| %s", level, str);
81 static bool gtls_inited = FALSE;
83 #if defined(GNUTLS_VERSION_NUMBER)
84 # if (GNUTLS_VERSION_NUMBER >= 0x020c00)
85 # undef gnutls_transport_set_lowat
86 # define gnutls_transport_set_lowat(A,B) Curl_nop_stmt
87 # define USE_GNUTLS_PRIORITY_SET_DIRECT 1
89 # if (GNUTLS_VERSION_NUMBER >= 0x020c03)
90 # define GNUTLS_MAPS_WINSOCK_ERRORS 1
95 * Custom push and pull callback functions used by GNU TLS to read and write
96 * to the socket. These functions are simple wrappers to send() and recv()
97 * (although here using the sread/swrite macros as defined by setup_once.h).
98 * We use custom functions rather than the GNU TLS defaults because it allows
99 * us to get specific about the fourth "flags" argument, and to use arbitrary
100 * private data with gnutls_transport_set_ptr if we wish.
102 * When these custom push and pull callbacks fail, GNU TLS checks its own
103 * session-specific error variable, and when not set also its own global
104 * errno variable, in order to take appropriate action. GNU TLS does not
105 * require that the transport is actually a socket. This implies that for
106 * Windows builds these callbacks should ideally set the session-specific
107 * error variable using function gnutls_transport_set_errno or as a last
108 * resort global errno variable using gnutls_transport_set_global_errno,
109 * with a transport agnostic error value. This implies that some winsock
110 * error translation must take place in these callbacks.
112 * Paragraph above applies to GNU TLS versions older than 2.12.3, since
113 * this version GNU TLS does its own internal winsock error translation
114 * using system_errno() function.
117 #if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
118 # define gtls_EINTR 4
120 # define gtls_EAGAIN 11
121 static int gtls_mapped_sockerrno(void)
135 static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len)
137 ssize_t ret = swrite(GNUTLS_POINTER_TO_INT_CAST(s), buf, len);
138 #if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
140 gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
145 static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len)
147 ssize_t ret = sread(GNUTLS_POINTER_TO_INT_CAST(s), buf, len);
148 #if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
150 gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
157 * Global GnuTLS init, called from Curl_ssl_init(). This calls functions that
158 * are not thread-safe and thus this function itself is not thread-safe and
159 * must only be called from within curl_global_init() to keep the thread
160 * situation under control!
162 int Curl_gtls_init(void)
166 ret = gnutls_global_init()?0:1;
168 gnutls_global_set_log_function(tls_log_func);
169 gnutls_global_set_log_level(2);
176 int Curl_gtls_cleanup(void)
179 gnutls_global_deinit();
185 static void showtime(struct SessionHandle *data,
190 const struct tm *tm = &buffer;
191 CURLcode result = Curl_gmtime(stamp, &buffer);
195 snprintf(data->state.buffer,
197 "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT\n",
199 Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
201 Curl_month[tm->tm_mon],
206 infof(data, "%s\n", data->state.buffer);
209 static gnutls_datum load_file (const char *file)
212 gnutls_datum loaded_file = { NULL, 0 };
216 if(!(f = fopen(file, "r")))
218 if(fseek(f, 0, SEEK_END) != 0
219 || (filelen = ftell(f)) < 0
220 || fseek(f, 0, SEEK_SET) != 0
221 || !(ptr = malloc((size_t)filelen)))
223 if(fread(ptr, 1, (size_t)filelen, f) < (size_t)filelen) {
228 loaded_file.data = ptr;
229 loaded_file.size = (unsigned int)filelen;
235 static void unload_file(gnutls_datum data) {
240 /* this function does a SSL/TLS (re-)handshake */
241 static CURLcode handshake(struct connectdata *conn,
246 struct SessionHandle *data = conn->data;
247 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
248 gnutls_session session = conn->ssl[sockindex].session;
249 curl_socket_t sockfd = conn->sock[sockindex];
255 /* check allowed time left */
256 timeout_ms = Curl_timeleft(data, NULL, duringconnect);
259 /* no need to continue if time already is up */
260 failf(data, "SSL connection timeout");
261 return CURLE_OPERATION_TIMEDOUT;
264 /* if ssl is expecting something, check if it's available. */
265 if(connssl->connecting_state == ssl_connect_2_reading
266 || connssl->connecting_state == ssl_connect_2_writing) {
268 curl_socket_t writefd = ssl_connect_2_writing==
269 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
270 curl_socket_t readfd = ssl_connect_2_reading==
271 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
273 what = Curl_socket_ready(readfd, writefd,
275 timeout_ms?timeout_ms:1000);
278 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
279 return CURLE_SSL_CONNECT_ERROR;
284 else if(timeout_ms) {
286 failf(data, "SSL connection timeout at %ld", timeout_ms);
287 return CURLE_OPERATION_TIMEDOUT;
290 /* socket is readable or writable */
293 rc = gnutls_handshake(session);
295 if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) {
296 connssl->connecting_state =
297 gnutls_record_get_direction(session)?
298 ssl_connect_2_writing:ssl_connect_2_reading;
303 else if((rc < 0) && !gnutls_error_is_fatal(rc)) {
304 const char *strerr = NULL;
306 if(rc == GNUTLS_E_WARNING_ALERT_RECEIVED) {
307 int alert = gnutls_alert_get(session);
308 strerr = gnutls_alert_get_name(alert);
312 strerr = gnutls_strerror(rc);
314 failf(data, "gnutls_handshake() warning: %s", strerr);
317 const char *strerr = NULL;
319 if(rc == GNUTLS_E_FATAL_ALERT_RECEIVED) {
320 int alert = gnutls_alert_get(session);
321 strerr = gnutls_alert_get_name(alert);
325 strerr = gnutls_strerror(rc);
327 failf(data, "gnutls_handshake() failed: %s", strerr);
328 return CURLE_SSL_CONNECT_ERROR;
331 /* Reset our connect state machine */
332 connssl->connecting_state = ssl_connect_1;
337 static gnutls_x509_crt_fmt do_file_type(const char *type)
339 if(!type || !type[0])
340 return GNUTLS_X509_FMT_PEM;
341 if(Curl_raw_equal(type, "PEM"))
342 return GNUTLS_X509_FMT_PEM;
343 if(Curl_raw_equal(type, "DER"))
344 return GNUTLS_X509_FMT_DER;
349 gtls_connect_step1(struct connectdata *conn,
352 #ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
353 static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
355 struct SessionHandle *data = conn->data;
356 gnutls_session session;
360 bool sni = TRUE; /* default is SNI enabled */
362 struct in6_addr addr;
367 if(conn->ssl[sockindex].state == ssl_connection_complete)
368 /* to make us tolerant against being called more than once for the
375 /* GnuTLS only supports SSLv3 and TLSv1 */
376 if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
377 failf(data, "GnuTLS does not support SSLv2");
378 return CURLE_SSL_CONNECT_ERROR;
380 else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3)
381 sni = FALSE; /* SSLv3 has no SNI */
383 /* allocate a cred struct */
384 rc = gnutls_certificate_allocate_credentials(&conn->ssl[sockindex].cred);
385 if(rc != GNUTLS_E_SUCCESS) {
386 failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc));
387 return CURLE_SSL_CONNECT_ERROR;
391 if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
392 infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username);
394 rc = gnutls_srp_allocate_client_credentials(
395 &conn->ssl[sockindex].srp_client_cred);
396 if(rc != GNUTLS_E_SUCCESS) {
397 failf(data, "gnutls_srp_allocate_client_cred() failed: %s",
398 gnutls_strerror(rc));
399 return CURLE_OUT_OF_MEMORY;
402 rc = gnutls_srp_set_client_credentials(conn->ssl[sockindex].
404 data->set.ssl.username,
405 data->set.ssl.password);
406 if(rc != GNUTLS_E_SUCCESS) {
407 failf(data, "gnutls_srp_set_client_cred() failed: %s",
408 gnutls_strerror(rc));
409 return CURLE_BAD_FUNCTION_ARGUMENT;
414 if(data->set.ssl.CAfile) {
415 /* set the trusted CA cert bundle file */
416 gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred,
417 GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
419 rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred,
420 data->set.ssl.CAfile,
421 GNUTLS_X509_FMT_PEM);
423 infof(data, "error reading ca cert file %s (%s)\n",
424 data->set.ssl.CAfile, gnutls_strerror(rc));
425 if(data->set.ssl.verifypeer)
426 return CURLE_SSL_CACERT_BADFILE;
429 infof(data, "found %d certificates in %s\n",
430 rc, data->set.ssl.CAfile);
433 if(data->set.ssl.CRLfile) {
434 /* set the CRL list file */
435 rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred,
436 data->set.ssl.CRLfile,
437 GNUTLS_X509_FMT_PEM);
439 failf(data, "error reading crl file %s (%s)",
440 data->set.ssl.CRLfile, gnutls_strerror(rc));
441 return CURLE_SSL_CRL_BADFILE;
444 infof(data, "found %d CRL in %s\n",
445 rc, data->set.ssl.CRLfile);
448 /* Initialize TLS session as a client */
449 rc = gnutls_init(&conn->ssl[sockindex].session, GNUTLS_CLIENT);
450 if(rc != GNUTLS_E_SUCCESS) {
451 failf(data, "gnutls_init() failed: %d", rc);
452 return CURLE_SSL_CONNECT_ERROR;
455 /* convenient assign */
456 session = conn->ssl[sockindex].session;
458 if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) &&
460 (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) &&
463 (gnutls_server_name_set(session, GNUTLS_NAME_DNS, conn->host.name,
464 strlen(conn->host.name)) < 0))
465 infof(data, "WARNING: failed to configure server name indication (SNI) "
468 /* Use default priorities */
469 rc = gnutls_set_default_priority(session);
470 if(rc != GNUTLS_E_SUCCESS)
471 return CURLE_SSL_CONNECT_ERROR;
473 if(data->set.ssl.version == CURL_SSLVERSION_SSLv3) {
474 #ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
475 static const int protocol_priority[] = { GNUTLS_SSL3, 0 };
476 rc = gnutls_protocol_set_priority(session, protocol_priority);
479 /* the combination of the cipher ARCFOUR with SSL 3.0 and TLS 1.0 is not
480 vulnerable to attacks such as the BEAST, why this code now explicitly
483 rc = gnutls_priority_set_direct(session,
484 "NORMAL:-VERS-TLS-ALL:+VERS-SSL3.0:"
485 "-CIPHER-ALL:+ARCFOUR-128",
488 if(rc != GNUTLS_E_SUCCESS)
489 return CURLE_SSL_CONNECT_ERROR;
492 #ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
493 /* Sets the priority on the certificate types supported by gnutls. Priority
494 is higher for types specified before others. After specifying the types
495 you want, you must append a 0. */
496 rc = gnutls_certificate_type_set_priority(session, cert_type_priority);
497 if(rc != GNUTLS_E_SUCCESS)
498 return CURLE_SSL_CONNECT_ERROR;
501 if(data->set.str[STRING_CERT]) {
502 if(gnutls_certificate_set_x509_key_file(
503 conn->ssl[sockindex].cred,
504 data->set.str[STRING_CERT],
505 data->set.str[STRING_KEY] ?
506 data->set.str[STRING_KEY] : data->set.str[STRING_CERT],
507 do_file_type(data->set.str[STRING_CERT_TYPE]) ) !=
509 failf(data, "error reading X.509 key or certificate file");
510 return CURLE_SSL_CONNECT_ERROR;
515 /* put the credentials to the current session */
516 if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
517 rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP,
518 conn->ssl[sockindex].srp_client_cred);
519 if(rc != GNUTLS_E_SUCCESS)
520 failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
524 rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
525 conn->ssl[sockindex].cred);
527 /* set the connection handle (file descriptor for the socket) */
528 gnutls_transport_set_ptr(session,
529 GNUTLS_INT_TO_POINTER_CAST(conn->sock[sockindex]));
531 /* register callback functions to send and receive data. */
532 gnutls_transport_set_push_function(session, Curl_gtls_push);
533 gnutls_transport_set_pull_function(session, Curl_gtls_pull);
535 /* lowat must be set to zero when using custom push and pull functions. */
536 gnutls_transport_set_lowat(session, 0);
538 /* This might be a reconnect, so we check for a session ID in the cache
539 to speed up things */
541 if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize)) {
542 /* we got a session id, use it! */
543 gnutls_session_set_data(session, ssl_sessionid, ssl_idsize);
545 /* Informational message */
546 infof (data, "SSL re-using session ID\n");
552 static Curl_recv gtls_recv;
553 static Curl_send gtls_send;
556 gtls_connect_step3(struct connectdata *conn,
559 unsigned int cert_list_size;
560 const gnutls_datum *chainp;
561 unsigned int verify_status;
562 gnutls_x509_crt x509_cert,x509_issuer;
563 gnutls_datum issuerp;
564 char certbuf[256]; /* big enough? */
570 struct SessionHandle *data = conn->data;
571 gnutls_session session = conn->ssl[sockindex].session;
575 CURLcode result = CURLE_OK;
577 /* This function will return the peer's raw certificate (chain) as sent by
578 the peer. These certificates are in raw format (DER encoded for
579 X.509). In case of a X.509 then a certificate list may be present. The
580 first certificate in the list is the peer's certificate, following the
581 issuer's certificate, then the issuer's issuer etc. */
583 chainp = gnutls_certificate_get_peers(session, &cert_list_size);
585 if(data->set.ssl.verifypeer ||
586 data->set.ssl.verifyhost ||
587 data->set.ssl.issuercert) {
589 if(data->set.ssl.authtype == CURL_TLSAUTH_SRP
590 && data->set.ssl.username != NULL
591 && !data->set.ssl.verifypeer
592 && gnutls_cipher_get(session)) {
593 /* no peer cert, but auth is ok if we have SRP user and cipher and no
598 failf(data, "failed to get server cert");
599 return CURLE_PEER_FAILED_VERIFICATION;
604 infof(data, "\t common name: WARNING couldn't obtain\n");
607 if(data->set.ssl.verifypeer) {
608 /* This function will try to verify the peer's certificate and return its
609 status (trusted, invalid etc.). The value of status should be one or
610 more of the gnutls_certificate_status_t enumerated elements bitwise
611 or'd. To avoid denial of service attacks some default upper limits
612 regarding the certificate key size and chain size are set. To override
613 them use gnutls_certificate_set_verify_limits(). */
615 rc = gnutls_certificate_verify_peers2(session, &verify_status);
617 failf(data, "server cert verify failed: %d", rc);
618 return CURLE_SSL_CONNECT_ERROR;
621 /* verify_status is a bitmask of gnutls_certificate_status bits */
622 if(verify_status & GNUTLS_CERT_INVALID) {
623 if(data->set.ssl.verifypeer) {
624 failf(data, "server certificate verification failed. CAfile: %s "
625 "CRLfile: %s", data->set.ssl.CAfile?data->set.ssl.CAfile:"none",
626 data->set.ssl.CRLfile?data->set.ssl.CRLfile:"none");
627 return CURLE_SSL_CACERT;
630 infof(data, "\t server certificate verification FAILED\n");
633 infof(data, "\t server certificate verification OK\n");
636 infof(data, "\t server certificate verification SKIPPED\n");
637 goto after_server_cert_verification;
640 /* initialize an X.509 certificate structure. */
641 gnutls_x509_crt_init(&x509_cert);
643 /* convert the given DER or PEM encoded Certificate to the native
644 gnutls_x509_crt_t format */
645 gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
647 if(data->set.ssl.issuercert) {
648 gnutls_x509_crt_init(&x509_issuer);
649 issuerp = load_file(data->set.ssl.issuercert);
650 gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
651 rc = gnutls_x509_crt_check_issuer(x509_cert,x509_issuer);
652 unload_file(issuerp);
654 failf(data, "server certificate issuer check failed (IssuerCert: %s)",
655 data->set.ssl.issuercert?data->set.ssl.issuercert:"none");
656 return CURLE_SSL_ISSUER_ERROR;
658 infof(data,"\t server certificate issuer check OK (Issuer Cert: %s)\n",
659 data->set.ssl.issuercert?data->set.ssl.issuercert:"none");
662 size=sizeof(certbuf);
663 rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
664 0, /* the first and only one */
669 infof(data, "error fetching CN from cert:%s\n",
670 gnutls_strerror(rc));
673 /* This function will check if the given certificate's subject matches the
674 given hostname. This is a basic implementation of the matching described
675 in RFC2818 (HTTPS), which takes into account wildcards, and the subject
676 alternative name PKIX extension. Returns non zero on success, and zero on
678 rc = gnutls_x509_crt_check_hostname(x509_cert, conn->host.name);
681 if(data->set.ssl.verifyhost) {
682 failf(data, "SSL: certificate subject name (%s) does not match "
683 "target host name '%s'", certbuf, conn->host.dispname);
684 gnutls_x509_crt_deinit(x509_cert);
685 return CURLE_PEER_FAILED_VERIFICATION;
688 infof(data, "\t common name: %s (does not match '%s')\n",
689 certbuf, conn->host.dispname);
692 infof(data, "\t common name: %s (matched)\n", certbuf);
694 /* Check for time-based validity */
695 certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
697 if(certclock == (time_t)-1) {
698 failf(data, "server cert expiration date verify failed");
699 return CURLE_SSL_CONNECT_ERROR;
702 if(certclock < time(NULL)) {
703 if(data->set.ssl.verifypeer) {
704 failf(data, "server certificate expiration date has passed.");
705 return CURLE_PEER_FAILED_VERIFICATION;
708 infof(data, "\t server certificate expiration date FAILED\n");
711 infof(data, "\t server certificate expiration date OK\n");
713 certclock = gnutls_x509_crt_get_activation_time(x509_cert);
715 if(certclock == (time_t)-1) {
716 failf(data, "server cert activation date verify failed");
717 return CURLE_SSL_CONNECT_ERROR;
720 if(certclock > time(NULL)) {
721 if(data->set.ssl.verifypeer) {
722 failf(data, "server certificate not activated yet.");
723 return CURLE_PEER_FAILED_VERIFICATION;
726 infof(data, "\t server certificate activation date FAILED\n");
729 infof(data, "\t server certificate activation date OK\n");
742 /* public key algorithm's parameters */
743 algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
744 infof(data, "\t certificate public key: %s\n",
745 gnutls_pk_algorithm_get_name(algo));
747 /* version of the X.509 certificate. */
748 infof(data, "\t certificate version: #%d\n",
749 gnutls_x509_crt_get_version(x509_cert));
752 size = sizeof(certbuf);
753 gnutls_x509_crt_get_dn(x509_cert, certbuf, &size);
754 infof(data, "\t subject: %s\n", certbuf);
756 certclock = gnutls_x509_crt_get_activation_time(x509_cert);
757 showtime(data, "start date", certclock);
759 certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
760 showtime(data, "expire date", certclock);
762 size = sizeof(certbuf);
763 gnutls_x509_crt_get_issuer_dn(x509_cert, certbuf, &size);
764 infof(data, "\t issuer: %s\n", certbuf);
766 gnutls_x509_crt_deinit(x509_cert);
768 after_server_cert_verification:
770 /* compression algorithm (if any) */
771 ptr = gnutls_compression_get_name(gnutls_compression_get(session));
772 /* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */
773 infof(data, "\t compression: %s\n", ptr);
775 /* the name of the cipher used. ie 3DES. */
776 ptr = gnutls_cipher_get_name(gnutls_cipher_get(session));
777 infof(data, "\t cipher: %s\n", ptr);
779 /* the MAC algorithms name. ie SHA1 */
780 ptr = gnutls_mac_get_name(gnutls_mac_get(session));
781 infof(data, "\t MAC: %s\n", ptr);
783 conn->ssl[sockindex].state = ssl_connection_complete;
784 conn->recv[sockindex] = gtls_recv;
785 conn->send[sockindex] = gtls_send;
788 /* we always unconditionally get the session id here, as even if we
789 already got it from the cache and asked to use it in the connection, it
790 might've been rejected and then a new one is in use now and we need to
792 void *connect_sessionid;
793 size_t connect_idsize;
795 /* get the session ID data size */
796 gnutls_session_get_data(session, NULL, &connect_idsize);
797 connect_sessionid = malloc(connect_idsize); /* get a buffer for it */
799 if(connect_sessionid) {
800 /* extract session ID to the allocated buffer */
801 gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
803 incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL));
805 /* there was one before in the cache, so instead of risking that the
806 previous one was rejected, we just kill that and store the new */
807 Curl_ssl_delsessionid(conn, ssl_sessionid);
810 /* store this session id */
811 result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize);
813 free(connect_sessionid);
814 result = CURLE_OUT_OF_MEMORY;
818 result = CURLE_OUT_OF_MEMORY;
826 * This function is called after the TCP connect has completed. Setup the TLS
827 * layer and do all necessary magic.
829 /* We use connssl->connecting_state to keep track of the connection status;
830 there are three states: 'ssl_connect_1' (not started yet or complete),
831 'ssl_connect_2_reading' (waiting for data from server), and
832 'ssl_connect_2_writing' (waiting to be able to write).
835 gtls_connect_common(struct connectdata *conn,
841 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
843 /* Initiate the connection, if not already done */
844 if(ssl_connect_1==connssl->connecting_state) {
845 rc = gtls_connect_step1 (conn, sockindex);
850 rc = handshake(conn, sockindex, TRUE, nonblocking);
852 /* handshake() sets its own error message with failf() */
855 /* Finish connecting once the handshake is done */
856 if(ssl_connect_1==connssl->connecting_state) {
857 rc = gtls_connect_step3(conn, sockindex);
862 *done = ssl_connect_1==connssl->connecting_state;
868 Curl_gtls_connect_nonblocking(struct connectdata *conn,
872 return gtls_connect_common(conn, sockindex, TRUE, done);
876 Curl_gtls_connect(struct connectdata *conn,
883 retcode = gtls_connect_common(conn, sockindex, FALSE, &done);
892 static ssize_t gtls_send(struct connectdata *conn,
898 ssize_t rc = gnutls_record_send(conn->ssl[sockindex].session, mem, len);
901 *curlcode = (rc == GNUTLS_E_AGAIN)
911 void Curl_gtls_close_all(struct SessionHandle *data)
913 /* FIX: make the OpenSSL code more generic and use parts of it here */
917 static void close_one(struct connectdata *conn,
920 if(conn->ssl[idx].session) {
921 gnutls_bye(conn->ssl[idx].session, GNUTLS_SHUT_RDWR);
922 gnutls_deinit(conn->ssl[idx].session);
923 conn->ssl[idx].session = NULL;
925 if(conn->ssl[idx].cred) {
926 gnutls_certificate_free_credentials(conn->ssl[idx].cred);
927 conn->ssl[idx].cred = NULL;
930 if(conn->ssl[idx].srp_client_cred) {
931 gnutls_srp_free_client_credentials(conn->ssl[idx].srp_client_cred);
932 conn->ssl[idx].srp_client_cred = NULL;
937 void Curl_gtls_close(struct connectdata *conn, int sockindex)
939 close_one(conn, sockindex);
943 * This function is called to shut down the SSL layer but keep the
944 * socket open (CCC - Clear Command Channel)
946 int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
950 struct SessionHandle *data = conn->data;
954 /* This has only been tested on the proftpd server, and the mod_tls code
955 sends a close notify alert without waiting for a close notify alert in
956 response. Thus we wait for a close notify alert from the server, but
957 we do not send one. Let's hope other servers do the same... */
959 if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
960 gnutls_bye(conn->ssl[sockindex].session, GNUTLS_SHUT_WR);
962 if(conn->ssl[sockindex].session) {
964 int what = Curl_socket_ready(conn->sock[sockindex],
965 CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
967 /* Something to read, let's do it and hope that it is the close
968 notify alert from the server */
969 result = gnutls_record_recv(conn->ssl[sockindex].session,
973 /* This is the expected response. There was no data but only
974 the close notify alert */
978 case GNUTLS_E_INTERRUPTED:
979 infof(data, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED\n");
989 failf(data, "SSL shutdown timeout");
994 /* anything that gets here is fatally bad */
995 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
1000 gnutls_deinit(conn->ssl[sockindex].session);
1002 gnutls_certificate_free_credentials(conn->ssl[sockindex].cred);
1005 if(data->set.ssl.authtype == CURL_TLSAUTH_SRP
1006 && data->set.ssl.username != NULL)
1007 gnutls_srp_free_client_credentials(conn->ssl[sockindex].srp_client_cred);
1010 conn->ssl[sockindex].cred = NULL;
1011 conn->ssl[sockindex].session = NULL;
1016 static ssize_t gtls_recv(struct connectdata *conn, /* connection data */
1017 int num, /* socketindex */
1018 char *buf, /* store read data here */
1019 size_t buffersize, /* max amount to read */
1024 ret = gnutls_record_recv(conn->ssl[num].session, buf, buffersize);
1025 if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
1026 *curlcode = CURLE_AGAIN;
1030 if(ret == GNUTLS_E_REHANDSHAKE) {
1031 /* BLOCKING call, this is bad but a work-around for now. Fixing this "the
1032 proper way" takes a whole lot of work. */
1033 CURLcode rc = handshake(conn, num, FALSE, FALSE);
1035 /* handshake() writes error message on its own */
1038 *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */
1043 failf(conn->data, "GnuTLS recv error (%d): %s",
1044 (int)ret, gnutls_strerror((int)ret));
1045 *curlcode = CURLE_RECV_ERROR;
1052 void Curl_gtls_session_free(void *ptr)
1057 size_t Curl_gtls_version(char *buffer, size_t size)
1059 return snprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
1062 int Curl_gtls_seed(struct SessionHandle *data)
1064 /* we have the "SSL is seeded" boolean static to prevent multiple
1065 time-consuming seedings in vain */
1066 static bool ssl_seeded = FALSE;
1068 /* Quickly add a bit of entropy */
1069 #ifndef USE_GNUTLS_NETTLE
1070 gcry_fast_random_poll();
1073 if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] ||
1074 data->set.str[STRING_SSL_EGDSOCKET]) {
1076 /* TODO: to a good job seeding the RNG
1077 This may involve the gcry_control function and these options:
1078 GCRYCTL_SET_RANDOM_SEED_FILE
1079 GCRYCTL_SET_RNDEGD_SOCKET
1086 void Curl_gtls_random(struct SessionHandle *data,
1087 unsigned char *entropy,
1090 #if defined(USE_GNUTLS_NETTLE)
1092 gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
1093 #elif defined(USE_GNUTLS)
1094 Curl_gtls_seed(data); /* Initiate the seed if not already done */
1095 gcry_randomize(entropy, length, GCRY_STRONG_RANDOM);
1099 void Curl_gtls_md5sum(unsigned char *tmp, /* input */
1101 unsigned char *md5sum, /* output */
1104 #if defined(USE_GNUTLS_NETTLE)
1105 struct md5_ctx MD5pw;
1107 md5_update(&MD5pw, tmplen, tmp);
1108 md5_digest(&MD5pw, md5len, md5sum);
1109 #elif defined(USE_GNUTLS)
1111 gcry_md_open(&MD5pw, GCRY_MD_MD5, 0);
1112 gcry_md_write(MD5pw, tmp, tmplen);
1113 memcpy(md5sum, gcry_md_read (MD5pw, 0), md5len);
1114 gcry_md_close(MD5pw);
1118 #endif /* USE_GNUTLS */