diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/ssluse.c | 74 |
1 files changed, 74 insertions, 0 deletions
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 <openssl/pkcs12.h> +#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; |