I hereby release my patches to stunnel for support of PKCS12 files into the public domain.
---------- Forwarded message ---------- From: Dmitry Bakshaev <dab1...@gmail.com> Date: 2016-05-18 20:26 GMT+04:00 Subject: PKCS12 support patch To: stunnel-users@stunnel.org googling internet about using certificate and keys from PKCS12 file lead to convert it to PEM. it requires some additional utilities (openssl not default windows application) and manual steps to convert. this patch allow using PKCS12 directly from stunnel. example configuration: cert = /home/dab/.certs/my.p12 PKCS12-files detected by file extension (.p12 or .pfx, no case sensetive) and load specially. password prompted if needed, empty password also supported. code based on examples from: https://groups.google.com/forum/#!topic/mailing.openssl.users/iuBmSqwsIG4 http://openssl-users.openssl.narkive.com/J0bR3cMA/ssl-ctx-use-privatekey-file patch tested on stunnel working on linux (gentoo: from our overlay http://bbgentoo.ilb.ru/repos/bbgentoo/bbgentoo_overlay/branches/drafts/net-misc/stunnel/ ) and windows.
--- stunnel-5.32/src/ctx.c.orig 2016-05-03 22:35:03.000000000 +0400 +++ stunnel-5.32/src/ctx.c 2016-05-17 21:17:45.835316702 +0400 @@ -37,6 +37,7 @@ #include "common.h" #include "prototypes.h" +#include <openssl/pkcs12.h> #ifndef OPENSSL_NO_DH DH *dh_params=NULL; @@ -73,6 +74,7 @@ #endif /* !defined(OPENSSL_NO_PSK) */ NOEXPORT int load_cert_file(SERVICE_OPTIONS *); NOEXPORT int load_key_file(SERVICE_OPTIONS *); +NOEXPORT int load_pkcs12_file(SERVICE_OPTIONS *); #ifndef OPENSSL_NO_ENGINE NOEXPORT int load_cert_engine(SERVICE_OPTIONS *); NOEXPORT int load_key_engine(SERVICE_OPTIONS *); @@ -430,6 +432,7 @@ NOEXPORT int auth_init(SERVICE_OPTIONS *section) { int cert_needed=1, key_needed=1; + char *ext; #ifndef OPENSSL_NO_PSK if(section->psk_keys) { @@ -451,6 +454,16 @@ key_needed=load_key_engine(section); } #endif + /* check file type(extension): is PKCS12? */ + if (cert_needed && (ext = strrchr(section->cert, '.')) != NULL && + (!strcasecmp(ext+1, "p12") || !strcasecmp(ext+1, "pfx"))) { + if (load_pkcs12_file(section)) { + return 1; /* FAILED */ + } + /* don't load any PEM files */ + cert_needed=key_needed=0; + } + if(cert_needed && load_cert_file(section)) return 1; /* FAILED */ if(key_needed && load_key_file(section)) @@ -617,6 +630,67 @@ return 0; /* OK */ } +NOEXPORT int load_pkcs12_file(SERVICE_OPTIONS *section) { + int i, reason; + UI_DATA ui_data; + + BIO *bio = NULL; + PKCS12 *p12 = NULL; + X509 * cert = NULL; + STACK_OF(X509) * ca = NULL; + EVP_PKEY * pkey = NULL; + char pass[PEM_BUFSIZE]; + + s_log(LOG_INFO, "Loading private key and certificate from file: %s", section->key); + if(file_permissions(section->key)) + return 1; /* FAILED */ + + ui_data.section=section; /* setup current section for callbacks */ + + if (!(bio = BIO_new_file(section->key, "rb"))) { + sslerror("BIO_new_file"); + return 1; /* FAILED */ + } + if (!(p12 = d2i_PKCS12_bio(bio, NULL))) { + sslerror("d2i_PKCS12_bio"); + return 1; /* FAILED */ + } + BIO_free(bio); + + for(i=0; i<=3; i++) { + if(!i && !cache_initialized) + continue; /* there is no cached value */ + /* try empty password */ + if(i==1 && PKCS12_parse(p12, "", &pkey, &cert, &ca)) + break; + /* try the cached password first */ + password_cb(pass, PEM_BUFSIZE, 0, (i ? (void *)&ui_data : NULL)); + if(PKCS12_parse(p12, pass, &pkey, &cert, &ca)) + break; + reason=ERR_GET_REASON(ERR_peek_error()); + if(i<=2 && reason==PKCS12_R_MAC_VERIFY_FAILURE) { + sslerror_queue(); /* dump the error queue */ + s_log(LOG_ERR, "Wrong pass phrase: retrying"); + continue; + } + sslerror("PKCS12_parse"); + return 1; /* FAILED */ + } + PKCS12_free(p12); + + if (!SSL_CTX_use_certificate(section->ctx, cert)) { + sslerror("SSL_CTX_use_certificate"); + return 1; /* FAILED */ + } + if (!SSL_CTX_use_PrivateKey(section->ctx, pkey)) { + sslerror("SSL_CTX_use_PrivateKey"); + return 1; /* FAILED */ + } + + s_log(LOG_INFO, "Private key and certificate loaded from file: %s", section->key); + return 0; /* OK */ +} + #ifndef OPENSSL_NO_ENGINE NOEXPORT int load_cert_engine(SERVICE_OPTIONS *section) {
_______________________________________________ stunnel-users mailing list stunnel-users@stunnel.org https://www.stunnel.org/cgi-bin/mailman/listinfo/stunnel-users