1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at http://curl.haxx.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 ***************************************************************************/ 22 23/* 24 * Source file for all GnuTLS-specific code for the TLS/SSL layer. No code 25 * but sslgen.c should ever call or use these functions. 26 * 27 * Note: don't use the GnuTLS' *_t variable type names in this source code, 28 * since they were not present in 1.0.X. 29 */ 30 31#include "setup.h" 32 33#ifdef USE_GNUTLS 34 35#include <gnutls/gnutls.h> 36#include <gnutls/x509.h> 37#include <gcrypt.h> 38 39#ifdef HAVE_SYS_SOCKET_H 40#include <sys/socket.h> 41#endif 42 43#include "urldata.h" 44#include "sendf.h" 45#include "inet_pton.h" 46#include "gtls.h" 47#include "sslgen.h" 48#include "parsedate.h" 49#include "connect.h" /* for the connect timeout */ 50#include "select.h" 51#include "rawstr.h" 52 53#define _MPRINTF_REPLACE /* use our functions only */ 54#include <curl/mprintf.h> 55#include "curl_memory.h" 56/* The last #include file should be: */ 57#include "memdebug.h" 58 59/* 60 Some hackish cast macros based on: 61 http://library.gnome.org/devel/glib/unstable/glib-Type-Conversion-Macros.html 62*/ 63#ifndef GNUTLS_POINTER_TO_INT_CAST 64#define GNUTLS_POINTER_TO_INT_CAST(p) ((int) (long) (p)) 65#endif 66#ifndef GNUTLS_INT_TO_POINTER_CAST 67#define GNUTLS_INT_TO_POINTER_CAST(i) ((void*) (long) (i)) 68#endif 69 70/* Enable GnuTLS debugging by defining GTLSDEBUG */ 71/*#define GTLSDEBUG */ 72 73#ifdef GTLSDEBUG 74static void tls_log_func(int level, const char *str) 75{ 76 fprintf(stderr, "|<%d>| %s", level, str); 77} 78#endif 79static bool gtls_inited = FALSE; 80 81#if defined(GNUTLS_VERSION_NUMBER) 82# if (GNUTLS_VERSION_NUMBER >= 0x020c00) 83# undef gnutls_transport_set_lowat 84# define gnutls_transport_set_lowat(A,B) Curl_nop_stmt 85# define USE_GNUTLS_PRIORITY_SET_DIRECT 1 86# endif 87# if (GNUTLS_VERSION_NUMBER >= 0x020c03) 88# undef gnutls_transport_set_global_errno 89# define gnutls_transport_set_global_errno(A) SET_ERRNO((A)) 90# endif 91#endif 92 93/* 94 * Custom push and pull callback functions used by GNU TLS to read and write 95 * to the socket. These functions are simple wrappers to send() and recv() 96 * (although here using the sread/swrite macros as defined by setup_once.h). 97 * We use custom functions rather than the GNU TLS defaults because it allows 98 * us to get specific about the fourth "flags" argument, and to use arbitrary 99 * private data with gnutls_transport_set_ptr if we wish. 100 * 101 * When these custom push and pull callbacks fail, GNU TLS checks its own 102 * session-specific error variable, and when not set also its own global 103 * errno variable, in order to take appropriate action. GNU TLS does not 104 * require that the transport is actually a socket. This implies that for 105 * Windows builds these callbacks should ideally set the session-specific 106 * error variable using function gnutls_transport_set_errno or as a last 107 * resort global errno variable using gnutls_transport_set_global_errno, 108 * with a transport agnostic error value. This implies that some winsock 109 * error translation must take place in these callbacks. 110 */ 111 112#ifdef USE_WINSOCK 113# define gtls_EINTR 4 114# define gtls_EIO 5 115# define gtls_EAGAIN 11 116static int gtls_mapped_sockerrno(void) 117{ 118 switch(SOCKERRNO) { 119 case WSAEWOULDBLOCK: 120 return gtls_EAGAIN; 121 case WSAEINTR: 122 return gtls_EINTR; 123 default: 124 break; 125 } 126 return gtls_EIO; 127} 128#endif 129 130static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len) 131{ 132 ssize_t ret = swrite(GNUTLS_POINTER_TO_INT_CAST(s), buf, len); 133#ifdef USE_WINSOCK 134 if(ret < 0) 135 gnutls_transport_set_global_errno(gtls_mapped_sockerrno()); 136#endif 137 return ret; 138} 139 140static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len) 141{ 142 ssize_t ret = sread(GNUTLS_POINTER_TO_INT_CAST(s), buf, len); 143#ifdef USE_WINSOCK 144 if(ret < 0) 145 gnutls_transport_set_global_errno(gtls_mapped_sockerrno()); 146#endif 147 return ret; 148} 149 150/* Curl_gtls_init() 151 * 152 * Global GnuTLS init, called from Curl_ssl_init(). This calls functions that 153 * are not thread-safe and thus this function itself is not thread-safe and 154 * must only be called from within curl_global_init() to keep the thread 155 * situation under control! 156 */ 157int Curl_gtls_init(void) 158{ 159 int ret = 1; 160 if(!gtls_inited) { 161 ret = gnutls_global_init()?0:1; 162#ifdef GTLSDEBUG 163 gnutls_global_set_log_function(tls_log_func); 164 gnutls_global_set_log_level(2); 165#endif 166 gtls_inited = TRUE; 167 } 168 return ret; 169} 170 171int Curl_gtls_cleanup(void) 172{ 173 if(gtls_inited) { 174 gnutls_global_deinit(); 175 gtls_inited = FALSE; 176 } 177 return 1; 178} 179 180static void showtime(struct SessionHandle *data, 181 const char *text, 182 time_t stamp) 183{ 184 struct tm buffer; 185 const struct tm *tm = &buffer; 186 CURLcode result = Curl_gmtime(stamp, &buffer); 187 if(result) 188 return; 189 190 snprintf(data->state.buffer, 191 BUFSIZE, 192 "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT\n", 193 text, 194 Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], 195 tm->tm_mday, 196 Curl_month[tm->tm_mon], 197 tm->tm_year + 1900, 198 tm->tm_hour, 199 tm->tm_min, 200 tm->tm_sec); 201 infof(data, "%s", data->state.buffer); 202} 203 204static gnutls_datum load_file (const char *file) 205{ 206 FILE *f; 207 gnutls_datum loaded_file = { NULL, 0 }; 208 long filelen; 209 void *ptr; 210 211 if(!(f = fopen(file, "r"))) 212 return loaded_file; 213 if(fseek(f, 0, SEEK_END) != 0 214 || (filelen = ftell(f)) < 0 215 || fseek(f, 0, SEEK_SET) != 0 216 || !(ptr = malloc((size_t)filelen))) 217 goto out; 218 if(fread(ptr, 1, (size_t)filelen, f) < (size_t)filelen) { 219 free(ptr); 220 goto out; 221 } 222 223 loaded_file.data = ptr; 224 loaded_file.size = (unsigned int)filelen; 225out: 226 fclose(f); 227 return loaded_file; 228} 229 230static void unload_file(gnutls_datum data) { 231 free(data.data); 232} 233 234 235/* this function does a SSL/TLS (re-)handshake */ 236static CURLcode handshake(struct connectdata *conn, 237 int sockindex, 238 bool duringconnect, 239 bool nonblocking) 240{ 241 struct SessionHandle *data = conn->data; 242 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 243 gnutls_session session = conn->ssl[sockindex].session; 244 curl_socket_t sockfd = conn->sock[sockindex]; 245 long timeout_ms; 246 int rc; 247 int what; 248 249 for(;;) { 250 /* check allowed time left */ 251 timeout_ms = Curl_timeleft(data, NULL, duringconnect); 252 253 if(timeout_ms < 0) { 254 /* no need to continue if time already is up */ 255 failf(data, "SSL connection timeout"); 256 return CURLE_OPERATION_TIMEDOUT; 257 } 258 259 /* if ssl is expecting something, check if it's available. */ 260 if(connssl->connecting_state == ssl_connect_2_reading 261 || connssl->connecting_state == ssl_connect_2_writing) { 262 263 curl_socket_t writefd = ssl_connect_2_writing== 264 connssl->connecting_state?sockfd:CURL_SOCKET_BAD; 265 curl_socket_t readfd = ssl_connect_2_reading== 266 connssl->connecting_state?sockfd:CURL_SOCKET_BAD; 267 268 what = Curl_socket_ready(readfd, writefd, 269 nonblocking?0: 270 timeout_ms?timeout_ms:1000); 271 if(what < 0) { 272 /* fatal error */ 273 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); 274 return CURLE_SSL_CONNECT_ERROR; 275 } 276 else if(0 == what) { 277 if(nonblocking) 278 return CURLE_OK; 279 else if(timeout_ms) { 280 /* timeout */ 281 failf(data, "SSL connection timeout at %ld", timeout_ms); 282 return CURLE_OPERATION_TIMEDOUT; 283 } 284 } 285 /* socket is readable or writable */ 286 } 287 288 rc = gnutls_handshake(session); 289 290 if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) { 291 connssl->connecting_state = 292 gnutls_record_get_direction(session)? 293 ssl_connect_2_writing:ssl_connect_2_reading; 294 if(nonblocking) 295 return CURLE_OK; 296 } 297 else if(rc < 0) { 298 failf(data, "gnutls_handshake() failed: %s", gnutls_strerror(rc)); 299 return CURLE_SSL_CONNECT_ERROR; 300 } 301 else { 302 /* Reset our connect state machine */ 303 connssl->connecting_state = ssl_connect_1; 304 return CURLE_OK; 305 } 306 } 307} 308 309static gnutls_x509_crt_fmt do_file_type(const char *type) 310{ 311 if(!type || !type[0]) 312 return GNUTLS_X509_FMT_PEM; 313 if(Curl_raw_equal(type, "PEM")) 314 return GNUTLS_X509_FMT_PEM; 315 if(Curl_raw_equal(type, "DER")) 316 return GNUTLS_X509_FMT_DER; 317 return -1; 318} 319 320static CURLcode 321gtls_connect_step1(struct connectdata *conn, 322 int sockindex) 323{ 324#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT 325 static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 }; 326#endif 327 struct SessionHandle *data = conn->data; 328 gnutls_session session; 329 int rc; 330 void *ssl_sessionid; 331 size_t ssl_idsize; 332 bool sni = TRUE; /* default is SNI enabled */ 333#ifdef ENABLE_IPV6 334 struct in6_addr addr; 335#else 336 struct in_addr addr; 337#endif 338 339 if(conn->ssl[sockindex].state == ssl_connection_complete) 340 /* to make us tolerant against being called more than once for the 341 same connection */ 342 return CURLE_OK; 343 344 if(!gtls_inited) 345 Curl_gtls_init(); 346 347 /* GnuTLS only supports SSLv3 and TLSv1 */ 348 if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) { 349 failf(data, "GnuTLS does not support SSLv2"); 350 return CURLE_SSL_CONNECT_ERROR; 351 } 352 else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3) 353 sni = FALSE; /* SSLv3 has no SNI */ 354 355 /* allocate a cred struct */ 356 rc = gnutls_certificate_allocate_credentials(&conn->ssl[sockindex].cred); 357 if(rc != GNUTLS_E_SUCCESS) { 358 failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc)); 359 return CURLE_SSL_CONNECT_ERROR; 360 } 361 362#ifdef USE_TLS_SRP 363 if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) { 364 infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username); 365 366 rc = gnutls_srp_allocate_client_credentials( 367 &conn->ssl[sockindex].srp_client_cred); 368 if(rc != GNUTLS_E_SUCCESS) { 369 failf(data, "gnutls_srp_allocate_client_cred() failed: %s", 370 gnutls_strerror(rc)); 371 return CURLE_OUT_OF_MEMORY; 372 } 373 374 rc = gnutls_srp_set_client_credentials(conn->ssl[sockindex]. 375 srp_client_cred, 376 data->set.ssl.username, 377 data->set.ssl.password); 378 if(rc != GNUTLS_E_SUCCESS) { 379 failf(data, "gnutls_srp_set_client_cred() failed: %s", 380 gnutls_strerror(rc)); 381 return CURLE_BAD_FUNCTION_ARGUMENT; 382 } 383 } 384#endif 385 386 if(data->set.ssl.CAfile) { 387 /* set the trusted CA cert bundle file */ 388 gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred, 389 GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT); 390 391 rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred, 392 data->set.ssl.CAfile, 393 GNUTLS_X509_FMT_PEM); 394 if(rc < 0) { 395 infof(data, "error reading ca cert file %s (%s)\n", 396 data->set.ssl.CAfile, gnutls_strerror(rc)); 397 if(data->set.ssl.verifypeer) 398 return CURLE_SSL_CACERT_BADFILE; 399 } 400 else 401 infof(data, "found %d certificates in %s\n", 402 rc, data->set.ssl.CAfile); 403 } 404 405 if(data->set.ssl.CRLfile) { 406 /* set the CRL list file */ 407 rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred, 408 data->set.ssl.CRLfile, 409 GNUTLS_X509_FMT_PEM); 410 if(rc < 0) { 411 failf(data, "error reading crl file %s (%s)\n", 412 data->set.ssl.CRLfile, gnutls_strerror(rc)); 413 return CURLE_SSL_CRL_BADFILE; 414 } 415 else 416 infof(data, "found %d CRL in %s\n", 417 rc, data->set.ssl.CRLfile); 418 } 419 420 /* Initialize TLS session as a client */ 421 rc = gnutls_init(&conn->ssl[sockindex].session, GNUTLS_CLIENT); 422 if(rc != GNUTLS_E_SUCCESS) { 423 failf(data, "gnutls_init() failed: %d", rc); 424 return CURLE_SSL_CONNECT_ERROR; 425 } 426 427 /* convenient assign */ 428 session = conn->ssl[sockindex].session; 429 430 if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) && 431#ifdef ENABLE_IPV6 432 (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) && 433#endif 434 sni && 435 (gnutls_server_name_set(session, GNUTLS_NAME_DNS, conn->host.name, 436 strlen(conn->host.name)) < 0)) 437 infof(data, "WARNING: failed to configure server name indication (SNI) " 438 "TLS extension\n"); 439 440 /* Use default priorities */ 441 rc = gnutls_set_default_priority(session); 442 if(rc != GNUTLS_E_SUCCESS) 443 return CURLE_SSL_CONNECT_ERROR; 444 445 if(data->set.ssl.version == CURL_SSLVERSION_SSLv3) { 446#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT 447 static const int protocol_priority[] = { GNUTLS_SSL3, 0 }; 448 rc = gnutls_protocol_set_priority(session, protocol_priority); 449#else 450 const char *err; 451 rc = gnutls_priority_set_direct(session, "-VERS-TLS-ALL:+VERS-SSL3.0", 452 &err); 453#endif 454 if(rc != GNUTLS_E_SUCCESS) 455 return CURLE_SSL_CONNECT_ERROR; 456 } 457 458#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT 459 /* Sets the priority on the certificate types supported by gnutls. Priority 460 is higher for types specified before others. After specifying the types 461 you want, you must append a 0. */ 462 rc = gnutls_certificate_type_set_priority(session, cert_type_priority); 463 if(rc != GNUTLS_E_SUCCESS) 464 return CURLE_SSL_CONNECT_ERROR; 465#endif 466 467 if(data->set.str[STRING_CERT]) { 468 if(gnutls_certificate_set_x509_key_file( 469 conn->ssl[sockindex].cred, 470 data->set.str[STRING_CERT], 471 data->set.str[STRING_KEY] ? 472 data->set.str[STRING_KEY] : data->set.str[STRING_CERT], 473 do_file_type(data->set.str[STRING_CERT_TYPE]) ) != 474 GNUTLS_E_SUCCESS) { 475 failf(data, "error reading X.509 key or certificate file"); 476 return CURLE_SSL_CONNECT_ERROR; 477 } 478 } 479 480#ifdef USE_TLS_SRP 481 /* put the credentials to the current session */ 482 if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) { 483 rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP, 484 conn->ssl[sockindex].srp_client_cred); 485 if(rc != GNUTLS_E_SUCCESS) 486 failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc)); 487 } 488 else 489#endif 490 rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, 491 conn->ssl[sockindex].cred); 492 493 /* set the connection handle (file descriptor for the socket) */ 494 gnutls_transport_set_ptr(session, 495 GNUTLS_INT_TO_POINTER_CAST(conn->sock[sockindex])); 496 497 /* register callback functions to send and receive data. */ 498 gnutls_transport_set_push_function(session, Curl_gtls_push); 499 gnutls_transport_set_pull_function(session, Curl_gtls_pull); 500 501 /* lowat must be set to zero when using custom push and pull functions. */ 502 gnutls_transport_set_lowat(session, 0); 503 504 /* This might be a reconnect, so we check for a session ID in the cache 505 to speed up things */ 506 507 if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize)) { 508 /* we got a session id, use it! */ 509 gnutls_session_set_data(session, ssl_sessionid, ssl_idsize); 510 511 /* Informational message */ 512 infof (data, "SSL re-using session ID\n"); 513 } 514 515 return CURLE_OK; 516} 517 518static Curl_recv gtls_recv; 519static Curl_send gtls_send; 520 521static CURLcode 522gtls_connect_step3(struct connectdata *conn, 523 int sockindex) 524{ 525 unsigned int cert_list_size; 526 const gnutls_datum *chainp; 527 unsigned int verify_status; 528 gnutls_x509_crt x509_cert,x509_issuer; 529 gnutls_datum issuerp; 530 char certbuf[256]; /* big enough? */ 531 size_t size; 532 unsigned int algo; 533 unsigned int bits; 534 time_t certclock; 535 const char *ptr; 536 struct SessionHandle *data = conn->data; 537 gnutls_session session = conn->ssl[sockindex].session; 538 int rc; 539 int incache; 540 void *ssl_sessionid; 541 CURLcode result = CURLE_OK; 542 543 /* This function will return the peer's raw certificate (chain) as sent by 544 the peer. These certificates are in raw format (DER encoded for 545 X.509). In case of a X.509 then a certificate list may be present. The 546 first certificate in the list is the peer's certificate, following the 547 issuer's certificate, then the issuer's issuer etc. */ 548 549 chainp = gnutls_certificate_get_peers(session, &cert_list_size); 550 if(!chainp) { 551 if(data->set.ssl.verifypeer || 552 data->set.ssl.verifyhost || 553 data->set.ssl.issuercert) { 554#ifdef USE_TLS_SRP 555 if(data->set.ssl.authtype == CURL_TLSAUTH_SRP 556 && data->set.ssl.username != NULL 557 && !data->set.ssl.verifypeer 558 && gnutls_cipher_get(session)) { 559 /* no peer cert, but auth is ok if we have SRP user and cipher and no 560 peer verify */ 561 } 562 else { 563#endif 564 failf(data, "failed to get server cert"); 565 return CURLE_PEER_FAILED_VERIFICATION; 566#ifdef USE_TLS_SRP 567 } 568#endif 569 } 570 infof(data, "\t common name: WARNING couldn't obtain\n"); 571 } 572 573 if(data->set.ssl.verifypeer) { 574 /* This function will try to verify the peer's certificate and return its 575 status (trusted, invalid etc.). The value of status should be one or 576 more of the gnutls_certificate_status_t enumerated elements bitwise 577 or'd. To avoid denial of service attacks some default upper limits 578 regarding the certificate key size and chain size are set. To override 579 them use gnutls_certificate_set_verify_limits(). */ 580 581 rc = gnutls_certificate_verify_peers2(session, &verify_status); 582 if(rc < 0) { 583 failf(data, "server cert verify failed: %d", rc); 584 return CURLE_SSL_CONNECT_ERROR; 585 } 586 587 /* verify_status is a bitmask of gnutls_certificate_status bits */ 588 if(verify_status & GNUTLS_CERT_INVALID) { 589 if(data->set.ssl.verifypeer) { 590 failf(data, "server certificate verification failed. CAfile: %s " 591 "CRLfile: %s", data->set.ssl.CAfile?data->set.ssl.CAfile:"none", 592 data->set.ssl.CRLfile?data->set.ssl.CRLfile:"none"); 593 return CURLE_SSL_CACERT; 594 } 595 else 596 infof(data, "\t server certificate verification FAILED\n"); 597 } 598 else 599 infof(data, "\t server certificate verification OK\n"); 600 } 601 else { 602 infof(data, "\t server certificate verification SKIPPED\n"); 603 goto after_server_cert_verification; 604 } 605 606 /* initialize an X.509 certificate structure. */ 607 gnutls_x509_crt_init(&x509_cert); 608 609 /* convert the given DER or PEM encoded Certificate to the native 610 gnutls_x509_crt_t format */ 611 gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER); 612 613 if(data->set.ssl.issuercert) { 614 gnutls_x509_crt_init(&x509_issuer); 615 issuerp = load_file(data->set.ssl.issuercert); 616 gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM); 617 rc = gnutls_x509_crt_check_issuer(x509_cert,x509_issuer); 618 unload_file(issuerp); 619 if(rc <= 0) { 620 failf(data, "server certificate issuer check failed (IssuerCert: %s)", 621 data->set.ssl.issuercert?data->set.ssl.issuercert:"none"); 622 return CURLE_SSL_ISSUER_ERROR; 623 } 624 infof(data,"\t server certificate issuer check OK (Issuer Cert: %s)\n", 625 data->set.ssl.issuercert?data->set.ssl.issuercert:"none"); 626 } 627 628 size=sizeof(certbuf); 629 rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME, 630 0, /* the first and only one */ 631 FALSE, 632 certbuf, 633 &size); 634 if(rc) { 635 infof(data, "error fetching CN from cert:%s\n", 636 gnutls_strerror(rc)); 637 } 638 639 /* This function will check if the given certificate's subject matches the 640 given hostname. This is a basic implementation of the matching described 641 in RFC2818 (HTTPS), which takes into account wildcards, and the subject 642 alternative name PKIX extension. Returns non zero on success, and zero on 643 failure. */ 644 rc = gnutls_x509_crt_check_hostname(x509_cert, conn->host.name); 645 646 if(!rc) { 647 if(data->set.ssl.verifyhost > 1) { 648 failf(data, "SSL: certificate subject name (%s) does not match " 649 "target host name '%s'", certbuf, conn->host.dispname); 650 gnutls_x509_crt_deinit(x509_cert); 651 return CURLE_PEER_FAILED_VERIFICATION; 652 } 653 else 654 infof(data, "\t common name: %s (does not match '%s')\n", 655 certbuf, conn->host.dispname); 656 } 657 else 658 infof(data, "\t common name: %s (matched)\n", certbuf); 659 660 /* Check for time-based validity */ 661 certclock = gnutls_x509_crt_get_expiration_time(x509_cert); 662 663 if(certclock == (time_t)-1) { 664 failf(data, "server cert expiration date verify failed"); 665 return CURLE_SSL_CONNECT_ERROR; 666 } 667 668 if(certclock < time(NULL)) { 669 if(data->set.ssl.verifypeer) { 670 failf(data, "server certificate expiration date has passed."); 671 return CURLE_PEER_FAILED_VERIFICATION; 672 } 673 else 674 infof(data, "\t server certificate expiration date FAILED\n"); 675 } 676 else 677 infof(data, "\t server certificate expiration date OK\n"); 678 679 certclock = gnutls_x509_crt_get_activation_time(x509_cert); 680 681 if(certclock == (time_t)-1) { 682 failf(data, "server cert activation date verify failed"); 683 return CURLE_SSL_CONNECT_ERROR; 684 } 685 686 if(certclock > time(NULL)) { 687 if(data->set.ssl.verifypeer) { 688 failf(data, "server certificate not activated yet."); 689 return CURLE_PEER_FAILED_VERIFICATION; 690 } 691 else 692 infof(data, "\t server certificate activation date FAILED\n"); 693 } 694 else 695 infof(data, "\t server certificate activation date OK\n"); 696 697 /* Show: 698 699 - ciphers used 700 - subject 701 - start date 702 - expire date 703 - common name 704 - issuer 705 706 */ 707 708 /* public key algorithm's parameters */ 709 algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits); 710 infof(data, "\t certificate public key: %s\n", 711 gnutls_pk_algorithm_get_name(algo)); 712 713 /* version of the X.509 certificate. */ 714 infof(data, "\t certificate version: #%d\n", 715 gnutls_x509_crt_get_version(x509_cert)); 716 717 718 size = sizeof(certbuf); 719 gnutls_x509_crt_get_dn(x509_cert, certbuf, &size); 720 infof(data, "\t subject: %s\n", certbuf); 721 722 certclock = gnutls_x509_crt_get_activation_time(x509_cert); 723 showtime(data, "start date", certclock); 724 725 certclock = gnutls_x509_crt_get_expiration_time(x509_cert); 726 showtime(data, "expire date", certclock); 727 728 size = sizeof(certbuf); 729 gnutls_x509_crt_get_issuer_dn(x509_cert, certbuf, &size); 730 infof(data, "\t issuer: %s\n", certbuf); 731 732 gnutls_x509_crt_deinit(x509_cert); 733 734after_server_cert_verification: 735 736 /* compression algorithm (if any) */ 737 ptr = gnutls_compression_get_name(gnutls_compression_get(session)); 738 /* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */ 739 infof(data, "\t compression: %s\n", ptr); 740 741 /* the name of the cipher used. ie 3DES. */ 742 ptr = gnutls_cipher_get_name(gnutls_cipher_get(session)); 743 infof(data, "\t cipher: %s\n", ptr); 744 745 /* the MAC algorithms name. ie SHA1 */ 746 ptr = gnutls_mac_get_name(gnutls_mac_get(session)); 747 infof(data, "\t MAC: %s\n", ptr); 748 749 conn->ssl[sockindex].state = ssl_connection_complete; 750 conn->recv[sockindex] = gtls_recv; 751 conn->send[sockindex] = gtls_send; 752 753 { 754 /* we always unconditionally get the session id here, as even if we 755 already got it from the cache and asked to use it in the connection, it 756 might've been rejected and then a new one is in use now and we need to 757 detect that. */ 758 void *connect_sessionid; 759 size_t connect_idsize; 760 761 /* get the session ID data size */ 762 gnutls_session_get_data(session, NULL, &connect_idsize); 763 connect_sessionid = malloc(connect_idsize); /* get a buffer for it */ 764 765 if(connect_sessionid) { 766 /* extract session ID to the allocated buffer */ 767 gnutls_session_get_data(session, connect_sessionid, &connect_idsize); 768 769 incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)); 770 if(incache) { 771 /* there was one before in the cache, so instead of risking that the 772 previous one was rejected, we just kill that and store the new */ 773 Curl_ssl_delsessionid(conn, ssl_sessionid); 774 } 775 776 /* store this session id */ 777 result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize); 778 if(result) { 779 free(connect_sessionid); 780 result = CURLE_OUT_OF_MEMORY; 781 } 782 } 783 else 784 result = CURLE_OUT_OF_MEMORY; 785 } 786 787 return result; 788} 789 790 791/* 792 * This function is called after the TCP connect has completed. Setup the TLS 793 * layer and do all necessary magic. 794 */ 795/* We use connssl->connecting_state to keep track of the connection status; 796 there are three states: 'ssl_connect_1' (not started yet or complete), 797 'ssl_connect_2_reading' (waiting for data from server), and 798 'ssl_connect_2_writing' (waiting to be able to write). 799 */ 800static CURLcode 801gtls_connect_common(struct connectdata *conn, 802 int sockindex, 803 bool nonblocking, 804 bool *done) 805{ 806 int rc; 807 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 808 809 /* Initiate the connection, if not already done */ 810 if(ssl_connect_1==connssl->connecting_state) { 811 rc = gtls_connect_step1 (conn, sockindex); 812 if(rc) 813 return rc; 814 } 815 816 rc = handshake(conn, sockindex, TRUE, nonblocking); 817 if(rc) 818 /* handshake() sets its own error message with failf() */ 819 return rc; 820 821 /* Finish connecting once the handshake is done */ 822 if(ssl_connect_1==connssl->connecting_state) { 823 rc = gtls_connect_step3(conn, sockindex); 824 if(rc) 825 return rc; 826 } 827 828 *done = ssl_connect_1==connssl->connecting_state; 829 830 return CURLE_OK; 831} 832 833CURLcode 834Curl_gtls_connect_nonblocking(struct connectdata *conn, 835 int sockindex, 836 bool *done) 837{ 838 return gtls_connect_common(conn, sockindex, TRUE, done); 839} 840 841CURLcode 842Curl_gtls_connect(struct connectdata *conn, 843 int sockindex) 844 845{ 846 CURLcode retcode; 847 bool done = FALSE; 848 849 retcode = gtls_connect_common(conn, sockindex, FALSE, &done); 850 if(retcode) 851 return retcode; 852 853 DEBUGASSERT(done); 854 855 return CURLE_OK; 856} 857 858static ssize_t gtls_send(struct connectdata *conn, 859 int sockindex, 860 const void *mem, 861 size_t len, 862 CURLcode *curlcode) 863{ 864 ssize_t rc = gnutls_record_send(conn->ssl[sockindex].session, mem, len); 865 866 if(rc < 0 ) { 867 *curlcode = (rc == GNUTLS_E_AGAIN) 868 ? CURLE_AGAIN 869 : CURLE_SEND_ERROR; 870 871 rc = -1; 872 } 873 874 return rc; 875} 876 877void Curl_gtls_close_all(struct SessionHandle *data) 878{ 879 /* FIX: make the OpenSSL code more generic and use parts of it here */ 880 (void)data; 881} 882 883static void close_one(struct connectdata *conn, 884 int idx) 885{ 886 if(conn->ssl[idx].session) { 887 gnutls_bye(conn->ssl[idx].session, GNUTLS_SHUT_RDWR); 888 gnutls_deinit(conn->ssl[idx].session); 889 conn->ssl[idx].session = NULL; 890 } 891 if(conn->ssl[idx].cred) { 892 gnutls_certificate_free_credentials(conn->ssl[idx].cred); 893 conn->ssl[idx].cred = NULL; 894 } 895#ifdef USE_TLS_SRP 896 if(conn->ssl[idx].srp_client_cred) { 897 gnutls_srp_free_client_credentials(conn->ssl[idx].srp_client_cred); 898 conn->ssl[idx].srp_client_cred = NULL; 899 } 900#endif 901} 902 903void Curl_gtls_close(struct connectdata *conn, int sockindex) 904{ 905 close_one(conn, sockindex); 906} 907 908/* 909 * This function is called to shut down the SSL layer but keep the 910 * socket open (CCC - Clear Command Channel) 911 */ 912int Curl_gtls_shutdown(struct connectdata *conn, int sockindex) 913{ 914 ssize_t result; 915 int retval = 0; 916 struct SessionHandle *data = conn->data; 917 int done = 0; 918 char buf[120]; 919 920 /* This has only been tested on the proftpd server, and the mod_tls code 921 sends a close notify alert without waiting for a close notify alert in 922 response. Thus we wait for a close notify alert from the server, but 923 we do not send one. Let's hope other servers do the same... */ 924 925 if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE) 926 gnutls_bye(conn->ssl[sockindex].session, GNUTLS_SHUT_WR); 927 928 if(conn->ssl[sockindex].session) { 929 while(!done) { 930 int what = Curl_socket_ready(conn->sock[sockindex], 931 CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT); 932 if(what > 0) { 933 /* Something to read, let's do it and hope that it is the close 934 notify alert from the server */ 935 result = gnutls_record_recv(conn->ssl[sockindex].session, 936 buf, sizeof(buf)); 937 switch(result) { 938 case 0: 939 /* This is the expected response. There was no data but only 940 the close notify alert */ 941 done = 1; 942 break; 943 case GNUTLS_E_AGAIN: 944 case GNUTLS_E_INTERRUPTED: 945 infof(data, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED\n"); 946 break; 947 default: 948 retval = -1; 949 done = 1; 950 break; 951 } 952 } 953 else if(0 == what) { 954 /* timeout */ 955 failf(data, "SSL shutdown timeout"); 956 done = 1; 957 break; 958 } 959 else { 960 /* anything that gets here is fatally bad */ 961 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); 962 retval = -1; 963 done = 1; 964 } 965 } 966 gnutls_deinit(conn->ssl[sockindex].session); 967 } 968 gnutls_certificate_free_credentials(conn->ssl[sockindex].cred); 969 970#ifdef USE_TLS_SRP 971 if(data->set.ssl.authtype == CURL_TLSAUTH_SRP 972 && data->set.ssl.username != NULL) 973 gnutls_srp_free_client_credentials(conn->ssl[sockindex].srp_client_cred); 974#endif 975 976 conn->ssl[sockindex].cred = NULL; 977 conn->ssl[sockindex].session = NULL; 978 979 return retval; 980} 981 982static ssize_t gtls_recv(struct connectdata *conn, /* connection data */ 983 int num, /* socketindex */ 984 char *buf, /* store read data here */ 985 size_t buffersize, /* max amount to read */ 986 CURLcode *curlcode) 987{ 988 ssize_t ret; 989 990 ret = gnutls_record_recv(conn->ssl[num].session, buf, buffersize); 991 if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) { 992 *curlcode = CURLE_AGAIN; 993 return -1; 994 } 995 996 if(ret == GNUTLS_E_REHANDSHAKE) { 997 /* BLOCKING call, this is bad but a work-around for now. Fixing this "the 998 proper way" takes a whole lot of work. */ 999 CURLcode rc = handshake(conn, num, FALSE, FALSE); 1000 if(rc) 1001 /* handshake() writes error message on its own */ 1002 *curlcode = rc; 1003 else 1004 *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */ 1005 return -1; 1006 } 1007 1008 if(ret < 0) { 1009 failf(conn->data, "GnuTLS recv error (%d): %s", 1010 (int)ret, gnutls_strerror((int)ret)); 1011 *curlcode = CURLE_RECV_ERROR; 1012 return -1; 1013 } 1014 1015 return ret; 1016} 1017 1018void Curl_gtls_session_free(void *ptr) 1019{ 1020 free(ptr); 1021} 1022 1023size_t Curl_gtls_version(char *buffer, size_t size) 1024{ 1025 return snprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL)); 1026} 1027 1028int Curl_gtls_seed(struct SessionHandle *data) 1029{ 1030 /* we have the "SSL is seeded" boolean static to prevent multiple 1031 time-consuming seedings in vain */ 1032 static bool ssl_seeded = FALSE; 1033 1034 /* Quickly add a bit of entropy */ 1035 gcry_fast_random_poll(); 1036 1037 if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] || 1038 data->set.str[STRING_SSL_EGDSOCKET]) { 1039 1040 /* TODO: to a good job seeding the RNG 1041 This may involve the gcry_control function and these options: 1042 GCRYCTL_SET_RANDOM_SEED_FILE 1043 GCRYCTL_SET_RNDEGD_SOCKET 1044 */ 1045 ssl_seeded = TRUE; 1046 } 1047 return 0; 1048} 1049 1050#endif /* USE_GNUTLS */ 1051