mirror of https://github.com/aria2/aria2
Teach Libssl backend to load .p12 files
parent
08e2e412dc
commit
f7b0fbbf53
|
@ -34,12 +34,30 @@
|
||||||
/* copyright --> */
|
/* copyright --> */
|
||||||
#include "LibsslTLSContext.h"
|
#include "LibsslTLSContext.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
|
#include <openssl/pkcs12.h>
|
||||||
|
#include <openssl/bio.h>
|
||||||
|
|
||||||
#include "LogFactory.h"
|
#include "LogFactory.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include "fmt.h"
|
#include "fmt.h"
|
||||||
#include "message.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 {
|
namespace aria2 {
|
||||||
|
|
||||||
|
@ -88,6 +106,9 @@ bool OpenSSLTLSContext::good() const
|
||||||
bool OpenSSLTLSContext::addCredentialFile(const std::string& certfile,
|
bool OpenSSLTLSContext::addCredentialFile(const std::string& certfile,
|
||||||
const std::string& keyfile)
|
const std::string& keyfile)
|
||||||
{
|
{
|
||||||
|
if (keyfile.empty()) {
|
||||||
|
return addP12CredentialFile(certfile);
|
||||||
|
}
|
||||||
if(SSL_CTX_use_PrivateKey_file(sslCtx_, keyfile.c_str(),
|
if(SSL_CTX_use_PrivateKey_file(sslCtx_, keyfile.c_str(),
|
||||||
SSL_FILETYPE_PEM) != 1) {
|
SSL_FILETYPE_PEM) != 1) {
|
||||||
A2_LOG_ERROR(fmt("Failed to load private key from %s. Cause: %s",
|
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()));
|
keyfile.c_str()));
|
||||||
return true;
|
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()
|
bool OpenSSLTLSContext::addSystemTrustedCACerts()
|
||||||
{
|
{
|
||||||
|
|
|
@ -55,6 +55,7 @@ public:
|
||||||
// private key `keyfile' must be decrypted.
|
// private key `keyfile' must be decrypted.
|
||||||
virtual bool addCredentialFile(const std::string& certfile,
|
virtual bool addCredentialFile(const std::string& certfile,
|
||||||
const std::string& keyfile) CXX11_OVERRIDE;
|
const std::string& keyfile) CXX11_OVERRIDE;
|
||||||
|
virtual bool addP12CredentialFile(const std::string& p12file);
|
||||||
|
|
||||||
virtual bool addSystemTrustedCACerts() CXX11_OVERRIDE;
|
virtual bool addSystemTrustedCACerts() CXX11_OVERRIDE;
|
||||||
|
|
||||||
|
|
|
@ -181,11 +181,7 @@ int MultiUrlRequestInfo::prepare()
|
||||||
#ifdef ENABLE_SSL
|
#ifdef ENABLE_SSL
|
||||||
if(option_->getAsBool(PREF_ENABLE_RPC) &&
|
if(option_->getAsBool(PREF_ENABLE_RPC) &&
|
||||||
option_->getAsBool(PREF_RPC_SECURE)) {
|
option_->getAsBool(PREF_RPC_SECURE)) {
|
||||||
if(option_->blank(PREF_RPC_CERTIFICATE)
|
if(option_->blank(PREF_RPC_CERTIFICATE)) {
|
||||||
#ifndef HAVE_APPLETLS
|
|
||||||
|| option_->blank(PREF_RPC_PRIVATE_KEY)
|
|
||||||
#endif // HAVE_APPLETLS
|
|
||||||
) {
|
|
||||||
throw DL_ABORT_EX("Specify --rpc-certificate and --rpc-private-key "
|
throw DL_ABORT_EX("Specify --rpc-certificate and --rpc-private-key "
|
||||||
"options in order to use secure RPC.");
|
"options in order to use secure RPC.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -792,20 +792,10 @@ std::vector<OptionHandler*> OptionHandlerFactory::createOptionHandlers()
|
||||||
handlers.push_back(op);
|
handlers.push_back(op);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
OptionHandler* op(
|
OptionHandler* op(new DefaultOptionHandler
|
||||||
#ifdef HAVE_APPLETLS
|
|
||||||
new DefaultOptionHandler
|
|
||||||
(PREF_RPC_CERTIFICATE,
|
(PREF_RPC_CERTIFICATE,
|
||||||
TEXT_RPC_CERTIFICATE,
|
TEXT_RPC_CERTIFICATE,
|
||||||
NO_DEFAULT_VALUE)
|
NO_DEFAULT_VALUE));
|
||||||
#else // HAVE_APPLETLS
|
|
||||||
new LocalFilePathOptionHandler
|
|
||||||
(PREF_RPC_CERTIFICATE,
|
|
||||||
TEXT_RPC_CERTIFICATE,
|
|
||||||
NO_DEFAULT_VALUE,
|
|
||||||
false)
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
op->addTag(TAG_RPC);
|
op->addTag(TAG_RPC);
|
||||||
handlers.push_back(op);
|
handlers.push_back(op);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue