1 /***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2021, 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.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
gtls_push(void * s,const void * buf,size_t len)89 static ssize_t 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
gtls_pull(void * s,void * buf,size_t len)96 static ssize_t 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
gtls_push_ssl(void * s,const void * buf,size_t len)103 static ssize_t 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
gtls_pull_ssl(void * s,void * buf,size_t len)108 static ssize_t 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 /* 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 */
gtls_init(void)120 static int 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
gtls_cleanup(void)134 static void 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 Curl_easy * data,struct connectdata * conn,int sockindex,bool duringconnect,bool nonblocking)203 static CURLcode handshake(struct Curl_easy *data,
204 struct connectdata *conn,
205 int sockindex,
206 bool duringconnect,
207 bool nonblocking)
208 {
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 Curl_easy * data)317 set_ssl_version_min_max(const char **prioritylist, struct Curl_easy *data)
318 {
319 struct connectdata *conn = data->conn;
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 Curl_easy * data,struct connectdata * conn,int sockindex)382 gtls_connect_step1(struct Curl_easy *data,
383 struct connectdata *conn,
384 int sockindex)
385 {
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 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, data);
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 = gtls_push_ssl;
702 gnutls_transport_pull = 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 = gtls_push;
710 gnutls_transport_pull = 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(data);
735 if(!Curl_ssl_getsessionid(data, conn,
736 &ssl_sessionid, &ssl_idsize, sockindex)) {
737 /* we got a session id, use it! */
738 gnutls_session_set_data(session, ssl_sessionid, ssl_idsize);
739
740 /* Informational message */
741 infof(data, "SSL re-using session ID\n");
742 }
743 Curl_ssl_sessionid_unlock(data);
744 }
745
746 return CURLE_OK;
747 }
748
pkp_pin_peer_pubkey(struct Curl_easy * data,gnutls_x509_crt_t cert,const char * pinnedpubkey)749 static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
750 gnutls_x509_crt_t cert,
751 const char *pinnedpubkey)
752 {
753 /* Scratch */
754 size_t len1 = 0, len2 = 0;
755 unsigned char *buff1 = NULL;
756
757 gnutls_pubkey_t key = NULL;
758
759 /* Result is returned to caller */
760 CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
761
762 /* if a path wasn't specified, don't pin */
763 if(NULL == pinnedpubkey)
764 return CURLE_OK;
765
766 if(NULL == cert)
767 return result;
768
769 do {
770 int ret;
771
772 /* Begin Gyrations to get the public key */
773 gnutls_pubkey_init(&key);
774
775 ret = gnutls_pubkey_import_x509(key, cert, 0);
776 if(ret < 0)
777 break; /* failed */
778
779 ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, NULL, &len1);
780 if(ret != GNUTLS_E_SHORT_MEMORY_BUFFER || len1 == 0)
781 break; /* failed */
782
783 buff1 = malloc(len1);
784 if(NULL == buff1)
785 break; /* failed */
786
787 len2 = len1;
788
789 ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, buff1, &len2);
790 if(ret < 0 || len1 != len2)
791 break; /* failed */
792
793 /* End Gyrations */
794
795 /* The one good exit point */
796 result = Curl_pin_peer_pubkey(data, pinnedpubkey, buff1, len1);
797 } while(0);
798
799 if(NULL != key)
800 gnutls_pubkey_deinit(key);
801
802 Curl_safefree(buff1);
803
804 return result;
805 }
806
807 static Curl_recv gtls_recv;
808 static Curl_send gtls_send;
809
810 static CURLcode
gtls_connect_step3(struct Curl_easy * data,struct connectdata * conn,int sockindex)811 gtls_connect_step3(struct Curl_easy *data,
812 struct connectdata *conn,
813 int sockindex)
814 {
815 unsigned int cert_list_size;
816 const gnutls_datum_t *chainp;
817 unsigned int verify_status = 0;
818 gnutls_x509_crt_t x509_cert, x509_issuer;
819 gnutls_datum_t issuerp;
820 gnutls_datum_t certfields;
821 char certname[65] = ""; /* limited to 64 chars by ASN.1 */
822 size_t size;
823 time_t certclock;
824 const char *ptr;
825 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
826 struct ssl_backend_data *backend = connssl->backend;
827 gnutls_session_t session = backend->session;
828 int rc;
829 gnutls_datum_t proto;
830 CURLcode result = CURLE_OK;
831 #ifndef CURL_DISABLE_VERBOSE_STRINGS
832 unsigned int algo;
833 unsigned int bits;
834 gnutls_protocol_t version = gnutls_protocol_get_version(session);
835 #endif
836 const char * const hostname = SSL_HOST_NAME();
837 long * const certverifyresult = &SSL_SET_OPTION_LVALUE(certverifyresult);
838
839 /* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
840 ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session),
841 gnutls_cipher_get(session),
842 gnutls_mac_get(session));
843
844 infof(data, "SSL connection using %s / %s\n",
845 gnutls_protocol_get_name(version), ptr);
846
847 /* This function will return the peer's raw certificate (chain) as sent by
848 the peer. These certificates are in raw format (DER encoded for
849 X.509). In case of a X.509 then a certificate list may be present. The
850 first certificate in the list is the peer's certificate, following the
851 issuer's certificate, then the issuer's issuer etc. */
852
853 chainp = gnutls_certificate_get_peers(session, &cert_list_size);
854 if(!chainp) {
855 if(SSL_CONN_CONFIG(verifypeer) ||
856 SSL_CONN_CONFIG(verifyhost) ||
857 SSL_SET_OPTION(issuercert)) {
858 #ifdef HAVE_GNUTLS_SRP
859 if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
860 && SSL_SET_OPTION(username) != NULL
861 && !SSL_CONN_CONFIG(verifypeer)
862 && gnutls_cipher_get(session)) {
863 /* no peer cert, but auth is ok if we have SRP user and cipher and no
864 peer verify */
865 }
866 else {
867 #endif
868 failf(data, "failed to get server cert");
869 *certverifyresult = GNUTLS_E_NO_CERTIFICATE_FOUND;
870 return CURLE_PEER_FAILED_VERIFICATION;
871 #ifdef HAVE_GNUTLS_SRP
872 }
873 #endif
874 }
875 infof(data, "\t common name: WARNING couldn't obtain\n");
876 }
877
878 if(data->set.ssl.certinfo && chainp) {
879 unsigned int i;
880
881 result = Curl_ssl_init_certinfo(data, cert_list_size);
882 if(result)
883 return result;
884
885 for(i = 0; i < cert_list_size; i++) {
886 const char *beg = (const char *) chainp[i].data;
887 const char *end = beg + chainp[i].size;
888
889 result = Curl_extract_certinfo(data, i, beg, end);
890 if(result)
891 return result;
892 }
893 }
894
895 if(SSL_CONN_CONFIG(verifypeer)) {
896 /* This function will try to verify the peer's certificate and return its
897 status (trusted, invalid etc.). The value of status should be one or
898 more of the gnutls_certificate_status_t enumerated elements bitwise
899 or'd. To avoid denial of service attacks some default upper limits
900 regarding the certificate key size and chain size are set. To override
901 them use gnutls_certificate_set_verify_limits(). */
902
903 rc = gnutls_certificate_verify_peers2(session, &verify_status);
904 if(rc < 0) {
905 failf(data, "server cert verify failed: %d", rc);
906 *certverifyresult = rc;
907 return CURLE_SSL_CONNECT_ERROR;
908 }
909
910 *certverifyresult = verify_status;
911
912 /* verify_status is a bitmask of gnutls_certificate_status bits */
913 if(verify_status & GNUTLS_CERT_INVALID) {
914 if(SSL_CONN_CONFIG(verifypeer)) {
915 failf(data, "server certificate verification failed. CAfile: %s "
916 "CRLfile: %s", SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile):
917 "none",
918 SSL_SET_OPTION(CRLfile)?SSL_SET_OPTION(CRLfile):"none");
919 return CURLE_PEER_FAILED_VERIFICATION;
920 }
921 else
922 infof(data, "\t server certificate verification FAILED\n");
923 }
924 else
925 infof(data, "\t server certificate verification OK\n");
926 }
927 else
928 infof(data, "\t server certificate verification SKIPPED\n");
929
930 if(SSL_CONN_CONFIG(verifystatus)) {
931 if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) {
932 gnutls_datum_t status_request;
933 gnutls_ocsp_resp_t ocsp_resp;
934
935 gnutls_ocsp_cert_status_t status;
936 gnutls_x509_crl_reason_t reason;
937
938 rc = gnutls_ocsp_status_request_get(session, &status_request);
939
940 infof(data, "\t server certificate status verification FAILED\n");
941
942 if(rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
943 failf(data, "No OCSP response received");
944 return CURLE_SSL_INVALIDCERTSTATUS;
945 }
946
947 if(rc < 0) {
948 failf(data, "Invalid OCSP response received");
949 return CURLE_SSL_INVALIDCERTSTATUS;
950 }
951
952 gnutls_ocsp_resp_init(&ocsp_resp);
953
954 rc = gnutls_ocsp_resp_import(ocsp_resp, &status_request);
955 if(rc < 0) {
956 failf(data, "Invalid OCSP response received");
957 return CURLE_SSL_INVALIDCERTSTATUS;
958 }
959
960 (void)gnutls_ocsp_resp_get_single(ocsp_resp, 0, NULL, NULL, NULL, NULL,
961 &status, NULL, NULL, NULL, &reason);
962
963 switch(status) {
964 case GNUTLS_OCSP_CERT_GOOD:
965 break;
966
967 case GNUTLS_OCSP_CERT_REVOKED: {
968 const char *crl_reason;
969
970 switch(reason) {
971 default:
972 case GNUTLS_X509_CRLREASON_UNSPECIFIED:
973 crl_reason = "unspecified reason";
974 break;
975
976 case GNUTLS_X509_CRLREASON_KEYCOMPROMISE:
977 crl_reason = "private key compromised";
978 break;
979
980 case GNUTLS_X509_CRLREASON_CACOMPROMISE:
981 crl_reason = "CA compromised";
982 break;
983
984 case GNUTLS_X509_CRLREASON_AFFILIATIONCHANGED:
985 crl_reason = "affiliation has changed";
986 break;
987
988 case GNUTLS_X509_CRLREASON_SUPERSEDED:
989 crl_reason = "certificate superseded";
990 break;
991
992 case GNUTLS_X509_CRLREASON_CESSATIONOFOPERATION:
993 crl_reason = "operation has ceased";
994 break;
995
996 case GNUTLS_X509_CRLREASON_CERTIFICATEHOLD:
997 crl_reason = "certificate is on hold";
998 break;
999
1000 case GNUTLS_X509_CRLREASON_REMOVEFROMCRL:
1001 crl_reason = "will be removed from delta CRL";
1002 break;
1003
1004 case GNUTLS_X509_CRLREASON_PRIVILEGEWITHDRAWN:
1005 crl_reason = "privilege withdrawn";
1006 break;
1007
1008 case GNUTLS_X509_CRLREASON_AACOMPROMISE:
1009 crl_reason = "AA compromised";
1010 break;
1011 }
1012
1013 failf(data, "Server certificate was revoked: %s", crl_reason);
1014 break;
1015 }
1016
1017 default:
1018 case GNUTLS_OCSP_CERT_UNKNOWN:
1019 failf(data, "Server certificate status is unknown");
1020 break;
1021 }
1022
1023 gnutls_ocsp_resp_deinit(ocsp_resp);
1024
1025 return CURLE_SSL_INVALIDCERTSTATUS;
1026 }
1027 else
1028 infof(data, "\t server certificate status verification OK\n");
1029 }
1030 else
1031 infof(data, "\t server certificate status verification SKIPPED\n");
1032
1033 /* initialize an X.509 certificate structure. */
1034 gnutls_x509_crt_init(&x509_cert);
1035
1036 if(chainp)
1037 /* convert the given DER or PEM encoded Certificate to the native
1038 gnutls_x509_crt_t format */
1039 gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
1040
1041 if(SSL_SET_OPTION(issuercert)) {
1042 gnutls_x509_crt_init(&x509_issuer);
1043 issuerp = load_file(SSL_SET_OPTION(issuercert));
1044 gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
1045 rc = gnutls_x509_crt_check_issuer(x509_cert, x509_issuer);
1046 gnutls_x509_crt_deinit(x509_issuer);
1047 unload_file(issuerp);
1048 if(rc <= 0) {
1049 failf(data, "server certificate issuer check failed (IssuerCert: %s)",
1050 SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none");
1051 gnutls_x509_crt_deinit(x509_cert);
1052 return CURLE_SSL_ISSUER_ERROR;
1053 }
1054 infof(data, "\t server certificate issuer check OK (Issuer Cert: %s)\n",
1055 SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none");
1056 }
1057
1058 size = sizeof(certname);
1059 rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
1060 0, /* the first and only one */
1061 FALSE,
1062 certname,
1063 &size);
1064 if(rc) {
1065 infof(data, "error fetching CN from cert:%s\n",
1066 gnutls_strerror(rc));
1067 }
1068
1069 /* This function will check if the given certificate's subject matches the
1070 given hostname. This is a basic implementation of the matching described
1071 in RFC2818 (HTTPS), which takes into account wildcards, and the subject
1072 alternative name PKIX extension. Returns non zero on success, and zero on
1073 failure. */
1074 rc = gnutls_x509_crt_check_hostname(x509_cert, hostname);
1075 #if GNUTLS_VERSION_NUMBER < 0x030306
1076 /* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP
1077 addresses. */
1078 if(!rc) {
1079 #ifdef ENABLE_IPV6
1080 #define use_addr in6_addr
1081 #else
1082 #define use_addr in_addr
1083 #endif
1084 unsigned char addrbuf[sizeof(struct use_addr)];
1085 size_t addrlen = 0;
1086
1087 if(Curl_inet_pton(AF_INET, hostname, addrbuf) > 0)
1088 addrlen = 4;
1089 #ifdef ENABLE_IPV6
1090 else if(Curl_inet_pton(AF_INET6, hostname, addrbuf) > 0)
1091 addrlen = 16;
1092 #endif
1093
1094 if(addrlen) {
1095 unsigned char certaddr[sizeof(struct use_addr)];
1096 int i;
1097
1098 for(i = 0; ; i++) {
1099 size_t certaddrlen = sizeof(certaddr);
1100 int ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr,
1101 &certaddrlen, NULL);
1102 /* If this happens, it wasn't an IP address. */
1103 if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
1104 continue;
1105 if(ret < 0)
1106 break;
1107 if(ret != GNUTLS_SAN_IPADDRESS)
1108 continue;
1109 if(certaddrlen == addrlen && !memcmp(addrbuf, certaddr, addrlen)) {
1110 rc = 1;
1111 break;
1112 }
1113 }
1114 }
1115 }
1116 #endif
1117 if(!rc) {
1118 if(SSL_CONN_CONFIG(verifyhost)) {
1119 failf(data, "SSL: certificate subject name (%s) does not match "
1120 "target host name '%s'", certname, SSL_HOST_DISPNAME());
1121 gnutls_x509_crt_deinit(x509_cert);
1122 return CURLE_PEER_FAILED_VERIFICATION;
1123 }
1124 else
1125 infof(data, "\t common name: %s (does not match '%s')\n",
1126 certname, SSL_HOST_DISPNAME());
1127 }
1128 else
1129 infof(data, "\t common name: %s (matched)\n", certname);
1130
1131 /* Check for time-based validity */
1132 certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
1133
1134 if(certclock == (time_t)-1) {
1135 if(SSL_CONN_CONFIG(verifypeer)) {
1136 failf(data, "server cert expiration date verify failed");
1137 *certverifyresult = GNUTLS_CERT_EXPIRED;
1138 gnutls_x509_crt_deinit(x509_cert);
1139 return CURLE_SSL_CONNECT_ERROR;
1140 }
1141 else
1142 infof(data, "\t server certificate expiration date verify FAILED\n");
1143 }
1144 else {
1145 if(certclock < time(NULL)) {
1146 if(SSL_CONN_CONFIG(verifypeer)) {
1147 failf(data, "server certificate expiration date has passed.");
1148 *certverifyresult = GNUTLS_CERT_EXPIRED;
1149 gnutls_x509_crt_deinit(x509_cert);
1150 return CURLE_PEER_FAILED_VERIFICATION;
1151 }
1152 else
1153 infof(data, "\t server certificate expiration date FAILED\n");
1154 }
1155 else
1156 infof(data, "\t server certificate expiration date OK\n");
1157 }
1158
1159 certclock = gnutls_x509_crt_get_activation_time(x509_cert);
1160
1161 if(certclock == (time_t)-1) {
1162 if(SSL_CONN_CONFIG(verifypeer)) {
1163 failf(data, "server cert activation date verify failed");
1164 *certverifyresult = GNUTLS_CERT_NOT_ACTIVATED;
1165 gnutls_x509_crt_deinit(x509_cert);
1166 return CURLE_SSL_CONNECT_ERROR;
1167 }
1168 else
1169 infof(data, "\t server certificate activation date verify FAILED\n");
1170 }
1171 else {
1172 if(certclock > time(NULL)) {
1173 if(SSL_CONN_CONFIG(verifypeer)) {
1174 failf(data, "server certificate not activated yet.");
1175 *certverifyresult = GNUTLS_CERT_NOT_ACTIVATED;
1176 gnutls_x509_crt_deinit(x509_cert);
1177 return CURLE_PEER_FAILED_VERIFICATION;
1178 }
1179 else
1180 infof(data, "\t server certificate activation date FAILED\n");
1181 }
1182 else
1183 infof(data, "\t server certificate activation date OK\n");
1184 }
1185
1186 ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
1187 data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
1188 if(ptr) {
1189 result = pkp_pin_peer_pubkey(data, x509_cert, ptr);
1190 if(result != CURLE_OK) {
1191 failf(data, "SSL: public key does not match pinned public key!");
1192 gnutls_x509_crt_deinit(x509_cert);
1193 return result;
1194 }
1195 }
1196
1197 /* Show:
1198
1199 - subject
1200 - start date
1201 - expire date
1202 - common name
1203 - issuer
1204
1205 */
1206
1207 #ifndef CURL_DISABLE_VERBOSE_STRINGS
1208 /* public key algorithm's parameters */
1209 algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
1210 infof(data, "\t certificate public key: %s\n",
1211 gnutls_pk_algorithm_get_name(algo));
1212
1213 /* version of the X.509 certificate. */
1214 infof(data, "\t certificate version: #%d\n",
1215 gnutls_x509_crt_get_version(x509_cert));
1216
1217
1218 rc = gnutls_x509_crt_get_dn2(x509_cert, &certfields);
1219 if(rc)
1220 infof(data, "Failed to get certificate name\n");
1221 else {
1222 infof(data, "\t subject: %s\n", certfields.data);
1223
1224 certclock = gnutls_x509_crt_get_activation_time(x509_cert);
1225 showtime(data, "start date", certclock);
1226
1227 certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
1228 showtime(data, "expire date", certclock);
1229
1230 gnutls_free(certfields.data);
1231 }
1232
1233 rc = gnutls_x509_crt_get_issuer_dn2(x509_cert, &certfields);
1234 if(rc)
1235 infof(data, "Failed to get certificate issuer\n");
1236 else {
1237 infof(data, "\t issuer: %s\n", certfields.data);
1238
1239 gnutls_free(certfields.data);
1240 }
1241 #endif
1242
1243 gnutls_x509_crt_deinit(x509_cert);
1244
1245 if(conn->bits.tls_enable_alpn) {
1246 rc = gnutls_alpn_get_selected_protocol(session, &proto);
1247 if(rc == 0) {
1248 infof(data, "ALPN, server accepted to use %.*s\n", proto.size,
1249 proto.data);
1250
1251 #ifdef USE_NGHTTP2
1252 if(proto.size == NGHTTP2_PROTO_VERSION_ID_LEN &&
1253 !memcmp(NGHTTP2_PROTO_VERSION_ID, proto.data,
1254 NGHTTP2_PROTO_VERSION_ID_LEN)) {
1255 conn->negnpn = CURL_HTTP_VERSION_2;
1256 }
1257 else
1258 #endif
1259 if(proto.size == ALPN_HTTP_1_1_LENGTH &&
1260 !memcmp(ALPN_HTTP_1_1, proto.data, ALPN_HTTP_1_1_LENGTH)) {
1261 conn->negnpn = CURL_HTTP_VERSION_1_1;
1262 }
1263 }
1264 else
1265 infof(data, "ALPN, server did not agree to a protocol\n");
1266
1267 Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
1268 BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
1269 }
1270
1271 conn->ssl[sockindex].state = ssl_connection_complete;
1272 conn->recv[sockindex] = gtls_recv;
1273 conn->send[sockindex] = gtls_send;
1274
1275 if(SSL_SET_OPTION(primary.sessionid)) {
1276 /* we always unconditionally get the session id here, as even if we
1277 already got it from the cache and asked to use it in the connection, it
1278 might've been rejected and then a new one is in use now and we need to
1279 detect that. */
1280 void *connect_sessionid;
1281 size_t connect_idsize = 0;
1282
1283 /* get the session ID data size */
1284 gnutls_session_get_data(session, NULL, &connect_idsize);
1285 connect_sessionid = malloc(connect_idsize); /* get a buffer for it */
1286
1287 if(connect_sessionid) {
1288 bool incache;
1289 void *ssl_sessionid;
1290
1291 /* extract session ID to the allocated buffer */
1292 gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
1293
1294 Curl_ssl_sessionid_lock(data);
1295 incache = !(Curl_ssl_getsessionid(data, conn, &ssl_sessionid, NULL,
1296 sockindex));
1297 if(incache) {
1298 /* there was one before in the cache, so instead of risking that the
1299 previous one was rejected, we just kill that and store the new */
1300 Curl_ssl_delsessionid(data, ssl_sessionid);
1301 }
1302
1303 /* store this session id */
1304 result = Curl_ssl_addsessionid(data, conn, connect_sessionid,
1305 connect_idsize, sockindex);
1306 Curl_ssl_sessionid_unlock(data);
1307 if(result) {
1308 free(connect_sessionid);
1309 result = CURLE_OUT_OF_MEMORY;
1310 }
1311 }
1312 else
1313 result = CURLE_OUT_OF_MEMORY;
1314 }
1315
1316 return result;
1317 }
1318
1319
1320 /*
1321 * This function is called after the TCP connect has completed. Setup the TLS
1322 * layer and do all necessary magic.
1323 */
1324 /* We use connssl->connecting_state to keep track of the connection status;
1325 there are three states: 'ssl_connect_1' (not started yet or complete),
1326 'ssl_connect_2_reading' (waiting for data from server), and
1327 'ssl_connect_2_writing' (waiting to be able to write).
1328 */
1329 static CURLcode
gtls_connect_common(struct Curl_easy * data,struct connectdata * conn,int sockindex,bool nonblocking,bool * done)1330 gtls_connect_common(struct Curl_easy *data,
1331 struct connectdata *conn,
1332 int sockindex,
1333 bool nonblocking,
1334 bool *done)
1335 {
1336 int rc;
1337 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1338
1339 /* Initiate the connection, if not already done */
1340 if(ssl_connect_1 == connssl->connecting_state) {
1341 rc = gtls_connect_step1(data, conn, sockindex);
1342 if(rc)
1343 return rc;
1344 }
1345
1346 rc = handshake(data, conn, sockindex, TRUE, nonblocking);
1347 if(rc)
1348 /* handshake() sets its own error message with failf() */
1349 return rc;
1350
1351 /* Finish connecting once the handshake is done */
1352 if(ssl_connect_1 == connssl->connecting_state) {
1353 rc = gtls_connect_step3(data, conn, sockindex);
1354 if(rc)
1355 return rc;
1356 }
1357
1358 *done = ssl_connect_1 == connssl->connecting_state;
1359
1360 return CURLE_OK;
1361 }
1362
gtls_connect_nonblocking(struct Curl_easy * data,struct connectdata * conn,int sockindex,bool * done)1363 static CURLcode gtls_connect_nonblocking(struct Curl_easy *data,
1364 struct connectdata *conn,
1365 int sockindex, bool *done)
1366 {
1367 return gtls_connect_common(data, conn, sockindex, TRUE, done);
1368 }
1369
gtls_connect(struct Curl_easy * data,struct connectdata * conn,int sockindex)1370 static CURLcode gtls_connect(struct Curl_easy *data, struct connectdata *conn,
1371 int sockindex)
1372 {
1373 CURLcode result;
1374 bool done = FALSE;
1375
1376 result = gtls_connect_common(data, conn, sockindex, FALSE, &done);
1377 if(result)
1378 return result;
1379
1380 DEBUGASSERT(done);
1381
1382 return CURLE_OK;
1383 }
1384
gtls_data_pending(const struct connectdata * conn,int connindex)1385 static bool gtls_data_pending(const struct connectdata *conn,
1386 int connindex)
1387 {
1388 const struct ssl_connect_data *connssl = &conn->ssl[connindex];
1389 bool res = FALSE;
1390 struct ssl_backend_data *backend = connssl->backend;
1391 if(backend->session &&
1392 0 != gnutls_record_check_pending(backend->session))
1393 res = TRUE;
1394
1395 #ifndef CURL_DISABLE_PROXY
1396 connssl = &conn->proxy_ssl[connindex];
1397 backend = connssl->backend;
1398 if(backend->session &&
1399 0 != gnutls_record_check_pending(backend->session))
1400 res = TRUE;
1401 #endif
1402
1403 return res;
1404 }
1405
gtls_send(struct Curl_easy * data,int sockindex,const void * mem,size_t len,CURLcode * curlcode)1406 static ssize_t gtls_send(struct Curl_easy *data,
1407 int sockindex,
1408 const void *mem,
1409 size_t len,
1410 CURLcode *curlcode)
1411 {
1412 struct connectdata *conn = data->conn;
1413 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1414 struct ssl_backend_data *backend = connssl->backend;
1415 ssize_t rc = gnutls_record_send(backend->session, mem, len);
1416
1417 if(rc < 0) {
1418 *curlcode = (rc == GNUTLS_E_AGAIN)
1419 ? CURLE_AGAIN
1420 : CURLE_SEND_ERROR;
1421
1422 rc = -1;
1423 }
1424
1425 return rc;
1426 }
1427
close_one(struct ssl_connect_data * connssl)1428 static void close_one(struct ssl_connect_data *connssl)
1429 {
1430 struct ssl_backend_data *backend = connssl->backend;
1431 if(backend->session) {
1432 gnutls_bye(backend->session, GNUTLS_SHUT_WR);
1433 gnutls_deinit(backend->session);
1434 backend->session = NULL;
1435 }
1436 if(backend->cred) {
1437 gnutls_certificate_free_credentials(backend->cred);
1438 backend->cred = NULL;
1439 }
1440 #ifdef HAVE_GNUTLS_SRP
1441 if(backend->srp_client_cred) {
1442 gnutls_srp_free_client_credentials(backend->srp_client_cred);
1443 backend->srp_client_cred = NULL;
1444 }
1445 #endif
1446 }
1447
gtls_close(struct Curl_easy * data,struct connectdata * conn,int sockindex)1448 static void gtls_close(struct Curl_easy *data, struct connectdata *conn,
1449 int sockindex)
1450 {
1451 (void) data;
1452 close_one(&conn->ssl[sockindex]);
1453 #ifndef CURL_DISABLE_PROXY
1454 close_one(&conn->proxy_ssl[sockindex]);
1455 #endif
1456 }
1457
1458 /*
1459 * This function is called to shut down the SSL layer but keep the
1460 * socket open (CCC - Clear Command Channel)
1461 */
gtls_shutdown(struct Curl_easy * data,struct connectdata * conn,int sockindex)1462 static int gtls_shutdown(struct Curl_easy *data, struct connectdata *conn,
1463 int sockindex)
1464 {
1465 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1466 struct ssl_backend_data *backend = connssl->backend;
1467 int retval = 0;
1468
1469 #ifndef CURL_DISABLE_FTP
1470 /* This has only been tested on the proftpd server, and the mod_tls code
1471 sends a close notify alert without waiting for a close notify alert in
1472 response. Thus we wait for a close notify alert from the server, but
1473 we do not send one. Let's hope other servers do the same... */
1474
1475 if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
1476 gnutls_bye(backend->session, GNUTLS_SHUT_WR);
1477 #endif
1478
1479 if(backend->session) {
1480 ssize_t result;
1481 bool done = FALSE;
1482 char buf[120];
1483
1484 while(!done) {
1485 int what = SOCKET_READABLE(conn->sock[sockindex],
1486 SSL_SHUTDOWN_TIMEOUT);
1487 if(what > 0) {
1488 /* Something to read, let's do it and hope that it is the close
1489 notify alert from the server */
1490 result = gnutls_record_recv(backend->session,
1491 buf, sizeof(buf));
1492 switch(result) {
1493 case 0:
1494 /* This is the expected response. There was no data but only
1495 the close notify alert */
1496 done = TRUE;
1497 break;
1498 case GNUTLS_E_AGAIN:
1499 case GNUTLS_E_INTERRUPTED:
1500 infof(data, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED\n");
1501 break;
1502 default:
1503 retval = -1;
1504 done = TRUE;
1505 break;
1506 }
1507 }
1508 else if(0 == what) {
1509 /* timeout */
1510 failf(data, "SSL shutdown timeout");
1511 done = TRUE;
1512 }
1513 else {
1514 /* anything that gets here is fatally bad */
1515 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
1516 retval = -1;
1517 done = TRUE;
1518 }
1519 }
1520 gnutls_deinit(backend->session);
1521 }
1522 gnutls_certificate_free_credentials(backend->cred);
1523
1524 #ifdef HAVE_GNUTLS_SRP
1525 if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
1526 && SSL_SET_OPTION(username) != NULL)
1527 gnutls_srp_free_client_credentials(backend->srp_client_cred);
1528 #endif
1529
1530 backend->cred = NULL;
1531 backend->session = NULL;
1532
1533 return retval;
1534 }
1535
gtls_recv(struct Curl_easy * data,int num,char * buf,size_t buffersize,CURLcode * curlcode)1536 static ssize_t gtls_recv(struct Curl_easy *data, /* connection data */
1537 int num, /* socketindex */
1538 char *buf, /* store read data here */
1539 size_t buffersize, /* max amount to read */
1540 CURLcode *curlcode)
1541 {
1542 struct connectdata *conn = data->conn;
1543 struct ssl_connect_data *connssl = &conn->ssl[num];
1544 struct ssl_backend_data *backend = connssl->backend;
1545 ssize_t ret;
1546
1547 ret = gnutls_record_recv(backend->session, buf, buffersize);
1548 if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
1549 *curlcode = CURLE_AGAIN;
1550 return -1;
1551 }
1552
1553 if(ret == GNUTLS_E_REHANDSHAKE) {
1554 /* BLOCKING call, this is bad but a work-around for now. Fixing this "the
1555 proper way" takes a whole lot of work. */
1556 CURLcode result = handshake(data, conn, num, FALSE, FALSE);
1557 if(result)
1558 /* handshake() writes error message on its own */
1559 *curlcode = result;
1560 else
1561 *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */
1562 return -1;
1563 }
1564
1565 if(ret < 0) {
1566 failf(data, "GnuTLS recv error (%d): %s",
1567
1568 (int)ret, gnutls_strerror((int)ret));
1569 *curlcode = CURLE_RECV_ERROR;
1570 return -1;
1571 }
1572
1573 return ret;
1574 }
1575
gtls_session_free(void * ptr)1576 static void gtls_session_free(void *ptr)
1577 {
1578 free(ptr);
1579 }
1580
gtls_version(char * buffer,size_t size)1581 static size_t gtls_version(char *buffer, size_t size)
1582 {
1583 return msnprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
1584 }
1585
1586 #ifndef USE_GNUTLS_NETTLE
gtls_seed(struct Curl_easy * data)1587 static int gtls_seed(struct Curl_easy *data)
1588 {
1589 /* we have the "SSL is seeded" boolean static to prevent multiple
1590 time-consuming seedings in vain */
1591 static bool ssl_seeded = FALSE;
1592
1593 /* Quickly add a bit of entropy */
1594 gcry_fast_random_poll();
1595
1596 if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] ||
1597 data->set.str[STRING_SSL_EGDSOCKET]) {
1598 ssl_seeded = TRUE;
1599 }
1600 return 0;
1601 }
1602 #endif
1603
1604 /* data might be NULL! */
gtls_random(struct Curl_easy * data,unsigned char * entropy,size_t length)1605 static CURLcode gtls_random(struct Curl_easy *data,
1606 unsigned char *entropy, size_t length)
1607 {
1608 #if defined(USE_GNUTLS_NETTLE)
1609 int rc;
1610 (void)data;
1611 rc = gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
1612 return rc?CURLE_FAILED_INIT:CURLE_OK;
1613 #elif defined(USE_GNUTLS)
1614 if(data)
1615 gtls_seed(data); /* Initiate the seed if not already done */
1616 gcry_randomize(entropy, length, GCRY_STRONG_RANDOM);
1617 #endif
1618 return CURLE_OK;
1619 }
1620
gtls_sha256sum(const unsigned char * tmp,size_t tmplen,unsigned char * sha256sum,size_t sha256len)1621 static CURLcode gtls_sha256sum(const unsigned char *tmp, /* input */
1622 size_t tmplen,
1623 unsigned char *sha256sum, /* output */
1624 size_t sha256len)
1625 {
1626 #if defined(USE_GNUTLS_NETTLE)
1627 struct sha256_ctx SHA256pw;
1628 sha256_init(&SHA256pw);
1629 sha256_update(&SHA256pw, (unsigned int)tmplen, tmp);
1630 sha256_digest(&SHA256pw, (unsigned int)sha256len, sha256sum);
1631 #elif defined(USE_GNUTLS)
1632 gcry_md_hd_t SHA256pw;
1633 gcry_md_open(&SHA256pw, GCRY_MD_SHA256, 0);
1634 gcry_md_write(SHA256pw, tmp, tmplen);
1635 memcpy(sha256sum, gcry_md_read(SHA256pw, 0), sha256len);
1636 gcry_md_close(SHA256pw);
1637 #endif
1638 return CURLE_OK;
1639 }
1640
gtls_cert_status_request(void)1641 static bool gtls_cert_status_request(void)
1642 {
1643 return TRUE;
1644 }
1645
gtls_get_internals(struct ssl_connect_data * connssl,CURLINFO info UNUSED_PARAM)1646 static void *gtls_get_internals(struct ssl_connect_data *connssl,
1647 CURLINFO info UNUSED_PARAM)
1648 {
1649 struct ssl_backend_data *backend = connssl->backend;
1650 (void)info;
1651 return backend->session;
1652 }
1653
1654 const struct Curl_ssl Curl_ssl_gnutls = {
1655 { CURLSSLBACKEND_GNUTLS, "gnutls" }, /* info */
1656
1657 SSLSUPP_CA_PATH |
1658 SSLSUPP_CERTINFO |
1659 SSLSUPP_PINNEDPUBKEY |
1660 SSLSUPP_HTTPS_PROXY,
1661
1662 sizeof(struct ssl_backend_data),
1663
1664 gtls_init, /* init */
1665 gtls_cleanup, /* cleanup */
1666 gtls_version, /* version */
1667 Curl_none_check_cxn, /* check_cxn */
1668 gtls_shutdown, /* shutdown */
1669 gtls_data_pending, /* data_pending */
1670 gtls_random, /* random */
1671 gtls_cert_status_request, /* cert_status_request */
1672 gtls_connect, /* connect */
1673 gtls_connect_nonblocking, /* connect_nonblocking */
1674 gtls_get_internals, /* get_internals */
1675 gtls_close, /* close_one */
1676 Curl_none_close_all, /* close_all */
1677 gtls_session_free, /* session_free */
1678 Curl_none_set_engine, /* set_engine */
1679 Curl_none_set_engine_default, /* set_engine_default */
1680 Curl_none_engines_list, /* engines_list */
1681 Curl_none_false_start, /* false_start */
1682 gtls_sha256sum /* sha256sum */
1683 };
1684
1685 #endif /* USE_GNUTLS */
1686