1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2014, 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/* This file is for implementing all "generic" SSL functions that all libcurl 24 internals should use. It is then responsible for calling the proper 25 "backend" function. 26 27 SSL-functions in libcurl should call functions in this source file, and not 28 to any specific SSL-layer. 29 30 Curl_ssl_ - prefix for generic ones 31 Curl_ossl_ - prefix for OpenSSL ones 32 Curl_gtls_ - prefix for GnuTLS ones 33 Curl_nss_ - prefix for NSS ones 34 Curl_qssl_ - prefix for QsoSSL ones 35 Curl_gskit_ - prefix for GSKit ones 36 Curl_polarssl_ - prefix for PolarSSL ones 37 Curl_cyassl_ - prefix for CyaSSL ones 38 Curl_schannel_ - prefix for Schannel SSPI ones 39 Curl_darwinssl_ - prefix for SecureTransport (Darwin) ones 40 41 Note that this source code uses curlssl_* functions, and they are all 42 defines/macros #defined by the lib-specific header files. 43 44 "SSL/TLS Strong Encryption: An Introduction" 45 http://httpd.apache.org/docs-2.0/ssl/ssl_intro.html 46*/ 47 48#include "curl_setup.h" 49 50#ifdef HAVE_SYS_TYPES_H 51#include <sys/types.h> 52#endif 53#ifdef HAVE_SYS_STAT_H 54#include <sys/stat.h> 55#endif 56#ifdef HAVE_FCNTL_H 57#include <fcntl.h> 58#endif 59 60#include "urldata.h" 61 62#include "vtls.h" /* generic SSL protos etc */ 63#include "openssl.h" /* OpenSSL versions */ 64#include "gtls.h" /* GnuTLS versions */ 65#include "nssg.h" /* NSS versions */ 66#include "qssl.h" /* QSOSSL versions */ 67#include "gskit.h" /* Global Secure ToolKit versions */ 68#include "polarssl.h" /* PolarSSL versions */ 69#include "axtls.h" /* axTLS versions */ 70#include "cyassl.h" /* CyaSSL versions */ 71#include "curl_schannel.h" /* Schannel SSPI version */ 72#include "curl_darwinssl.h" /* SecureTransport (Darwin) version */ 73#include "slist.h" 74#include "sendf.h" 75#include "rawstr.h" 76#include "url.h" 77#include "curl_memory.h" 78#include "progress.h" 79#include "share.h" 80#include "timeval.h" 81 82#define _MPRINTF_REPLACE /* use our functions only */ 83#include <curl/mprintf.h> 84 85/* The last #include file should be: */ 86#include "memdebug.h" 87 88/* convenience macro to check if this handle is using a shared SSL session */ 89#define SSLSESSION_SHARED(data) (data->share && \ 90 (data->share->specifier & \ 91 (1<<CURL_LOCK_DATA_SSL_SESSION))) 92 93static bool safe_strequal(char* str1, char* str2) 94{ 95 if(str1 && str2) 96 /* both pointers point to something then compare them */ 97 return (0 != Curl_raw_equal(str1, str2)) ? TRUE : FALSE; 98 else 99 /* if both pointers are NULL then treat them as equal */ 100 return (!str1 && !str2) ? TRUE : FALSE; 101} 102 103bool 104Curl_ssl_config_matches(struct ssl_config_data* data, 105 struct ssl_config_data* needle) 106{ 107 if((data->version == needle->version) && 108 (data->verifypeer == needle->verifypeer) && 109 (data->verifyhost == needle->verifyhost) && 110 safe_strequal(data->CApath, needle->CApath) && 111 safe_strequal(data->CAfile, needle->CAfile) && 112 safe_strequal(data->random_file, needle->random_file) && 113 safe_strequal(data->egdsocket, needle->egdsocket) && 114 safe_strequal(data->cipher_list, needle->cipher_list)) 115 return TRUE; 116 117 return FALSE; 118} 119 120bool 121Curl_clone_ssl_config(struct ssl_config_data *source, 122 struct ssl_config_data *dest) 123{ 124 dest->sessionid = source->sessionid; 125 dest->verifyhost = source->verifyhost; 126 dest->verifypeer = source->verifypeer; 127 dest->version = source->version; 128 129 if(source->CAfile) { 130 dest->CAfile = strdup(source->CAfile); 131 if(!dest->CAfile) 132 return FALSE; 133 } 134 else 135 dest->CAfile = NULL; 136 137 if(source->CApath) { 138 dest->CApath = strdup(source->CApath); 139 if(!dest->CApath) 140 return FALSE; 141 } 142 else 143 dest->CApath = NULL; 144 145 if(source->cipher_list) { 146 dest->cipher_list = strdup(source->cipher_list); 147 if(!dest->cipher_list) 148 return FALSE; 149 } 150 else 151 dest->cipher_list = NULL; 152 153 if(source->egdsocket) { 154 dest->egdsocket = strdup(source->egdsocket); 155 if(!dest->egdsocket) 156 return FALSE; 157 } 158 else 159 dest->egdsocket = NULL; 160 161 if(source->random_file) { 162 dest->random_file = strdup(source->random_file); 163 if(!dest->random_file) 164 return FALSE; 165 } 166 else 167 dest->random_file = NULL; 168 169 return TRUE; 170} 171 172void Curl_free_ssl_config(struct ssl_config_data* sslc) 173{ 174 Curl_safefree(sslc->CAfile); 175 Curl_safefree(sslc->CApath); 176 Curl_safefree(sslc->cipher_list); 177 Curl_safefree(sslc->egdsocket); 178 Curl_safefree(sslc->random_file); 179} 180 181 182/* 183 * Curl_rand() returns a random unsigned integer, 32bit. 184 * 185 * This non-SSL function is put here only because this file is the only one 186 * with knowledge of what the underlying SSL libraries provide in terms of 187 * randomizers. 188 * 189 * NOTE: 'data' may be passed in as NULL when coming from external API without 190 * easy handle! 191 * 192 */ 193 194unsigned int Curl_rand(struct SessionHandle *data) 195{ 196 unsigned int r; 197 static unsigned int randseed; 198 static bool seeded = FALSE; 199 200#ifdef CURLDEBUG 201 char *force_entropy = getenv("CURL_ENTROPY"); 202 if(force_entropy) { 203 if(!seeded) { 204 size_t elen = strlen(force_entropy); 205 size_t clen = sizeof(randseed); 206 size_t min = elen < clen ? elen : clen; 207 memcpy((char *)&randseed, force_entropy, min); 208 seeded = TRUE; 209 } 210 else 211 randseed++; 212 return randseed; 213 } 214#endif 215 216#ifndef have_curlssl_random 217 (void)data; 218#else 219 if(data) { 220 curlssl_random(data, (unsigned char *)&r, sizeof(r)); 221 return r; 222 } 223#endif 224 225#ifdef RANDOM_FILE 226 if(!seeded) { 227 /* if there's a random file to read a seed from, use it */ 228 int fd = open(RANDOM_FILE, O_RDONLY); 229 if(fd > -1) { 230 /* read random data into the randseed variable */ 231 ssize_t nread = read(fd, &randseed, sizeof(randseed)); 232 if(nread == sizeof(randseed)) 233 seeded = TRUE; 234 close(fd); 235 } 236 } 237#endif 238 239 if(!seeded) { 240 struct timeval now = curlx_tvnow(); 241 randseed += (unsigned int)now.tv_usec + (unsigned int)now.tv_sec; 242 randseed = randseed * 1103515245 + 12345; 243 randseed = randseed * 1103515245 + 12345; 244 randseed = randseed * 1103515245 + 12345; 245 seeded = TRUE; 246 } 247 248 /* Return an unsigned 32-bit pseudo-random number. */ 249 r = randseed = randseed * 1103515245 + 12345; 250 return (r << 16) | ((r >> 16) & 0xFFFF); 251} 252 253#ifdef USE_SSL 254 255/* "global" init done? */ 256static bool init_ssl=FALSE; 257 258/** 259 * Global SSL init 260 * 261 * @retval 0 error initializing SSL 262 * @retval 1 SSL initialized successfully 263 */ 264int Curl_ssl_init(void) 265{ 266 /* make sure this is only done once */ 267 if(init_ssl) 268 return 1; 269 init_ssl = TRUE; /* never again */ 270 271 return curlssl_init(); 272} 273 274 275/* Global cleanup */ 276void Curl_ssl_cleanup(void) 277{ 278 if(init_ssl) { 279 /* only cleanup if we did a previous init */ 280 curlssl_cleanup(); 281 init_ssl = FALSE; 282 } 283} 284 285CURLcode 286Curl_ssl_connect(struct connectdata *conn, int sockindex) 287{ 288 CURLcode res; 289 /* mark this is being ssl-enabled from here on. */ 290 conn->ssl[sockindex].use = TRUE; 291 conn->ssl[sockindex].state = ssl_connection_negotiating; 292 293 res = curlssl_connect(conn, sockindex); 294 295 if(!res) 296 Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */ 297 298 return res; 299} 300 301CURLcode 302Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex, 303 bool *done) 304{ 305 CURLcode res; 306 /* mark this is being ssl requested from here on. */ 307 conn->ssl[sockindex].use = TRUE; 308#ifdef curlssl_connect_nonblocking 309 res = curlssl_connect_nonblocking(conn, sockindex, done); 310#else 311 *done = TRUE; /* fallback to BLOCKING */ 312 res = curlssl_connect(conn, sockindex); 313#endif /* non-blocking connect support */ 314 if(!res && *done) 315 Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */ 316 return res; 317} 318 319/* 320 * Check if there's a session ID for the given connection in the cache, and if 321 * there's one suitable, it is provided. Returns TRUE when no entry matched. 322 */ 323int Curl_ssl_getsessionid(struct connectdata *conn, 324 void **ssl_sessionid, 325 size_t *idsize) /* set 0 if unknown */ 326{ 327 struct curl_ssl_session *check; 328 struct SessionHandle *data = conn->data; 329 size_t i; 330 long *general_age; 331 bool no_match = TRUE; 332 333 *ssl_sessionid = NULL; 334 335 if(!conn->ssl_config.sessionid) 336 /* session ID re-use is disabled */ 337 return TRUE; 338 339 /* Lock if shared */ 340 if(SSLSESSION_SHARED(data)) { 341 Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE); 342 general_age = &data->share->sessionage; 343 } 344 else 345 general_age = &data->state.sessionage; 346 347 for(i = 0; i < data->set.ssl.max_ssl_sessions; i++) { 348 check = &data->state.session[i]; 349 if(!check->sessionid) 350 /* not session ID means blank entry */ 351 continue; 352 if(Curl_raw_equal(conn->host.name, check->name) && 353 (conn->remote_port == check->remote_port) && 354 Curl_ssl_config_matches(&conn->ssl_config, &check->ssl_config)) { 355 /* yes, we have a session ID! */ 356 (*general_age)++; /* increase general age */ 357 check->age = *general_age; /* set this as used in this age */ 358 *ssl_sessionid = check->sessionid; 359 if(idsize) 360 *idsize = check->idsize; 361 no_match = FALSE; 362 break; 363 } 364 } 365 366 /* Unlock */ 367 if(SSLSESSION_SHARED(data)) 368 Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION); 369 370 return no_match; 371} 372 373/* 374 * Kill a single session ID entry in the cache. 375 */ 376void Curl_ssl_kill_session(struct curl_ssl_session *session) 377{ 378 if(session->sessionid) { 379 /* defensive check */ 380 381 /* free the ID the SSL-layer specific way */ 382 curlssl_session_free(session->sessionid); 383 384 session->sessionid = NULL; 385 session->age = 0; /* fresh */ 386 387 Curl_free_ssl_config(&session->ssl_config); 388 389 Curl_safefree(session->name); 390 } 391} 392 393/* 394 * Delete the given session ID from the cache. 395 */ 396void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid) 397{ 398 size_t i; 399 struct SessionHandle *data=conn->data; 400 401 if(SSLSESSION_SHARED(data)) 402 Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE); 403 404 for(i = 0; i < data->set.ssl.max_ssl_sessions; i++) { 405 struct curl_ssl_session *check = &data->state.session[i]; 406 407 if(check->sessionid == ssl_sessionid) { 408 Curl_ssl_kill_session(check); 409 break; 410 } 411 } 412 413 if(SSLSESSION_SHARED(data)) 414 Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION); 415} 416 417/* 418 * Store session id in the session cache. The ID passed on to this function 419 * must already have been extracted and allocated the proper way for the SSL 420 * layer. Curl_XXXX_session_free() will be called to free/kill the session ID 421 * later on. 422 */ 423CURLcode Curl_ssl_addsessionid(struct connectdata *conn, 424 void *ssl_sessionid, 425 size_t idsize) 426{ 427 size_t i; 428 struct SessionHandle *data=conn->data; /* the mother of all structs */ 429 struct curl_ssl_session *store = &data->state.session[0]; 430 long oldest_age=data->state.session[0].age; /* zero if unused */ 431 char *clone_host; 432 long *general_age; 433 434 /* Even though session ID re-use might be disabled, that only disables USING 435 IT. We still store it here in case the re-using is again enabled for an 436 upcoming transfer */ 437 438 clone_host = strdup(conn->host.name); 439 if(!clone_host) 440 return CURLE_OUT_OF_MEMORY; /* bail out */ 441 442 /* Now we should add the session ID and the host name to the cache, (remove 443 the oldest if necessary) */ 444 445 /* If using shared SSL session, lock! */ 446 if(SSLSESSION_SHARED(data)) { 447 Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE); 448 general_age = &data->share->sessionage; 449 } 450 else { 451 general_age = &data->state.sessionage; 452 } 453 454 /* find an empty slot for us, or find the oldest */ 455 for(i = 1; (i < data->set.ssl.max_ssl_sessions) && 456 data->state.session[i].sessionid; i++) { 457 if(data->state.session[i].age < oldest_age) { 458 oldest_age = data->state.session[i].age; 459 store = &data->state.session[i]; 460 } 461 } 462 if(i == data->set.ssl.max_ssl_sessions) 463 /* cache is full, we must "kill" the oldest entry! */ 464 Curl_ssl_kill_session(store); 465 else 466 store = &data->state.session[i]; /* use this slot */ 467 468 /* now init the session struct wisely */ 469 store->sessionid = ssl_sessionid; 470 store->idsize = idsize; 471 store->age = *general_age; /* set current age */ 472 if(store->name) 473 /* free it if there's one already present */ 474 free(store->name); 475 store->name = clone_host; /* clone host name */ 476 store->remote_port = conn->remote_port; /* port number */ 477 478 479 /* Unlock */ 480 if(SSLSESSION_SHARED(data)) 481 Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION); 482 483 if(!Curl_clone_ssl_config(&conn->ssl_config, &store->ssl_config)) { 484 store->sessionid = NULL; /* let caller free sessionid */ 485 free(clone_host); 486 return CURLE_OUT_OF_MEMORY; 487 } 488 489 return CURLE_OK; 490} 491 492 493void Curl_ssl_close_all(struct SessionHandle *data) 494{ 495 size_t i; 496 /* kill the session ID cache if not shared */ 497 if(data->state.session && !SSLSESSION_SHARED(data)) { 498 for(i = 0; i < data->set.ssl.max_ssl_sessions; i++) 499 /* the single-killer function handles empty table slots */ 500 Curl_ssl_kill_session(&data->state.session[i]); 501 502 /* free the cache data */ 503 Curl_safefree(data->state.session); 504 } 505 506 curlssl_close_all(data); 507} 508 509void Curl_ssl_close(struct connectdata *conn, int sockindex) 510{ 511 DEBUGASSERT((sockindex <= 1) && (sockindex >= -1)); 512 curlssl_close(conn, sockindex); 513} 514 515CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex) 516{ 517 if(curlssl_shutdown(conn, sockindex)) 518 return CURLE_SSL_SHUTDOWN_FAILED; 519 520 conn->ssl[sockindex].use = FALSE; /* get back to ordinary socket usage */ 521 conn->ssl[sockindex].state = ssl_connection_none; 522 523 conn->recv[sockindex] = Curl_recv_plain; 524 conn->send[sockindex] = Curl_send_plain; 525 526 return CURLE_OK; 527} 528 529/* Selects an SSL crypto engine 530 */ 531CURLcode Curl_ssl_set_engine(struct SessionHandle *data, const char *engine) 532{ 533 return curlssl_set_engine(data, engine); 534} 535 536/* Selects the default SSL crypto engine 537 */ 538CURLcode Curl_ssl_set_engine_default(struct SessionHandle *data) 539{ 540 return curlssl_set_engine_default(data); 541} 542 543/* Return list of OpenSSL crypto engine names. */ 544struct curl_slist *Curl_ssl_engines_list(struct SessionHandle *data) 545{ 546 return curlssl_engines_list(data); 547} 548 549/* 550 * This sets up a session ID cache to the specified size. Make sure this code 551 * is agnostic to what underlying SSL technology we use. 552 */ 553CURLcode Curl_ssl_initsessions(struct SessionHandle *data, size_t amount) 554{ 555 struct curl_ssl_session *session; 556 557 if(data->state.session) 558 /* this is just a precaution to prevent multiple inits */ 559 return CURLE_OK; 560 561 session = calloc(amount, sizeof(struct curl_ssl_session)); 562 if(!session) 563 return CURLE_OUT_OF_MEMORY; 564 565 /* store the info in the SSL section */ 566 data->set.ssl.max_ssl_sessions = amount; 567 data->state.session = session; 568 data->state.sessionage = 1; /* this is brand new */ 569 return CURLE_OK; 570} 571 572size_t Curl_ssl_version(char *buffer, size_t size) 573{ 574 return curlssl_version(buffer, size); 575} 576 577/* 578 * This function tries to determine connection status. 579 * 580 * Return codes: 581 * 1 means the connection is still in place 582 * 0 means the connection has been closed 583 * -1 means the connection status is unknown 584 */ 585int Curl_ssl_check_cxn(struct connectdata *conn) 586{ 587 return curlssl_check_cxn(conn); 588} 589 590bool Curl_ssl_data_pending(const struct connectdata *conn, 591 int connindex) 592{ 593 return curlssl_data_pending(conn, connindex); 594} 595 596void Curl_ssl_free_certinfo(struct SessionHandle *data) 597{ 598 int i; 599 struct curl_certinfo *ci = &data->info.certs; 600 if(ci->num_of_certs) { 601 /* free all individual lists used */ 602 for(i=0; i<ci->num_of_certs; i++) { 603 curl_slist_free_all(ci->certinfo[i]); 604 ci->certinfo[i] = NULL; 605 } 606 free(ci->certinfo); /* free the actual array too */ 607 ci->certinfo = NULL; 608 ci->num_of_certs = 0; 609 } 610} 611 612int Curl_ssl_init_certinfo(struct SessionHandle * data, 613 int num) 614{ 615 struct curl_certinfo * ci = &data->info.certs; 616 struct curl_slist * * table; 617 618 /* Initialize the certificate information structures. Return 0 if OK, else 1. 619 */ 620 Curl_ssl_free_certinfo(data); 621 ci->num_of_certs = num; 622 table = calloc((size_t) num, sizeof(struct curl_slist *)); 623 if(!table) 624 return 1; 625 626 ci->certinfo = table; 627 return 0; 628} 629 630/* 631 * 'value' is NOT a zero terminated string 632 */ 633CURLcode Curl_ssl_push_certinfo_len(struct SessionHandle *data, 634 int certnum, 635 const char *label, 636 const char *value, 637 size_t valuelen) 638{ 639 struct curl_certinfo * ci = &data->info.certs; 640 char * output; 641 struct curl_slist * nl; 642 CURLcode res = CURLE_OK; 643 size_t labellen = strlen(label); 644 size_t outlen = labellen + 1 + valuelen + 1; /* label:value\0 */ 645 646 output = malloc(outlen); 647 if(!output) 648 return CURLE_OUT_OF_MEMORY; 649 650 /* sprintf the label and colon */ 651 snprintf(output, outlen, "%s:", label); 652 653 /* memcpy the value (it might not be zero terminated) */ 654 memcpy(&output[labellen+1], value, valuelen); 655 656 /* zero terminate the output */ 657 output[labellen + 1 + valuelen] = 0; 658 659 nl = Curl_slist_append_nodup(ci->certinfo[certnum], output); 660 if(!nl) { 661 free(output); 662 curl_slist_free_all(ci->certinfo[certnum]); 663 res = CURLE_OUT_OF_MEMORY; 664 } 665 666 ci->certinfo[certnum] = nl; 667 return res; 668} 669 670/* 671 * This is a convenience function for push_certinfo_len that takes a zero 672 * terminated value. 673 */ 674CURLcode Curl_ssl_push_certinfo(struct SessionHandle *data, 675 int certnum, 676 const char *label, 677 const char *value) 678{ 679 size_t valuelen = strlen(value); 680 681 return Curl_ssl_push_certinfo_len(data, certnum, label, value, valuelen); 682} 683 684#ifdef have_curlssl_md5sum 685void Curl_ssl_md5sum(unsigned char *tmp, /* input */ 686 size_t tmplen, 687 unsigned char *md5sum, /* output */ 688 size_t md5len) 689{ 690 curlssl_md5sum(tmp, tmplen, md5sum, md5len); 691} 692#endif 693 694#endif /* USE_SSL */ 695