summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNils Maier <maierman@web.de>2013-09-22 12:14:51 +0200
committerNils Maier <maierman@web.de>2013-09-22 12:55:27 +0200
commitf7b0fbbf532bdce896b1f2a1bdf3bdd0acdb88e6 (patch)
tree5cfb133a1f8f085ee095c2fe131bd54b90cb1a80
parent08e2e412dc562513d48900c071707a3cccb9c22f (diff)
Teach Libssl backend to load .p12 files
-rw-r--r--src/LibsslTLSContext.cc92
-rw-r--r--src/LibsslTLSContext.h1
-rw-r--r--src/MultiUrlRequestInfo.cc6
-rw-r--r--src/OptionHandlerFactory.cc14
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);
}