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 #include "setup.h"
00035
00036 #include <string.h>
00037 #include <stdlib.h>
00038 #include <ctype.h>
00039 #ifdef HAVE_SYS_SOCKET_H
00040 #include <sys/socket.h>
00041 #endif
00042
00043 #include "urldata.h"
00044 #include "sendf.h"
00045 #include "formdata.h"
00046 #include "url.h"
00047 #include "inet_pton.h"
00048 #include "ssluse.h"
00049 #include "connect.h"
00050 #include "strequal.h"
00051 #include "select.h"
00052 #include "sslgen.h"
00053
00054 #define _MPRINTF_REPLACE
00055 #include <curl/mprintf.h>
00056
00057 #ifdef USE_SSLEAY
00058
00059 #ifdef USE_OPENSSL
00060 #include <openssl/rand.h>
00061 #include <openssl/x509v3.h>
00062 #else
00063 #include <rand.h>
00064 #include <x509v3.h>
00065 #endif
00066
00067 #include "memory.h"
00068 #include "easyif.h"
00069
00070
00071 #include "memdebug.h"
00072
00073 #ifndef min
00074 #define min(a, b) ((a) < (b) ? (a) : (b))
00075 #endif
00076
00077 #if OPENSSL_VERSION_NUMBER >= 0x0090581fL
00078 #define HAVE_SSL_GET1_SESSION 1
00079 #else
00080 #undef HAVE_SSL_GET1_SESSION
00081 #endif
00082
00083 #if OPENSSL_VERSION_NUMBER >= 0x00904100L
00084 #define HAVE_USERDATA_IN_PWD_CALLBACK 1
00085 #else
00086 #undef HAVE_USERDATA_IN_PWD_CALLBACK
00087 #endif
00088
00089 #if OPENSSL_VERSION_NUMBER >= 0x00907001L
00090
00091 #define HAVE_ENGINE_LOAD_FOUR_ARGS
00092 #else
00093
00094 #undef HAVE_ENGINE_LOAD_FOUR_ARGS
00095 #endif
00096
00097 #if (OPENSSL_VERSION_NUMBER >= 0x00903001L) && defined(HAVE_OPENSSL_PKCS12_H)
00098
00099 #define HAVE_PKCS12_SUPPORT
00100 #else
00101
00102 #undef HAVE_PKCS12_SUPPORT
00103 #endif
00104
00105 #if OPENSSL_VERSION_NUMBER >= 0x00906001L
00106 #define HAVE_ERR_ERROR_STRING_N 1
00107 #endif
00108
00109 #if OPENSSL_VERSION_NUMBER >= 0x00909000L
00110 #define SSL_METHOD_QUAL const
00111 #else
00112 #define SSL_METHOD_QUAL
00113 #endif
00114
00115
00116
00117
00118
00119
00120
00121 #define RAND_LOAD_LENGTH 1024
00122
00123 #ifndef HAVE_USERDATA_IN_PWD_CALLBACK
00124 static char global_passwd[64];
00125 #endif
00126
00127 static int passwd_callback(char *buf, int num, int verify
00128 #if HAVE_USERDATA_IN_PWD_CALLBACK
00129
00130
00131
00132 , void *global_passwd
00133 #endif
00134 )
00135 {
00136 if(verify)
00137 fprintf(stderr, "%s\n", buf);
00138 else {
00139 if(num > (int)strlen((char *)global_passwd)) {
00140 strcpy(buf, global_passwd);
00141 return (int)strlen(buf);
00142 }
00143 }
00144 return 0;
00145 }
00146
00147
00148
00149
00150
00151
00152
00153
00154 #ifdef HAVE_RAND_STATUS
00155 #define seed_enough(x) rand_enough()
00156 static bool rand_enough(void)
00157 {
00158 return (bool)(0 != RAND_status());
00159 }
00160 #else
00161 #define seed_enough(x) rand_enough(x)
00162 static bool rand_enough(int nread)
00163 {
00164
00165 return (bool)(nread > 500);
00166 }
00167 #endif
00168
00169 static int ossl_seed(struct SessionHandle *data)
00170 {
00171 char *buf = data->state.buffer;
00172 int nread=0;
00173
00174
00175
00176
00177 #ifndef RANDOM_FILE
00178
00179
00180 if(data->set.ssl.random_file)
00181 #define RANDOM_FILE ""
00182 #endif
00183 {
00184
00185 nread += RAND_load_file((data->set.ssl.random_file?
00186 data->set.ssl.random_file:RANDOM_FILE),
00187 RAND_LOAD_LENGTH);
00188 if(seed_enough(nread))
00189 return nread;
00190 }
00191
00192 #if defined(HAVE_RAND_EGD)
00193
00194
00195 #ifndef EGD_SOCKET
00196
00197
00198 if(data->set.ssl.egdsocket)
00199 #define EGD_SOCKET ""
00200 #endif
00201 {
00202
00203
00204 int ret = RAND_egd(data->set.ssl.egdsocket?
00205 data->set.ssl.egdsocket:EGD_SOCKET);
00206 if(-1 != ret) {
00207 nread += ret;
00208 if(seed_enough(nread))
00209 return nread;
00210 }
00211 }
00212 #endif
00213
00214
00215
00216 #ifdef HAVE_RAND_SCREEN
00217
00218 RAND_screen();
00219 nread = 100;
00220 #else
00221 {
00222 int len;
00223 char *area;
00224
00225
00226
00227
00228
00229
00230
00231 do {
00232 area = Curl_FormBoundary();
00233 if(!area)
00234 return 3;
00235
00236 len = (int)strlen(area);
00237 RAND_add(area, len, (len >> 1));
00238
00239 free(area);
00240 } while (!RAND_status());
00241 }
00242 #endif
00243
00244
00245 buf[0]=0;
00246 RAND_file_name(buf, BUFSIZE);
00247 if(buf[0]) {
00248
00249 nread += RAND_load_file(buf, RAND_LOAD_LENGTH);
00250 if(seed_enough(nread))
00251 return nread;
00252 }
00253
00254 infof(data, "libcurl is now using a weak random seed!\n");
00255 return nread;
00256 }
00257
00258 int Curl_ossl_seed(struct SessionHandle *data)
00259 {
00260
00261
00262 static bool ssl_seeded = FALSE;
00263
00264 if(!ssl_seeded || data->set.ssl.random_file || data->set.ssl.egdsocket) {
00265 ossl_seed(data);
00266 ssl_seeded = TRUE;
00267 }
00268 return 0;
00269 }
00270
00271
00272 #ifndef SSL_FILETYPE_ENGINE
00273 #define SSL_FILETYPE_ENGINE 42
00274 #endif
00275 #ifndef SSL_FILETYPE_PKCS12
00276 #define SSL_FILETYPE_PKCS12 43
00277 #endif
00278 static int do_file_type(const char *type)
00279 {
00280 if(!type || !type[0])
00281 return SSL_FILETYPE_PEM;
00282 if(curl_strequal(type, "PEM"))
00283 return SSL_FILETYPE_PEM;
00284 if(curl_strequal(type, "DER"))
00285 return SSL_FILETYPE_ASN1;
00286 if(curl_strequal(type, "ENG"))
00287 return SSL_FILETYPE_ENGINE;
00288 if(curl_strequal(type, "P12"))
00289 return SSL_FILETYPE_PKCS12;
00290 return -1;
00291 }
00292
00293 static
00294 int cert_stuff(struct connectdata *conn,
00295 SSL_CTX* ctx,
00296 char *cert_file,
00297 const char *cert_type,
00298 char *key_file,
00299 const char *key_type)
00300 {
00301 struct SessionHandle *data = conn->data;
00302 int file_type;
00303
00304 if(cert_file != NULL) {
00305 SSL *ssl;
00306 X509 *x509;
00307 int cert_done = 0;
00308
00309 if(data->set.key_passwd) {
00310 #ifndef HAVE_USERDATA_IN_PWD_CALLBACK
00311
00312
00313
00314
00315 size_t len = strlen(data->set.key_passwd);
00316 if(len < sizeof(global_passwd))
00317 memcpy(global_passwd, data->set.key_passwd, len+1);
00318 #else
00319
00320
00321
00322 SSL_CTX_set_default_passwd_cb_userdata(ctx,
00323 data->set.key_passwd);
00324 #endif
00325
00326 SSL_CTX_set_default_passwd_cb(ctx, passwd_callback);
00327 }
00328
00329 file_type = do_file_type(cert_type);
00330
00331 #define SSL_CLIENT_CERT_ERR \
00332 "unable to use client certificate (no key found or wrong pass phrase?)"
00333
00334 switch(file_type) {
00335 case SSL_FILETYPE_PEM:
00336
00337 if(SSL_CTX_use_certificate_chain_file(ctx,
00338 cert_file) != 1) {
00339 failf(data, SSL_CLIENT_CERT_ERR);
00340 return 0;
00341 }
00342 break;
00343
00344 case SSL_FILETYPE_ASN1:
00345
00346
00347
00348 if(SSL_CTX_use_certificate_file(ctx,
00349 cert_file,
00350 file_type) != 1) {
00351 failf(data, SSL_CLIENT_CERT_ERR);
00352 return 0;
00353 }
00354 break;
00355 case SSL_FILETYPE_ENGINE:
00356 failf(data, "file type ENG for certificate not implemented");
00357 return 0;
00358
00359 case SSL_FILETYPE_PKCS12:
00360 {
00361 #ifdef HAVE_PKCS12_SUPPORT
00362 FILE *f;
00363 PKCS12 *p12;
00364 EVP_PKEY *pri;
00365
00366 f = fopen(cert_file,"rb");
00367 if (!f) {
00368 failf(data, "could not open PKCS12 file '%s'", cert_file);
00369 return 0;
00370 }
00371 p12 = d2i_PKCS12_fp(f, NULL);
00372 fclose(f);
00373
00374 PKCS12_PBE_add();
00375
00376 if (!PKCS12_parse(p12, data->set.key_passwd, &pri, &x509, NULL)) {
00377 failf(data,
00378 "could not parse PKCS12 file, check password, OpenSSL error %s",
00379 ERR_error_string(ERR_get_error(), NULL) );
00380 PKCS12_free(p12);
00381 return 0;
00382 }
00383
00384 PKCS12_free(p12);
00385
00386 if(SSL_CTX_use_certificate(ctx, x509) != 1) {
00387 failf(data, SSL_CLIENT_CERT_ERR);
00388 EVP_PKEY_free(pri);
00389 X509_free(x509);
00390 return 0;
00391 }
00392
00393 if(SSL_CTX_use_PrivateKey(ctx, pri) != 1) {
00394 failf(data, "unable to use private key from PKCS12 file '%s'",
00395 cert_file);
00396 EVP_PKEY_free(pri);
00397 X509_free(x509);
00398 return 0;
00399 }
00400
00401 EVP_PKEY_free(pri);
00402 X509_free(x509);
00403 cert_done = 1;
00404 break;
00405 #else
00406 failf(data, "file type P12 for certificate not supported");
00407 return 0;
00408 #endif
00409 }
00410 default:
00411 failf(data, "not supported file type '%s' for certificate", cert_type);
00412 return 0;
00413 }
00414
00415 file_type = do_file_type(key_type);
00416
00417 switch(file_type) {
00418 case SSL_FILETYPE_PEM:
00419 if(cert_done)
00420 break;
00421 if(key_file == NULL)
00422
00423 key_file=cert_file;
00424 case SSL_FILETYPE_ASN1:
00425 if(SSL_CTX_use_PrivateKey_file(ctx, key_file, file_type) != 1) {
00426 failf(data, "unable to set private key file: '%s' type %s\n",
00427 key_file, key_type?key_type:"PEM");
00428 return 0;
00429 }
00430 break;
00431 case SSL_FILETYPE_ENGINE:
00432 #ifdef HAVE_OPENSSL_ENGINE_H
00433 {
00434 EVP_PKEY *priv_key = NULL;
00435 if(data->state.engine) {
00436 #ifdef HAVE_ENGINE_LOAD_FOUR_ARGS
00437 UI_METHOD *ui_method = UI_OpenSSL();
00438 #endif
00439 if(!key_file || !key_file[0]) {
00440 failf(data, "no key set to load from crypto engine\n");
00441 return 0;
00442 }
00443
00444 priv_key = (EVP_PKEY *)
00445 ENGINE_load_private_key(data->state.engine,key_file,
00446 #ifdef HAVE_ENGINE_LOAD_FOUR_ARGS
00447 ui_method,
00448 #endif
00449 data->set.key_passwd);
00450 if(!priv_key) {
00451 failf(data, "failed to load private key from crypto engine\n");
00452 return 0;
00453 }
00454 if(SSL_CTX_use_PrivateKey(ctx, priv_key) != 1) {
00455 failf(data, "unable to set private key\n");
00456 EVP_PKEY_free(priv_key);
00457 return 0;
00458 }
00459 EVP_PKEY_free(priv_key);
00460 }
00461 else {
00462 failf(data, "crypto engine not set, can't load private key\n");
00463 return 0;
00464 }
00465 }
00466 break;
00467 #else
00468 failf(data, "file type ENG for private key not supported\n");
00469 return 0;
00470 #endif
00471 case SSL_FILETYPE_PKCS12:
00472 if(!cert_done) {
00473 failf(data, "file type P12 for private key not supported\n");
00474 return 0;
00475 }
00476 break;
00477 default:
00478 failf(data, "not supported file type for private key\n");
00479 return 0;
00480 }
00481
00482 ssl=SSL_new(ctx);
00483 if (NULL == ssl) {
00484 failf(data,"unable to create an SSL structure\n");
00485 return 0;
00486 }
00487
00488 x509=SSL_get_certificate(ssl);
00489
00490
00491
00492 if(x509 != NULL) {
00493 EVP_PKEY *pktmp = X509_get_pubkey(x509);
00494 EVP_PKEY_copy_parameters(pktmp,SSL_get_privatekey(ssl));
00495 EVP_PKEY_free(pktmp);
00496 }
00497
00498 SSL_free(ssl);
00499
00500
00501
00502
00503
00504
00505
00506 if(!SSL_CTX_check_private_key(ctx)) {
00507 failf(data, "Private key does not match the certificate public key");
00508 return(0);
00509 }
00510 #ifndef HAVE_USERDATA_IN_PWD_CALLBACK
00511
00512 memset(global_passwd, 0, sizeof(global_passwd));
00513 #endif
00514 }
00515 return(1);
00516 }
00517
00518 static
00519 int cert_verify_callback(int ok, X509_STORE_CTX *ctx)
00520 {
00521 X509 *err_cert;
00522 char buf[256];
00523
00524 err_cert=X509_STORE_CTX_get_current_cert(ctx);
00525 X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf));
00526 return ok;
00527 }
00528
00529
00530
00531 static char *SSL_strerror(unsigned long error, char *buf, size_t size)
00532 {
00533 #ifdef HAVE_ERR_ERROR_STRING_N
00534
00535
00536
00537 ERR_error_string_n(error, buf, size);
00538 #else
00539 (void) size;
00540 ERR_error_string(error, buf);
00541 #endif
00542 return (buf);
00543 }
00544
00545 #endif
00546
00547 #ifdef USE_SSLEAY
00548
00554 int Curl_ossl_init(void)
00555 {
00556 #ifdef HAVE_ENGINE_LOAD_BUILTIN_ENGINES
00557 ENGINE_load_builtin_engines();
00558 #endif
00559
00560
00561 SSL_load_error_strings();
00562
00563
00564 if (!SSLeay_add_ssl_algorithms())
00565 return 0;
00566
00567 return 1;
00568 }
00569
00570 #endif
00571
00572 #ifdef USE_SSLEAY
00573
00574
00575 void Curl_ossl_cleanup(void)
00576 {
00577
00578 ERR_free_strings();
00579
00580
00581
00582 EVP_cleanup();
00583
00584 #ifdef HAVE_ENGINE_cleanup
00585 ENGINE_cleanup();
00586 #endif
00587
00588 #ifdef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA
00589
00590
00591 CRYPTO_cleanup_all_ex_data();
00592 #endif
00593 }
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603 int Curl_ossl_check_cxn(struct connectdata *conn)
00604 {
00605 int rc;
00606 char buf;
00607
00608 rc = SSL_peek(conn->ssl[FIRSTSOCKET].handle, (void*)&buf, 1);
00609 if (rc > 0)
00610 return 1;
00611
00612 if (rc == 0)
00613 return 0;
00614
00615 return -1;
00616 }
00617
00618 #endif
00619
00620
00621
00622 CURLcode Curl_ossl_set_engine(struct SessionHandle *data, const char *engine)
00623 {
00624 #if defined(USE_SSLEAY) && defined(HAVE_OPENSSL_ENGINE_H)
00625 ENGINE *e = ENGINE_by_id(engine);
00626
00627 if (!e) {
00628 failf(data, "SSL Engine '%s' not found", engine);
00629 return (CURLE_SSL_ENGINE_NOTFOUND);
00630 }
00631
00632 if (data->state.engine) {
00633 ENGINE_finish(data->state.engine);
00634 ENGINE_free(data->state.engine);
00635 data->state.engine = NULL;
00636 }
00637 if (!ENGINE_init(e)) {
00638 char buf[256];
00639
00640 ENGINE_free(e);
00641 failf(data, "Failed to initialise SSL Engine '%s':\n%s",
00642 engine, SSL_strerror(ERR_get_error(), buf, sizeof(buf)));
00643 return (CURLE_SSL_ENGINE_INITFAILED);
00644 }
00645 data->state.engine = e;
00646 return (CURLE_OK);
00647 #else
00648 (void)engine;
00649 failf(data, "SSL Engine not supported");
00650 return (CURLE_SSL_ENGINE_NOTFOUND);
00651 #endif
00652 }
00653
00654 #ifdef USE_SSLEAY
00655
00656
00657 CURLcode Curl_ossl_set_engine_default(struct SessionHandle *data)
00658 {
00659 #ifdef HAVE_OPENSSL_ENGINE_H
00660 if (data->state.engine) {
00661 if (ENGINE_set_default(data->state.engine, ENGINE_METHOD_ALL) > 0) {
00662 infof(data,"set default crypto engine '%s'\n", ENGINE_get_id(data->state.engine));
00663 }
00664 else {
00665 failf(data, "set default crypto engine '%s' failed", ENGINE_get_id(data->state.engine));
00666 return CURLE_SSL_ENGINE_SETFAILED;
00667 }
00668 }
00669 #else
00670 (void) data;
00671 #endif
00672 return CURLE_OK;
00673 }
00674 #endif
00675
00676
00677
00678 struct curl_slist *Curl_ossl_engines_list(struct SessionHandle *data)
00679 {
00680 struct curl_slist *list = NULL;
00681 #if defined(USE_SSLEAY) && defined(HAVE_OPENSSL_ENGINE_H)
00682 struct curl_slist *beg = NULL;
00683 ENGINE *e;
00684
00685 for (e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) {
00686 list = curl_slist_append(list, ENGINE_get_id(e));
00687 if (list == NULL) {
00688 curl_slist_free_all(beg);
00689 return NULL;
00690 }
00691 else if (beg == NULL) {
00692 beg = list;
00693 }
00694 }
00695 #endif
00696 (void) data;
00697 return (list);
00698 }
00699
00700
00701 #ifdef USE_SSLEAY
00702
00703
00704
00705
00706 void Curl_ossl_close(struct connectdata *conn)
00707 {
00708 int i;
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718 ERR_remove_state(0);
00719
00720 for(i=0; i<2; i++) {
00721 struct ssl_connect_data *connssl = &conn->ssl[i];
00722
00723 if(connssl->handle) {
00724 (void)SSL_shutdown(connssl->handle);
00725 SSL_set_connect_state(connssl->handle);
00726
00727 SSL_free (connssl->handle);
00728 connssl->handle = NULL;
00729 }
00730 if(connssl->ctx) {
00731 SSL_CTX_free (connssl->ctx);
00732 connssl->ctx = NULL;
00733 }
00734 connssl->use = FALSE;
00735 }
00736 }
00737
00738
00739
00740
00741
00742 int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
00743 {
00744 int retval = 0;
00745 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
00746 struct SessionHandle *data = conn->data;
00747 char buf[120];
00748
00749 unsigned long sslerror;
00750 ssize_t nread;
00751 int err;
00752 int done = 0;
00753
00754
00755
00756
00757
00758
00759 if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
00760 (void)SSL_shutdown(connssl->handle);
00761
00762 if(connssl->handle) {
00763 while(!done) {
00764 int what = Curl_socket_ready(conn->sock[sockindex],
00765 CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
00766 if(what > 0) {
00767
00768
00769 nread = (ssize_t)SSL_read(conn->ssl[sockindex].handle, buf,
00770 sizeof(buf));
00771 err = SSL_get_error(conn->ssl[sockindex].handle, (int)nread);
00772
00773 switch(err) {
00774 case SSL_ERROR_NONE:
00775 case SSL_ERROR_ZERO_RETURN:
00776
00777
00778 done = 1;
00779 break;
00780 case SSL_ERROR_WANT_READ:
00781
00782 infof(data, "SSL_ERROR_WANT_READ\n");
00783 break;
00784 case SSL_ERROR_WANT_WRITE:
00785
00786 infof(data, "SSL_ERROR_WANT_WRITE\n");
00787 done = 1;
00788 break;
00789 default:
00790
00791 sslerror = ERR_get_error();
00792 failf(conn->data, "SSL read: %s, errno %d",
00793 ERR_error_string(sslerror, buf),
00794 SOCKERRNO);
00795 done = 1;
00796 break;
00797 }
00798 }
00799 else if(0 == what) {
00800
00801 failf(data, "SSL shutdown timeout");
00802 done = 1;
00803 break;
00804 }
00805 else {
00806
00807 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
00808 retval = -1;
00809 done = 1;
00810 }
00811 }
00812
00813 if(data->set.verbose) {
00814 #ifdef HAVE_SSL_GET_SHUTDOWN
00815 switch(SSL_get_shutdown(connssl->handle)) {
00816 case SSL_SENT_SHUTDOWN:
00817 infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN\n");
00818 break;
00819 case SSL_RECEIVED_SHUTDOWN:
00820 infof(data, "SSL_get_shutdown() returned SSL_RECEIVED_SHUTDOWN\n");
00821 break;
00822 case SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN:
00823 infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN|"
00824 "SSL_RECEIVED__SHUTDOWN\n");
00825 break;
00826 }
00827 #endif
00828 }
00829
00830 connssl->use = FALSE;
00831
00832 SSL_free (connssl->handle);
00833 connssl->handle = NULL;
00834 }
00835 return retval;
00836 }
00837
00838 void Curl_ossl_session_free(void *ptr)
00839 {
00840
00841 SSL_SESSION_free(ptr);
00842 }
00843
00844
00845
00846
00847
00848 int Curl_ossl_close_all(struct SessionHandle *data)
00849 {
00850 #ifdef HAVE_OPENSSL_ENGINE_H
00851 if(data->state.engine) {
00852 ENGINE_finish(data->state.engine);
00853 ENGINE_free(data->state.engine);
00854 data->state.engine = NULL;
00855 }
00856 #else
00857 (void)data;
00858 #endif
00859 return 0;
00860 }
00861
00862 static int Curl_ASN1_UTCTIME_output(struct connectdata *conn,
00863 const char *prefix,
00864 ASN1_UTCTIME *tm)
00865 {
00866 char *asn1_string;
00867 int gmt=FALSE;
00868 int i;
00869 int year=0,month=0,day=0,hour=0,minute=0,second=0;
00870 struct SessionHandle *data = conn->data;
00871
00872 #ifdef CURL_DISABLE_VERBOSE_STRINGS
00873 (void)prefix;
00874 #endif
00875
00876 if(!data->set.verbose)
00877 return 0;
00878
00879 i=tm->length;
00880 asn1_string=(char *)tm->data;
00881
00882 if(i < 10)
00883 return 1;
00884 if(asn1_string[i-1] == 'Z')
00885 gmt=TRUE;
00886 for (i=0; i<10; i++)
00887 if((asn1_string[i] > '9') || (asn1_string[i] < '0'))
00888 return 2;
00889
00890 year= (asn1_string[0]-'0')*10+(asn1_string[1]-'0');
00891 if(year < 50)
00892 year+=100;
00893
00894 month= (asn1_string[2]-'0')*10+(asn1_string[3]-'0');
00895 if((month > 12) || (month < 1))
00896 return 3;
00897
00898 day= (asn1_string[4]-'0')*10+(asn1_string[5]-'0');
00899 hour= (asn1_string[6]-'0')*10+(asn1_string[7]-'0');
00900 minute= (asn1_string[8]-'0')*10+(asn1_string[9]-'0');
00901
00902 if((asn1_string[10] >= '0') && (asn1_string[10] <= '9') &&
00903 (asn1_string[11] >= '0') && (asn1_string[11] <= '9'))
00904 second= (asn1_string[10]-'0')*10+(asn1_string[11]-'0');
00905
00906 infof(data,
00907 "%s%04d-%02d-%02d %02d:%02d:%02d %s\n",
00908 prefix, year+1900, month, day, hour, minute, second, (gmt?"GMT":""));
00909
00910 return 0;
00911 }
00912
00913 #endif
00914
00915
00916 #ifdef USE_SSLEAY
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929 #define HOST_NOMATCH 0
00930 #define HOST_MATCH 1
00931
00932 static int hostmatch(const char *hostname, const char *pattern)
00933 {
00934 while (1) {
00935 int c = *pattern++;
00936
00937 if (c == '\0')
00938 return (*hostname ? HOST_NOMATCH : HOST_MATCH);
00939
00940 if (c == '*') {
00941 c = *pattern;
00942 if (c == '\0')
00943 return HOST_MATCH;
00944
00945 while (*hostname) {
00946
00947 if (hostmatch(hostname++,pattern) == HOST_MATCH)
00948 return HOST_MATCH;
00949 }
00950 break;
00951 }
00952
00953 if (toupper(c) != toupper(*hostname++))
00954 break;
00955 }
00956 return HOST_NOMATCH;
00957 }
00958
00959 static int
00960 cert_hostcheck(const char *match_pattern, const char *hostname)
00961 {
00962 if (!match_pattern || !*match_pattern ||
00963 !hostname || !*hostname)
00964 return 0;
00965
00966 if(curl_strequal(hostname,match_pattern))
00967 return 1;
00968
00969 if (hostmatch(hostname,match_pattern) == HOST_MATCH)
00970 return 1;
00971 return 0;
00972 }
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995 static CURLcode verifyhost(struct connectdata *conn,
00996 X509 *server_cert)
00997 {
00998 bool matched = FALSE;
00999 int target = GEN_DNS;
01000 int addrlen = 0;
01001 struct SessionHandle *data = conn->data;
01002 STACK_OF(GENERAL_NAME) *altnames;
01003 #ifdef ENABLE_IPV6
01004 struct in6_addr addr;
01005 #else
01006 struct in_addr addr;
01007 #endif
01008 CURLcode res = CURLE_OK;
01009
01010 #ifdef ENABLE_IPV6
01011 if(conn->bits.ipv6_ip &&
01012 Curl_inet_pton(AF_INET6, conn->host.name, &addr)) {
01013 target = GEN_IPADD;
01014 addrlen = sizeof(struct in6_addr);
01015 }
01016 else
01017 #endif
01018 if(Curl_inet_pton(AF_INET, conn->host.name, &addr)) {
01019 target = GEN_IPADD;
01020 addrlen = sizeof(struct in_addr);
01021 }
01022
01023
01024 altnames = X509_get_ext_d2i(server_cert, NID_subject_alt_name, NULL, NULL);
01025
01026 if(altnames) {
01027 int numalts;
01028 int i;
01029
01030
01031
01032 numalts = sk_GENERAL_NAME_num(altnames);
01033
01034
01035 for (i=0; (i<numalts) && !matched; i++) {
01036
01037 const GENERAL_NAME *check = sk_GENERAL_NAME_value(altnames, i);
01038
01039
01040 if(check->type == target) {
01041
01042 const char *altptr = (char *)ASN1_STRING_data(check->d.ia5);
01043 int altlen;
01044
01045 switch(target) {
01046 case GEN_DNS:
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057 if (cert_hostcheck(altptr, conn->host.name))
01058 matched = TRUE;
01059 break;
01060
01061 case GEN_IPADD:
01062
01063
01064 altlen = ASN1_STRING_length(check->d.ia5);
01065 if((altlen == addrlen) && !memcmp(altptr, &addr, altlen))
01066 matched = TRUE;
01067 break;
01068 }
01069 }
01070 }
01071 GENERAL_NAMES_free(altnames);
01072 }
01073
01074 if(matched)
01075
01076 infof(data, "\t subjectAltName: %s matched\n", conn->host.dispname);
01077 else {
01078
01079
01080 int j,i=-1 ;
01081
01082
01083
01084 unsigned char *nulstr = (unsigned char *)"";
01085 unsigned char *peer_CN = nulstr;
01086
01087 X509_NAME *name = X509_get_subject_name(server_cert) ;
01088 if (name)
01089 while ((j=X509_NAME_get_index_by_NID(name,NID_commonName,i))>=0)
01090 i=j;
01091
01092
01093
01094
01095
01096 if (i>=0) {
01097 ASN1_STRING *tmp = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name,i));
01098
01099
01100
01101
01102
01103
01104 if (tmp && ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) {
01105 j = ASN1_STRING_length(tmp);
01106 if (j >= 0) {
01107 peer_CN = OPENSSL_malloc(j+1);
01108 if (peer_CN) {
01109 memcpy(peer_CN, ASN1_STRING_data(tmp), j);
01110 peer_CN[j] = '\0';
01111 }
01112 }
01113 }
01114 else
01115 j = ASN1_STRING_to_UTF8(&peer_CN, tmp);
01116 }
01117
01118 if (peer_CN == nulstr)
01119 peer_CN = NULL;
01120 #ifdef CURL_DOES_CONVERSIONS
01121 else {
01122
01123 size_t rc;
01124 rc = Curl_convert_from_utf8(data, peer_CN, strlen(peer_CN));
01125
01126 if (rc != CURLE_OK) {
01127 OPENSSL_free(peer_CN);
01128 return rc;
01129 }
01130 }
01131 #endif
01132
01133 if (!peer_CN) {
01134 if(data->set.ssl.verifyhost > 1) {
01135 failf(data,
01136 "SSL: unable to obtain common name from peer certificate");
01137 return CURLE_SSL_PEER_CERTIFICATE;
01138 }
01139 else {
01140
01141
01142 infof(data, "\t common name: WARNING couldn't obtain\n");
01143 }
01144 }
01145 else if(!cert_hostcheck((const char *)peer_CN, conn->host.name)) {
01146 if(data->set.ssl.verifyhost > 1) {
01147 failf(data, "SSL: certificate subject name '%s' does not match "
01148 "target host name '%s'", peer_CN, conn->host.dispname);
01149 res = CURLE_SSL_PEER_CERTIFICATE;
01150 }
01151 else
01152 infof(data, "\t common name: %s (does not match '%s')\n",
01153 peer_CN, conn->host.dispname);
01154 }
01155 else {
01156 infof(data, "\t common name: %s (matched)\n", peer_CN);
01157 }
01158 if(peer_CN)
01159 OPENSSL_free(peer_CN);
01160 }
01161 return res;
01162 }
01163 #endif
01164
01165
01166
01167 #ifdef SSL_CTRL_SET_MSG_CALLBACK
01168
01169 static const char *ssl_msg_type(int ssl_ver, int msg)
01170 {
01171 if (ssl_ver == SSL2_VERSION_MAJOR) {
01172 switch (msg) {
01173 case SSL2_MT_ERROR:
01174 return "Error";
01175 case SSL2_MT_CLIENT_HELLO:
01176 return "Client hello";
01177 case SSL2_MT_CLIENT_MASTER_KEY:
01178 return "Client key";
01179 case SSL2_MT_CLIENT_FINISHED:
01180 return "Client finished";
01181 case SSL2_MT_SERVER_HELLO:
01182 return "Server hello";
01183 case SSL2_MT_SERVER_VERIFY:
01184 return "Server verify";
01185 case SSL2_MT_SERVER_FINISHED:
01186 return "Server finished";
01187 case SSL2_MT_REQUEST_CERTIFICATE:
01188 return "Request CERT";
01189 case SSL2_MT_CLIENT_CERTIFICATE:
01190 return "Client CERT";
01191 }
01192 }
01193 else if (ssl_ver == SSL3_VERSION_MAJOR) {
01194 switch (msg) {
01195 case SSL3_MT_HELLO_REQUEST:
01196 return "Hello request";
01197 case SSL3_MT_CLIENT_HELLO:
01198 return "Client hello";
01199 case SSL3_MT_SERVER_HELLO:
01200 return "Server hello";
01201 case SSL3_MT_CERTIFICATE:
01202 return "CERT";
01203 case SSL3_MT_SERVER_KEY_EXCHANGE:
01204 return "Server key exchange";
01205 case SSL3_MT_CLIENT_KEY_EXCHANGE:
01206 return "Client key exchange";
01207 case SSL3_MT_CERTIFICATE_REQUEST:
01208 return "Request CERT";
01209 case SSL3_MT_SERVER_DONE:
01210 return "Server finished";
01211 case SSL3_MT_CERTIFICATE_VERIFY:
01212 return "CERT verify";
01213 case SSL3_MT_FINISHED:
01214 return "Finished";
01215 }
01216 }
01217 return "Unknown";
01218 }
01219
01220 static const char *tls_rt_type(int type)
01221 {
01222 return (
01223 type == SSL3_RT_CHANGE_CIPHER_SPEC ? "TLS change cipher, " :
01224 type == SSL3_RT_ALERT ? "TLS alert, " :
01225 type == SSL3_RT_HANDSHAKE ? "TLS handshake, " :
01226 type == SSL3_RT_APPLICATION_DATA ? "TLS app data, " :
01227 "TLS Unknown, ");
01228 }
01229
01230
01231
01232
01233
01234 static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
01235 const void *buf, size_t len, const SSL *ssl,
01236 struct connectdata *conn)
01237 {
01238 struct SessionHandle *data;
01239 const char *msg_name, *tls_rt_name;
01240 char ssl_buf[1024];
01241 int ver, msg_type, txt_len;
01242
01243 if (!conn || !conn->data || !conn->data->set.fdebug ||
01244 (direction != 0 && direction != 1))
01245 return;
01246
01247 data = conn->data;
01248 ssl_ver >>= 8;
01249 ver = (ssl_ver == SSL2_VERSION_MAJOR ? '2' :
01250 ssl_ver == SSL3_VERSION_MAJOR ? '3' : '?');
01251
01252
01253
01254
01255
01256 if (ssl_ver == SSL3_VERSION_MAJOR && content_type != 0)
01257 tls_rt_name = tls_rt_type(content_type);
01258 else
01259 tls_rt_name = "";
01260
01261 msg_type = *(char*)buf;
01262 msg_name = ssl_msg_type(ssl_ver, msg_type);
01263
01264 txt_len = snprintf(ssl_buf, sizeof(ssl_buf), "SSLv%c, %s%s (%d):\n",
01265 ver, tls_rt_name, msg_name, msg_type);
01266 Curl_debug(data, CURLINFO_TEXT, ssl_buf, (size_t)txt_len, NULL);
01267
01268 Curl_debug(data, (direction == 1) ? CURLINFO_SSL_DATA_OUT :
01269 CURLINFO_SSL_DATA_IN, (char *)buf, len, NULL);
01270 (void) ssl;
01271 }
01272 #endif
01273
01274 #ifdef USE_SSLEAY
01275
01276
01277 static CURLcode
01278 Curl_ossl_connect_step1(struct connectdata *conn,
01279 int sockindex)
01280 {
01281 CURLcode retcode = CURLE_OK;
01282
01283 struct SessionHandle *data = conn->data;
01284 SSL_METHOD_QUAL SSL_METHOD *req_method=NULL;
01285 void *ssl_sessionid=NULL;
01286 curl_socket_t sockfd = conn->sock[sockindex];
01287 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
01288
01289 DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
01290
01291
01292 Curl_ossl_seed(data);
01293
01294
01295 switch(data->set.ssl.version) {
01296 default:
01297 case CURL_SSLVERSION_DEFAULT:
01298
01299 req_method = SSLv23_client_method();
01300 break;
01301 case CURL_SSLVERSION_TLSv1:
01302 req_method = TLSv1_client_method();
01303 break;
01304 case CURL_SSLVERSION_SSLv2:
01305 req_method = SSLv2_client_method();
01306 break;
01307 case CURL_SSLVERSION_SSLv3:
01308 req_method = SSLv3_client_method();
01309 break;
01310 }
01311
01312 if (connssl->ctx)
01313 SSL_CTX_free(connssl->ctx);
01314 connssl->ctx = SSL_CTX_new(req_method);
01315
01316 if(!connssl->ctx) {
01317 failf(data, "SSL: couldn't create a context!");
01318 return CURLE_OUT_OF_MEMORY;
01319 }
01320
01321 #ifdef SSL_CTRL_SET_MSG_CALLBACK
01322 if (data->set.fdebug && data->set.verbose) {
01323
01324
01325 if (!SSL_CTX_callback_ctrl(connssl->ctx, SSL_CTRL_SET_MSG_CALLBACK,
01326 (void (*)(void))ssl_tls_trace)) {
01327 infof(data, "SSL: couldn't set callback!\n");
01328 }
01329 else if (!SSL_CTX_ctrl(connssl->ctx, SSL_CTRL_SET_MSG_CALLBACK_ARG, 0,
01330 conn)) {
01331 infof(data, "SSL: couldn't set callback argument!\n");
01332 }
01333 }
01334 #endif
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344 SSL_CTX_set_options(connssl->ctx, SSL_OP_ALL);
01345
01346 #if 0
01347
01348
01349
01350
01351
01352 if (data->state.used_interface == Curl_if_multi)
01353 SSL_CTX_ctrl(connssl->ctx, BIO_C_SET_NBIO, 1, NULL);
01354 #endif
01355
01356 if(data->set.cert) {
01357 if(!cert_stuff(conn,
01358 connssl->ctx,
01359 data->set.cert,
01360 data->set.cert_type,
01361 data->set.key,
01362 data->set.key_type)) {
01363
01364 return CURLE_SSL_CERTPROBLEM;
01365 }
01366 }
01367
01368 if(data->set.ssl.cipher_list) {
01369 if(!SSL_CTX_set_cipher_list(connssl->ctx,
01370 data->set.ssl.cipher_list)) {
01371 failf(data, "failed setting cipher list");
01372 return CURLE_SSL_CIPHER;
01373 }
01374 }
01375
01376 if (data->set.ssl.CAfile || data->set.ssl.CApath) {
01377
01378
01379 if (!SSL_CTX_load_verify_locations(connssl->ctx, data->set.ssl.CAfile,
01380 data->set.ssl.CApath)) {
01381 if (data->set.ssl.verifypeer) {
01382
01383 failf(data,"error setting certificate verify locations:\n"
01384 " CAfile: %s\n CApath: %s\n",
01385 data->set.ssl.CAfile ? data->set.ssl.CAfile : "none",
01386 data->set.ssl.CApath ? data->set.ssl.CApath : "none");
01387 return CURLE_SSL_CACERT_BADFILE;
01388 }
01389 else {
01390
01391
01392 infof(data, "error setting certificate verify locations,"
01393 " continuing anyway:\n");
01394 }
01395 }
01396 else {
01397
01398 infof(data, "successfully set certificate verify locations:\n");
01399 }
01400 infof(data,
01401 " CAfile: %s\n"
01402 " CApath: %s\n",
01403 data->set.ssl.CAfile ? data->set.ssl.CAfile : "none",
01404 data->set.ssl.CApath ? data->set.ssl.CApath : "none");
01405 }
01406
01407
01408
01409
01410 SSL_CTX_set_verify(connssl->ctx,
01411 data->set.ssl.verifypeer?SSL_VERIFY_PEER:SSL_VERIFY_NONE,
01412 cert_verify_callback);
01413
01414
01415 if(data->set.ssl.fsslctx) {
01416 retcode = (*data->set.ssl.fsslctx)(data, connssl->ctx,
01417 data->set.ssl.fsslctxp);
01418 if(retcode) {
01419 failf(data,"error signaled by ssl ctx callback");
01420 return retcode;
01421 }
01422 }
01423
01424
01425 if (connssl->handle)
01426 SSL_free(connssl->handle);
01427 connssl->handle = SSL_new(connssl->ctx);
01428 if (!connssl->handle) {
01429 failf(data, "SSL: couldn't create a context (handle)!");
01430 return CURLE_OUT_OF_MEMORY;
01431 }
01432 SSL_set_connect_state(connssl->handle);
01433
01434 connssl->server_cert = 0x0;
01435
01436
01437 if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) {
01438
01439 if (!SSL_set_session(connssl->handle, ssl_sessionid)) {
01440 failf(data, "SSL: SSL_set_session failed: %s",
01441 ERR_error_string(ERR_get_error(),NULL));
01442 return CURLE_SSL_CONNECT_ERROR;
01443 }
01444
01445 infof (data, "SSL re-using session ID\n");
01446 }
01447
01448
01449 if (!SSL_set_fd(connssl->handle, sockfd)) {
01450 failf(data, "SSL: SSL_set_fd failed: %s",
01451 ERR_error_string(ERR_get_error(),NULL));
01452 return CURLE_SSL_CONNECT_ERROR;
01453 }
01454
01455 connssl->connecting_state = ssl_connect_2;
01456 return CURLE_OK;
01457 }
01458
01459 static CURLcode
01460 Curl_ossl_connect_step2(struct connectdata *conn,
01461 int sockindex, long *timeout_ms)
01462 {
01463 struct SessionHandle *data = conn->data;
01464 int err;
01465 long has_passed;
01466 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
01467
01468 DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
01469 || ssl_connect_2_reading == connssl->connecting_state
01470 || ssl_connect_2_writing == connssl->connecting_state);
01471
01472
01473
01474
01475
01476 if(data->set.timeout && data->set.connecttimeout) {
01477
01478 if(data->set.timeout<data->set.connecttimeout)
01479 *timeout_ms = data->set.timeout;
01480 else
01481 *timeout_ms = data->set.connecttimeout;
01482 }
01483 else if(data->set.timeout)
01484 *timeout_ms = data->set.timeout;
01485 else if(data->set.connecttimeout)
01486 *timeout_ms = data->set.connecttimeout;
01487 else
01488
01489 *timeout_ms = DEFAULT_CONNECT_TIMEOUT;
01490
01491
01492 has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle);
01493
01494
01495 *timeout_ms -= has_passed;
01496
01497 if(*timeout_ms < 0) {
01498
01499 failf(data, "SSL connection timeout");
01500 return CURLE_OPERATION_TIMEOUTED;
01501 }
01502
01503 err = SSL_connect(connssl->handle);
01504
01505
01506
01507
01508 if(1 != err) {
01509 int detail = SSL_get_error(connssl->handle, err);
01510
01511 if(SSL_ERROR_WANT_READ == detail) {
01512 connssl->connecting_state = ssl_connect_2_reading;
01513 return CURLE_OK;
01514 }
01515 else if(SSL_ERROR_WANT_WRITE == detail) {
01516 connssl->connecting_state = ssl_connect_2_writing;
01517 return CURLE_OK;
01518 }
01519 else {
01520
01521 unsigned long errdetail;
01522 char error_buffer[256];
01523
01524 CURLcode rc;
01525 const char *cert_problem = NULL;
01526
01527 connssl->connecting_state = ssl_connect_2;
01528
01529
01530
01531 errdetail = ERR_get_error();
01532
01533
01534
01535 switch(errdetail) {
01536 case 0x1407E086:
01537
01538
01539
01540
01541
01542 case 0x14090086:
01543
01544
01545
01546
01547 cert_problem = "SSL certificate problem, verify that the CA cert is"
01548 " OK. Details:\n";
01549 rc = CURLE_SSL_CACERT;
01550 break;
01551 default:
01552 rc = CURLE_SSL_CONNECT_ERROR;
01553 break;
01554 }
01555
01556
01557
01558
01559
01560
01561
01562 if (CURLE_SSL_CONNECT_ERROR == rc && errdetail == 0) {
01563 failf(data, "Unknown SSL protocol error in connection to %s:%d ",
01564 conn->host.name, conn->port);
01565 return rc;
01566 }
01567
01568
01569 SSL_strerror(errdetail, error_buffer, sizeof(error_buffer));
01570 failf(data, "%s%s", cert_problem ? cert_problem : "", error_buffer);
01571 return rc;
01572 }
01573 }
01574 else {
01575
01576 connssl->connecting_state = ssl_connect_3;
01577
01578
01579 infof (data, "SSL connection using %s\n",
01580 SSL_get_cipher(connssl->handle));
01581
01582 return CURLE_OK;
01583 }
01584 }
01585
01586 static CURLcode
01587 Curl_ossl_connect_step3(struct connectdata *conn,
01588 int sockindex)
01589 {
01590 CURLcode retcode = CURLE_OK;
01591 char * str;
01592 long lerr;
01593 ASN1_TIME *certdate;
01594 void *ssl_sessionid=NULL;
01595 struct SessionHandle *data = conn->data;
01596 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
01597
01598 DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
01599
01600 if(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) {
01601
01602
01603 SSL_SESSION *our_ssl_sessionid;
01604 #ifdef HAVE_SSL_GET1_SESSION
01605 our_ssl_sessionid = SSL_get1_session(connssl->handle);
01606
01607
01608
01609
01610
01611 #else
01612 our_ssl_sessionid = SSL_get_session(connssl->handle);
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622 #endif
01623 retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid,
01624 0 );
01625 if(retcode) {
01626 failf(data, "failed to store ssl session");
01627 return retcode;
01628 }
01629 }
01630
01631
01632
01633
01634
01635
01636
01637
01638 connssl->server_cert = SSL_get_peer_certificate(connssl->handle);
01639 if(!connssl->server_cert) {
01640 failf(data, "SSL: couldn't get peer certificate!");
01641 return CURLE_SSL_PEER_CERTIFICATE;
01642 }
01643 infof (data, "Server certificate:\n");
01644
01645 str = X509_NAME_oneline(X509_get_subject_name(connssl->server_cert),
01646 NULL, 0);
01647 if(!str) {
01648 failf(data, "SSL: couldn't get X509-subject!");
01649 X509_free(connssl->server_cert);
01650 connssl->server_cert = NULL;
01651 return CURLE_SSL_CONNECT_ERROR;
01652 }
01653 infof(data, "\t subject: %s\n", str);
01654 CRYPTO_free(str);
01655
01656 certdate = X509_get_notBefore(connssl->server_cert);
01657 Curl_ASN1_UTCTIME_output(conn, "\t start date: ", certdate);
01658
01659 certdate = X509_get_notAfter(connssl->server_cert);
01660 Curl_ASN1_UTCTIME_output(conn, "\t expire date: ", certdate);
01661
01662 if(data->set.ssl.verifyhost) {
01663 retcode = verifyhost(conn, connssl->server_cert);
01664 if(retcode) {
01665 X509_free(connssl->server_cert);
01666 connssl->server_cert = NULL;
01667 return retcode;
01668 }
01669 }
01670
01671 str = X509_NAME_oneline(X509_get_issuer_name(connssl->server_cert),
01672 NULL, 0);
01673 if(!str) {
01674 failf(data, "SSL: couldn't get X509-issuer name!");
01675 retcode = CURLE_SSL_CONNECT_ERROR;
01676 }
01677 else {
01678 infof(data, "\t issuer: %s\n", str);
01679 CRYPTO_free(str);
01680
01681
01682
01683
01684 lerr = data->set.ssl.certverifyresult=
01685 SSL_get_verify_result(connssl->handle);
01686 if(data->set.ssl.certverifyresult != X509_V_OK) {
01687 if(data->set.ssl.verifypeer) {
01688
01689
01690 failf(data, "SSL certificate verify result: %s (%ld)",
01691 X509_verify_cert_error_string(lerr), lerr);
01692 retcode = CURLE_SSL_PEER_CERTIFICATE;
01693 }
01694 else
01695 infof(data, "SSL certificate verify result: %s (%ld),"
01696 " continuing anyway.\n",
01697 X509_verify_cert_error_string(lerr), lerr);
01698 }
01699 else
01700 infof(data, "SSL certificate verify ok.\n");
01701 }
01702
01703 X509_free(connssl->server_cert);
01704 connssl->server_cert = NULL;
01705 connssl->connecting_state = ssl_connect_done;
01706 return retcode;
01707 }
01708
01709 static CURLcode
01710 Curl_ossl_connect_common(struct connectdata *conn,
01711 int sockindex,
01712 bool nonblocking,
01713 bool *done)
01714 {
01715 CURLcode retcode;
01716 struct SessionHandle *data = conn->data;
01717 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
01718 curl_socket_t sockfd = conn->sock[sockindex];
01719 long timeout_ms;
01720
01721 if (ssl_connect_1==connssl->connecting_state) {
01722 retcode = Curl_ossl_connect_step1(conn, sockindex);
01723 if (retcode)
01724 return retcode;
01725 }
01726
01727 timeout_ms = 0;
01728 while (ssl_connect_2 == connssl->connecting_state ||
01729 ssl_connect_2_reading == connssl->connecting_state ||
01730 ssl_connect_2_writing == connssl->connecting_state) {
01731
01732
01733 if (connssl->connecting_state == ssl_connect_2_reading
01734 || connssl->connecting_state == ssl_connect_2_writing) {
01735
01736 int writefd = ssl_connect_2_writing==
01737 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
01738 int readfd = ssl_connect_2_reading==
01739 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
01740
01741 while(1) {
01742 int what = Curl_socket_ready(readfd, writefd, nonblocking?0:(int)timeout_ms);
01743 if(what > 0)
01744
01745 break;
01746 else if(0 == what) {
01747 if (nonblocking) {
01748 *done = FALSE;
01749 return CURLE_OK;
01750 }
01751 else {
01752
01753 failf(data, "SSL connection timeout");
01754 return CURLE_OPERATION_TIMEDOUT;
01755 }
01756 }
01757 else {
01758
01759 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
01760 return CURLE_SSL_CONNECT_ERROR;
01761 }
01762 }
01763 }
01764
01765
01766 retcode = Curl_ossl_connect_step2(conn, sockindex, &timeout_ms);
01767 if (retcode)
01768 return retcode;
01769
01770 }
01771
01772
01773 if (ssl_connect_3==connssl->connecting_state) {
01774 retcode = Curl_ossl_connect_step3(conn, sockindex);
01775 if (retcode)
01776 return retcode;
01777 }
01778
01779 if (ssl_connect_done==connssl->connecting_state) {
01780 *done = TRUE;
01781 }
01782 else {
01783 *done = FALSE;
01784 }
01785
01786
01787 connssl->connecting_state = ssl_connect_1;
01788
01789 return CURLE_OK;
01790 }
01791
01792 CURLcode
01793 Curl_ossl_connect_nonblocking(struct connectdata *conn,
01794 int sockindex,
01795 bool *done)
01796 {
01797 return Curl_ossl_connect_common(conn, sockindex, TRUE, done);
01798 }
01799
01800 CURLcode
01801 Curl_ossl_connect(struct connectdata *conn,
01802 int sockindex)
01803 {
01804 CURLcode retcode;
01805 bool done = FALSE;
01806
01807 retcode = Curl_ossl_connect_common(conn, sockindex, FALSE, &done);
01808 if (retcode)
01809 return retcode;
01810
01811 DEBUGASSERT(done);
01812
01813 return CURLE_OK;
01814 }
01815
01816
01817 ssize_t Curl_ossl_send(struct connectdata *conn,
01818 int sockindex,
01819 void *mem,
01820 size_t len)
01821 {
01822
01823
01824 int err;
01825 char error_buffer[120];
01826
01827 unsigned long sslerror;
01828 int rc = SSL_write(conn->ssl[sockindex].handle, mem, (int)len);
01829
01830 if(rc < 0) {
01831 err = SSL_get_error(conn->ssl[sockindex].handle, rc);
01832
01833 switch(err) {
01834 case SSL_ERROR_WANT_READ:
01835 case SSL_ERROR_WANT_WRITE:
01836
01837
01838
01839 return 0;
01840 case SSL_ERROR_SYSCALL:
01841 failf(conn->data, "SSL_write() returned SYSCALL, errno = %d\n",
01842 SOCKERRNO);
01843 return -1;
01844 case SSL_ERROR_SSL:
01845
01846
01847 sslerror = ERR_get_error();
01848 failf(conn->data, "SSL_write() error: %s\n",
01849 ERR_error_string(sslerror, error_buffer));
01850 return -1;
01851 }
01852
01853 failf(conn->data, "SSL_write() return error %d\n", err);
01854 return -1;
01855 }
01856 return (ssize_t)rc;
01857 }
01858
01859
01860
01861
01862
01863
01864 ssize_t Curl_ossl_recv(struct connectdata *conn,
01865 int num,
01866 char *buf,
01867 size_t buffersize,
01868 bool *wouldblock)
01869 {
01870 char error_buffer[120];
01871
01872 unsigned long sslerror;
01873 ssize_t nread = (ssize_t)SSL_read(conn->ssl[num].handle, buf,
01874 (int)buffersize);
01875 *wouldblock = FALSE;
01876 if(nread < 0) {
01877
01878 int err = SSL_get_error(conn->ssl[num].handle, (int)nread);
01879
01880 switch(err) {
01881 case SSL_ERROR_NONE:
01882 case SSL_ERROR_ZERO_RETURN:
01883 break;
01884 case SSL_ERROR_WANT_READ:
01885 case SSL_ERROR_WANT_WRITE:
01886
01887 *wouldblock = TRUE;
01888 return -1;
01889 default:
01890
01891 sslerror = ERR_get_error();
01892 failf(conn->data, "SSL read: %s, errno %d",
01893 ERR_error_string(sslerror, error_buffer),
01894 SOCKERRNO);
01895 return -1;
01896 }
01897 }
01898 return nread;
01899 }
01900
01901 size_t Curl_ossl_version(char *buffer, size_t size)
01902 {
01903 #ifdef YASSL_VERSION
01904
01905
01906 return snprintf(buffer, size, " yassl/%s", YASSL_VERSION);
01907 #else
01908
01909 #if (SSLEAY_VERSION_NUMBER >= 0x905000)
01910 {
01911 char sub[2];
01912 unsigned long ssleay_value;
01913 sub[1]='\0';
01914 ssleay_value=SSLeay();
01915 if(ssleay_value < 0x906000) {
01916 ssleay_value=SSLEAY_VERSION_NUMBER;
01917 sub[0]='\0';
01918 }
01919 else {
01920 if(ssleay_value&0xff0) {
01921 sub[0]=(char)(((ssleay_value>>4)&0xff) + 'a' -1);
01922 }
01923 else
01924 sub[0]='\0';
01925 }
01926
01927 return snprintf(buffer, size, " OpenSSL/%lx.%lx.%lx%s",
01928 (ssleay_value>>28)&0xf,
01929 (ssleay_value>>20)&0xff,
01930 (ssleay_value>>12)&0xff,
01931 sub);
01932 }
01933
01934 #else
01935
01936 #if (SSLEAY_VERSION_NUMBER >= 0x900000)
01937 return snprintf(buffer, size, " OpenSSL/%lx.%lx.%lx",
01938 (SSLEAY_VERSION_NUMBER>>28)&0xff,
01939 (SSLEAY_VERSION_NUMBER>>20)&0xff,
01940 (SSLEAY_VERSION_NUMBER>>12)&0xf);
01941
01942 #else
01943 {
01944 char sub[2];
01945 sub[1]='\0';
01946 if(SSLEAY_VERSION_NUMBER&0x0f) {
01947 sub[0]=(SSLEAY_VERSION_NUMBER&0x0f) + 'a' -1;
01948 }
01949 else
01950 sub[0]='\0';
01951
01952 return snprintf(buffer, size, " SSL/%x.%x.%x%s",
01953 (SSLEAY_VERSION_NUMBER>>12)&0xff,
01954 (SSLEAY_VERSION_NUMBER>>8)&0xf,
01955 (SSLEAY_VERSION_NUMBER>>4)&0xf, sub);
01956 }
01957 #endif
01958 #endif
01959
01960 #endif
01961 }
01962 #endif