00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include "setup.h"
00041
00042 #include <string.h>
00043 #include <stdlib.h>
00044 #include <ctype.h>
00045 #ifdef HAVE_SYS_SOCKET_H
00046 #include <sys/socket.h>
00047 #endif
00048
00049 #include "urldata.h"
00050 #define SSLGEN_C
00051 #include "sslgen.h"
00052 #include "ssluse.h"
00053 #include "gtls.h"
00054 #include "nssg.h"
00055 #include "sendf.h"
00056 #include "strequal.h"
00057 #include "url.h"
00058 #include "memory.h"
00059
00060 #include "memdebug.h"
00061
00062
00063 static bool init_ssl=FALSE;
00064
00065 static bool safe_strequal(char* str1, char* str2);
00066
00067 static bool safe_strequal(char* str1, char* str2)
00068 {
00069 if(str1 && str2)
00070
00071 return (bool)(0 != strequal(str1, str2));
00072 else
00073
00074 return (bool)(!str1 && !str2);
00075 }
00076
00077 bool
00078 Curl_ssl_config_matches(struct ssl_config_data* data,
00079 struct ssl_config_data* needle)
00080 {
00081 if((data->version == needle->version) &&
00082 (data->verifypeer == needle->verifypeer) &&
00083 (data->verifyhost == needle->verifyhost) &&
00084 safe_strequal(data->CApath, needle->CApath) &&
00085 safe_strequal(data->CAfile, needle->CAfile) &&
00086 safe_strequal(data->random_file, needle->random_file) &&
00087 safe_strequal(data->egdsocket, needle->egdsocket) &&
00088 safe_strequal(data->cipher_list, needle->cipher_list))
00089 return TRUE;
00090
00091 return FALSE;
00092 }
00093
00094 bool
00095 Curl_clone_ssl_config(struct ssl_config_data *source,
00096 struct ssl_config_data *dest)
00097 {
00098 dest->verifyhost = source->verifyhost;
00099 dest->verifypeer = source->verifypeer;
00100 dest->version = source->version;
00101
00102 if(source->CAfile) {
00103 dest->CAfile = strdup(source->CAfile);
00104 if(!dest->CAfile)
00105 return FALSE;
00106 }
00107
00108 if(source->CApath) {
00109 dest->CApath = strdup(source->CApath);
00110 if(!dest->CApath)
00111 return FALSE;
00112 }
00113
00114 if(source->cipher_list) {
00115 dest->cipher_list = strdup(source->cipher_list);
00116 if(!dest->cipher_list)
00117 return FALSE;
00118 }
00119
00120 if(source->egdsocket) {
00121 dest->egdsocket = strdup(source->egdsocket);
00122 if(!dest->egdsocket)
00123 return FALSE;
00124 }
00125
00126 if(source->random_file) {
00127 dest->random_file = strdup(source->random_file);
00128 if(!dest->random_file)
00129 return FALSE;
00130 }
00131
00132 return TRUE;
00133 }
00134
00135 void Curl_free_ssl_config(struct ssl_config_data* sslc)
00136 {
00137 if(sslc->CAfile)
00138 free(sslc->CAfile);
00139
00140 if(sslc->CApath)
00141 free(sslc->CApath);
00142
00143 if(sslc->cipher_list)
00144 free(sslc->cipher_list);
00145
00146 if(sslc->egdsocket)
00147 free(sslc->egdsocket);
00148
00149 if(sslc->random_file)
00150 free(sslc->random_file);
00151 }
00152
00159 int Curl_ssl_init(void)
00160 {
00161
00162 if(init_ssl)
00163 return 1;
00164 init_ssl = TRUE;
00165
00166 #ifdef USE_SSLEAY
00167 return Curl_ossl_init();
00168 #else
00169 #ifdef USE_GNUTLS
00170 return Curl_gtls_init();
00171 #else
00172 #ifdef USE_NSS
00173 return Curl_nss_init();
00174 #else
00175
00176 return 1;
00177 #endif
00178 #endif
00179 #endif
00180 }
00181
00182
00183
00184 void Curl_ssl_cleanup(void)
00185 {
00186 if(init_ssl) {
00187
00188 #ifdef USE_SSLEAY
00189 Curl_ossl_cleanup();
00190 #else
00191 #ifdef USE_GNUTLS
00192 Curl_gtls_cleanup();
00193 #ifdef USE_NSS
00194 Curl_nss_cleanup();
00195 #endif
00196 #endif
00197 #endif
00198 init_ssl = FALSE;
00199 }
00200 }
00201
00202 CURLcode
00203 Curl_ssl_connect(struct connectdata *conn, int sockindex)
00204 {
00205 #ifdef USE_SSL
00206
00207 conn->ssl[sockindex].use = TRUE;
00208
00209 #ifdef USE_SSLEAY
00210 return Curl_ossl_connect(conn, sockindex);
00211 #else
00212 #ifdef USE_GNUTLS
00213 return Curl_gtls_connect(conn, sockindex);
00214 #else
00215 #ifdef USE_NSS
00216 return Curl_nss_connect(conn, sockindex);
00217 #endif
00218 #endif
00219 #endif
00220
00221 #else
00222
00223 (void)conn;
00224 (void)sockindex;
00225 return CURLE_OK;
00226 #endif
00227 }
00228
00229 CURLcode
00230 Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex,
00231 bool *done)
00232 {
00233 #if defined(USE_SSL) && defined(USE_SSLEAY)
00234
00235 conn->ssl[sockindex].use = TRUE;
00236 return Curl_ossl_connect_nonblocking(conn, sockindex, done);
00237
00238 #else
00239 #ifdef USE_NSS
00240 *done = TRUE;
00241 return Curl_nss_connect(conn, sockindex);
00242 #else
00243
00244
00245 *done = TRUE;
00246 return Curl_ssl_connect(conn, sockindex);
00247 #endif
00248 #endif
00249 }
00250
00251 #ifdef USE_SSL
00252
00253
00254
00255
00256
00257 int Curl_ssl_getsessionid(struct connectdata *conn,
00258 void **ssl_sessionid,
00259 size_t *idsize)
00260 {
00261 struct curl_ssl_session *check;
00262 struct SessionHandle *data = conn->data;
00263 long i;
00264
00265 if(!conn->ssl_config.sessionid)
00266
00267 return TRUE;
00268
00269 for(i=0; i< data->set.ssl.numsessions; i++) {
00270 check = &data->state.session[i];
00271 if(!check->sessionid)
00272
00273 continue;
00274 if(curl_strequal(conn->host.name, check->name) &&
00275 (conn->remote_port == check->remote_port) &&
00276 Curl_ssl_config_matches(&conn->ssl_config, &check->ssl_config)) {
00277
00278 data->state.sessionage++;
00279 check->age = data->state.sessionage;
00280 *ssl_sessionid = check->sessionid;
00281 if(idsize)
00282 *idsize = check->idsize;
00283 return FALSE;
00284 }
00285 }
00286 *ssl_sessionid = NULL;
00287 return TRUE;
00288 }
00289
00290
00291
00292
00293 static int kill_session(struct curl_ssl_session *session)
00294 {
00295 if(session->sessionid) {
00296
00297
00298
00299 #ifdef USE_SSLEAY
00300 Curl_ossl_session_free(session->sessionid);
00301 #else
00302 #ifdef USE_GNUTLS
00303 Curl_gtls_session_free(session->sessionid);
00304 #else
00305 #ifdef USE_NSS
00306
00307 #endif
00308 #endif
00309 #endif
00310 session->sessionid=NULL;
00311 session->age = 0;
00312
00313 Curl_free_ssl_config(&session->ssl_config);
00314
00315 Curl_safefree(session->name);
00316 session->name = NULL;
00317
00318 return 0;
00319 }
00320 else
00321 return 1;
00322 }
00323
00324
00325
00326
00327
00328
00329
00330 CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
00331 void *ssl_sessionid,
00332 size_t idsize)
00333 {
00334 int i;
00335 struct SessionHandle *data=conn->data;
00336 struct curl_ssl_session *store = &data->state.session[0];
00337 long oldest_age=data->state.session[0].age;
00338 char *clone_host;
00339
00340
00341
00342
00343
00344 clone_host = strdup(conn->host.name);
00345 if(!clone_host)
00346 return CURLE_OUT_OF_MEMORY;
00347
00348
00349
00350
00351
00352 for(i=1; (i<data->set.ssl.numsessions) &&
00353 data->state.session[i].sessionid; i++) {
00354 if(data->state.session[i].age < oldest_age) {
00355 oldest_age = data->state.session[i].age;
00356 store = &data->state.session[i];
00357 }
00358 }
00359 if(i == data->set.ssl.numsessions)
00360
00361 kill_session(store);
00362 else
00363 store = &data->state.session[i];
00364
00365
00366 store->sessionid = ssl_sessionid;
00367 store->idsize = idsize;
00368 store->age = data->state.sessionage;
00369 store->name = clone_host;
00370 store->remote_port = conn->remote_port;
00371
00372 if (!Curl_clone_ssl_config(&conn->ssl_config, &store->ssl_config))
00373 return CURLE_OUT_OF_MEMORY;
00374
00375 return CURLE_OK;
00376 }
00377
00378
00379 #endif
00380
00381 void Curl_ssl_close_all(struct SessionHandle *data)
00382 {
00383 #ifdef USE_SSL
00384 int i;
00385
00386 if(data->state.session) {
00387 for(i=0; i< data->set.ssl.numsessions; i++)
00388
00389 kill_session(&data->state.session[i]);
00390
00391
00392 free(data->state.session);
00393 data->state.session = NULL;
00394 }
00395 #ifdef USE_SSLEAY
00396 Curl_ossl_close_all(data);
00397 #else
00398 #ifdef USE_GNUTLS
00399 Curl_gtls_close_all(data);
00400 #else
00401 #ifdef USE_NSS
00402 Curl_nss_close_all(data);
00403 #endif
00404 #endif
00405 #endif
00406 #else
00407 (void)data;
00408 #endif
00409 }
00410
00411 void Curl_ssl_close(struct connectdata *conn)
00412 {
00413 if(conn->ssl[FIRSTSOCKET].use) {
00414 #ifdef USE_SSLEAY
00415 Curl_ossl_close(conn);
00416 #endif
00417 #ifdef USE_GNUTLS
00418 Curl_gtls_close(conn);
00419 #endif
00420 #ifdef USE_NSS
00421 Curl_nss_close(conn);
00422 #endif
00423 conn->ssl[FIRSTSOCKET].use = FALSE;
00424 }
00425 }
00426
00427 CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex)
00428 {
00429 if(conn->ssl[sockindex].use) {
00430 #ifdef USE_SSLEAY
00431 if(Curl_ossl_shutdown(conn, sockindex))
00432 return CURLE_SSL_SHUTDOWN_FAILED;
00433 #else
00434 #ifdef USE_GNUTLS
00435 if(Curl_gtls_shutdown(conn, sockindex))
00436 return CURLE_SSL_SHUTDOWN_FAILED;
00437 #else
00438 (void)conn;
00439 (void)sockindex;
00440 #endif
00441 #endif
00442 }
00443 return CURLE_OK;
00444 }
00445
00446
00447
00448 CURLcode Curl_ssl_set_engine(struct SessionHandle *data, const char *engine)
00449 {
00450 #ifdef USE_SSLEAY
00451 return Curl_ossl_set_engine(data, engine);
00452 #else
00453 #ifdef USE_GNUTLS
00454
00455 (void)data;
00456 (void)engine;
00457 return CURLE_FAILED_INIT;
00458 #else
00459 #ifdef USE_NSS
00460
00461 (void)data;
00462 (void)engine;
00463 return CURLE_FAILED_INIT;
00464 #else
00465
00466 (void)data;
00467 (void)engine;
00468 return CURLE_FAILED_INIT;
00469 #endif
00470 #endif
00471 #endif
00472 }
00473
00474
00475
00476 CURLcode Curl_ssl_set_engine_default(struct SessionHandle *data)
00477 {
00478 #ifdef USE_SSLEAY
00479 return Curl_ossl_set_engine_default(data);
00480 #else
00481 #ifdef USE_GNUTLS
00482
00483 (void)data;
00484 return CURLE_FAILED_INIT;
00485 #else
00486 #ifdef USE_NSS
00487
00488 (void)data;
00489 return CURLE_FAILED_INIT;
00490 #else
00491
00492 (void)data;
00493 return CURLE_FAILED_INIT;
00494 #endif
00495 #endif
00496 #endif
00497 }
00498
00499
00500 struct curl_slist *Curl_ssl_engines_list(struct SessionHandle *data)
00501 {
00502 #ifdef USE_SSLEAY
00503 return Curl_ossl_engines_list(data);
00504 #else
00505 #ifdef USE_GNUTLS
00506
00507 (void)data;
00508 return NULL;
00509 #else
00510 #ifdef USE_NSS
00511
00512
00513 (void)data;
00514 return NULL;
00515 #else
00516 (void)data;
00517 return NULL;
00518 #endif
00519 #endif
00520 #endif
00521 }
00522
00523
00524 ssize_t Curl_ssl_send(struct connectdata *conn,
00525 int sockindex,
00526 void *mem,
00527 size_t len)
00528 {
00529 #ifdef USE_SSLEAY
00530 return Curl_ossl_send(conn, sockindex, mem, len);
00531 #else
00532 #ifdef USE_GNUTLS
00533 return Curl_gtls_send(conn, sockindex, mem, len);
00534 #else
00535 #ifdef USE_NSS
00536 return Curl_nss_send(conn, sockindex, mem, len);
00537 #else
00538 (void)conn;
00539 (void)sockindex;
00540 (void)mem;
00541 (void)len;
00542 return 0;
00543 #endif
00544 #endif
00545 #endif
00546 }
00547
00548
00549
00550
00551
00552
00553
00554 ssize_t Curl_ssl_recv(struct connectdata *conn,
00555 int sockindex,
00556 char *mem,
00557 size_t len)
00558 {
00559 #ifdef USE_SSL
00560 ssize_t nread;
00561 bool block = FALSE;
00562
00563 #ifdef USE_SSLEAY
00564 nread = Curl_ossl_recv(conn, sockindex, mem, len, &block);
00565 #else
00566 #ifdef USE_GNUTLS
00567 nread = Curl_gtls_recv(conn, sockindex, mem, len, &block);
00568 #else
00569 #ifdef USE_NSS
00570 nread = Curl_nss_recv(conn, sockindex, mem, len, &block);
00571 #endif
00572 #endif
00573 #endif
00574 if(nread == -1) {
00575 if(!block)
00576 return 0;
00577 else
00578 return -1;
00579 }
00580
00581 return (int)nread;
00582
00583 #else
00584 (void)conn;
00585 (void)sockindex;
00586 (void)mem;
00587 (void)len;
00588 return 0;
00589 #endif
00590 }
00591
00592
00593
00594
00595
00596
00597 CURLcode Curl_ssl_initsessions(struct SessionHandle *data, long amount)
00598 {
00599 #ifdef USE_SSL
00600 struct curl_ssl_session *session;
00601
00602 if(data->state.session)
00603
00604 return CURLE_OK;
00605
00606 session = (struct curl_ssl_session *)
00607 calloc(sizeof(struct curl_ssl_session), amount);
00608 if(!session)
00609 return CURLE_OUT_OF_MEMORY;
00610
00611
00612 data->set.ssl.numsessions = amount;
00613 data->state.session = session;
00614 data->state.sessionage = 1;
00615 #else
00616
00617 (void)data;
00618 (void)amount;
00619 #endif
00620
00621 return CURLE_OK;
00622 }
00623
00624 size_t Curl_ssl_version(char *buffer, size_t size)
00625 {
00626 #ifdef USE_SSLEAY
00627 return Curl_ossl_version(buffer, size);
00628 #else
00629 #ifdef USE_GNUTLS
00630 return Curl_gtls_version(buffer, size);
00631 #else
00632 #ifdef USE_NSS
00633 return Curl_nss_version(buffer, size);
00634 #else
00635 (void)buffer;
00636 (void)size;
00637 return 0;
00638 #endif
00639 #endif
00640 #endif
00641 }
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652 int Curl_ssl_check_cxn(struct connectdata *conn)
00653 {
00654 #ifdef USE_SSLEAY
00655 return Curl_ossl_check_cxn(conn);
00656 #else
00657 #ifdef USE_NSS
00658 return Curl_nss_check_cxn(conn);
00659 #else
00660 (void)conn;
00661
00662 return -1;
00663 #endif
00664 #endif
00665 }
00666
00667 bool Curl_ssl_data_pending(struct connectdata *conn,
00668 int connindex)
00669 {
00670 #ifdef USE_SSLEAY
00671
00672 if(conn->ssl[connindex].handle)
00673
00674 return (bool)(0 != SSL_pending(conn->ssl[connindex].handle));
00675 #else
00676 (void)conn;
00677 (void)connindex;
00678 #endif
00679 return FALSE;
00680
00681 }