diff -urNw curl/docs/curl.1 curl-cvs-new/docs/curl.1 --- curl/docs/curl.1 2007-01-06 04:41:15.000000000 +0530 +++ curl-cvs-new/docs/curl.1 2007-01-18 18:36:32.000000000 +0530 @@ -324,6 +324,10 @@ them independently. If this option is used several times, the last one will be used. + +.IP "--scdump " +(HTTPS) stores dump of server certificate to given file. + .IP "--cert-type " (SSL) Tells curl what certificate type the provided certificate is in. PEM, DER and ENG are recognized types. If not specified, PEM is assumed. diff -urNw curl/docs/libcurl/curl_easy_setopt.3 curl-cvs-new/docs/libcurl/curl_easy_setopt.3 --- curl/docs/libcurl/curl_easy_setopt.3 2007-01-17 14:27:20.000000000 +0530 +++ curl-cvs-new/docs/libcurl/curl_easy_setopt.3 2007-01-18 18:45:08.000000000 +0530 @@ -1179,6 +1179,10 @@ Pass a pointer to a zero terminated string as parameter. The string should be the format of your private key. Supported formats are "PEM", "DER" and "ENG". +.IP +.B CURLOPT_SSL_KEY_EXPORT +Pass a FILE* for get dump of server certificate + The format "ENG" enables you to load the private key from a crypto engine. In this case \fICURLOPT_SSLKEY\fP is used as an identifier passed to the engine. You have to set the crypto engine with \fICURLOPT_SSLENGINE\fP. diff -urNw curl/include/curl/curl.h curl-cvs-new/include/curl/curl.h --- curl/include/curl/curl.h 2007-01-08 16:54:11.000000000 +0530 +++ curl-cvs-new/include/curl/curl.h 2007-01-18 18:47:45.000000000 +0530 @@ -1054,6 +1054,9 @@ /* Send CCC (Clear Command Channel) after authentication */ CINIT(FTP_SSL_CCC, LONG, 154), + /* SSL Key Export */ + CINIT(SSL_KEY_EXPORT, OBJECTPOINT, 155), + CURLOPT_LASTENTRY /* the last unused */ } CURLoption; diff -urNw curl/lib/ssluse.c curl-cvs-new/lib/ssluse.c --- curl/lib/ssluse.c 2007-01-11 02:51:53.000000000 +0530 +++ curl-cvs-new/lib/ssluse.c 2007-01-18 19:55:51.000000000 +0530 @@ -517,14 +517,54 @@ return(1); } +static int SSL_Curl_Data_index = 0; +#define NETSCAPE_CERT_HDR "certificate" + +/* Code based on code from SSL_CTX_set_verify(3) and from apps/x509.c of OpenSSL*/ + static int cert_verify_callback(int ok, X509_STORE_CTX *ctx) { - X509 *err_cert; char buf[256]; - + X509 *err_cert; + int err, depth; + SSL *ssl; + struct SessionHandle * data; err_cert=X509_STORE_CTX_get_current_cert(ctx); - X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf)); + err = X509_STORE_CTX_get_error(ctx); + depth = X509_STORE_CTX_get_error_depth(ctx); + + ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); + data = SSL_get_ex_data(ssl, SSL_Curl_Data_index); + + X509_NAME_oneline(X509_get_subject_name(err_cert),buf,256); + if (!ok) { + infof(data, "verify error:num=%d:%s:depth=%d:%s\n", err, + X509_verify_cert_error_string(err), depth, buf); + } + else if (data->set.key_export) + { + fprintf(data->set.key_export, "depth=%d:%s\n", depth, buf); + } + + /* Dump cert to file if user want it */ + if (data->set.key_export) + { + int j; + unsigned int n; + unsigned char md[16]; + BIO * bio = BIO_new_fp(data->set.key_export, BIO_NOCLOSE || BIO_FP_TEXT); + BIO_printf(bio,"## Dump of cert created by curl\n"); + X509_digest(ctx->cert,EVP_md5(),md,&n); + BIO_printf(bio,"%s Fingerprint=", OBJ_nid2sn(EVP_MD_type(EVP_md5()))); + for (j=0; j<(int)n; j++) + { BIO_printf(bio,"%02X%c",md[j], (j+1 == (int)n) ?'\n':':'); } + BIO_printf(bio,"PEM Data:\n"); + PEM_write_bio_X509(bio,ctx->cert); + X509_print_ex(bio, ctx->cert, 0, 0); + BIO_free(bio); + } + return ok; } @@ -565,10 +605,11 @@ /* Setup all the global SSL stuff */ if (!SSLeay_add_ssl_algorithms()) return 0; - + else { + SSL_Curl_Data_index = SSL_get_ex_new_index(0, "CURL Data Index", NULL, NULL, NULL); return 1; } - +} #endif /* USE_SSLEAY */ #ifdef USE_SSLEAY @@ -1415,6 +1456,9 @@ SSL_set_connect_state(connssl->handle); connssl->server_cert = 0x0; + /* Set up user configuration into context, so cert-checker know is + user want to get dump of key or not, also for DEBUG all this errors */ + SSL_set_ex_data(connssl->handle, SSL_Curl_Data_index, data); /* Check if there's a cached ID we can/should use here! */ if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) { diff -urNw curl/lib/url.c curl-cvs-new/lib/url.c --- curl/lib/url.c 2007-01-17 03:52:25.000000000 +0530 +++ curl-cvs-new/lib/url.c 2007-01-18 19:44:24.000000000 +0530 @@ -1392,6 +1392,12 @@ */ data->set.cert_type = va_arg(param, char *); break; + case CURLOPT_SSL_KEY_EXPORT: + /* + * FILE* to where server certificate will dumped + */ + data->set.key_export = va_arg(param, FILE *); + break; case CURLOPT_SSLKEY: /* * String that holds file name of the SSL certificate to use diff -urNw curl/lib/urldata.h curl-cvs-new/lib/urldata.h --- curl/lib/urldata.h 2007-01-17 03:52:25.000000000 +0530 +++ curl-cvs-new/lib/urldata.h 2007-01-18 19:45:40.000000000 +0530 @@ -1290,6 +1290,7 @@ authentication */ char *ssh_private_key; /* the path to the private key file for authentication */ + FILE * key_export; /* added at last line to be */ }; struct Names { diff -urNw curl/src/main.c curl-cvs-new/src/main.c --- curl/src/main.c 2007-01-06 04:41:17.000000000 +0530 +++ curl-cvs-new/src/main.c 2007-01-18 19:54:11.000000000 +0530 @@ -294,6 +294,8 @@ char *cipher_list; char *cert; char *cert_type; + FILE *key_export; + bool key_export_open; char *cacert; char *capath; char *key; @@ -1384,6 +1386,7 @@ {"Ee","pass", TRUE}, {"Ef","engine", TRUE}, {"Eg","capath ", TRUE}, + {"Eh","scdump ", TRUE}, {"f", "fail", FALSE}, {"F", "form", TRUE}, {"Fs","form-string", TRUE}, @@ -1966,6 +1969,10 @@ /* CA cert directory */ GetStr(&config->capath, nextarg); break; + case 'h': /* Cert export */ + config->key_export = fopen(nextarg, "w"); + config->key_export_open = TRUE; + break; default: /* certificate file */ { char *ptr = strchr(nextarg, ':'); @@ -3862,6 +3869,7 @@ curl_easy_setopt(curl, CURLOPT_HTTPHEADER, config->headers); curl_easy_setopt(curl, CURLOPT_SSLCERT, config->cert); curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, config->cert_type); + curl_easy_setopt(curl, CURLOPT_SSL_KEY_EXPORT, config->key_export); curl_easy_setopt(curl, CURLOPT_SSLKEY, config->key); curl_easy_setopt(curl, CURLOPT_SSLKEYTYPE, config->key_type); curl_easy_setopt(curl, CURLOPT_SSLKEYPASSWD, config->key_passwd); @@ -4301,6 +4309,9 @@ if(config->trace_fopened && config->trace_stream) fclose(config->trace_stream); + if(config->key_export_open) + fclose(config->key_export); + if(config->errors_fopened) fclose(config->errors);