1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
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.
13  *
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.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  ***************************************************************************/
22 
23 /*
24  * Source file for all GnuTLS-specific code for the TLS/SSL layer. No code
25  * but vtls.c should ever call or use these functions.
26  *
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.
29  */
30 
31 #include "curl_setup.h"
32 
33 #ifdef USE_GNUTLS
34 
35 #include <gnutls/abstract.h>
36 #include <gnutls/gnutls.h>
37 #include <gnutls/x509.h>
38 
39 #ifdef USE_GNUTLS_NETTLE
40 #include <gnutls/crypto.h>
41 #include <nettle/md5.h>
42 #else
43 #include <gcrypt.h>
44 #endif
45 
46 #include "urldata.h"
47 #include "sendf.h"
48 #include "inet_pton.h"
49 #include "gtls.h"
50 #include "vtls.h"
51 #include "parsedate.h"
52 #include "connect.h" /* for the connect timeout */
53 #include "select.h"
54 #include "rawstr.h"
55 #include "warnless.h"
56 #include "x509asn1.h"
57 #include "curl_printf.h"
58 #include "curl_memory.h"
59 /* The last #include file should be: */
60 #include "memdebug.h"
61 
62 /*
63  Some hackish cast macros based on:
64  http://library.gnome.org/devel/glib/unstable/glib-Type-Conversion-Macros.html
65 */
66 #ifndef GNUTLS_POINTER_TO_INT_CAST
67 #define GNUTLS_POINTER_TO_INT_CAST(p) ((int) (long) (p))
68 #endif
69 #ifndef GNUTLS_INT_TO_POINTER_CAST
70 #define GNUTLS_INT_TO_POINTER_CAST(i) ((void*) (long) (i))
71 #endif
72 
73 /* Enable GnuTLS debugging by defining GTLSDEBUG */
74 /*#define GTLSDEBUG */
75 
76 #ifdef GTLSDEBUG
tls_log_func(int level,const char * str)77 static void tls_log_func(int level, const char *str)
78 {
79     fprintf(stderr, "|<%d>| %s", level, str);
80 }
81 #endif
82 static bool gtls_inited = FALSE;
83 
84 #if defined(GNUTLS_VERSION_NUMBER)
85 #  if (GNUTLS_VERSION_NUMBER >= 0x020c00)
86 #    undef gnutls_transport_set_lowat
87 #    define gnutls_transport_set_lowat(A,B) Curl_nop_stmt
88 #    define USE_GNUTLS_PRIORITY_SET_DIRECT 1
89 #  endif
90 #  if (GNUTLS_VERSION_NUMBER >= 0x020c03)
91 #    define GNUTLS_MAPS_WINSOCK_ERRORS 1
92 #  endif
93 
94 #  if (GNUTLS_VERSION_NUMBER >= 0x030200)
95 #    define HAS_ALPN
96 #  endif
97 
98 #  if (GNUTLS_VERSION_NUMBER >= 0x03020d)
99 #    define HAS_OCSP
100 #  endif
101 
102 #  if (GNUTLS_VERSION_NUMBER >= 0x030306)
103 #    define HAS_CAPATH
104 #  endif
105 #endif
106 
107 #ifdef HAS_OCSP
108 # include <gnutls/ocsp.h>
109 #endif
110 
111 /*
112  * Custom push and pull callback functions used by GNU TLS to read and write
113  * to the socket.  These functions are simple wrappers to send() and recv()
114  * (although here using the sread/swrite macros as defined by
115  * curl_setup_once.h).
116  * We use custom functions rather than the GNU TLS defaults because it allows
117  * us to get specific about the fourth "flags" argument, and to use arbitrary
118  * private data with gnutls_transport_set_ptr if we wish.
119  *
120  * When these custom push and pull callbacks fail, GNU TLS checks its own
121  * session-specific error variable, and when not set also its own global
122  * errno variable, in order to take appropriate action. GNU TLS does not
123  * require that the transport is actually a socket. This implies that for
124  * Windows builds these callbacks should ideally set the session-specific
125  * error variable using function gnutls_transport_set_errno or as a last
126  * resort global errno variable using gnutls_transport_set_global_errno,
127  * with a transport agnostic error value. This implies that some winsock
128  * error translation must take place in these callbacks.
129  *
130  * Paragraph above applies to GNU TLS versions older than 2.12.3, since
131  * this version GNU TLS does its own internal winsock error translation
132  * using system_errno() function.
133  */
134 
135 #if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
136 #  define gtls_EINTR  4
137 #  define gtls_EIO    5
138 #  define gtls_EAGAIN 11
gtls_mapped_sockerrno(void)139 static int gtls_mapped_sockerrno(void)
140 {
141   switch(SOCKERRNO) {
142   case WSAEWOULDBLOCK:
143     return gtls_EAGAIN;
144   case WSAEINTR:
145     return gtls_EINTR;
146   default:
147     break;
148   }
149   return gtls_EIO;
150 }
151 #endif
152 
Curl_gtls_push(void * s,const void * buf,size_t len)153 static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len)
154 {
155   ssize_t ret = swrite(GNUTLS_POINTER_TO_INT_CAST(s), buf, len);
156 #if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
157   if(ret < 0)
158     gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
159 #endif
160   return ret;
161 }
162 
Curl_gtls_pull(void * s,void * buf,size_t len)163 static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len)
164 {
165   ssize_t ret = sread(GNUTLS_POINTER_TO_INT_CAST(s), buf, len);
166 #if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
167   if(ret < 0)
168     gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
169 #endif
170   return ret;
171 }
172 
173 /* Curl_gtls_init()
174  *
175  * Global GnuTLS init, called from Curl_ssl_init(). This calls functions that
176  * are not thread-safe and thus this function itself is not thread-safe and
177  * must only be called from within curl_global_init() to keep the thread
178  * situation under control!
179  */
Curl_gtls_init(void)180 int Curl_gtls_init(void)
181 {
182   int ret = 1;
183   if(!gtls_inited) {
184     ret = gnutls_global_init()?0:1;
185 #ifdef GTLSDEBUG
186     gnutls_global_set_log_function(tls_log_func);
187     gnutls_global_set_log_level(2);
188 #endif
189     gtls_inited = TRUE;
190   }
191   return ret;
192 }
193 
Curl_gtls_cleanup(void)194 int Curl_gtls_cleanup(void)
195 {
196   if(gtls_inited) {
197     gnutls_global_deinit();
198     gtls_inited = FALSE;
199   }
200   return 1;
201 }
202 
showtime(struct SessionHandle * data,const char * text,time_t stamp)203 static void showtime(struct SessionHandle *data,
204                      const char *text,
205                      time_t stamp)
206 {
207   struct tm buffer;
208   const struct tm *tm = &buffer;
209   CURLcode result = Curl_gmtime(stamp, &buffer);
210   if(result)
211     return;
212 
213   snprintf(data->state.buffer,
214            BUFSIZE,
215            "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT",
216            text,
217            Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
218            tm->tm_mday,
219            Curl_month[tm->tm_mon],
220            tm->tm_year + 1900,
221            tm->tm_hour,
222            tm->tm_min,
223            tm->tm_sec);
224   infof(data, "%s\n", data->state.buffer);
225 }
226 
load_file(const char * file)227 static gnutls_datum_t load_file (const char *file)
228 {
229   FILE *f;
230   gnutls_datum_t loaded_file = { NULL, 0 };
231   long filelen;
232   void *ptr;
233 
234   if(!(f = fopen(file, "rb")))
235     return loaded_file;
236   if(fseek(f, 0, SEEK_END) != 0
237      || (filelen = ftell(f)) < 0
238      || fseek(f, 0, SEEK_SET) != 0
239      || !(ptr = malloc((size_t)filelen)))
240     goto out;
241   if(fread(ptr, 1, (size_t)filelen, f) < (size_t)filelen) {
242     free(ptr);
243     goto out;
244   }
245 
246   loaded_file.data = ptr;
247   loaded_file.size = (unsigned int)filelen;
248 out:
249   fclose(f);
250   return loaded_file;
251 }
252 
unload_file(gnutls_datum_t data)253 static void unload_file(gnutls_datum_t data) {
254   free(data.data);
255 }
256 
257 
258 /* this function does a SSL/TLS (re-)handshake */
handshake(struct connectdata * conn,int sockindex,bool duringconnect,bool nonblocking)259 static CURLcode handshake(struct connectdata *conn,
260                           int sockindex,
261                           bool duringconnect,
262                           bool nonblocking)
263 {
264   struct SessionHandle *data = conn->data;
265   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
266   gnutls_session_t session = conn->ssl[sockindex].session;
267   curl_socket_t sockfd = conn->sock[sockindex];
268   long timeout_ms;
269   int rc;
270   int what;
271 
272   for(;;) {
273     /* check allowed time left */
274     timeout_ms = Curl_timeleft(data, NULL, duringconnect);
275 
276     if(timeout_ms < 0) {
277       /* no need to continue if time already is up */
278       failf(data, "SSL connection timeout");
279       return CURLE_OPERATION_TIMEDOUT;
280     }
281 
282     /* if ssl is expecting something, check if it's available. */
283     if(connssl->connecting_state == ssl_connect_2_reading
284        || connssl->connecting_state == ssl_connect_2_writing) {
285 
286       curl_socket_t writefd = ssl_connect_2_writing==
287         connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
288       curl_socket_t readfd = ssl_connect_2_reading==
289         connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
290 
291       what = Curl_socket_ready(readfd, writefd,
292                                nonblocking?0:
293                                timeout_ms?timeout_ms:1000);
294       if(what < 0) {
295         /* fatal error */
296         failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
297         return CURLE_SSL_CONNECT_ERROR;
298       }
299       else if(0 == what) {
300         if(nonblocking)
301           return CURLE_OK;
302         else if(timeout_ms) {
303           /* timeout */
304           failf(data, "SSL connection timeout at %ld", timeout_ms);
305           return CURLE_OPERATION_TIMEDOUT;
306         }
307       }
308       /* socket is readable or writable */
309     }
310 
311     rc = gnutls_handshake(session);
312 
313     if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) {
314       connssl->connecting_state =
315         gnutls_record_get_direction(session)?
316         ssl_connect_2_writing:ssl_connect_2_reading;
317       continue;
318     }
319     else if((rc < 0) && !gnutls_error_is_fatal(rc)) {
320       const char *strerr = NULL;
321 
322       if(rc == GNUTLS_E_WARNING_ALERT_RECEIVED) {
323         int alert = gnutls_alert_get(session);
324         strerr = gnutls_alert_get_name(alert);
325       }
326 
327       if(strerr == NULL)
328         strerr = gnutls_strerror(rc);
329 
330       infof(data, "gnutls_handshake() warning: %s\n", strerr);
331       continue;
332     }
333     else if(rc < 0) {
334       const char *strerr = NULL;
335 
336       if(rc == GNUTLS_E_FATAL_ALERT_RECEIVED) {
337         int alert = gnutls_alert_get(session);
338         strerr = gnutls_alert_get_name(alert);
339       }
340 
341       if(strerr == NULL)
342         strerr = gnutls_strerror(rc);
343 
344       failf(data, "gnutls_handshake() failed: %s", strerr);
345       return CURLE_SSL_CONNECT_ERROR;
346     }
347 
348     /* Reset our connect state machine */
349     connssl->connecting_state = ssl_connect_1;
350     return CURLE_OK;
351   }
352 }
353 
do_file_type(const char * type)354 static gnutls_x509_crt_fmt_t do_file_type(const char *type)
355 {
356   if(!type || !type[0])
357     return GNUTLS_X509_FMT_PEM;
358   if(Curl_raw_equal(type, "PEM"))
359     return GNUTLS_X509_FMT_PEM;
360   if(Curl_raw_equal(type, "DER"))
361     return GNUTLS_X509_FMT_DER;
362   return -1;
363 }
364 
365 static CURLcode
gtls_connect_step1(struct connectdata * conn,int sockindex)366 gtls_connect_step1(struct connectdata *conn,
367                    int sockindex)
368 {
369   struct SessionHandle *data = conn->data;
370   gnutls_session_t session;
371   int rc;
372   void *ssl_sessionid;
373   size_t ssl_idsize;
374   bool sni = TRUE; /* default is SNI enabled */
375 #ifdef ENABLE_IPV6
376   struct in6_addr addr;
377 #else
378   struct in_addr addr;
379 #endif
380 #ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
381   static const int cipher_priority[] = {
382   /* These two ciphers were added to GnuTLS as late as ver. 3.0.1,
383      but this code path is only ever used for ver. < 2.12.0.
384      GNUTLS_CIPHER_AES_128_GCM,
385      GNUTLS_CIPHER_AES_256_GCM,
386   */
387     GNUTLS_CIPHER_AES_128_CBC,
388     GNUTLS_CIPHER_AES_256_CBC,
389     GNUTLS_CIPHER_CAMELLIA_128_CBC,
390     GNUTLS_CIPHER_CAMELLIA_256_CBC,
391     GNUTLS_CIPHER_3DES_CBC,
392   };
393   static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
394   static int protocol_priority[] = { 0, 0, 0, 0 };
395 #else
396 #define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509"
397 /* If GnuTLS was compiled without support for SRP it will error out if SRP is
398    requested in the priority string, so treat it specially
399  */
400 #define GNUTLS_SRP "+SRP"
401   const char* prioritylist;
402   const char *err = NULL;
403 #endif
404 
405   if(conn->ssl[sockindex].state == ssl_connection_complete)
406     /* to make us tolerant against being called more than once for the
407        same connection */
408     return CURLE_OK;
409 
410   if(!gtls_inited)
411     Curl_gtls_init();
412 
413   /* GnuTLS only supports SSLv3 and TLSv1 */
414   if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
415     failf(data, "GnuTLS does not support SSLv2");
416     return CURLE_SSL_CONNECT_ERROR;
417   }
418   else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3)
419     sni = FALSE; /* SSLv3 has no SNI */
420 
421   /* allocate a cred struct */
422   rc = gnutls_certificate_allocate_credentials(&conn->ssl[sockindex].cred);
423   if(rc != GNUTLS_E_SUCCESS) {
424     failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc));
425     return CURLE_SSL_CONNECT_ERROR;
426   }
427 
428 #ifdef USE_TLS_SRP
429   if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
430     infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username);
431 
432     rc = gnutls_srp_allocate_client_credentials(
433            &conn->ssl[sockindex].srp_client_cred);
434     if(rc != GNUTLS_E_SUCCESS) {
435       failf(data, "gnutls_srp_allocate_client_cred() failed: %s",
436             gnutls_strerror(rc));
437       return CURLE_OUT_OF_MEMORY;
438     }
439 
440     rc = gnutls_srp_set_client_credentials(conn->ssl[sockindex].
441                                            srp_client_cred,
442                                            data->set.ssl.username,
443                                            data->set.ssl.password);
444     if(rc != GNUTLS_E_SUCCESS) {
445       failf(data, "gnutls_srp_set_client_cred() failed: %s",
446             gnutls_strerror(rc));
447       return CURLE_BAD_FUNCTION_ARGUMENT;
448     }
449   }
450 #endif
451 
452   if(data->set.ssl.CAfile) {
453     /* set the trusted CA cert bundle file */
454     gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred,
455                                         GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
456 
457     rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred,
458                                                 data->set.ssl.CAfile,
459                                                 GNUTLS_X509_FMT_PEM);
460     if(rc < 0) {
461       infof(data, "error reading ca cert file %s (%s)\n",
462             data->set.ssl.CAfile, gnutls_strerror(rc));
463       if(data->set.ssl.verifypeer)
464         return CURLE_SSL_CACERT_BADFILE;
465     }
466     else
467       infof(data, "found %d certificates in %s\n",
468             rc, data->set.ssl.CAfile);
469   }
470 
471 #ifdef HAS_CAPATH
472   if(data->set.ssl.CApath) {
473     /* set the trusted CA cert directory */
474     rc = gnutls_certificate_set_x509_trust_dir(conn->ssl[sockindex].cred,
475                                                 data->set.ssl.CApath,
476                                                 GNUTLS_X509_FMT_PEM);
477     if(rc < 0) {
478       infof(data, "error reading ca cert file %s (%s)\n",
479             data->set.ssl.CAfile, gnutls_strerror(rc));
480       if(data->set.ssl.verifypeer)
481         return CURLE_SSL_CACERT_BADFILE;
482     }
483     else
484       infof(data, "found %d certificates in %s\n",
485             rc, data->set.ssl.CApath);
486   }
487 #endif
488 
489   if(data->set.ssl.CRLfile) {
490     /* set the CRL list file */
491     rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred,
492                                               data->set.ssl.CRLfile,
493                                               GNUTLS_X509_FMT_PEM);
494     if(rc < 0) {
495       failf(data, "error reading crl file %s (%s)",
496             data->set.ssl.CRLfile, gnutls_strerror(rc));
497       return CURLE_SSL_CRL_BADFILE;
498     }
499     else
500       infof(data, "found %d CRL in %s\n",
501             rc, data->set.ssl.CRLfile);
502   }
503 
504   /* Initialize TLS session as a client */
505   rc = gnutls_init(&conn->ssl[sockindex].session, GNUTLS_CLIENT);
506   if(rc != GNUTLS_E_SUCCESS) {
507     failf(data, "gnutls_init() failed: %d", rc);
508     return CURLE_SSL_CONNECT_ERROR;
509   }
510 
511   /* convenient assign */
512   session = conn->ssl[sockindex].session;
513 
514   if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) &&
515 #ifdef ENABLE_IPV6
516      (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) &&
517 #endif
518      sni &&
519      (gnutls_server_name_set(session, GNUTLS_NAME_DNS, conn->host.name,
520                              strlen(conn->host.name)) < 0))
521     infof(data, "WARNING: failed to configure server name indication (SNI) "
522           "TLS extension\n");
523 
524   /* Use default priorities */
525   rc = gnutls_set_default_priority(session);
526   if(rc != GNUTLS_E_SUCCESS)
527     return CURLE_SSL_CONNECT_ERROR;
528 
529 #ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
530   rc = gnutls_cipher_set_priority(session, cipher_priority);
531   if(rc != GNUTLS_E_SUCCESS)
532     return CURLE_SSL_CONNECT_ERROR;
533 
534   /* Sets the priority on the certificate types supported by gnutls. Priority
535    is higher for types specified before others. After specifying the types
536    you want, you must append a 0. */
537   rc = gnutls_certificate_type_set_priority(session, cert_type_priority);
538   if(rc != GNUTLS_E_SUCCESS)
539     return CURLE_SSL_CONNECT_ERROR;
540 
541   if(data->set.ssl.cipher_list != NULL) {
542     failf(data, "can't pass a custom cipher list to older GnuTLS"
543           " versions");
544     return CURLE_SSL_CONNECT_ERROR;
545   }
546 
547   switch (data->set.ssl.version) {
548     case CURL_SSLVERSION_SSLv3:
549       protocol_priority[0] = GNUTLS_SSL3;
550       break;
551     case CURL_SSLVERSION_DEFAULT:
552     case CURL_SSLVERSION_TLSv1:
553       protocol_priority[0] = GNUTLS_TLS1_0;
554       protocol_priority[1] = GNUTLS_TLS1_1;
555       protocol_priority[2] = GNUTLS_TLS1_2;
556       break;
557     case CURL_SSLVERSION_TLSv1_0:
558       protocol_priority[0] = GNUTLS_TLS1_0;
559       break;
560     case CURL_SSLVERSION_TLSv1_1:
561       protocol_priority[0] = GNUTLS_TLS1_1;
562       break;
563     case CURL_SSLVERSION_TLSv1_2:
564       protocol_priority[0] = GNUTLS_TLS1_2;
565     break;
566       case CURL_SSLVERSION_SSLv2:
567     default:
568       failf(data, "GnuTLS does not support SSLv2");
569       return CURLE_SSL_CONNECT_ERROR;
570       break;
571   }
572   rc = gnutls_protocol_set_priority(session, protocol_priority);
573   if(rc != GNUTLS_E_SUCCESS) {
574     failf(data, "Did you pass a valid GnuTLS cipher list?");
575     return CURLE_SSL_CONNECT_ERROR;
576   }
577 
578 #else
579   /* Ensure +SRP comes at the *end* of all relevant strings so that it can be
580    * removed if a run-time error indicates that SRP is not supported by this
581    * GnuTLS version */
582   switch (data->set.ssl.version) {
583     case CURL_SSLVERSION_SSLv3:
584       prioritylist = GNUTLS_CIPHERS ":-VERS-TLS-ALL:+VERS-SSL3.0";
585       sni = false;
586       break;
587     case CURL_SSLVERSION_DEFAULT:
588     case CURL_SSLVERSION_TLSv1:
589       prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:" GNUTLS_SRP;
590       break;
591     case CURL_SSLVERSION_TLSv1_0:
592       prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
593                      "+VERS-TLS1.0:" GNUTLS_SRP;
594       break;
595     case CURL_SSLVERSION_TLSv1_1:
596       prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
597                      "+VERS-TLS1.1:" GNUTLS_SRP;
598       break;
599     case CURL_SSLVERSION_TLSv1_2:
600       prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
601                      "+VERS-TLS1.2:" GNUTLS_SRP;
602       break;
603     case CURL_SSLVERSION_SSLv2:
604     default:
605       failf(data, "GnuTLS does not support SSLv2");
606       return CURLE_SSL_CONNECT_ERROR;
607       break;
608   }
609   rc = gnutls_priority_set_direct(session, prioritylist, &err);
610   if((rc == GNUTLS_E_INVALID_REQUEST) && err) {
611     if(!strcmp(err, GNUTLS_SRP)) {
612       /* This GnuTLS was probably compiled without support for SRP.
613        * Note that fact and try again without it. */
614       int validprioritylen = curlx_uztosi(err - prioritylist);
615       char *prioritycopy = strdup(prioritylist);
616       if(!prioritycopy)
617         return CURLE_OUT_OF_MEMORY;
618 
619       infof(data, "This GnuTLS does not support SRP\n");
620       if(validprioritylen)
621         /* Remove the :+SRP */
622         prioritycopy[validprioritylen - 1] = 0;
623       rc = gnutls_priority_set_direct(session, prioritycopy, &err);
624       free(prioritycopy);
625     }
626   }
627   if(rc != GNUTLS_E_SUCCESS) {
628     failf(data, "Error %d setting GnuTLS cipher list starting with %s",
629           rc, err);
630     return CURLE_SSL_CONNECT_ERROR;
631   }
632 #endif
633 
634 #ifdef HAS_ALPN
635   if(data->set.ssl_enable_alpn) {
636     int cur = 0;
637     gnutls_datum_t protocols[2];
638 
639 #ifdef USE_NGHTTP2
640     if(data->set.httpversion == CURL_HTTP_VERSION_2_0) {
641       protocols[cur].data = (unsigned char *)NGHTTP2_PROTO_VERSION_ID;
642       protocols[cur].size = NGHTTP2_PROTO_VERSION_ID_LEN;
643       cur++;
644       infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
645     }
646 #endif
647 
648     protocols[cur].data = (unsigned char *)ALPN_HTTP_1_1;
649     protocols[cur].size = ALPN_HTTP_1_1_LENGTH;
650     cur++;
651     infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
652 
653     gnutls_alpn_set_protocols(session, protocols, cur, 0);
654   }
655 #endif
656 
657   if(data->set.str[STRING_CERT]) {
658     if(gnutls_certificate_set_x509_key_file(
659          conn->ssl[sockindex].cred,
660          data->set.str[STRING_CERT],
661          data->set.str[STRING_KEY] ?
662          data->set.str[STRING_KEY] : data->set.str[STRING_CERT],
663          do_file_type(data->set.str[STRING_CERT_TYPE]) ) !=
664        GNUTLS_E_SUCCESS) {
665       failf(data, "error reading X.509 key or certificate file");
666       return CURLE_SSL_CONNECT_ERROR;
667     }
668   }
669 
670 #ifdef USE_TLS_SRP
671   /* put the credentials to the current session */
672   if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
673     rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP,
674                                 conn->ssl[sockindex].srp_client_cred);
675     if(rc != GNUTLS_E_SUCCESS) {
676       failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
677       return CURLE_SSL_CONNECT_ERROR;
678     }
679   }
680   else
681 #endif
682   {
683     rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
684                                 conn->ssl[sockindex].cred);
685     if(rc != GNUTLS_E_SUCCESS) {
686       failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
687       return CURLE_SSL_CONNECT_ERROR;
688     }
689   }
690 
691   /* set the connection handle (file descriptor for the socket) */
692   gnutls_transport_set_ptr(session,
693                            GNUTLS_INT_TO_POINTER_CAST(conn->sock[sockindex]));
694 
695   /* register callback functions to send and receive data. */
696   gnutls_transport_set_push_function(session, Curl_gtls_push);
697   gnutls_transport_set_pull_function(session, Curl_gtls_pull);
698 
699   /* lowat must be set to zero when using custom push and pull functions. */
700   gnutls_transport_set_lowat(session, 0);
701 
702 #ifdef HAS_OCSP
703   if(data->set.ssl.verifystatus) {
704     rc = gnutls_ocsp_status_request_enable_client(session, NULL, 0, NULL);
705     if(rc != GNUTLS_E_SUCCESS) {
706       failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc);
707       return CURLE_SSL_CONNECT_ERROR;
708     }
709   }
710 #endif
711 
712   /* This might be a reconnect, so we check for a session ID in the cache
713      to speed up things */
714 
715   if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize)) {
716     /* we got a session id, use it! */
717     gnutls_session_set_data(session, ssl_sessionid, ssl_idsize);
718 
719     /* Informational message */
720     infof (data, "SSL re-using session ID\n");
721   }
722 
723   return CURLE_OK;
724 }
725 
pkp_pin_peer_pubkey(gnutls_x509_crt_t cert,const char * pinnedpubkey)726 static CURLcode pkp_pin_peer_pubkey(gnutls_x509_crt_t cert,
727                                     const char *pinnedpubkey)
728 {
729   /* Scratch */
730   size_t len1 = 0, len2 = 0;
731   unsigned char *buff1 = NULL;
732 
733   gnutls_pubkey_t key = NULL;
734 
735   /* Result is returned to caller */
736   int ret = 0;
737   CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
738 
739   /* if a path wasn't specified, don't pin */
740   if(NULL == pinnedpubkey)
741     return CURLE_OK;
742 
743   if(NULL == cert)
744     return result;
745 
746   do {
747     /* Begin Gyrations to get the public key     */
748     gnutls_pubkey_init(&key);
749 
750     ret = gnutls_pubkey_import_x509(key, cert, 0);
751     if(ret < 0)
752       break; /* failed */
753 
754     ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, NULL, &len1);
755     if(ret != GNUTLS_E_SHORT_MEMORY_BUFFER || len1 == 0)
756       break; /* failed */
757 
758     buff1 = malloc(len1);
759     if(NULL == buff1)
760       break; /* failed */
761 
762     len2 = len1;
763 
764     ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, buff1, &len2);
765     if(ret < 0 || len1 != len2)
766       break; /* failed */
767 
768     /* End Gyrations */
769 
770     /* The one good exit point */
771     result = Curl_pin_peer_pubkey(pinnedpubkey, buff1, len1);
772   } while(0);
773 
774   if(NULL != key)
775     gnutls_pubkey_deinit(key);
776 
777   Curl_safefree(buff1);
778 
779   return result;
780 }
781 
782 static Curl_recv gtls_recv;
783 static Curl_send gtls_send;
784 
785 static CURLcode
gtls_connect_step3(struct connectdata * conn,int sockindex)786 gtls_connect_step3(struct connectdata *conn,
787                    int sockindex)
788 {
789   unsigned int cert_list_size;
790   const gnutls_datum_t *chainp;
791   unsigned int verify_status = 0;
792   gnutls_x509_crt_t x509_cert, x509_issuer;
793   gnutls_datum_t issuerp;
794   char certbuf[256] = ""; /* big enough? */
795   size_t size;
796   unsigned int algo;
797   unsigned int bits;
798   time_t certclock;
799   const char *ptr;
800   struct SessionHandle *data = conn->data;
801   gnutls_session_t session = conn->ssl[sockindex].session;
802   int rc;
803   bool incache;
804   void *ssl_sessionid;
805 #ifdef HAS_ALPN
806   gnutls_datum_t proto;
807 #endif
808   CURLcode result = CURLE_OK;
809 
810   gnutls_protocol_t version = gnutls_protocol_get_version(session);
811 
812   /* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
813   ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session),
814                                      gnutls_cipher_get(session),
815                                      gnutls_mac_get(session));
816 
817   infof(data, "SSL connection using %s / %s\n",
818         gnutls_protocol_get_name(version), ptr);
819 
820   /* This function will return the peer's raw certificate (chain) as sent by
821      the peer. These certificates are in raw format (DER encoded for
822      X.509). In case of a X.509 then a certificate list may be present. The
823      first certificate in the list is the peer's certificate, following the
824      issuer's certificate, then the issuer's issuer etc. */
825 
826   chainp = gnutls_certificate_get_peers(session, &cert_list_size);
827   if(!chainp) {
828     if(data->set.ssl.verifypeer ||
829        data->set.ssl.verifyhost ||
830        data->set.ssl.issuercert) {
831 #ifdef USE_TLS_SRP
832       if(data->set.ssl.authtype == CURL_TLSAUTH_SRP
833          && data->set.ssl.username != NULL
834          && !data->set.ssl.verifypeer
835          && gnutls_cipher_get(session)) {
836         /* no peer cert, but auth is ok if we have SRP user and cipher and no
837            peer verify */
838       }
839       else {
840 #endif
841         failf(data, "failed to get server cert");
842         return CURLE_PEER_FAILED_VERIFICATION;
843 #ifdef USE_TLS_SRP
844       }
845 #endif
846     }
847     infof(data, "\t common name: WARNING couldn't obtain\n");
848   }
849 
850   if(data->set.ssl.certinfo && chainp) {
851     unsigned int i;
852 
853     result = Curl_ssl_init_certinfo(data, cert_list_size);
854     if(result)
855       return result;
856 
857     for(i = 0; i < cert_list_size; i++) {
858       const char *beg = (const char *) chainp[i].data;
859       const char *end = beg + chainp[i].size;
860 
861       result = Curl_extract_certinfo(conn, i, beg, end);
862       if(result)
863         return result;
864     }
865   }
866 
867   if(data->set.ssl.verifypeer) {
868     /* This function will try to verify the peer's certificate and return its
869        status (trusted, invalid etc.). The value of status should be one or
870        more of the gnutls_certificate_status_t enumerated elements bitwise
871        or'd. To avoid denial of service attacks some default upper limits
872        regarding the certificate key size and chain size are set. To override
873        them use gnutls_certificate_set_verify_limits(). */
874 
875     rc = gnutls_certificate_verify_peers2(session, &verify_status);
876     if(rc < 0) {
877       failf(data, "server cert verify failed: %d", rc);
878       return CURLE_SSL_CONNECT_ERROR;
879     }
880 
881     /* verify_status is a bitmask of gnutls_certificate_status bits */
882     if(verify_status & GNUTLS_CERT_INVALID) {
883       if(data->set.ssl.verifypeer) {
884         failf(data, "server certificate verification failed. CAfile: %s "
885               "CRLfile: %s", data->set.ssl.CAfile?data->set.ssl.CAfile:"none",
886               data->set.ssl.CRLfile?data->set.ssl.CRLfile:"none");
887         return CURLE_SSL_CACERT;
888       }
889       else
890         infof(data, "\t server certificate verification FAILED\n");
891     }
892     else
893       infof(data, "\t server certificate verification OK\n");
894   }
895   else
896     infof(data, "\t server certificate verification SKIPPED\n");
897 
898 #ifdef HAS_OCSP
899   if(data->set.ssl.verifystatus) {
900     if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) {
901       gnutls_datum_t status_request;
902       gnutls_ocsp_resp_t ocsp_resp;
903 
904       gnutls_ocsp_cert_status_t status;
905       gnutls_x509_crl_reason_t reason;
906 
907       rc = gnutls_ocsp_status_request_get(session, &status_request);
908 
909       infof(data, "\t server certificate status verification FAILED\n");
910 
911       if(rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
912         failf(data, "No OCSP response received");
913         return CURLE_SSL_INVALIDCERTSTATUS;
914       }
915 
916       if(rc < 0) {
917         failf(data, "Invalid OCSP response received");
918         return CURLE_SSL_INVALIDCERTSTATUS;
919       }
920 
921       gnutls_ocsp_resp_init(&ocsp_resp);
922 
923       rc = gnutls_ocsp_resp_import(ocsp_resp, &status_request);
924       if(rc < 0) {
925         failf(data, "Invalid OCSP response received");
926         return CURLE_SSL_INVALIDCERTSTATUS;
927       }
928 
929       rc = gnutls_ocsp_resp_get_single(ocsp_resp, 0, NULL, NULL, NULL, NULL,
930                                        &status, NULL, NULL, NULL, &reason);
931 
932       switch(status) {
933       case GNUTLS_OCSP_CERT_GOOD:
934         break;
935 
936       case GNUTLS_OCSP_CERT_REVOKED: {
937         const char *crl_reason;
938 
939         switch(reason) {
940           default:
941           case GNUTLS_X509_CRLREASON_UNSPECIFIED:
942             crl_reason = "unspecified reason";
943             break;
944 
945           case GNUTLS_X509_CRLREASON_KEYCOMPROMISE:
946             crl_reason = "private key compromised";
947             break;
948 
949           case GNUTLS_X509_CRLREASON_CACOMPROMISE:
950             crl_reason = "CA compromised";
951             break;
952 
953           case GNUTLS_X509_CRLREASON_AFFILIATIONCHANGED:
954             crl_reason = "affiliation has changed";
955             break;
956 
957           case GNUTLS_X509_CRLREASON_SUPERSEDED:
958             crl_reason = "certificate superseded";
959             break;
960 
961           case GNUTLS_X509_CRLREASON_CESSATIONOFOPERATION:
962             crl_reason = "operation has ceased";
963             break;
964 
965           case GNUTLS_X509_CRLREASON_CERTIFICATEHOLD:
966             crl_reason = "certificate is on hold";
967             break;
968 
969           case GNUTLS_X509_CRLREASON_REMOVEFROMCRL:
970             crl_reason = "will be removed from delta CRL";
971             break;
972 
973           case GNUTLS_X509_CRLREASON_PRIVILEGEWITHDRAWN:
974             crl_reason = "privilege withdrawn";
975             break;
976 
977           case GNUTLS_X509_CRLREASON_AACOMPROMISE:
978             crl_reason = "AA compromised";
979             break;
980         }
981 
982         failf(data, "Server certificate was revoked: %s", crl_reason);
983         break;
984       }
985 
986       default:
987       case GNUTLS_OCSP_CERT_UNKNOWN:
988         failf(data, "Server certificate status is unknown");
989         break;
990       }
991 
992       gnutls_ocsp_resp_deinit(ocsp_resp);
993 
994       return CURLE_SSL_INVALIDCERTSTATUS;
995     }
996     else
997       infof(data, "\t server certificate status verification OK\n");
998   }
999   else
1000     infof(data, "\t server certificate status verification SKIPPED\n");
1001 #endif
1002 
1003   /* initialize an X.509 certificate structure. */
1004   gnutls_x509_crt_init(&x509_cert);
1005 
1006   if(chainp)
1007     /* convert the given DER or PEM encoded Certificate to the native
1008        gnutls_x509_crt_t format */
1009     gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
1010 
1011   if(data->set.ssl.issuercert) {
1012     gnutls_x509_crt_init(&x509_issuer);
1013     issuerp = load_file(data->set.ssl.issuercert);
1014     gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
1015     rc = gnutls_x509_crt_check_issuer(x509_cert, x509_issuer);
1016     gnutls_x509_crt_deinit(x509_issuer);
1017     unload_file(issuerp);
1018     if(rc <= 0) {
1019       failf(data, "server certificate issuer check failed (IssuerCert: %s)",
1020             data->set.ssl.issuercert?data->set.ssl.issuercert:"none");
1021       gnutls_x509_crt_deinit(x509_cert);
1022       return CURLE_SSL_ISSUER_ERROR;
1023     }
1024     infof(data, "\t server certificate issuer check OK (Issuer Cert: %s)\n",
1025           data->set.ssl.issuercert?data->set.ssl.issuercert:"none");
1026   }
1027 
1028   size=sizeof(certbuf);
1029   rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
1030                                      0, /* the first and only one */
1031                                      FALSE,
1032                                      certbuf,
1033                                      &size);
1034   if(rc) {
1035     infof(data, "error fetching CN from cert:%s\n",
1036           gnutls_strerror(rc));
1037   }
1038 
1039   /* This function will check if the given certificate's subject matches the
1040      given hostname. This is a basic implementation of the matching described
1041      in RFC2818 (HTTPS), which takes into account wildcards, and the subject
1042      alternative name PKIX extension. Returns non zero on success, and zero on
1043      failure. */
1044   rc = gnutls_x509_crt_check_hostname(x509_cert, conn->host.name);
1045 #if GNUTLS_VERSION_NUMBER < 0x030306
1046   /* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP
1047      addresses. */
1048   if(!rc) {
1049 #ifdef ENABLE_IPV6
1050     #define use_addr in6_addr
1051 #else
1052     #define use_addr in_addr
1053 #endif
1054     unsigned char addrbuf[sizeof(struct use_addr)];
1055     unsigned char certaddr[sizeof(struct use_addr)];
1056     size_t addrlen = 0, certaddrlen;
1057     int i;
1058     int ret = 0;
1059 
1060     if(Curl_inet_pton(AF_INET, conn->host.name, addrbuf) > 0)
1061       addrlen = 4;
1062 #ifdef ENABLE_IPV6
1063     else if(Curl_inet_pton(AF_INET6, conn->host.name, addrbuf) > 0)
1064       addrlen = 16;
1065 #endif
1066 
1067     if(addrlen) {
1068       for(i=0; ; i++) {
1069         certaddrlen = sizeof(certaddr);
1070         ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr,
1071                                                    &certaddrlen, NULL);
1072         /* If this happens, it wasn't an IP address. */
1073         if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
1074           continue;
1075         if(ret < 0)
1076           break;
1077         if(ret != GNUTLS_SAN_IPADDRESS)
1078           continue;
1079         if(certaddrlen == addrlen && !memcmp(addrbuf, certaddr, addrlen)) {
1080           rc = 1;
1081           break;
1082         }
1083       }
1084     }
1085   }
1086 #endif
1087   if(!rc) {
1088     if(data->set.ssl.verifyhost) {
1089       failf(data, "SSL: certificate subject name (%s) does not match "
1090             "target host name '%s'", certbuf, conn->host.dispname);
1091       gnutls_x509_crt_deinit(x509_cert);
1092       return CURLE_PEER_FAILED_VERIFICATION;
1093     }
1094     else
1095       infof(data, "\t common name: %s (does not match '%s')\n",
1096             certbuf, conn->host.dispname);
1097   }
1098   else
1099     infof(data, "\t common name: %s (matched)\n", certbuf);
1100 
1101   /* Check for time-based validity */
1102   certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
1103 
1104   if(certclock == (time_t)-1) {
1105     if(data->set.ssl.verifypeer) {
1106       failf(data, "server cert expiration date verify failed");
1107       gnutls_x509_crt_deinit(x509_cert);
1108       return CURLE_SSL_CONNECT_ERROR;
1109     }
1110     else
1111       infof(data, "\t server certificate expiration date verify FAILED\n");
1112   }
1113   else {
1114     if(certclock < time(NULL)) {
1115       if(data->set.ssl.verifypeer) {
1116         failf(data, "server certificate expiration date has passed.");
1117         gnutls_x509_crt_deinit(x509_cert);
1118         return CURLE_PEER_FAILED_VERIFICATION;
1119       }
1120       else
1121         infof(data, "\t server certificate expiration date FAILED\n");
1122     }
1123     else
1124       infof(data, "\t server certificate expiration date OK\n");
1125   }
1126 
1127   certclock = gnutls_x509_crt_get_activation_time(x509_cert);
1128 
1129   if(certclock == (time_t)-1) {
1130     if(data->set.ssl.verifypeer) {
1131       failf(data, "server cert activation date verify failed");
1132       gnutls_x509_crt_deinit(x509_cert);
1133       return CURLE_SSL_CONNECT_ERROR;
1134     }
1135     else
1136       infof(data, "\t server certificate activation date verify FAILED\n");
1137   }
1138   else {
1139     if(certclock > time(NULL)) {
1140       if(data->set.ssl.verifypeer) {
1141         failf(data, "server certificate not activated yet.");
1142         gnutls_x509_crt_deinit(x509_cert);
1143         return CURLE_PEER_FAILED_VERIFICATION;
1144       }
1145       else
1146         infof(data, "\t server certificate activation date FAILED\n");
1147     }
1148     else
1149       infof(data, "\t server certificate activation date OK\n");
1150   }
1151 
1152   ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
1153   if(ptr) {
1154     result = pkp_pin_peer_pubkey(x509_cert, ptr);
1155     if(result != CURLE_OK) {
1156       failf(data, "SSL: public key does not match pinned public key!");
1157       gnutls_x509_crt_deinit(x509_cert);
1158       return result;
1159     }
1160   }
1161 
1162   /* Show:
1163 
1164   - subject
1165   - start date
1166   - expire date
1167   - common name
1168   - issuer
1169 
1170   */
1171 
1172   /* public key algorithm's parameters */
1173   algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
1174   infof(data, "\t certificate public key: %s\n",
1175         gnutls_pk_algorithm_get_name(algo));
1176 
1177   /* version of the X.509 certificate. */
1178   infof(data, "\t certificate version: #%d\n",
1179         gnutls_x509_crt_get_version(x509_cert));
1180 
1181 
1182   size = sizeof(certbuf);
1183   gnutls_x509_crt_get_dn(x509_cert, certbuf, &size);
1184   infof(data, "\t subject: %s\n", certbuf);
1185 
1186   certclock = gnutls_x509_crt_get_activation_time(x509_cert);
1187   showtime(data, "start date", certclock);
1188 
1189   certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
1190   showtime(data, "expire date", certclock);
1191 
1192   size = sizeof(certbuf);
1193   gnutls_x509_crt_get_issuer_dn(x509_cert, certbuf, &size);
1194   infof(data, "\t issuer: %s\n", certbuf);
1195 
1196   gnutls_x509_crt_deinit(x509_cert);
1197 
1198   /* compression algorithm (if any) */
1199   ptr = gnutls_compression_get_name(gnutls_compression_get(session));
1200   /* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */
1201   infof(data, "\t compression: %s\n", ptr);
1202 
1203 #ifdef HAS_ALPN
1204   if(data->set.ssl_enable_alpn) {
1205     rc = gnutls_alpn_get_selected_protocol(session, &proto);
1206     if(rc == 0) {
1207       infof(data, "ALPN, server accepted to use %.*s\n", proto.size,
1208           proto.data);
1209 
1210 #ifdef USE_NGHTTP2
1211       if(proto.size == NGHTTP2_PROTO_VERSION_ID_LEN &&
1212          !memcmp(NGHTTP2_PROTO_VERSION_ID, proto.data,
1213                  NGHTTP2_PROTO_VERSION_ID_LEN)) {
1214         conn->negnpn = CURL_HTTP_VERSION_2_0;
1215       }
1216       else
1217 #endif
1218       if(proto.size == ALPN_HTTP_1_1_LENGTH &&
1219          !memcmp(ALPN_HTTP_1_1, proto.data, ALPN_HTTP_1_1_LENGTH)) {
1220         conn->negnpn = CURL_HTTP_VERSION_1_1;
1221       }
1222     }
1223     else
1224       infof(data, "ALPN, server did not agree to a protocol\n");
1225   }
1226 #endif
1227 
1228   conn->ssl[sockindex].state = ssl_connection_complete;
1229   conn->recv[sockindex] = gtls_recv;
1230   conn->send[sockindex] = gtls_send;
1231 
1232   {
1233     /* we always unconditionally get the session id here, as even if we
1234        already got it from the cache and asked to use it in the connection, it
1235        might've been rejected and then a new one is in use now and we need to
1236        detect that. */
1237     void *connect_sessionid;
1238     size_t connect_idsize = 0;
1239 
1240     /* get the session ID data size */
1241     gnutls_session_get_data(session, NULL, &connect_idsize);
1242     connect_sessionid = malloc(connect_idsize); /* get a buffer for it */
1243 
1244     if(connect_sessionid) {
1245       /* extract session ID to the allocated buffer */
1246       gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
1247 
1248       incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL));
1249       if(incache) {
1250         /* there was one before in the cache, so instead of risking that the
1251            previous one was rejected, we just kill that and store the new */
1252         Curl_ssl_delsessionid(conn, ssl_sessionid);
1253       }
1254 
1255       /* store this session id */
1256       result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize);
1257       if(result) {
1258         free(connect_sessionid);
1259         result = CURLE_OUT_OF_MEMORY;
1260       }
1261     }
1262     else
1263       result = CURLE_OUT_OF_MEMORY;
1264   }
1265 
1266   return result;
1267 }
1268 
1269 
1270 /*
1271  * This function is called after the TCP connect has completed. Setup the TLS
1272  * layer and do all necessary magic.
1273  */
1274 /* We use connssl->connecting_state to keep track of the connection status;
1275    there are three states: 'ssl_connect_1' (not started yet or complete),
1276    'ssl_connect_2_reading' (waiting for data from server), and
1277    'ssl_connect_2_writing' (waiting to be able to write).
1278  */
1279 static CURLcode
gtls_connect_common(struct connectdata * conn,int sockindex,bool nonblocking,bool * done)1280 gtls_connect_common(struct connectdata *conn,
1281                     int sockindex,
1282                     bool nonblocking,
1283                     bool *done)
1284 {
1285   int rc;
1286   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1287 
1288   /* Initiate the connection, if not already done */
1289   if(ssl_connect_1==connssl->connecting_state) {
1290     rc = gtls_connect_step1 (conn, sockindex);
1291     if(rc)
1292       return rc;
1293   }
1294 
1295   rc = handshake(conn, sockindex, TRUE, nonblocking);
1296   if(rc)
1297     /* handshake() sets its own error message with failf() */
1298     return rc;
1299 
1300   /* Finish connecting once the handshake is done */
1301   if(ssl_connect_1==connssl->connecting_state) {
1302     rc = gtls_connect_step3(conn, sockindex);
1303     if(rc)
1304       return rc;
1305   }
1306 
1307   *done = ssl_connect_1==connssl->connecting_state;
1308 
1309   return CURLE_OK;
1310 }
1311 
1312 CURLcode
Curl_gtls_connect_nonblocking(struct connectdata * conn,int sockindex,bool * done)1313 Curl_gtls_connect_nonblocking(struct connectdata *conn,
1314                               int sockindex,
1315                               bool *done)
1316 {
1317   return gtls_connect_common(conn, sockindex, TRUE, done);
1318 }
1319 
1320 CURLcode
Curl_gtls_connect(struct connectdata * conn,int sockindex)1321 Curl_gtls_connect(struct connectdata *conn,
1322                   int sockindex)
1323 
1324 {
1325   CURLcode result;
1326   bool done = FALSE;
1327 
1328   result = gtls_connect_common(conn, sockindex, FALSE, &done);
1329   if(result)
1330     return result;
1331 
1332   DEBUGASSERT(done);
1333 
1334   return CURLE_OK;
1335 }
1336 
gtls_send(struct connectdata * conn,int sockindex,const void * mem,size_t len,CURLcode * curlcode)1337 static ssize_t gtls_send(struct connectdata *conn,
1338                          int sockindex,
1339                          const void *mem,
1340                          size_t len,
1341                          CURLcode *curlcode)
1342 {
1343   ssize_t rc = gnutls_record_send(conn->ssl[sockindex].session, mem, len);
1344 
1345   if(rc < 0 ) {
1346     *curlcode = (rc == GNUTLS_E_AGAIN)
1347       ? CURLE_AGAIN
1348       : CURLE_SEND_ERROR;
1349 
1350     rc = -1;
1351   }
1352 
1353   return rc;
1354 }
1355 
close_one(struct connectdata * conn,int idx)1356 static void close_one(struct connectdata *conn,
1357                       int idx)
1358 {
1359   if(conn->ssl[idx].session) {
1360     gnutls_bye(conn->ssl[idx].session, GNUTLS_SHUT_RDWR);
1361     gnutls_deinit(conn->ssl[idx].session);
1362     conn->ssl[idx].session = NULL;
1363   }
1364   if(conn->ssl[idx].cred) {
1365     gnutls_certificate_free_credentials(conn->ssl[idx].cred);
1366     conn->ssl[idx].cred = NULL;
1367   }
1368 #ifdef USE_TLS_SRP
1369   if(conn->ssl[idx].srp_client_cred) {
1370     gnutls_srp_free_client_credentials(conn->ssl[idx].srp_client_cred);
1371     conn->ssl[idx].srp_client_cred = NULL;
1372   }
1373 #endif
1374 }
1375 
Curl_gtls_close(struct connectdata * conn,int sockindex)1376 void Curl_gtls_close(struct connectdata *conn, int sockindex)
1377 {
1378   close_one(conn, sockindex);
1379 }
1380 
1381 /*
1382  * This function is called to shut down the SSL layer but keep the
1383  * socket open (CCC - Clear Command Channel)
1384  */
Curl_gtls_shutdown(struct connectdata * conn,int sockindex)1385 int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
1386 {
1387   ssize_t result;
1388   int retval = 0;
1389   struct SessionHandle *data = conn->data;
1390   int done = 0;
1391   char buf[120];
1392 
1393   /* This has only been tested on the proftpd server, and the mod_tls code
1394      sends a close notify alert without waiting for a close notify alert in
1395      response. Thus we wait for a close notify alert from the server, but
1396      we do not send one. Let's hope other servers do the same... */
1397 
1398   if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
1399       gnutls_bye(conn->ssl[sockindex].session, GNUTLS_SHUT_WR);
1400 
1401   if(conn->ssl[sockindex].session) {
1402     while(!done) {
1403       int what = Curl_socket_ready(conn->sock[sockindex],
1404                                    CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
1405       if(what > 0) {
1406         /* Something to read, let's do it and hope that it is the close
1407            notify alert from the server */
1408         result = gnutls_record_recv(conn->ssl[sockindex].session,
1409                                     buf, sizeof(buf));
1410         switch(result) {
1411         case 0:
1412           /* This is the expected response. There was no data but only
1413              the close notify alert */
1414           done = 1;
1415           break;
1416         case GNUTLS_E_AGAIN:
1417         case GNUTLS_E_INTERRUPTED:
1418           infof(data, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED\n");
1419           break;
1420         default:
1421           retval = -1;
1422           done = 1;
1423           break;
1424         }
1425       }
1426       else if(0 == what) {
1427         /* timeout */
1428         failf(data, "SSL shutdown timeout");
1429         done = 1;
1430         break;
1431       }
1432       else {
1433         /* anything that gets here is fatally bad */
1434         failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
1435         retval = -1;
1436         done = 1;
1437       }
1438     }
1439     gnutls_deinit(conn->ssl[sockindex].session);
1440   }
1441   gnutls_certificate_free_credentials(conn->ssl[sockindex].cred);
1442 
1443 #ifdef USE_TLS_SRP
1444   if(data->set.ssl.authtype == CURL_TLSAUTH_SRP
1445      && data->set.ssl.username != NULL)
1446     gnutls_srp_free_client_credentials(conn->ssl[sockindex].srp_client_cred);
1447 #endif
1448 
1449   conn->ssl[sockindex].cred = NULL;
1450   conn->ssl[sockindex].session = NULL;
1451 
1452   return retval;
1453 }
1454 
gtls_recv(struct connectdata * conn,int num,char * buf,size_t buffersize,CURLcode * curlcode)1455 static ssize_t gtls_recv(struct connectdata *conn, /* connection data */
1456                          int num,                  /* socketindex */
1457                          char *buf,                /* store read data here */
1458                          size_t buffersize,        /* max amount to read */
1459                          CURLcode *curlcode)
1460 {
1461   ssize_t ret;
1462 
1463   ret = gnutls_record_recv(conn->ssl[num].session, buf, buffersize);
1464   if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
1465     *curlcode = CURLE_AGAIN;
1466     return -1;
1467   }
1468 
1469   if(ret == GNUTLS_E_REHANDSHAKE) {
1470     /* BLOCKING call, this is bad but a work-around for now. Fixing this "the
1471        proper way" takes a whole lot of work. */
1472     CURLcode result = handshake(conn, num, FALSE, FALSE);
1473     if(result)
1474       /* handshake() writes error message on its own */
1475       *curlcode = result;
1476     else
1477       *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */
1478     return -1;
1479   }
1480 
1481   if(ret < 0) {
1482     failf(conn->data, "GnuTLS recv error (%d): %s",
1483           (int)ret, gnutls_strerror((int)ret));
1484     *curlcode = CURLE_RECV_ERROR;
1485     return -1;
1486   }
1487 
1488   return ret;
1489 }
1490 
Curl_gtls_session_free(void * ptr)1491 void Curl_gtls_session_free(void *ptr)
1492 {
1493   free(ptr);
1494 }
1495 
Curl_gtls_version(char * buffer,size_t size)1496 size_t Curl_gtls_version(char *buffer, size_t size)
1497 {
1498   return snprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
1499 }
1500 
1501 #ifndef USE_GNUTLS_NETTLE
Curl_gtls_seed(struct SessionHandle * data)1502 static int Curl_gtls_seed(struct SessionHandle *data)
1503 {
1504   /* we have the "SSL is seeded" boolean static to prevent multiple
1505      time-consuming seedings in vain */
1506   static bool ssl_seeded = FALSE;
1507 
1508   /* Quickly add a bit of entropy */
1509   gcry_fast_random_poll();
1510 
1511   if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] ||
1512      data->set.str[STRING_SSL_EGDSOCKET]) {
1513 
1514     /* TODO: to a good job seeding the RNG
1515        This may involve the gcry_control function and these options:
1516        GCRYCTL_SET_RANDOM_SEED_FILE
1517        GCRYCTL_SET_RNDEGD_SOCKET
1518     */
1519     ssl_seeded = TRUE;
1520   }
1521   return 0;
1522 }
1523 #endif
1524 
1525 /* data might be NULL! */
Curl_gtls_random(struct SessionHandle * data,unsigned char * entropy,size_t length)1526 int Curl_gtls_random(struct SessionHandle *data,
1527                      unsigned char *entropy,
1528                      size_t length)
1529 {
1530 #if defined(USE_GNUTLS_NETTLE)
1531   (void)data;
1532   gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
1533 #elif defined(USE_GNUTLS)
1534   if(data)
1535     Curl_gtls_seed(data); /* Initiate the seed if not already done */
1536   gcry_randomize(entropy, length, GCRY_STRONG_RANDOM);
1537 #endif
1538   return 0;
1539 }
1540 
Curl_gtls_md5sum(unsigned char * tmp,size_t tmplen,unsigned char * md5sum,size_t md5len)1541 void Curl_gtls_md5sum(unsigned char *tmp, /* input */
1542                       size_t tmplen,
1543                       unsigned char *md5sum, /* output */
1544                       size_t md5len)
1545 {
1546 #if defined(USE_GNUTLS_NETTLE)
1547   struct md5_ctx MD5pw;
1548   md5_init(&MD5pw);
1549   md5_update(&MD5pw, (unsigned int)tmplen, tmp);
1550   md5_digest(&MD5pw, (unsigned int)md5len, md5sum);
1551 #elif defined(USE_GNUTLS)
1552   gcry_md_hd_t MD5pw;
1553   gcry_md_open(&MD5pw, GCRY_MD_MD5, 0);
1554   gcry_md_write(MD5pw, tmp, tmplen);
1555   memcpy(md5sum, gcry_md_read (MD5pw, 0), md5len);
1556   gcry_md_close(MD5pw);
1557 #endif
1558 }
1559 
Curl_gtls_cert_status_request(void)1560 bool Curl_gtls_cert_status_request(void)
1561 {
1562 #ifdef HAS_OCSP
1563   return TRUE;
1564 #else
1565   return FALSE;
1566 #endif
1567 }
1568 
1569 #endif /* USE_GNUTLS */
1570