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
00041
00042
00043
00044
00045
00046
00047 #include "curl_setup.h"
00048
00049 #ifdef HAVE_SYS_TYPES_H
00050 #include <sys/types.h>
00051 #endif
00052 #ifdef HAVE_SYS_STAT_H
00053 #include <sys/stat.h>
00054 #endif
00055 #ifdef HAVE_FCNTL_H
00056 #include <fcntl.h>
00057 #endif
00058
00059 #include "urldata.h"
00060
00061 #include "vtls.h"
00062 #include "slist.h"
00063 #include "sendf.h"
00064 #include "strcase.h"
00065 #include "url.h"
00066 #include "progress.h"
00067 #include "share.h"
00068 #include "multiif.h"
00069 #include "timeval.h"
00070 #include "curl_md5.h"
00071 #include "warnless.h"
00072 #include "curl_base64.h"
00073 #include "curl_printf.h"
00074
00075
00076 #include "curl_memory.h"
00077 #include "memdebug.h"
00078
00079
00080 #define SSLSESSION_SHARED(data) (data->share && \
00081 (data->share->specifier & \
00082 (1<<CURL_LOCK_DATA_SSL_SESSION)))
00083
00084 #define CLONE_STRING(var) \
00085 if(source->var) { \
00086 dest->var = strdup(source->var); \
00087 if(!dest->var) \
00088 return FALSE; \
00089 } \
00090 else \
00091 dest->var = NULL;
00092
00093 bool
00094 Curl_ssl_config_matches(struct ssl_primary_config* data,
00095 struct ssl_primary_config* needle)
00096 {
00097 if((data->version == needle->version) &&
00098 (data->verifypeer == needle->verifypeer) &&
00099 (data->verifyhost == needle->verifyhost) &&
00100 Curl_safe_strcasecompare(data->CApath, needle->CApath) &&
00101 Curl_safe_strcasecompare(data->CAfile, needle->CAfile) &&
00102 Curl_safe_strcasecompare(data->clientcert, needle->clientcert) &&
00103 Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list))
00104 return TRUE;
00105
00106 return FALSE;
00107 }
00108
00109 bool
00110 Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
00111 struct ssl_primary_config *dest)
00112 {
00113 dest->verifyhost = source->verifyhost;
00114 dest->verifypeer = source->verifypeer;
00115 dest->version = source->version;
00116
00117 CLONE_STRING(CAfile);
00118 CLONE_STRING(CApath);
00119 CLONE_STRING(cipher_list);
00120 CLONE_STRING(egdsocket);
00121 CLONE_STRING(random_file);
00122 CLONE_STRING(clientcert);
00123 return TRUE;
00124 }
00125
00126 void Curl_free_primary_ssl_config(struct ssl_primary_config* sslc)
00127 {
00128 Curl_safefree(sslc->CAfile);
00129 Curl_safefree(sslc->CApath);
00130 Curl_safefree(sslc->cipher_list);
00131 Curl_safefree(sslc->egdsocket);
00132 Curl_safefree(sslc->random_file);
00133 Curl_safefree(sslc->clientcert);
00134 }
00135
00136 int Curl_ssl_backend(void)
00137 {
00138 return (int)CURL_SSL_BACKEND;
00139 }
00140
00141 #ifdef USE_SSL
00142
00143
00144 static bool init_ssl=FALSE;
00145
00152 int Curl_ssl_init(void)
00153 {
00154
00155 if(init_ssl)
00156 return 1;
00157 init_ssl = TRUE;
00158
00159 return curlssl_init();
00160 }
00161
00162
00163
00164 void Curl_ssl_cleanup(void)
00165 {
00166 if(init_ssl) {
00167
00168 curlssl_cleanup();
00169 init_ssl = FALSE;
00170 }
00171 }
00172
00173 static bool ssl_prefs_check(struct Curl_easy *data)
00174 {
00175
00176 if((data->set.ssl.primary.version < 0)
00177 || (data->set.ssl.primary.version >= CURL_SSLVERSION_LAST)) {
00178 failf(data, "Unrecognized parameter value passed via CURLOPT_SSLVERSION");
00179 return FALSE;
00180 }
00181 return TRUE;
00182 }
00183
00184 static CURLcode
00185 ssl_connect_init_proxy(struct connectdata *conn, int sockindex)
00186 {
00187 DEBUGASSERT(conn->bits.proxy_ssl_connected[sockindex]);
00188 if(ssl_connection_complete == conn->ssl[sockindex].state &&
00189 !conn->proxy_ssl[sockindex].use) {
00190 #if defined(HTTPS_PROXY_SUPPORT)
00191 conn->proxy_ssl[sockindex] = conn->ssl[sockindex];
00192 memset(&conn->ssl[sockindex], 0, sizeof(conn->ssl[sockindex]));
00193 #else
00194 return CURLE_NOT_BUILT_IN;
00195 #endif
00196 }
00197 return CURLE_OK;
00198 }
00199
00200 CURLcode
00201 Curl_ssl_connect(struct connectdata *conn, int sockindex)
00202 {
00203 CURLcode result;
00204
00205 if(conn->bits.proxy_ssl_connected[sockindex]) {
00206 result = ssl_connect_init_proxy(conn, sockindex);
00207 if(result)
00208 return result;
00209 }
00210
00211 if(!ssl_prefs_check(conn->data))
00212 return CURLE_SSL_CONNECT_ERROR;
00213
00214
00215 conn->ssl[sockindex].use = TRUE;
00216 conn->ssl[sockindex].state = ssl_connection_negotiating;
00217
00218 result = curlssl_connect(conn, sockindex);
00219
00220 if(!result)
00221 Curl_pgrsTime(conn->data, TIMER_APPCONNECT);
00222
00223 return result;
00224 }
00225
00226 CURLcode
00227 Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex,
00228 bool *done)
00229 {
00230 CURLcode result;
00231 if(conn->bits.proxy_ssl_connected[sockindex]) {
00232 result = ssl_connect_init_proxy(conn, sockindex);
00233 if(result)
00234 return result;
00235 }
00236
00237 if(!ssl_prefs_check(conn->data))
00238 return CURLE_SSL_CONNECT_ERROR;
00239
00240
00241 conn->ssl[sockindex].use = TRUE;
00242 #ifdef curlssl_connect_nonblocking
00243 result = curlssl_connect_nonblocking(conn, sockindex, done);
00244 #else
00245 *done = TRUE;
00246 result = curlssl_connect(conn, sockindex);
00247 #endif
00248 if(!result && *done)
00249 Curl_pgrsTime(conn->data, TIMER_APPCONNECT);
00250 return result;
00251 }
00252
00253
00254
00255
00256 void Curl_ssl_sessionid_lock(struct connectdata *conn)
00257 {
00258 if(SSLSESSION_SHARED(conn->data))
00259 Curl_share_lock(conn->data,
00260 CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE);
00261 }
00262
00263
00264
00265
00266 void Curl_ssl_sessionid_unlock(struct connectdata *conn)
00267 {
00268 if(SSLSESSION_SHARED(conn->data))
00269 Curl_share_unlock(conn->data, CURL_LOCK_DATA_SSL_SESSION);
00270 }
00271
00272
00273
00274
00275
00276 bool Curl_ssl_getsessionid(struct connectdata *conn,
00277 void **ssl_sessionid,
00278 size_t *idsize,
00279 int sockindex)
00280 {
00281 struct curl_ssl_session *check;
00282 struct Curl_easy *data = conn->data;
00283 size_t i;
00284 long *general_age;
00285 bool no_match = TRUE;
00286
00287 const bool isProxy = CONNECT_PROXY_SSL();
00288 struct ssl_primary_config * const ssl_config = isProxy ?
00289 &conn->proxy_ssl_config :
00290 &conn->ssl_config;
00291 const char * const name = isProxy ? conn->http_proxy.host.name :
00292 conn->host.name;
00293 int port = isProxy ? (int)conn->port : conn->remote_port;
00294 *ssl_sessionid = NULL;
00295
00296 DEBUGASSERT(data->set.general_ssl.sessionid);
00297
00298 if(!data->set.general_ssl.sessionid)
00299
00300 return TRUE;
00301
00302
00303 if(SSLSESSION_SHARED(data))
00304 general_age = &data->share->sessionage;
00305 else
00306 general_age = &data->state.sessionage;
00307
00308 for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) {
00309 check = &data->state.session[i];
00310 if(!check->sessionid)
00311
00312 continue;
00313 if(strcasecompare(name, check->name) &&
00314 ((!conn->bits.conn_to_host && !check->conn_to_host) ||
00315 (conn->bits.conn_to_host && check->conn_to_host &&
00316 strcasecompare(conn->conn_to_host.name, check->conn_to_host))) &&
00317 ((!conn->bits.conn_to_port && check->conn_to_port == -1) ||
00318 (conn->bits.conn_to_port && check->conn_to_port != -1 &&
00319 conn->conn_to_port == check->conn_to_port)) &&
00320 (port == check->remote_port) &&
00321 strcasecompare(conn->handler->scheme, check->scheme) &&
00322 Curl_ssl_config_matches(ssl_config, &check->ssl_config)) {
00323
00324 (*general_age)++;
00325 check->age = *general_age;
00326 *ssl_sessionid = check->sessionid;
00327 if(idsize)
00328 *idsize = check->idsize;
00329 no_match = FALSE;
00330 break;
00331 }
00332 }
00333
00334 return no_match;
00335 }
00336
00337
00338
00339
00340 void Curl_ssl_kill_session(struct curl_ssl_session *session)
00341 {
00342 if(session->sessionid) {
00343
00344
00345
00346 curlssl_session_free(session->sessionid);
00347
00348 session->sessionid = NULL;
00349 session->age = 0;
00350
00351 Curl_free_primary_ssl_config(&session->ssl_config);
00352
00353 Curl_safefree(session->name);
00354 Curl_safefree(session->conn_to_host);
00355 }
00356 }
00357
00358
00359
00360
00361 void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid)
00362 {
00363 size_t i;
00364 struct Curl_easy *data=conn->data;
00365
00366 for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) {
00367 struct curl_ssl_session *check = &data->state.session[i];
00368
00369 if(check->sessionid == ssl_sessionid) {
00370 Curl_ssl_kill_session(check);
00371 break;
00372 }
00373 }
00374 }
00375
00376
00377
00378
00379
00380
00381
00382 CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
00383 void *ssl_sessionid,
00384 size_t idsize,
00385 int sockindex)
00386 {
00387 size_t i;
00388 struct Curl_easy *data=conn->data;
00389 struct curl_ssl_session *store = &data->state.session[0];
00390 long oldest_age=data->state.session[0].age;
00391 char *clone_host;
00392 char *clone_conn_to_host;
00393 int conn_to_port;
00394 long *general_age;
00395 const bool isProxy = CONNECT_PROXY_SSL();
00396 struct ssl_primary_config * const ssl_config = isProxy ?
00397 &conn->proxy_ssl_config :
00398 &conn->ssl_config;
00399
00400 DEBUGASSERT(data->set.general_ssl.sessionid);
00401
00402 clone_host = strdup(isProxy ? conn->http_proxy.host.name : conn->host.name);
00403 if(!clone_host)
00404 return CURLE_OUT_OF_MEMORY;
00405
00406 if(conn->bits.conn_to_host) {
00407 clone_conn_to_host = strdup(conn->conn_to_host.name);
00408 if(!clone_conn_to_host) {
00409 free(clone_host);
00410 return CURLE_OUT_OF_MEMORY;
00411 }
00412 }
00413 else
00414 clone_conn_to_host = NULL;
00415
00416 if(conn->bits.conn_to_port)
00417 conn_to_port = conn->conn_to_port;
00418 else
00419 conn_to_port = -1;
00420
00421
00422
00423
00424
00425 if(SSLSESSION_SHARED(data)) {
00426 general_age = &data->share->sessionage;
00427 }
00428 else {
00429 general_age = &data->state.sessionage;
00430 }
00431
00432
00433 for(i = 1; (i < data->set.general_ssl.max_ssl_sessions) &&
00434 data->state.session[i].sessionid; i++) {
00435 if(data->state.session[i].age < oldest_age) {
00436 oldest_age = data->state.session[i].age;
00437 store = &data->state.session[i];
00438 }
00439 }
00440 if(i == data->set.general_ssl.max_ssl_sessions)
00441
00442 Curl_ssl_kill_session(store);
00443 else
00444 store = &data->state.session[i];
00445
00446
00447 store->sessionid = ssl_sessionid;
00448 store->idsize = idsize;
00449 store->age = *general_age;
00450
00451 free(store->name);
00452 free(store->conn_to_host);
00453 store->name = clone_host;
00454 store->conn_to_host = clone_conn_to_host;
00455 store->conn_to_port = conn_to_port;
00456
00457 store->remote_port = isProxy ? (int)conn->port : conn->remote_port;
00458 store->scheme = conn->handler->scheme;
00459
00460 if(!Curl_clone_primary_ssl_config(ssl_config, &store->ssl_config)) {
00461 store->sessionid = NULL;
00462 free(clone_host);
00463 free(clone_conn_to_host);
00464 return CURLE_OUT_OF_MEMORY;
00465 }
00466
00467 return CURLE_OK;
00468 }
00469
00470
00471 void Curl_ssl_close_all(struct Curl_easy *data)
00472 {
00473 size_t i;
00474
00475 if(data->state.session && !SSLSESSION_SHARED(data)) {
00476 for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++)
00477
00478 Curl_ssl_kill_session(&data->state.session[i]);
00479
00480
00481 Curl_safefree(data->state.session);
00482 }
00483
00484 curlssl_close_all(data);
00485 }
00486
00487 #if defined(USE_SSLEAY) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \
00488 defined(USE_DARWINSSL) || defined(USE_NSS)
00489
00490 int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks,
00491 int numsocks)
00492 {
00493 struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
00494
00495 if(!numsocks)
00496 return GETSOCK_BLANK;
00497
00498 if(connssl->connecting_state == ssl_connect_2_writing) {
00499
00500 socks[0] = conn->sock[FIRSTSOCKET];
00501 return GETSOCK_WRITESOCK(0);
00502 }
00503 else if(connssl->connecting_state == ssl_connect_2_reading) {
00504
00505 socks[0] = conn->sock[FIRSTSOCKET];
00506 return GETSOCK_READSOCK(0);
00507 }
00508
00509 return GETSOCK_BLANK;
00510 }
00511 #else
00512 int Curl_ssl_getsock(struct connectdata *conn,
00513 curl_socket_t *socks,
00514 int numsocks)
00515 {
00516 (void)conn;
00517 (void)socks;
00518 (void)numsocks;
00519 return GETSOCK_BLANK;
00520 }
00521
00522 #endif
00523
00524 void Curl_ssl_close(struct connectdata *conn, int sockindex)
00525 {
00526 DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
00527 curlssl_close(conn, sockindex);
00528 }
00529
00530 CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex)
00531 {
00532 if(curlssl_shutdown(conn, sockindex))
00533 return CURLE_SSL_SHUTDOWN_FAILED;
00534
00535 conn->ssl[sockindex].use = FALSE;
00536 conn->ssl[sockindex].state = ssl_connection_none;
00537
00538 conn->recv[sockindex] = Curl_recv_plain;
00539 conn->send[sockindex] = Curl_send_plain;
00540
00541 return CURLE_OK;
00542 }
00543
00544
00545
00546 CURLcode Curl_ssl_set_engine(struct Curl_easy *data, const char *engine)
00547 {
00548 return curlssl_set_engine(data, engine);
00549 }
00550
00551
00552
00553 CURLcode Curl_ssl_set_engine_default(struct Curl_easy *data)
00554 {
00555 return curlssl_set_engine_default(data);
00556 }
00557
00558
00559 struct curl_slist *Curl_ssl_engines_list(struct Curl_easy *data)
00560 {
00561 return curlssl_engines_list(data);
00562 }
00563
00564
00565
00566
00567
00568 CURLcode Curl_ssl_initsessions(struct Curl_easy *data, size_t amount)
00569 {
00570 struct curl_ssl_session *session;
00571
00572 if(data->state.session)
00573
00574 return CURLE_OK;
00575
00576 session = calloc(amount, sizeof(struct curl_ssl_session));
00577 if(!session)
00578 return CURLE_OUT_OF_MEMORY;
00579
00580
00581 data->set.general_ssl.max_ssl_sessions = amount;
00582 data->state.session = session;
00583 data->state.sessionage = 1;
00584 return CURLE_OK;
00585 }
00586
00587 size_t Curl_ssl_version(char *buffer, size_t size)
00588 {
00589 return curlssl_version(buffer, size);
00590 }
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600 int Curl_ssl_check_cxn(struct connectdata *conn)
00601 {
00602 return curlssl_check_cxn(conn);
00603 }
00604
00605 bool Curl_ssl_data_pending(const struct connectdata *conn,
00606 int connindex)
00607 {
00608 return curlssl_data_pending(conn, connindex);
00609 }
00610
00611 void Curl_ssl_free_certinfo(struct Curl_easy *data)
00612 {
00613 int i;
00614 struct curl_certinfo *ci = &data->info.certs;
00615
00616 if(ci->num_of_certs) {
00617
00618 for(i=0; i<ci->num_of_certs; i++) {
00619 curl_slist_free_all(ci->certinfo[i]);
00620 ci->certinfo[i] = NULL;
00621 }
00622
00623 free(ci->certinfo);
00624 ci->certinfo = NULL;
00625 ci->num_of_certs = 0;
00626 }
00627 }
00628
00629 CURLcode Curl_ssl_init_certinfo(struct Curl_easy *data, int num)
00630 {
00631 struct curl_certinfo *ci = &data->info.certs;
00632 struct curl_slist **table;
00633
00634
00635 Curl_ssl_free_certinfo(data);
00636
00637
00638 table = calloc((size_t) num, sizeof(struct curl_slist *));
00639 if(!table)
00640 return CURLE_OUT_OF_MEMORY;
00641
00642 ci->num_of_certs = num;
00643 ci->certinfo = table;
00644
00645 return CURLE_OK;
00646 }
00647
00648
00649
00650
00651 CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data,
00652 int certnum,
00653 const char *label,
00654 const char *value,
00655 size_t valuelen)
00656 {
00657 struct curl_certinfo *ci = &data->info.certs;
00658 char *output;
00659 struct curl_slist *nl;
00660 CURLcode result = CURLE_OK;
00661 size_t labellen = strlen(label);
00662 size_t outlen = labellen + 1 + valuelen + 1;
00663
00664 output = malloc(outlen);
00665 if(!output)
00666 return CURLE_OUT_OF_MEMORY;
00667
00668
00669 snprintf(output, outlen, "%s:", label);
00670
00671
00672 memcpy(&output[labellen+1], value, valuelen);
00673
00674
00675 output[labellen + 1 + valuelen] = 0;
00676
00677 nl = Curl_slist_append_nodup(ci->certinfo[certnum], output);
00678 if(!nl) {
00679 free(output);
00680 curl_slist_free_all(ci->certinfo[certnum]);
00681 result = CURLE_OUT_OF_MEMORY;
00682 }
00683
00684 ci->certinfo[certnum] = nl;
00685 return result;
00686 }
00687
00688
00689
00690
00691
00692 CURLcode Curl_ssl_push_certinfo(struct Curl_easy *data,
00693 int certnum,
00694 const char *label,
00695 const char *value)
00696 {
00697 size_t valuelen = strlen(value);
00698
00699 return Curl_ssl_push_certinfo_len(data, certnum, label, value, valuelen);
00700 }
00701
00702 CURLcode Curl_ssl_random(struct Curl_easy *data,
00703 unsigned char *entropy,
00704 size_t length)
00705 {
00706 int rc = curlssl_random(data, entropy, length);
00707 if(rc) {
00708 failf(data, "PRNG seeding failed");
00709 return CURLE_FAILED_INIT;
00710 }
00711 return CURLE_OK;
00712 }
00713
00714
00715
00716
00717
00718 static CURLcode pubkey_pem_to_der(const char *pem,
00719 unsigned char **der, size_t *der_len)
00720 {
00721 char *stripped_pem, *begin_pos, *end_pos;
00722 size_t pem_count, stripped_pem_count = 0, pem_len;
00723 CURLcode result;
00724
00725
00726 if(!pem)
00727 return CURLE_BAD_CONTENT_ENCODING;
00728
00729 begin_pos = strstr(pem, "-----BEGIN PUBLIC KEY-----");
00730 if(!begin_pos)
00731 return CURLE_BAD_CONTENT_ENCODING;
00732
00733 pem_count = begin_pos - pem;
00734
00735 if(0 != pem_count && '\n' != pem[pem_count - 1])
00736 return CURLE_BAD_CONTENT_ENCODING;
00737
00738
00739 pem_count += 26;
00740
00741
00742 end_pos = strstr(pem + pem_count, "\n-----END PUBLIC KEY-----");
00743 if(!end_pos)
00744 return CURLE_BAD_CONTENT_ENCODING;
00745
00746 pem_len = end_pos - pem;
00747
00748 stripped_pem = malloc(pem_len - pem_count + 1);
00749 if(!stripped_pem)
00750 return CURLE_OUT_OF_MEMORY;
00751
00752
00753
00754
00755
00756
00757 while(pem_count < pem_len) {
00758 if('\n' != pem[pem_count] && '\r' != pem[pem_count])
00759 stripped_pem[stripped_pem_count++] = pem[pem_count];
00760 ++pem_count;
00761 }
00762
00763 stripped_pem[stripped_pem_count] = '\0';
00764
00765 result = Curl_base64_decode(stripped_pem, der, der_len);
00766
00767 Curl_safefree(stripped_pem);
00768
00769 return result;
00770 }
00771
00772
00773
00774
00775
00776 CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
00777 const char *pinnedpubkey,
00778 const unsigned char *pubkey, size_t pubkeylen)
00779 {
00780 FILE *fp;
00781 unsigned char *buf = NULL, *pem_ptr = NULL;
00782 long filesize;
00783 size_t size, pem_len;
00784 CURLcode pem_read;
00785 CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
00786 #ifdef curlssl_sha256sum
00787 CURLcode encode;
00788 size_t encodedlen, pinkeylen;
00789 char *encoded, *pinkeycopy, *begin_pos, *end_pos;
00790 unsigned char *sha256sumdigest = NULL;
00791 #endif
00792
00793
00794 if(!pinnedpubkey)
00795 return CURLE_OK;
00796 if(!pubkey || !pubkeylen)
00797 return result;
00798
00799
00800 if(strncmp(pinnedpubkey, "sha256//", 8) == 0) {
00801 #ifdef curlssl_sha256sum
00802
00803 sha256sumdigest = malloc(SHA256_DIGEST_LENGTH);
00804 if(!sha256sumdigest)
00805 return CURLE_OUT_OF_MEMORY;
00806 curlssl_sha256sum(pubkey, pubkeylen,
00807 sha256sumdigest, SHA256_DIGEST_LENGTH);
00808 encode = Curl_base64_encode(data, (char *)sha256sumdigest,
00809 SHA256_DIGEST_LENGTH, &encoded, &encodedlen);
00810 Curl_safefree(sha256sumdigest);
00811
00812 if(encode)
00813 return encode;
00814
00815 infof(data, "\t public key hash: sha256//%s\n", encoded);
00816
00817
00818 pinkeylen = strlen(pinnedpubkey) + 1;
00819 pinkeycopy = malloc(pinkeylen);
00820 if(!pinkeycopy) {
00821 Curl_safefree(encoded);
00822 return CURLE_OUT_OF_MEMORY;
00823 }
00824 memcpy(pinkeycopy, pinnedpubkey, pinkeylen);
00825
00826 begin_pos = pinkeycopy;
00827 do {
00828 end_pos = strstr(begin_pos, ";sha256//");
00829
00830
00831
00832
00833 if(end_pos)
00834 end_pos[0] = '\0';
00835
00836
00837 if(encodedlen == strlen(begin_pos + 8) &&
00838 !memcmp(encoded, begin_pos + 8, encodedlen)) {
00839 result = CURLE_OK;
00840 break;
00841 }
00842
00843
00844
00845
00846
00847 if(end_pos) {
00848 end_pos[0] = ';';
00849 begin_pos = strstr(end_pos, "sha256//");
00850 }
00851 } while(end_pos && begin_pos);
00852 Curl_safefree(encoded);
00853 Curl_safefree(pinkeycopy);
00854 #else
00855
00856 (void)data;
00857 #endif
00858 return result;
00859 }
00860
00861 fp = fopen(pinnedpubkey, "rb");
00862 if(!fp)
00863 return result;
00864
00865 do {
00866
00867 if(fseek(fp, 0, SEEK_END))
00868 break;
00869 filesize = ftell(fp);
00870 if(fseek(fp, 0, SEEK_SET))
00871 break;
00872 if(filesize < 0 || filesize > MAX_PINNED_PUBKEY_SIZE)
00873 break;
00874
00875
00876
00877
00878
00879 size = curlx_sotouz((curl_off_t) filesize);
00880 if(pubkeylen > size)
00881 break;
00882
00883
00884
00885
00886
00887 buf = malloc(size + 1);
00888 if(!buf)
00889 break;
00890
00891
00892 if((int) fread(buf, size, 1, fp) != 1)
00893 break;
00894
00895
00896 if(pubkeylen == size) {
00897 if(!memcmp(pubkey, buf, pubkeylen))
00898 result = CURLE_OK;
00899 break;
00900 }
00901
00902
00903
00904
00905
00906 buf[size] = '\0';
00907 pem_read = pubkey_pem_to_der((const char *)buf, &pem_ptr, &pem_len);
00908
00909 if(pem_read)
00910 break;
00911
00912
00913
00914
00915
00916 if(pubkeylen == pem_len && !memcmp(pubkey, pem_ptr, pubkeylen))
00917 result = CURLE_OK;
00918 } while(0);
00919
00920 Curl_safefree(buf);
00921 Curl_safefree(pem_ptr);
00922 fclose(fp);
00923
00924 return result;
00925 }
00926
00927 #ifndef CURL_DISABLE_CRYPTO_AUTH
00928 CURLcode Curl_ssl_md5sum(unsigned char *tmp,
00929 size_t tmplen,
00930 unsigned char *md5sum,
00931 size_t md5len)
00932 {
00933 #ifdef curlssl_md5sum
00934 curlssl_md5sum(tmp, tmplen, md5sum, md5len);
00935 #else
00936 MD5_context *MD5pw;
00937
00938 (void) md5len;
00939
00940 MD5pw = Curl_MD5_init(Curl_DIGEST_MD5);
00941 if(!MD5pw)
00942 return CURLE_OUT_OF_MEMORY;
00943 Curl_MD5_update(MD5pw, tmp, curlx_uztoui(tmplen));
00944 Curl_MD5_final(MD5pw, md5sum);
00945 #endif
00946 return CURLE_OK;
00947 }
00948 #endif
00949
00950
00951
00952
00953 bool Curl_ssl_cert_status_request(void)
00954 {
00955 #ifdef curlssl_cert_status_request
00956 return curlssl_cert_status_request();
00957 #else
00958 return FALSE;
00959 #endif
00960 }
00961
00962
00963
00964
00965 bool Curl_ssl_false_start(void)
00966 {
00967 #ifdef curlssl_false_start
00968 return curlssl_false_start();
00969 #else
00970 return FALSE;
00971 #endif
00972 }
00973
00974 #endif