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