Revert changes relative to lib/*.[ch] recent renaming
[platform/upstream/curl.git] / lib / gtls.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2012, 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 sslgen.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 "setup.h"
32
33 #ifdef USE_GNUTLS
34
35 #include <gnutls/gnutls.h>
36 #include <gnutls/x509.h>
37
38 #ifdef USE_GNUTLS_NETTLE
39 #include <gnutls/crypto.h>
40 #include <nettle/md5.h>
41 #else
42 #include <gcrypt.h>
43 #endif
44
45 #include "urldata.h"
46 #include "sendf.h"
47 #include "inet_pton.h"
48 #include "gtls.h"
49 #include "sslgen.h"
50 #include "parsedate.h"
51 #include "connect.h" /* for the connect timeout */
52 #include "select.h"
53 #include "rawstr.h"
54
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: */
59 #include "memdebug.h"
60
61 /*
62  Some hackish cast macros based on:
63  http://library.gnome.org/devel/glib/unstable/glib-Type-Conversion-Macros.html
64 */
65 #ifndef GNUTLS_POINTER_TO_INT_CAST
66 #define GNUTLS_POINTER_TO_INT_CAST(p) ((int) (long) (p))
67 #endif
68 #ifndef GNUTLS_INT_TO_POINTER_CAST
69 #define GNUTLS_INT_TO_POINTER_CAST(i) ((void*) (long) (i))
70 #endif
71
72 /* Enable GnuTLS debugging by defining GTLSDEBUG */
73 /*#define GTLSDEBUG */
74
75 #ifdef GTLSDEBUG
76 static void tls_log_func(int level, const char *str)
77 {
78     fprintf(stderr, "|<%d>| %s", level, str);
79 }
80 #endif
81 static bool gtls_inited = FALSE;
82
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
88 #  endif
89 #  if (GNUTLS_VERSION_NUMBER >= 0x020c03)
90 #    define GNUTLS_MAPS_WINSOCK_ERRORS 1
91 #  endif
92 #endif
93
94 /*
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.
101  *
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.
111  *
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.
115  */
116
117 #if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
118 #  define gtls_EINTR  4
119 #  define gtls_EIO    5
120 #  define gtls_EAGAIN 11
121 static int gtls_mapped_sockerrno(void)
122 {
123   switch(SOCKERRNO) {
124   case WSAEWOULDBLOCK:
125     return gtls_EAGAIN;
126   case WSAEINTR:
127     return gtls_EINTR;
128   default:
129     break;
130   }
131   return gtls_EIO;
132 }
133 #endif
134
135 static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len)
136 {
137   ssize_t ret = swrite(GNUTLS_POINTER_TO_INT_CAST(s), buf, len);
138 #if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
139   if(ret < 0)
140     gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
141 #endif
142   return ret;
143 }
144
145 static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len)
146 {
147   ssize_t ret = sread(GNUTLS_POINTER_TO_INT_CAST(s), buf, len);
148 #if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
149   if(ret < 0)
150     gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
151 #endif
152   return ret;
153 }
154
155 /* Curl_gtls_init()
156  *
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!
161  */
162 int Curl_gtls_init(void)
163 {
164   int ret = 1;
165   if(!gtls_inited) {
166     ret = gnutls_global_init()?0:1;
167 #ifdef GTLSDEBUG
168     gnutls_global_set_log_function(tls_log_func);
169     gnutls_global_set_log_level(2);
170 #endif
171     gtls_inited = TRUE;
172   }
173   return ret;
174 }
175
176 int Curl_gtls_cleanup(void)
177 {
178   if(gtls_inited) {
179     gnutls_global_deinit();
180     gtls_inited = FALSE;
181   }
182   return 1;
183 }
184
185 static void showtime(struct SessionHandle *data,
186                      const char *text,
187                      time_t stamp)
188 {
189   struct tm buffer;
190   const struct tm *tm = &buffer;
191   CURLcode result = Curl_gmtime(stamp, &buffer);
192   if(result)
193     return;
194
195   snprintf(data->state.buffer,
196            BUFSIZE,
197            "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT\n",
198            text,
199            Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
200            tm->tm_mday,
201            Curl_month[tm->tm_mon],
202            tm->tm_year + 1900,
203            tm->tm_hour,
204            tm->tm_min,
205            tm->tm_sec);
206   infof(data, "%s\n", data->state.buffer);
207 }
208
209 static gnutls_datum load_file (const char *file)
210 {
211   FILE *f;
212   gnutls_datum loaded_file = { NULL, 0 };
213   long filelen;
214   void *ptr;
215
216   if(!(f = fopen(file, "r")))
217     return loaded_file;
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)))
222     goto out;
223   if(fread(ptr, 1, (size_t)filelen, f) < (size_t)filelen) {
224     free(ptr);
225     goto out;
226   }
227
228   loaded_file.data = ptr;
229   loaded_file.size = (unsigned int)filelen;
230 out:
231   fclose(f);
232   return loaded_file;
233 }
234
235 static void unload_file(gnutls_datum data) {
236   free(data.data);
237 }
238
239
240 /* this function does a SSL/TLS (re-)handshake */
241 static CURLcode handshake(struct connectdata *conn,
242                           int sockindex,
243                           bool duringconnect,
244                           bool nonblocking)
245 {
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];
250   long timeout_ms;
251   int rc;
252   int what;
253
254   for(;;) {
255     /* check allowed time left */
256     timeout_ms = Curl_timeleft(data, NULL, duringconnect);
257
258     if(timeout_ms < 0) {
259       /* no need to continue if time already is up */
260       failf(data, "SSL connection timeout");
261       return CURLE_OPERATION_TIMEDOUT;
262     }
263
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) {
267
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;
272
273       what = Curl_socket_ready(readfd, writefd,
274                                nonblocking?0:
275                                timeout_ms?timeout_ms:1000);
276       if(what < 0) {
277         /* fatal error */
278         failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
279         return CURLE_SSL_CONNECT_ERROR;
280       }
281       else if(0 == what) {
282         if(nonblocking)
283           return CURLE_OK;
284         else if(timeout_ms) {
285           /* timeout */
286           failf(data, "SSL connection timeout at %ld", timeout_ms);
287           return CURLE_OPERATION_TIMEDOUT;
288         }
289       }
290       /* socket is readable or writable */
291     }
292
293     rc = gnutls_handshake(session);
294
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;
299       continue;
300       if(nonblocking)
301         return CURLE_OK;
302     }
303     else if((rc < 0) && !gnutls_error_is_fatal(rc)) {
304       const char *strerr = NULL;
305
306       if(rc == GNUTLS_E_WARNING_ALERT_RECEIVED) {
307         int alert = gnutls_alert_get(session);
308         strerr = gnutls_alert_get_name(alert);
309       }
310
311       if(strerr == NULL)
312         strerr = gnutls_strerror(rc);
313
314       failf(data, "gnutls_handshake() warning: %s", strerr);
315     }
316     else if(rc < 0) {
317       const char *strerr = NULL;
318
319       if(rc == GNUTLS_E_FATAL_ALERT_RECEIVED) {
320         int alert = gnutls_alert_get(session);
321         strerr = gnutls_alert_get_name(alert);
322       }
323
324       if(strerr == NULL)
325         strerr = gnutls_strerror(rc);
326
327       failf(data, "gnutls_handshake() failed: %s", strerr);
328       return CURLE_SSL_CONNECT_ERROR;
329     }
330
331     /* Reset our connect state machine */
332     connssl->connecting_state = ssl_connect_1;
333     return CURLE_OK;
334   }
335 }
336
337 static gnutls_x509_crt_fmt do_file_type(const char *type)
338 {
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;
345   return -1;
346 }
347
348 static CURLcode
349 gtls_connect_step1(struct connectdata *conn,
350                    int sockindex)
351 {
352 #ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
353   static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
354 #endif
355   struct SessionHandle *data = conn->data;
356   gnutls_session session;
357   int rc;
358   void *ssl_sessionid;
359   size_t ssl_idsize;
360   bool sni = TRUE; /* default is SNI enabled */
361 #ifdef ENABLE_IPV6
362   struct in6_addr addr;
363 #else
364   struct in_addr addr;
365 #endif
366
367   if(conn->ssl[sockindex].state == ssl_connection_complete)
368     /* to make us tolerant against being called more than once for the
369        same connection */
370     return CURLE_OK;
371
372   if(!gtls_inited)
373     Curl_gtls_init();
374
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;
379   }
380   else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3)
381     sni = FALSE; /* SSLv3 has no SNI */
382
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;
388   }
389
390 #ifdef USE_TLS_SRP
391   if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
392     infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username);
393
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;
400     }
401
402     rc = gnutls_srp_set_client_credentials(conn->ssl[sockindex].
403                                            srp_client_cred,
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;
410     }
411   }
412 #endif
413
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);
418
419     rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred,
420                                                 data->set.ssl.CAfile,
421                                                 GNUTLS_X509_FMT_PEM);
422     if(rc < 0) {
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;
427     }
428     else
429       infof(data, "found %d certificates in %s\n",
430             rc, data->set.ssl.CAfile);
431   }
432
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);
438     if(rc < 0) {
439       failf(data, "error reading crl file %s (%s)",
440             data->set.ssl.CRLfile, gnutls_strerror(rc));
441       return CURLE_SSL_CRL_BADFILE;
442     }
443     else
444       infof(data, "found %d CRL in %s\n",
445             rc, data->set.ssl.CRLfile);
446   }
447
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;
453   }
454
455   /* convenient assign */
456   session = conn->ssl[sockindex].session;
457
458   if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) &&
459 #ifdef ENABLE_IPV6
460      (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) &&
461 #endif
462      sni &&
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) "
466           "TLS extension\n");
467
468   /* Use default priorities */
469   rc = gnutls_set_default_priority(session);
470   if(rc != GNUTLS_E_SUCCESS)
471     return CURLE_SSL_CONNECT_ERROR;
472
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);
477 #else
478     const char *err;
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
481        asks for that
482     */
483     rc = gnutls_priority_set_direct(session,
484                                     "NORMAL:-VERS-TLS-ALL:+VERS-SSL3.0:"
485                                     "-CIPHER-ALL:+ARCFOUR-128",
486                                     &err);
487 #endif
488     if(rc != GNUTLS_E_SUCCESS)
489       return CURLE_SSL_CONNECT_ERROR;
490   }
491
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;
499 #endif
500
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]) ) !=
508        GNUTLS_E_SUCCESS) {
509       failf(data, "error reading X.509 key or certificate file");
510       return CURLE_SSL_CONNECT_ERROR;
511     }
512   }
513
514 #ifdef USE_TLS_SRP
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));
521   }
522   else
523 #endif
524     rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
525                                 conn->ssl[sockindex].cred);
526
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]));
530
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);
534
535   /* lowat must be set to zero when using custom push and pull functions. */
536   gnutls_transport_set_lowat(session, 0);
537
538   /* This might be a reconnect, so we check for a session ID in the cache
539      to speed up things */
540
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);
544
545     /* Informational message */
546     infof (data, "SSL re-using session ID\n");
547   }
548
549   return CURLE_OK;
550 }
551
552 static Curl_recv gtls_recv;
553 static Curl_send gtls_send;
554
555 static CURLcode
556 gtls_connect_step3(struct connectdata *conn,
557                    int sockindex)
558 {
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? */
565   size_t size;
566   unsigned int algo;
567   unsigned int bits;
568   time_t certclock;
569   const char *ptr;
570   struct SessionHandle *data = conn->data;
571   gnutls_session session = conn->ssl[sockindex].session;
572   int rc;
573   int incache;
574   void *ssl_sessionid;
575   CURLcode result = CURLE_OK;
576
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. */
582
583   chainp = gnutls_certificate_get_peers(session, &cert_list_size);
584   if(!chainp) {
585     if(data->set.ssl.verifypeer ||
586        data->set.ssl.verifyhost ||
587        data->set.ssl.issuercert) {
588 #ifdef USE_TLS_SRP
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
594            peer verify */
595       }
596       else {
597 #endif
598         failf(data, "failed to get server cert");
599         return CURLE_PEER_FAILED_VERIFICATION;
600 #ifdef USE_TLS_SRP
601       }
602 #endif
603     }
604     infof(data, "\t common name: WARNING couldn't obtain\n");
605   }
606
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(). */
614
615     rc = gnutls_certificate_verify_peers2(session, &verify_status);
616     if(rc < 0) {
617       failf(data, "server cert verify failed: %d", rc);
618       return CURLE_SSL_CONNECT_ERROR;
619     }
620
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;
628       }
629       else
630         infof(data, "\t server certificate verification FAILED\n");
631     }
632     else
633       infof(data, "\t server certificate verification OK\n");
634   }
635   else {
636     infof(data, "\t server certificate verification SKIPPED\n");
637     goto after_server_cert_verification;
638   }
639
640   /* initialize an X.509 certificate structure. */
641   gnutls_x509_crt_init(&x509_cert);
642
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);
646
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);
653     if(rc <= 0) {
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;
657     }
658     infof(data,"\t server certificate issuer check OK (Issuer Cert: %s)\n",
659           data->set.ssl.issuercert?data->set.ssl.issuercert:"none");
660   }
661
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 */
665                                      FALSE,
666                                      certbuf,
667                                      &size);
668   if(rc) {
669     infof(data, "error fetching CN from cert:%s\n",
670           gnutls_strerror(rc));
671   }
672
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
677      failure. */
678   rc = gnutls_x509_crt_check_hostname(x509_cert, conn->host.name);
679
680   if(!rc) {
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;
686     }
687     else
688       infof(data, "\t common name: %s (does not match '%s')\n",
689             certbuf, conn->host.dispname);
690   }
691   else
692     infof(data, "\t common name: %s (matched)\n", certbuf);
693
694   /* Check for time-based validity */
695   certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
696
697   if(certclock == (time_t)-1) {
698     failf(data, "server cert expiration date verify failed");
699     return CURLE_SSL_CONNECT_ERROR;
700   }
701
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;
706     }
707     else
708       infof(data, "\t server certificate expiration date FAILED\n");
709   }
710   else
711     infof(data, "\t server certificate expiration date OK\n");
712
713   certclock = gnutls_x509_crt_get_activation_time(x509_cert);
714
715   if(certclock == (time_t)-1) {
716     failf(data, "server cert activation date verify failed");
717     return CURLE_SSL_CONNECT_ERROR;
718   }
719
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;
724     }
725     else
726       infof(data, "\t server certificate activation date FAILED\n");
727   }
728   else
729     infof(data, "\t server certificate activation date OK\n");
730
731   /* Show:
732
733   - ciphers used
734   - subject
735   - start date
736   - expire date
737   - common name
738   - issuer
739
740   */
741
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));
746
747   /* version of the X.509 certificate. */
748   infof(data, "\t certificate version: #%d\n",
749         gnutls_x509_crt_get_version(x509_cert));
750
751
752   size = sizeof(certbuf);
753   gnutls_x509_crt_get_dn(x509_cert, certbuf, &size);
754   infof(data, "\t subject: %s\n", certbuf);
755
756   certclock = gnutls_x509_crt_get_activation_time(x509_cert);
757   showtime(data, "start date", certclock);
758
759   certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
760   showtime(data, "expire date", certclock);
761
762   size = sizeof(certbuf);
763   gnutls_x509_crt_get_issuer_dn(x509_cert, certbuf, &size);
764   infof(data, "\t issuer: %s\n", certbuf);
765
766   gnutls_x509_crt_deinit(x509_cert);
767
768 after_server_cert_verification:
769
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);
774
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);
778
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);
782
783   conn->ssl[sockindex].state = ssl_connection_complete;
784   conn->recv[sockindex] = gtls_recv;
785   conn->send[sockindex] = gtls_send;
786
787   {
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
791        detect that. */
792     void *connect_sessionid;
793     size_t connect_idsize;
794
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 */
798
799     if(connect_sessionid) {
800       /* extract session ID to the allocated buffer */
801       gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
802
803       incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL));
804       if(incache) {
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);
808       }
809
810       /* store this session id */
811       result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize);
812       if(result) {
813         free(connect_sessionid);
814         result = CURLE_OUT_OF_MEMORY;
815       }
816     }
817     else
818       result = CURLE_OUT_OF_MEMORY;
819   }
820
821   return result;
822 }
823
824
825 /*
826  * This function is called after the TCP connect has completed. Setup the TLS
827  * layer and do all necessary magic.
828  */
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).
833  */
834 static CURLcode
835 gtls_connect_common(struct connectdata *conn,
836                     int sockindex,
837                     bool nonblocking,
838                     bool *done)
839 {
840   int rc;
841   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
842
843   /* Initiate the connection, if not already done */
844   if(ssl_connect_1==connssl->connecting_state) {
845     rc = gtls_connect_step1 (conn, sockindex);
846     if(rc)
847       return rc;
848   }
849
850   rc = handshake(conn, sockindex, TRUE, nonblocking);
851   if(rc)
852     /* handshake() sets its own error message with failf() */
853     return rc;
854
855   /* Finish connecting once the handshake is done */
856   if(ssl_connect_1==connssl->connecting_state) {
857     rc = gtls_connect_step3(conn, sockindex);
858     if(rc)
859       return rc;
860   }
861
862   *done = ssl_connect_1==connssl->connecting_state;
863
864   return CURLE_OK;
865 }
866
867 CURLcode
868 Curl_gtls_connect_nonblocking(struct connectdata *conn,
869                               int sockindex,
870                               bool *done)
871 {
872   return gtls_connect_common(conn, sockindex, TRUE, done);
873 }
874
875 CURLcode
876 Curl_gtls_connect(struct connectdata *conn,
877                   int sockindex)
878
879 {
880   CURLcode retcode;
881   bool done = FALSE;
882
883   retcode = gtls_connect_common(conn, sockindex, FALSE, &done);
884   if(retcode)
885     return retcode;
886
887   DEBUGASSERT(done);
888
889   return CURLE_OK;
890 }
891
892 static ssize_t gtls_send(struct connectdata *conn,
893                          int sockindex,
894                          const void *mem,
895                          size_t len,
896                          CURLcode *curlcode)
897 {
898   ssize_t rc = gnutls_record_send(conn->ssl[sockindex].session, mem, len);
899
900   if(rc < 0 ) {
901     *curlcode = (rc == GNUTLS_E_AGAIN)
902       ? CURLE_AGAIN
903       : CURLE_SEND_ERROR;
904
905     rc = -1;
906   }
907
908   return rc;
909 }
910
911 void Curl_gtls_close_all(struct SessionHandle *data)
912 {
913   /* FIX: make the OpenSSL code more generic and use parts of it here */
914   (void)data;
915 }
916
917 static void close_one(struct connectdata *conn,
918                       int idx)
919 {
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;
924   }
925   if(conn->ssl[idx].cred) {
926     gnutls_certificate_free_credentials(conn->ssl[idx].cred);
927     conn->ssl[idx].cred = NULL;
928   }
929 #ifdef USE_TLS_SRP
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;
933   }
934 #endif
935 }
936
937 void Curl_gtls_close(struct connectdata *conn, int sockindex)
938 {
939   close_one(conn, sockindex);
940 }
941
942 /*
943  * This function is called to shut down the SSL layer but keep the
944  * socket open (CCC - Clear Command Channel)
945  */
946 int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
947 {
948   ssize_t result;
949   int retval = 0;
950   struct SessionHandle *data = conn->data;
951   int done = 0;
952   char buf[120];
953
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... */
958
959   if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
960       gnutls_bye(conn->ssl[sockindex].session, GNUTLS_SHUT_WR);
961
962   if(conn->ssl[sockindex].session) {
963     while(!done) {
964       int what = Curl_socket_ready(conn->sock[sockindex],
965                                    CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
966       if(what > 0) {
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,
970                                     buf, sizeof(buf));
971         switch(result) {
972         case 0:
973           /* This is the expected response. There was no data but only
974              the close notify alert */
975           done = 1;
976           break;
977         case GNUTLS_E_AGAIN:
978         case GNUTLS_E_INTERRUPTED:
979           infof(data, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED\n");
980           break;
981         default:
982           retval = -1;
983           done = 1;
984           break;
985         }
986       }
987       else if(0 == what) {
988         /* timeout */
989         failf(data, "SSL shutdown timeout");
990         done = 1;
991         break;
992       }
993       else {
994         /* anything that gets here is fatally bad */
995         failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
996         retval = -1;
997         done = 1;
998       }
999     }
1000     gnutls_deinit(conn->ssl[sockindex].session);
1001   }
1002   gnutls_certificate_free_credentials(conn->ssl[sockindex].cred);
1003
1004 #ifdef USE_TLS_SRP
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);
1008 #endif
1009
1010   conn->ssl[sockindex].cred = NULL;
1011   conn->ssl[sockindex].session = NULL;
1012
1013   return retval;
1014 }
1015
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 */
1020                          CURLcode *curlcode)
1021 {
1022   ssize_t ret;
1023
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;
1027     return -1;
1028   }
1029
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);
1034     if(rc)
1035       /* handshake() writes error message on its own */
1036       *curlcode = rc;
1037     else
1038       *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */
1039     return -1;
1040   }
1041
1042   if(ret < 0) {
1043     failf(conn->data, "GnuTLS recv error (%d): %s",
1044           (int)ret, gnutls_strerror((int)ret));
1045     *curlcode = CURLE_RECV_ERROR;
1046     return -1;
1047   }
1048
1049   return ret;
1050 }
1051
1052 void Curl_gtls_session_free(void *ptr)
1053 {
1054   free(ptr);
1055 }
1056
1057 size_t Curl_gtls_version(char *buffer, size_t size)
1058 {
1059   return snprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
1060 }
1061
1062 int Curl_gtls_seed(struct SessionHandle *data)
1063 {
1064   /* we have the "SSL is seeded" boolean static to prevent multiple
1065      time-consuming seedings in vain */
1066   static bool ssl_seeded = FALSE;
1067
1068   /* Quickly add a bit of entropy */
1069 #ifndef USE_GNUTLS_NETTLE
1070   gcry_fast_random_poll();
1071 #endif
1072
1073   if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] ||
1074      data->set.str[STRING_SSL_EGDSOCKET]) {
1075
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
1080     */
1081     ssl_seeded = TRUE;
1082   }
1083   return 0;
1084 }
1085
1086 void Curl_gtls_random(struct SessionHandle *data,
1087                       unsigned char *entropy,
1088                       size_t length)
1089 {
1090 #if defined(USE_GNUTLS_NETTLE)
1091   (void)data;
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);
1096 #endif
1097 }
1098
1099 void Curl_gtls_md5sum(unsigned char *tmp, /* input */
1100                       size_t tmplen,
1101                       unsigned char *md5sum, /* output */
1102                       size_t md5len)
1103 {
1104 #if defined(USE_GNUTLS_NETTLE)
1105   struct md5_ctx MD5pw;
1106   md5_init(&MD5pw);
1107   md5_update(&MD5pw, tmplen, tmp);
1108   md5_digest(&MD5pw, md5len, md5sum);
1109 #elif defined(USE_GNUTLS)
1110   gcry_md_hd_t MD5pw;
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);
1115 #endif
1116 }
1117
1118 #endif /* USE_GNUTLS */