diff --git a/CHANGES b/CHANGES index f72103274..700b02b63 100644 --- a/CHANGES +++ b/CHANGES @@ -7,6 +7,11 @@ Changelog +Daniel (18 December 2004) +- Samuel Listopad added support for PKCS12 formatted certificates. + +- Samuel Listopad fixed -E to support "C:/path" (with forward slash) as well. + Daniel (16 December 2004) - Gisle found and fixed a problem in the directory re-use for FTP. diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 2c00be14a..ec8f7c4f9 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -10,6 +10,7 @@ Curl and libcurl 7.12.3 This release includes the following changes: + o PKCS12 certificate support added o added CURLINFO_SSL_ENGINES (and "--engine list") o new configure options: --disable-cookies, --disable-crypto-auth and --disable-verbose @@ -26,6 +27,7 @@ This release includes the following changes: This release includes the following bugfixes: + o curl -E on windows accepts "c:/path" with forward-slash o various improvements for large file support on windows o file handle leak in aborted multipart formpost file upload o -T upload multiple files with backslashes in file names @@ -69,10 +71,11 @@ This release would not have looked like this without help, code, reports and advice from friends like these: Peter Wullinger, Guillaume Arluison, Alexander Krasnostavsky, Mohun Biswas, - Tomas Pospisek, Gisle Vanem, Dan Fandrich, Paul Nolan, Andres Garcia, - Tim Sneddon, Ian Gulliver, Jean-Philippe Barrette-LaPierre, Jeff Phillips, + Tomas Pospisek, Gisle Vanem, Dan Fandrich, Paul Nolan, Andres Garcia, Tim + Sneddon, Ian Gulliver, Jean-Philippe Barrette-LaPierre, Jeff Phillips, Wojciech Zwiefka, David Phillips, Reinout van Schouwen, Maurice Barnum, Richard Atterer, Rene Bernhardt, Matt Veenstra, Bryan Henderson, Ton Voon, - Kai Sommerfeld, David Byron, Harshal Pradhan, Tom Lee, Dinar + Kai Sommerfeld, David Byron, Harshal Pradhan, Tom Lee, Dinar, Jean-Marc + Ranger, Samuel Listopad Thanks! (and sorry if I forgot to mention someone) diff --git a/lib/ssluse.c b/lib/ssluse.c index 875f89a89..47ee042ab 100644 --- a/lib/ssluse.c +++ b/lib/ssluse.c @@ -90,6 +90,16 @@ #undef HAVE_ENGINE_LOAD_FOUR_ARGS #endif +#if OPENSSL_VERSION_NUMBER >= 0x00903001L +/* OpenSSL has PKCS 12 support */ +#define HAVE_PKCS12_SUPPORT +#include +#else +/* OpenSSL/SSLEay does not have PKCS12 support */ +#undef HAVE_PKCS12_SUPPORT +#endif + + #if OPENSSL_VERSION_NUMBER >= 0x00906001L #define HAVE_ERR_ERROR_STRING_N 1 #endif @@ -234,6 +244,9 @@ int random_the_seed(struct SessionHandle *data) #ifndef SSL_FILETYPE_ENGINE #define SSL_FILETYPE_ENGINE 42 #endif +#ifndef SSL_FILETYPE_PKCS12 +#define SSL_FILETYPE_PKCS12 43 +#endif static int do_file_type(const char *type) { if(!type || !type[0]) @@ -244,6 +257,8 @@ static int do_file_type(const char *type) return SSL_FILETYPE_ASN1; if(curl_strequal(type, "ENG")) return SSL_FILETYPE_ENGINE; + if(curl_strequal(type, "P12")) + return SSL_FILETYPE_PKCS12; return -1; } @@ -261,6 +276,7 @@ int cert_stuff(struct connectdata *conn, if(cert_file != NULL) { SSL *ssl; X509 *x509; + int cert_done = 0; if(data->set.key_passwd) { #ifndef HAVE_USERDATA_IN_PWD_CALLBACK @@ -312,6 +328,56 @@ int cert_stuff(struct connectdata *conn, failf(data, "file type ENG for certificate not implemented"); return 0; + case SSL_FILETYPE_PKCS12: + { +#ifdef HAVE_PKCS12_SUPPORT + FILE *f; + PKCS12 *p12; + EVP_PKEY *pri; + + f = fopen(cert_file,"rb"); + if (!f) { + failf(data, "could not open PKCS12 file '%s'", cert_file); + return 0; + } + p12 = d2i_PKCS12_fp(f, NULL); + fclose(f); + + PKCS12_PBE_add(); + + if (!PKCS12_parse(p12, data->set.key_passwd, &pri, &x509, NULL)) { + failf(data, + "could not parse PKCS12 file, check password, OpenSSL error %s", + ERR_error_string(ERR_get_error(), NULL) ); + return 0; + } + + PKCS12_free(p12); + + if(SSL_CTX_use_certificate(ctx, x509) != 1) { + failf(data, SSL_CLIENT_CERT_ERR); + EVP_PKEY_free(pri); + X509_free(x509); + return 0; + } + + if(SSL_CTX_use_PrivateKey(ctx, pri) != 1) { + failf(data, "unable to use private key from PKCS12 file '%s'", + cert_file); + EVP_PKEY_free(pri); + X509_free(x509); + return 0; + } + + EVP_PKEY_free(pri); + X509_free(x509); + cert_done = 1; + break; +#else + failf(data, "file type P12 for certificate not supported"); + return 0; +#endif + } default: failf(data, "not supported file type '%s' for certificate", cert_type); return 0; @@ -321,6 +387,8 @@ int cert_stuff(struct connectdata *conn, switch(file_type) { case SSL_FILETYPE_PEM: + if(cert_done) + break; if(key_file == NULL) /* cert & key can only be in PEM case in the same file */ key_file=cert_file; @@ -371,6 +439,12 @@ int cert_stuff(struct connectdata *conn, failf(data, "file type ENG for private key not supported\n"); return 0; #endif + case SSL_FILETYPE_PKCS12: + if(!cert_done) { + failf(data, "file type P12 for private key not supported\n"); + return 0; + } + break; default: failf(data, "not supported file type for private key\n"); return 0;