diff options
| author | Nils Maier <maierman@web.de> | 2013-09-22 12:14:51 +0200 |
|---|---|---|
| committer | Nils Maier <maierman@web.de> | 2013-09-22 12:55:27 +0200 |
| commit | f7b0fbbf532bdce896b1f2a1bdf3bdd0acdb88e6 (patch) | |
| tree | 5cfb133a1f8f085ee095c2fe131bd54b90cb1a80 | |
| parent | 08e2e412dc562513d48900c071707a3cccb9c22f (diff) | |
Teach Libssl backend to load .p12 files
| -rw-r--r-- | src/LibsslTLSContext.cc | 92 | ||||
| -rw-r--r-- | src/LibsslTLSContext.h | 1 | ||||
| -rw-r--r-- | src/MultiUrlRequestInfo.cc | 6 | ||||
| -rw-r--r-- | src/OptionHandlerFactory.cc | 14 |
4 files changed, 96 insertions, 17 deletions
diff --git a/src/LibsslTLSContext.cc b/src/LibsslTLSContext.cc index c0507227..6f59a5d4 100644 --- a/src/LibsslTLSContext.cc +++ b/src/LibsslTLSContext.cc @@ -34,12 +34,30 @@ /* copyright --> */ #include "LibsslTLSContext.h" +#include <sstream> + #include <openssl/err.h> +#include <openssl/pkcs12.h> +#include <openssl/bio.h> #include "LogFactory.h" #include "Logger.h" #include "fmt.h" #include "message.h" +#include "BufferedFile.h" + +namespace { + struct bio_deleter { + void operator()(BIO *b) { + if (b) BIO_free(b); + } + }; + struct p12_deleter { + void operator()(PKCS12 *p) { + if (p) PKCS12_free(p); + } + }; +} // namespace namespace aria2 { @@ -88,6 +106,9 @@ bool OpenSSLTLSContext::good() const bool OpenSSLTLSContext::addCredentialFile(const std::string& certfile, const std::string& keyfile) { + if (keyfile.empty()) { + return addP12CredentialFile(certfile); + } if(SSL_CTX_use_PrivateKey_file(sslCtx_, keyfile.c_str(), SSL_FILETYPE_PEM) != 1) { A2_LOG_ERROR(fmt("Failed to load private key from %s. Cause: %s", @@ -106,6 +127,77 @@ bool OpenSSLTLSContext::addCredentialFile(const std::string& certfile, keyfile.c_str())); return true; } +bool OpenSSLTLSContext::addP12CredentialFile(const std::string& p12file) +{ + // Need this to "decrypt" p12 files. + OpenSSL_add_all_algorithms(); + + std::stringstream ss; + BufferedFile(p12file.c_str(), "rb").transfer(ss); + + void *ptr = const_cast<char*>(ss.str().c_str()); + size_t len = ss.str().length(); + std::unique_ptr<BIO, bio_deleter> bio(BIO_new_mem_buf(ptr, len)); + A2_LOG_DEBUG(fmt("p12 size: %" PRIu64, len)); + + if (!bio) { + A2_LOG_ERROR("Failed to open p12 file: no memory"); + return false; + } + std::unique_ptr<PKCS12, p12_deleter> p12(d2i_PKCS12_bio(bio.get(), nullptr)); + if (!p12) { + A2_LOG_ERROR(fmt("Failed to open p12 file: %s", + ERR_error_string(ERR_get_error(), nullptr))); + return false; + } + EVP_PKEY *pkey; + X509 *cert; + STACK_OF(X509) *ca = 0; + if (!PKCS12_parse(p12.get(), "", &pkey, &cert, &ca)) { + A2_LOG_ERROR(fmt("Failed to parse p12 file: %s", + ERR_error_string(ERR_get_error(), nullptr))); + return false; + } + + bool rv = false; + if (pkey && cert) { + rv = SSL_CTX_use_PrivateKey(sslCtx_, pkey); + if (!rv) { + A2_LOG_ERROR(fmt("Failed to use p12 file pkey: %s", + ERR_error_string(ERR_get_error(), nullptr))); + } + if (rv) { + rv = SSL_CTX_use_certificate(sslCtx_, cert); + if (!rv) { + A2_LOG_ERROR(fmt("Failed to use p12 file cert: %s", + ERR_error_string(ERR_get_error(), nullptr))); + } + } + if (rv && ca && sk_X509_num(ca)) { + rv = SSL_CTX_add_extra_chain_cert(sslCtx_, ca); + if (!rv) { + A2_LOG_ERROR(fmt("Failed to use p12 file chain: %s", + ERR_error_string(ERR_get_error(), nullptr))); + } + } + } + else { + A2_LOG_ERROR(fmt("Failed to use p12 file: no pkey or cert %s", + ERR_error_string(ERR_get_error(), nullptr))); + } + if (pkey) EVP_PKEY_free(pkey); + if (cert) X509_free(cert); + if (ca) sk_X509_pop_free(ca, X509_free); + + if (!rv) { + A2_LOG_ERROR(fmt("Failed to use p12 file: %s", + ERR_error_string(ERR_get_error(), nullptr))); + } + else { + A2_LOG_INFO("Using certificate and key from p12 file"); + } + return rv; +} bool OpenSSLTLSContext::addSystemTrustedCACerts() { diff --git a/src/LibsslTLSContext.h b/src/LibsslTLSContext.h index 9462cbb9..326f6a63 100644 --- a/src/LibsslTLSContext.h +++ b/src/LibsslTLSContext.h @@ -55,6 +55,7 @@ public: // private key `keyfile' must be decrypted. virtual bool addCredentialFile(const std::string& certfile, const std::string& keyfile) CXX11_OVERRIDE; + virtual bool addP12CredentialFile(const std::string& p12file); virtual bool addSystemTrustedCACerts() CXX11_OVERRIDE; diff --git a/src/MultiUrlRequestInfo.cc b/src/MultiUrlRequestInfo.cc index 8347e331..6e5edd37 100644 --- a/src/MultiUrlRequestInfo.cc +++ b/src/MultiUrlRequestInfo.cc @@ -181,11 +181,7 @@ int MultiUrlRequestInfo::prepare() #ifdef ENABLE_SSL if(option_->getAsBool(PREF_ENABLE_RPC) && option_->getAsBool(PREF_RPC_SECURE)) { - if(option_->blank(PREF_RPC_CERTIFICATE) -#ifndef HAVE_APPLETLS - || option_->blank(PREF_RPC_PRIVATE_KEY) -#endif // HAVE_APPLETLS - ) { + if(option_->blank(PREF_RPC_CERTIFICATE)) { throw DL_ABORT_EX("Specify --rpc-certificate and --rpc-private-key " "options in order to use secure RPC."); } diff --git a/src/OptionHandlerFactory.cc b/src/OptionHandlerFactory.cc index 71c760ff..33e749db 100644 --- a/src/OptionHandlerFactory.cc +++ b/src/OptionHandlerFactory.cc @@ -792,20 +792,10 @@ std::vector<OptionHandler*> OptionHandlerFactory::createOptionHandlers() handlers.push_back(op); } { - OptionHandler* op( -#ifdef HAVE_APPLETLS - new DefaultOptionHandler - (PREF_RPC_CERTIFICATE, - TEXT_RPC_CERTIFICATE, - NO_DEFAULT_VALUE) -#else // HAVE_APPLETLS - new LocalFilePathOptionHandler + OptionHandler* op(new DefaultOptionHandler (PREF_RPC_CERTIFICATE, TEXT_RPC_CERTIFICATE, - NO_DEFAULT_VALUE, - false) -#endif - ); + NO_DEFAULT_VALUE)); op->addTag(TAG_RPC); handlers.push_back(op); } |
