1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2013, 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#ifndef have_curlssl_random 201 (void)data; 202#else 203 if(data) { 204 Curl_ssl_random(data, (unsigned char *)&r, sizeof(r)); 205 return r; 206 } 207#endif 208 209#ifdef RANDOM_FILE 210 if(!seeded) { 211 /* if there's a random file to read a seed from, use it */ 212 int fd = open(RANDOM_FILE, O_RDONLY); 213 if(fd > -1) { 214 /* read random data into the randseed variable */ 215 ssize_t nread = read(fd, &randseed, sizeof(randseed)); 216 if(nread == sizeof(randseed)) 217 seeded = TRUE; 218 close(fd); 219 } 220 } 221#endif 222 223 if(!seeded) { 224 struct timeval now = curlx_tvnow(); 225 randseed += (unsigned int)now.tv_usec + (unsigned int)now.tv_sec; 226 randseed = randseed * 1103515245 + 12345; 227 randseed = randseed * 1103515245 + 12345; 228 randseed = randseed * 1103515245 + 12345; 229 seeded = TRUE; 230 } 231 232 /* Return an unsigned 32-bit pseudo-random number. */ 233 r = randseed = randseed * 1103515245 + 12345; 234 return (r << 16) | ((r >> 16) & 0xFFFF); 235} 236 237#ifdef USE_SSL 238 239/* "global" init done? */ 240static bool init_ssl=FALSE; 241 242/** 243 * Global SSL init 244 * 245 * @retval 0 error initializing SSL 246 * @retval 1 SSL initialized successfully 247 */ 248int Curl_ssl_init(void) 249{ 250 /* make sure this is only done once */ 251 if(init_ssl) 252 return 1; 253 init_ssl = TRUE; /* never again */ 254 255 return curlssl_init(); 256} 257 258 259/* Global cleanup */ 260void Curl_ssl_cleanup(void) 261{ 262 if(init_ssl) { 263 /* only cleanup if we did a previous init */ 264 curlssl_cleanup(); 265 init_ssl = FALSE; 266 } 267} 268 269CURLcode 270Curl_ssl_connect(struct connectdata *conn, int sockindex) 271{ 272 CURLcode res; 273 /* mark this is being ssl-enabled from here on. */ 274 conn->ssl[sockindex].use = TRUE; 275 conn->ssl[sockindex].state = ssl_connection_negotiating; 276 277 res = curlssl_connect(conn, sockindex); 278 279 if(!res) 280 Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */ 281 282 return res; 283} 284 285CURLcode 286Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex, 287 bool *done) 288{ 289 CURLcode res; 290 /* mark this is being ssl requested from here on. */ 291 conn->ssl[sockindex].use = TRUE; 292#ifdef curlssl_connect_nonblocking 293 res = curlssl_connect_nonblocking(conn, sockindex, done); 294#else 295 *done = TRUE; /* fallback to BLOCKING */ 296 res = curlssl_connect(conn, sockindex); 297#endif /* non-blocking connect support */ 298 if(!res && *done) 299 Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */ 300 return res; 301} 302 303/* 304 * Check if there's a session ID for the given connection in the cache, and if 305 * there's one suitable, it is provided. Returns TRUE when no entry matched. 306 */ 307int Curl_ssl_getsessionid(struct connectdata *conn, 308 void **ssl_sessionid, 309 size_t *idsize) /* set 0 if unknown */ 310{ 311 struct curl_ssl_session *check; 312 struct SessionHandle *data = conn->data; 313 size_t i; 314 long *general_age; 315 bool no_match = TRUE; 316 317 *ssl_sessionid = NULL; 318 319 if(!conn->ssl_config.sessionid) 320 /* session ID re-use is disabled */ 321 return TRUE; 322 323 /* Lock if shared */ 324 if(SSLSESSION_SHARED(data)) { 325 Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE); 326 general_age = &data->share->sessionage; 327 } 328 else 329 general_age = &data->state.sessionage; 330 331 for(i = 0; i < data->set.ssl.max_ssl_sessions; i++) { 332 check = &data->state.session[i]; 333 if(!check->sessionid) 334 /* not session ID means blank entry */ 335 continue; 336 if(Curl_raw_equal(conn->host.name, check->name) && 337 (conn->remote_port == check->remote_port) && 338 Curl_ssl_config_matches(&conn->ssl_config, &check->ssl_config)) { 339 /* yes, we have a session ID! */ 340 (*general_age)++; /* increase general age */ 341 check->age = *general_age; /* set this as used in this age */ 342 *ssl_sessionid = check->sessionid; 343 if(idsize) 344 *idsize = check->idsize; 345 no_match = FALSE; 346 break; 347 } 348 } 349 350 /* Unlock */ 351 if(SSLSESSION_SHARED(data)) 352 Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION); 353 354 return no_match; 355} 356 357/* 358 * Kill a single session ID entry in the cache. 359 */ 360void Curl_ssl_kill_session(struct curl_ssl_session *session) 361{ 362 if(session->sessionid) { 363 /* defensive check */ 364 365 /* free the ID the SSL-layer specific way */ 366 curlssl_session_free(session->sessionid); 367 368 session->sessionid = NULL; 369 session->age = 0; /* fresh */ 370 371 Curl_free_ssl_config(&session->ssl_config); 372 373 Curl_safefree(session->name); 374 } 375} 376 377/* 378 * Delete the given session ID from the cache. 379 */ 380void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid) 381{ 382 size_t i; 383 struct SessionHandle *data=conn->data; 384 385 if(SSLSESSION_SHARED(data)) 386 Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE); 387 388 for(i = 0; i < data->set.ssl.max_ssl_sessions; i++) { 389 struct curl_ssl_session *check = &data->state.session[i]; 390 391 if(check->sessionid == ssl_sessionid) { 392 Curl_ssl_kill_session(check); 393 break; 394 } 395 } 396 397 if(SSLSESSION_SHARED(data)) 398 Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION); 399} 400 401/* 402 * Store session id in the session cache. The ID passed on to this function 403 * must already have been extracted and allocated the proper way for the SSL 404 * layer. Curl_XXXX_session_free() will be called to free/kill the session ID 405 * later on. 406 */ 407CURLcode Curl_ssl_addsessionid(struct connectdata *conn, 408 void *ssl_sessionid, 409 size_t idsize) 410{ 411 size_t i; 412 struct SessionHandle *data=conn->data; /* the mother of all structs */ 413 struct curl_ssl_session *store = &data->state.session[0]; 414 long oldest_age=data->state.session[0].age; /* zero if unused */ 415 char *clone_host; 416 long *general_age; 417 418 /* Even though session ID re-use might be disabled, that only disables USING 419 IT. We still store it here in case the re-using is again enabled for an 420 upcoming transfer */ 421 422 clone_host = strdup(conn->host.name); 423 if(!clone_host) 424 return CURLE_OUT_OF_MEMORY; /* bail out */ 425 426 /* Now we should add the session ID and the host name to the cache, (remove 427 the oldest if necessary) */ 428 429 /* If using shared SSL session, lock! */ 430 if(SSLSESSION_SHARED(data)) { 431 Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE); 432 general_age = &data->share->sessionage; 433 } 434 else { 435 general_age = &data->state.sessionage; 436 } 437 438 /* find an empty slot for us, or find the oldest */ 439 for(i = 1; (i < data->set.ssl.max_ssl_sessions) && 440 data->state.session[i].sessionid; i++) { 441 if(data->state.session[i].age < oldest_age) { 442 oldest_age = data->state.session[i].age; 443 store = &data->state.session[i]; 444 } 445 } 446 if(i == data->set.ssl.max_ssl_sessions) 447 /* cache is full, we must "kill" the oldest entry! */ 448 Curl_ssl_kill_session(store); 449 else 450 store = &data->state.session[i]; /* use this slot */ 451 452 /* now init the session struct wisely */ 453 store->sessionid = ssl_sessionid; 454 store->idsize = idsize; 455 store->age = *general_age; /* set current age */ 456 if(store->name) 457 /* free it if there's one already present */ 458 free(store->name); 459 store->name = clone_host; /* clone host name */ 460 store->remote_port = conn->remote_port; /* port number */ 461 462 463 /* Unlock */ 464 if(SSLSESSION_SHARED(data)) 465 Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION); 466 467 if(!Curl_clone_ssl_config(&conn->ssl_config, &store->ssl_config)) { 468 store->sessionid = NULL; /* let caller free sessionid */ 469 free(clone_host); 470 return CURLE_OUT_OF_MEMORY; 471 } 472 473 return CURLE_OK; 474} 475 476 477void Curl_ssl_close_all(struct SessionHandle *data) 478{ 479 size_t i; 480 /* kill the session ID cache if not shared */ 481 if(data->state.session && !SSLSESSION_SHARED(data)) { 482 for(i = 0; i < data->set.ssl.max_ssl_sessions; i++) 483 /* the single-killer function handles empty table slots */ 484 Curl_ssl_kill_session(&data->state.session[i]); 485 486 /* free the cache data */ 487 Curl_safefree(data->state.session); 488 } 489 490 curlssl_close_all(data); 491} 492 493void Curl_ssl_close(struct connectdata *conn, int sockindex) 494{ 495 DEBUGASSERT((sockindex <= 1) && (sockindex >= -1)); 496 curlssl_close(conn, sockindex); 497} 498 499CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex) 500{ 501 if(curlssl_shutdown(conn, sockindex)) 502 return CURLE_SSL_SHUTDOWN_FAILED; 503 504 conn->ssl[sockindex].use = FALSE; /* get back to ordinary socket usage */ 505 conn->ssl[sockindex].state = ssl_connection_none; 506 507 conn->recv[sockindex] = Curl_recv_plain; 508 conn->send[sockindex] = Curl_send_plain; 509 510 return CURLE_OK; 511} 512 513/* Selects an SSL crypto engine 514 */ 515CURLcode Curl_ssl_set_engine(struct SessionHandle *data, const char *engine) 516{ 517 return curlssl_set_engine(data, engine); 518} 519 520/* Selects the default SSL crypto engine 521 */ 522CURLcode Curl_ssl_set_engine_default(struct SessionHandle *data) 523{ 524 return curlssl_set_engine_default(data); 525} 526 527/* Return list of OpenSSL crypto engine names. */ 528struct curl_slist *Curl_ssl_engines_list(struct SessionHandle *data) 529{ 530 return curlssl_engines_list(data); 531} 532 533/* 534 * This sets up a session ID cache to the specified size. Make sure this code 535 * is agnostic to what underlying SSL technology we use. 536 */ 537CURLcode Curl_ssl_initsessions(struct SessionHandle *data, size_t amount) 538{ 539 struct curl_ssl_session *session; 540 541 if(data->state.session) 542 /* this is just a precaution to prevent multiple inits */ 543 return CURLE_OK; 544 545 session = calloc(amount, sizeof(struct curl_ssl_session)); 546 if(!session) 547 return CURLE_OUT_OF_MEMORY; 548 549 /* store the info in the SSL section */ 550 data->set.ssl.max_ssl_sessions = amount; 551 data->state.session = session; 552 data->state.sessionage = 1; /* this is brand new */ 553 return CURLE_OK; 554} 555 556size_t Curl_ssl_version(char *buffer, size_t size) 557{ 558 return curlssl_version(buffer, size); 559} 560 561/* 562 * This function tries to determine connection status. 563 * 564 * Return codes: 565 * 1 means the connection is still in place 566 * 0 means the connection has been closed 567 * -1 means the connection status is unknown 568 */ 569int Curl_ssl_check_cxn(struct connectdata *conn) 570{ 571 return curlssl_check_cxn(conn); 572} 573 574bool Curl_ssl_data_pending(const struct connectdata *conn, 575 int connindex) 576{ 577 return curlssl_data_pending(conn, connindex); 578} 579 580void Curl_ssl_free_certinfo(struct SessionHandle *data) 581{ 582 int i; 583 struct curl_certinfo *ci = &data->info.certs; 584 if(ci->num_of_certs) { 585 /* free all individual lists used */ 586 for(i=0; i<ci->num_of_certs; i++) { 587 curl_slist_free_all(ci->certinfo[i]); 588 ci->certinfo[i] = NULL; 589 } 590 free(ci->certinfo); /* free the actual array too */ 591 ci->certinfo = NULL; 592 ci->num_of_certs = 0; 593 } 594} 595 596int Curl_ssl_init_certinfo(struct SessionHandle * data, 597 int num) 598{ 599 struct curl_certinfo * ci = &data->info.certs; 600 struct curl_slist * * table; 601 602 /* Initialize the certificate information structures. Return 0 if OK, else 1. 603 */ 604 Curl_ssl_free_certinfo(data); 605 ci->num_of_certs = num; 606 table = calloc((size_t) num, sizeof(struct curl_slist *)); 607 if(!table) 608 return 1; 609 610 ci->certinfo = table; 611 return 0; 612} 613 614/* 615 * 'value' is NOT a zero terminated string 616 */ 617CURLcode Curl_ssl_push_certinfo_len(struct SessionHandle *data, 618 int certnum, 619 const char *label, 620 const char *value, 621 size_t valuelen) 622{ 623 struct curl_certinfo * ci = &data->info.certs; 624 char * output; 625 struct curl_slist * nl; 626 CURLcode res = CURLE_OK; 627 size_t labellen = strlen(label); 628 size_t outlen = labellen + 1 + valuelen + 1; /* label:value\0 */ 629 630 output = malloc(outlen); 631 if(!output) 632 return CURLE_OUT_OF_MEMORY; 633 634 /* sprintf the label and colon */ 635 snprintf(output, outlen, "%s:", label); 636 637 /* memcpy the value (it might not be zero terminated) */ 638 memcpy(&output[labellen+1], value, valuelen); 639 640 /* zero terminate the output */ 641 output[labellen + 1 + valuelen] = 0; 642 643 nl = Curl_slist_append_nodup(ci->certinfo[certnum], output); 644 if(!nl) { 645 free(output); 646 curl_slist_free_all(ci->certinfo[certnum]); 647 res = CURLE_OUT_OF_MEMORY; 648 } 649 650 ci->certinfo[certnum] = nl; 651 return res; 652} 653 654/* 655 * This is a convenience function for push_certinfo_len that takes a zero 656 * terminated value. 657 */ 658CURLcode Curl_ssl_push_certinfo(struct SessionHandle *data, 659 int certnum, 660 const char *label, 661 const char *value) 662{ 663 size_t valuelen = strlen(value); 664 665 return Curl_ssl_push_certinfo_len(data, certnum, label, value, valuelen); 666} 667 668/* these functions are only provided by some SSL backends */ 669 670#ifdef have_curlssl_random 671void Curl_ssl_random(struct SessionHandle *data, 672 unsigned char *entropy, 673 size_t length) 674{ 675 curlssl_random(data, entropy, length); 676} 677#endif 678 679#ifdef have_curlssl_md5sum 680void Curl_ssl_md5sum(unsigned char *tmp, /* input */ 681 size_t tmplen, 682 unsigned char *md5sum, /* output */ 683 size_t md5len) 684{ 685 curlssl_md5sum(tmp, tmplen, md5sum, md5len); 686} 687#endif 688 689#endif /* USE_SSL */ 690