mirror of
https://github.com/OpenVPN/openvpn3.git
synced 2024-09-20 12:12:15 +02:00
OpenSSL PKI cleanup
* Added C++11 features such as move constructor and move assignment method. * Since these classes are already object wrappers, it's redundant to manage them via RC. * Use the "::" prefix to denote OpenSSL symbols from the top-level namespace. Signed-off-by: James Yonan <james@openvpn.net>
This commit is contained in:
parent
d5eb77c53c
commit
95e761f3cc
@ -21,8 +21,7 @@
|
||||
|
||||
// Wrap an OpenSSL X509_CRL object
|
||||
|
||||
#ifndef OPENVPN_OPENSSL_PKI_CRL_H
|
||||
#define OPENVPN_OPENSSL_PKI_CRL_H
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@ -32,16 +31,18 @@
|
||||
|
||||
#include <openvpn/common/size.hpp>
|
||||
#include <openvpn/common/exception.hpp>
|
||||
#include <openvpn/common/rc.hpp>
|
||||
#include <openvpn/openssl/util/error.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
namespace OpenSSLPKI {
|
||||
|
||||
class CRL : public RC<thread_unsafe_refcount>
|
||||
class CRL
|
||||
{
|
||||
public:
|
||||
CRL() : crl_(nullptr) {}
|
||||
CRL()
|
||||
: crl_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
explicit CRL(const std::string& crl_txt)
|
||||
: crl_(nullptr)
|
||||
@ -50,27 +51,48 @@ namespace openvpn {
|
||||
}
|
||||
|
||||
CRL(const CRL& other)
|
||||
: crl_(nullptr)
|
||||
: crl_(dup(other.crl_))
|
||||
{
|
||||
assign(other.crl_);
|
||||
}
|
||||
|
||||
void operator=(const CRL& other)
|
||||
CRL(CRL&& other) noexcept
|
||||
: crl_(other.crl_)
|
||||
{
|
||||
assign(other.crl_);
|
||||
other.crl_ = nullptr;
|
||||
}
|
||||
|
||||
CRL& operator=(const CRL& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
erase();
|
||||
crl_ = dup(other.crl_);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
CRL& operator=(CRL&& other) noexcept
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
erase();
|
||||
crl_ = other.crl_;
|
||||
other.crl_ = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool defined() const { return crl_ != nullptr; }
|
||||
X509_CRL* obj() const { return crl_; }
|
||||
::X509_CRL* obj() const { return crl_; }
|
||||
|
||||
void parse_pem(const std::string& crl_txt)
|
||||
{
|
||||
BIO *bio = BIO_new_mem_buf(const_cast<char *>(crl_txt.c_str()), crl_txt.length());
|
||||
BIO *bio = ::BIO_new_mem_buf(const_cast<char *>(crl_txt.c_str()), crl_txt.length());
|
||||
if (!bio)
|
||||
throw OpenSSLException();
|
||||
|
||||
X509_CRL *crl = PEM_read_bio_X509_CRL(bio, nullptr, nullptr, nullptr);
|
||||
BIO_free(bio);
|
||||
::X509_CRL *crl = ::PEM_read_bio_X509_CRL(bio, nullptr, nullptr, nullptr);
|
||||
::BIO_free(bio);
|
||||
if (!crl)
|
||||
throw OpenSSLException("CRL::parse_pem");
|
||||
|
||||
@ -82,19 +104,19 @@ namespace openvpn {
|
||||
{
|
||||
if (crl_)
|
||||
{
|
||||
BIO *bio = BIO_new(BIO_s_mem());
|
||||
const int ret = PEM_write_bio_X509_CRL(bio, crl_);
|
||||
BIO *bio = ::BIO_new(BIO_s_mem());
|
||||
const int ret = ::PEM_write_bio_X509_CRL(bio, crl_);
|
||||
if (ret == 0)
|
||||
{
|
||||
BIO_free(bio);
|
||||
::BIO_free(bio);
|
||||
throw OpenSSLException("CRL::render_pem");
|
||||
}
|
||||
|
||||
{
|
||||
char *temp;
|
||||
const int buf_len = BIO_get_mem_data(bio, &temp);
|
||||
const int buf_len = ::BIO_get_mem_data(bio, &temp);
|
||||
std::string ret = std::string(temp, buf_len);
|
||||
BIO_free(bio);
|
||||
::BIO_free(bio);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@ -102,59 +124,46 @@ namespace openvpn {
|
||||
return "";
|
||||
}
|
||||
|
||||
void erase()
|
||||
{
|
||||
if (crl_)
|
||||
{
|
||||
X509_CRL_free(crl_);
|
||||
crl_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
~CRL()
|
||||
{
|
||||
erase();
|
||||
}
|
||||
|
||||
private:
|
||||
void erase()
|
||||
{
|
||||
if (crl_)
|
||||
::X509_CRL_free(crl_);
|
||||
}
|
||||
|
||||
static X509_CRL *dup(const X509_CRL *crl)
|
||||
{
|
||||
if (crl)
|
||||
{
|
||||
return X509_CRL_dup(const_cast<X509_CRL *>(crl));
|
||||
}
|
||||
return ::X509_CRL_dup(const_cast<X509_CRL *>(crl));
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void assign(const X509_CRL *crl)
|
||||
{
|
||||
erase();
|
||||
crl_ = dup(crl);
|
||||
}
|
||||
|
||||
X509_CRL *crl_;
|
||||
::X509_CRL *crl_;
|
||||
};
|
||||
|
||||
typedef RCPtr<CRL> CRLPtr;
|
||||
|
||||
class CRLList : public std::vector<CRLPtr>
|
||||
class CRLList : public std::vector<CRL>
|
||||
{
|
||||
public:
|
||||
typedef CRL Item;
|
||||
typedef CRLPtr ItemPtr;
|
||||
typedef X509 CRL;
|
||||
|
||||
bool defined() const { return !empty(); }
|
||||
bool defined() const
|
||||
{
|
||||
return !empty();
|
||||
}
|
||||
|
||||
std::string render_pem() const
|
||||
{
|
||||
std::string ret;
|
||||
for (const_iterator i = begin(); i != end(); ++i)
|
||||
ret += (*i)->render_pem();
|
||||
for (const auto &e : *this)
|
||||
ret += e.render_pem();
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
}
|
||||
} // namespace openvpn
|
||||
|
||||
#endif // OPENVPN_OPENSSL_PKI_CRL_H
|
||||
}
|
||||
|
@ -21,8 +21,7 @@
|
||||
|
||||
// Wrap an OpenSSL DH object
|
||||
|
||||
#ifndef OPENVPN_OPENSSL_PKI_DH_H
|
||||
#define OPENVPN_OPENSSL_PKI_DH_H
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
@ -57,7 +56,10 @@ namespace openvpn {
|
||||
class DH
|
||||
{
|
||||
public:
|
||||
DH() : dh_(nullptr) {}
|
||||
DH()
|
||||
: dh_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
explicit DH(const std::string& dh_txt)
|
||||
: dh_(nullptr)
|
||||
@ -66,15 +68,34 @@ namespace openvpn {
|
||||
}
|
||||
|
||||
DH(const DH& other)
|
||||
: dh_(nullptr)
|
||||
{
|
||||
dup(other.dh_);
|
||||
}
|
||||
|
||||
DH(DH&& other) noexcept
|
||||
: dh_(other.dh_)
|
||||
{
|
||||
other.dh_ = nullptr;
|
||||
}
|
||||
|
||||
void operator=(const DH& other)
|
||||
{
|
||||
erase();
|
||||
dup(other.dh_);
|
||||
if (this != &other)
|
||||
{
|
||||
erase();
|
||||
dup(other.dh_);
|
||||
}
|
||||
}
|
||||
|
||||
DH& operator=(DH&& other) noexcept
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
erase();
|
||||
dh_ = other.dh_;
|
||||
other.dh_ = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool defined() const { return dh_ != nullptr; }
|
||||
@ -82,12 +103,12 @@ namespace openvpn {
|
||||
|
||||
void parse_pem(const std::string& dh_txt)
|
||||
{
|
||||
BIO *bio = BIO_new_mem_buf(const_cast<char *>(dh_txt.c_str()), dh_txt.length());
|
||||
BIO *bio = ::BIO_new_mem_buf(const_cast<char *>(dh_txt.c_str()), dh_txt.length());
|
||||
if (!bio)
|
||||
throw OpenSSLException();
|
||||
|
||||
::DH *dh = PEM_read_bio_DHparams(bio, nullptr, nullptr, nullptr);
|
||||
BIO_free(bio);
|
||||
::DH *dh = ::PEM_read_bio_DHparams(bio, nullptr, nullptr, nullptr);
|
||||
::BIO_free(bio);
|
||||
if (!dh)
|
||||
throw OpenSSLException("DH::parse_pem");
|
||||
|
||||
@ -99,19 +120,19 @@ namespace openvpn {
|
||||
{
|
||||
if (dh_)
|
||||
{
|
||||
BIO *bio = BIO_new(BIO_s_mem());
|
||||
const int ret = PEM_write_bio_DHparams(bio, dh_);
|
||||
BIO *bio = ::BIO_new(BIO_s_mem());
|
||||
const int ret = ::PEM_write_bio_DHparams(bio, dh_);
|
||||
if (ret == 0)
|
||||
{
|
||||
BIO_free(bio);
|
||||
::BIO_free(bio);
|
||||
throw OpenSSLException("DH::render_pem");
|
||||
}
|
||||
|
||||
{
|
||||
char *temp;
|
||||
const int buf_len = BIO_get_mem_data(bio, &temp);
|
||||
const int buf_len = ::BIO_get_mem_data(bio, &temp);
|
||||
std::string ret = std::string(temp, buf_len);
|
||||
BIO_free(bio);
|
||||
::BIO_free(bio);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@ -119,21 +140,18 @@ namespace openvpn {
|
||||
return "";
|
||||
}
|
||||
|
||||
void erase()
|
||||
{
|
||||
if (dh_)
|
||||
{
|
||||
DH_free(dh_);
|
||||
dh_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
~DH()
|
||||
{
|
||||
erase();
|
||||
}
|
||||
|
||||
private:
|
||||
void erase()
|
||||
{
|
||||
if (dh_)
|
||||
::DH_free(dh_);
|
||||
}
|
||||
|
||||
void dup(const ::DH *dh)
|
||||
{
|
||||
dh_ = DH_private::dup(dh);
|
||||
@ -142,7 +160,4 @@ namespace openvpn {
|
||||
::DH *dh_;
|
||||
};
|
||||
}
|
||||
} // namespace openvpn
|
||||
|
||||
#endif // OPENVPN_OPENSSL_PKI_DH_H
|
||||
|
||||
}
|
||||
|
@ -21,10 +21,10 @@
|
||||
|
||||
// Wrap an OpenSSL EVP_PKEY object
|
||||
|
||||
#ifndef OPENVPN_OPENSSL_PKI_PKEY_H
|
||||
#define OPENVPN_OPENSSL_PKI_PKEY_H
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/bio.h>
|
||||
@ -32,6 +32,7 @@
|
||||
#include <openvpn/common/size.hpp>
|
||||
#include <openvpn/common/exception.hpp>
|
||||
#include <openvpn/openssl/util/error.hpp>
|
||||
#include <openvpn/pki/pktype.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
namespace OpenSSLPKI {
|
||||
@ -39,7 +40,10 @@ namespace openvpn {
|
||||
class PKey
|
||||
{
|
||||
public:
|
||||
PKey() : pkey_(nullptr) {}
|
||||
PKey()
|
||||
: pkey_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
PKey(const std::string& pkey_txt, const std::string& title)
|
||||
: pkey_(nullptr)
|
||||
@ -48,45 +52,69 @@ namespace openvpn {
|
||||
}
|
||||
|
||||
PKey(const PKey& other)
|
||||
: pkey_(nullptr)
|
||||
: pkey_(dup(other.pkey_)),
|
||||
priv_key_pwd(other.priv_key_pwd)
|
||||
{
|
||||
assign(other.pkey_);
|
||||
}
|
||||
|
||||
void operator=(const PKey& other)
|
||||
PKey(PKey&& other) noexcept
|
||||
: pkey_(other.pkey_),
|
||||
priv_key_pwd(std::move(other.priv_key_pwd))
|
||||
{
|
||||
assign(other.pkey_);
|
||||
priv_key_pwd = other.priv_key_pwd;
|
||||
other.pkey_ = nullptr;
|
||||
}
|
||||
|
||||
PKey& operator=(const PKey& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
erase();
|
||||
pkey_ = dup(other.pkey_);
|
||||
priv_key_pwd = other.priv_key_pwd;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
PKey& operator=(PKey&& other) noexcept
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
erase();
|
||||
pkey_ = other.pkey_;
|
||||
other.pkey_ = nullptr;
|
||||
priv_key_pwd = std::move(other.priv_key_pwd);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool defined() const { return pkey_ != nullptr; }
|
||||
EVP_PKEY* obj() const { return pkey_; }
|
||||
::EVP_PKEY* obj() const { return pkey_; }
|
||||
|
||||
SSLConfigAPI::PKType key_type() const
|
||||
PKType::Type key_type() const
|
||||
{
|
||||
switch (EVP_PKEY_id(pkey_))
|
||||
switch (::EVP_PKEY_id(pkey_))
|
||||
{
|
||||
case EVP_PKEY_RSA:
|
||||
case EVP_PKEY_RSA2:
|
||||
return SSLConfigAPI::PK_RSA;
|
||||
return PKType::PK_RSA;
|
||||
case EVP_PKEY_EC:
|
||||
return SSLConfigAPI::PK_EC;
|
||||
return PKType::PK_EC;
|
||||
case EVP_PKEY_DSA:
|
||||
case EVP_PKEY_DSA1:
|
||||
case EVP_PKEY_DSA2:
|
||||
case EVP_PKEY_DSA3:
|
||||
case EVP_PKEY_DSA4:
|
||||
return SSLConfigAPI::PK_DSA;
|
||||
return PKType::PK_DSA;
|
||||
case EVP_PKEY_NONE:
|
||||
return SSLConfigAPI::PK_NONE;
|
||||
return PKType::PK_NONE;
|
||||
default:
|
||||
return SSLConfigAPI::PK_UNKNOWN;
|
||||
return PKType::PK_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
size_t key_length() const
|
||||
{
|
||||
int ret = i2d_PrivateKey(pkey_, NULL);
|
||||
int ret = ::i2d_PrivateKey(pkey_, NULL);
|
||||
if (ret < 0)
|
||||
return 0;
|
||||
|
||||
@ -101,12 +129,12 @@ namespace openvpn {
|
||||
|
||||
void parse_pem(const std::string& pkey_txt, const std::string& title)
|
||||
{
|
||||
BIO *bio = BIO_new_mem_buf(const_cast<char *>(pkey_txt.c_str()), pkey_txt.length());
|
||||
BIO *bio = ::BIO_new_mem_buf(const_cast<char *>(pkey_txt.c_str()), pkey_txt.length());
|
||||
if (!bio)
|
||||
throw OpenSSLException();
|
||||
|
||||
EVP_PKEY *pkey = PEM_read_bio_PrivateKey(bio, nullptr, pem_password_callback, this);
|
||||
BIO_free(bio);
|
||||
::EVP_PKEY *pkey = ::PEM_read_bio_PrivateKey(bio, nullptr, pem_password_callback, this);
|
||||
::BIO_free(bio);
|
||||
if (!pkey)
|
||||
throw OpenSSLException(std::string("PKey::parse_pem: error in ") + title + std::string(":"));
|
||||
|
||||
@ -118,19 +146,19 @@ namespace openvpn {
|
||||
{
|
||||
if (pkey_)
|
||||
{
|
||||
BIO *bio = BIO_new(BIO_s_mem());
|
||||
const int ret = PEM_write_bio_PrivateKey(bio, pkey_, nullptr, nullptr, 0, nullptr, nullptr);
|
||||
BIO *bio = ::BIO_new(BIO_s_mem());
|
||||
const int ret = ::PEM_write_bio_PrivateKey(bio, pkey_, nullptr, nullptr, 0, nullptr, nullptr);
|
||||
if (ret == 0)
|
||||
{
|
||||
BIO_free(bio);
|
||||
::BIO_free(bio);
|
||||
throw OpenSSLException("PKey::render_pem");
|
||||
}
|
||||
|
||||
{
|
||||
char *temp;
|
||||
const int buf_len = BIO_get_mem_data(bio, &temp);
|
||||
const int buf_len = ::BIO_get_mem_data(bio, &temp);
|
||||
std::string ret = std::string(temp, buf_len);
|
||||
BIO_free(bio);
|
||||
::BIO_free(bio);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@ -138,15 +166,6 @@ namespace openvpn {
|
||||
return "";
|
||||
}
|
||||
|
||||
void erase()
|
||||
{
|
||||
if (pkey_)
|
||||
{
|
||||
EVP_PKEY_free(pkey_);
|
||||
pkey_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
~PKey()
|
||||
{
|
||||
erase();
|
||||
@ -165,33 +184,31 @@ namespace openvpn {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static EVP_PKEY *dup(const EVP_PKEY *pkey)
|
||||
void erase()
|
||||
{
|
||||
if (pkey_)
|
||||
::EVP_PKEY_free(pkey_);
|
||||
}
|
||||
|
||||
static ::EVP_PKEY *dup(const ::EVP_PKEY *pkey)
|
||||
{
|
||||
// No OpenSSL EVP_PKEY_dup method so we roll our own
|
||||
if (pkey)
|
||||
{
|
||||
EVP_PKEY* pDupKey = EVP_PKEY_new();
|
||||
RSA* pRSA = EVP_PKEY_get1_RSA(const_cast<EVP_PKEY *>(pkey));
|
||||
RSA* pRSADupKey = RSAPrivateKey_dup(pRSA);
|
||||
RSA_free(pRSA);
|
||||
EVP_PKEY_set1_RSA(pDupKey, pRSADupKey);
|
||||
RSA_free(pRSADupKey);
|
||||
::EVP_PKEY* pDupKey = ::EVP_PKEY_new();
|
||||
::RSA* pRSA = ::EVP_PKEY_get1_RSA(const_cast<::EVP_PKEY *>(pkey));
|
||||
::RSA* pRSADupKey = ::RSAPrivateKey_dup(pRSA);
|
||||
::RSA_free(pRSA);
|
||||
::EVP_PKEY_set1_RSA(pDupKey, pRSADupKey);
|
||||
::RSA_free(pRSADupKey);
|
||||
return pDupKey;
|
||||
}
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void assign(const EVP_PKEY *pkey)
|
||||
{
|
||||
erase();
|
||||
pkey_ = dup(pkey);
|
||||
}
|
||||
|
||||
::EVP_PKEY *pkey_;
|
||||
std::string priv_key_pwd;
|
||||
EVP_PKEY *pkey_;
|
||||
};
|
||||
}
|
||||
} // namespace openvpn
|
||||
|
||||
#endif // OPENVPN_OPENSSL_PKI_PKEY_H
|
||||
}
|
||||
|
@ -21,8 +21,7 @@
|
||||
|
||||
// Wrap an OpenSSL X509 object
|
||||
|
||||
#ifndef OPENVPN_OPENSSL_PKI_X509_H
|
||||
#define OPENVPN_OPENSSL_PKI_X509_H
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@ -32,92 +31,77 @@
|
||||
|
||||
#include <openvpn/common/size.hpp>
|
||||
#include <openvpn/common/exception.hpp>
|
||||
#include <openvpn/common/rc.hpp>
|
||||
#include <openvpn/openssl/util/error.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
namespace OpenSSLPKI {
|
||||
|
||||
class X509;
|
||||
|
||||
class X509Base
|
||||
class X509
|
||||
{
|
||||
public:
|
||||
X509Base() : x509_(nullptr) {}
|
||||
explicit X509Base(::X509 *x509) : x509_(x509) {}
|
||||
X509()
|
||||
: x509_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
X509(const std::string& cert_txt, const std::string& title)
|
||||
: x509_(nullptr)
|
||||
{
|
||||
parse_pem(cert_txt, title);
|
||||
}
|
||||
|
||||
explicit X509(::X509 *x509, const bool create=true)
|
||||
{
|
||||
if (create)
|
||||
x509_ = x509;
|
||||
else
|
||||
x509_ = dup(x509);
|
||||
}
|
||||
|
||||
X509(const X509& other)
|
||||
: x509_(dup(other.x509_))
|
||||
{
|
||||
}
|
||||
|
||||
X509(X509&& other) noexcept
|
||||
: x509_(other.x509_)
|
||||
{
|
||||
other.x509_ = nullptr;
|
||||
}
|
||||
|
||||
X509& operator=(const X509& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
erase();
|
||||
x509_ = dup(other.x509_);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
X509& operator=(X509&& other) noexcept
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
erase();
|
||||
x509_ = other.x509_;
|
||||
other.x509_ = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool defined() const { return x509_ != nullptr; }
|
||||
::X509* obj() const { return x509_; }
|
||||
::X509* obj_dup() const { return dup(x509_); }
|
||||
|
||||
std::string render_pem() const
|
||||
{
|
||||
if (x509_)
|
||||
{
|
||||
BIO *bio = BIO_new(BIO_s_mem());
|
||||
const int ret = PEM_write_bio_X509(bio, x509_);
|
||||
if (ret == 0)
|
||||
{
|
||||
BIO_free(bio);
|
||||
throw OpenSSLException("X509::render_pem");
|
||||
}
|
||||
|
||||
{
|
||||
char *temp;
|
||||
const int buf_len = BIO_get_mem_data(bio, &temp);
|
||||
std::string ret = std::string(temp, buf_len);
|
||||
BIO_free(bio);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
private:
|
||||
static ::X509 *dup(const ::X509 *x509)
|
||||
{
|
||||
if (x509)
|
||||
return X509_dup(const_cast< ::X509 * >(x509));
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
friend class X509;
|
||||
::X509 *x509_;
|
||||
};
|
||||
|
||||
class X509 : public X509Base, public RC<thread_unsafe_refcount>
|
||||
{
|
||||
public:
|
||||
typedef RCPtr<X509> Ptr;
|
||||
|
||||
X509() {}
|
||||
|
||||
X509(const std::string& cert_txt, const std::string& title)
|
||||
{
|
||||
parse_pem(cert_txt, title);
|
||||
}
|
||||
|
||||
X509(const X509& other)
|
||||
{
|
||||
dup(other.x509_);
|
||||
}
|
||||
|
||||
void operator=(const X509& other)
|
||||
{
|
||||
erase();
|
||||
dup(other.x509_);
|
||||
}
|
||||
|
||||
void parse_pem(const std::string& cert_txt, const std::string& title)
|
||||
{
|
||||
BIO *bio = BIO_new_mem_buf(const_cast<char *>(cert_txt.c_str()), cert_txt.length());
|
||||
BIO *bio = ::BIO_new_mem_buf(const_cast<char *>(cert_txt.c_str()), cert_txt.length());
|
||||
if (!bio)
|
||||
throw OpenSSLException();
|
||||
|
||||
::X509 *cert = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr);
|
||||
BIO_free(bio);
|
||||
::X509 *cert = ::PEM_read_bio_X509(bio, nullptr, nullptr, nullptr);
|
||||
::BIO_free(bio);
|
||||
if (!cert)
|
||||
throw OpenSSLException(std::string("X509::parse_pem: error in ") + title + std::string(":"));
|
||||
|
||||
@ -125,13 +109,28 @@ namespace openvpn {
|
||||
x509_ = cert;
|
||||
}
|
||||
|
||||
void erase()
|
||||
std::string render_pem() const
|
||||
{
|
||||
if (x509_)
|
||||
{
|
||||
X509_free(x509_);
|
||||
x509_ = nullptr;
|
||||
BIO *bio = ::BIO_new(BIO_s_mem());
|
||||
const int ret = ::PEM_write_bio_X509(bio, x509_);
|
||||
if (ret == 0)
|
||||
{
|
||||
::BIO_free(bio);
|
||||
throw OpenSSLException("X509::render_pem");
|
||||
}
|
||||
|
||||
{
|
||||
char *temp;
|
||||
const int buf_len = ::BIO_get_mem_data(bio, &temp);
|
||||
std::string ret = std::string(temp, buf_len);
|
||||
::BIO_free(bio);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
~X509()
|
||||
@ -140,29 +139,40 @@ namespace openvpn {
|
||||
}
|
||||
|
||||
private:
|
||||
void dup(const ::X509 *x509)
|
||||
static ::X509 *dup(const ::X509 *x509)
|
||||
{
|
||||
x509_ = X509Base::dup(x509);
|
||||
if (x509)
|
||||
return ::X509_dup(const_cast< ::X509 * >(x509));
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void erase()
|
||||
{
|
||||
if (x509_)
|
||||
::X509_free(x509_);
|
||||
}
|
||||
|
||||
::X509 *x509_;
|
||||
};
|
||||
|
||||
class X509List : public std::vector<X509::Ptr>
|
||||
class X509List : public std::vector<X509>
|
||||
{
|
||||
public:
|
||||
typedef X509 Item;
|
||||
typedef X509::Ptr ItemPtr;
|
||||
|
||||
bool defined() const { return !empty(); }
|
||||
bool defined() const
|
||||
{
|
||||
return !empty();
|
||||
}
|
||||
|
||||
std::string render_pem() const
|
||||
{
|
||||
std::string ret;
|
||||
for (const_iterator i = begin(); i != end(); ++i)
|
||||
ret += (*i)->render_pem();
|
||||
for (const auto &e : *this)
|
||||
ret += e.render_pem();
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
}
|
||||
} // namespace openvpn
|
||||
|
||||
#endif // OPENVPN_OPENSSL_PKI_X509_H
|
||||
}
|
||||
|
@ -21,12 +21,10 @@
|
||||
|
||||
// Wrap an OpenSSL X509Store object
|
||||
|
||||
#ifndef OPENVPN_OPENSSL_PKI_X509STORE_H
|
||||
#define OPENVPN_OPENSSL_PKI_X509STORE_H
|
||||
#pragma once
|
||||
|
||||
#include <openvpn/common/size.hpp>
|
||||
#include <openvpn/common/exception.hpp>
|
||||
#include <openvpn/common/rc.hpp>
|
||||
#include <openvpn/pki/cclist.hpp>
|
||||
#include <openvpn/openssl/util/error.hpp>
|
||||
#include <openvpn/openssl/pki/x509.hpp>
|
||||
@ -35,16 +33,17 @@
|
||||
namespace openvpn {
|
||||
namespace OpenSSLPKI {
|
||||
|
||||
class X509Store : public RC<thread_unsafe_refcount>
|
||||
class X509Store
|
||||
{
|
||||
public:
|
||||
OPENVPN_SIMPLE_EXCEPTION(x509_store_init_error);
|
||||
OPENVPN_SIMPLE_EXCEPTION(x509_store_add_cert_error);
|
||||
OPENVPN_SIMPLE_EXCEPTION(x509_store_add_crl_error);
|
||||
OPENVPN_EXCEPTION(x509_store_error);
|
||||
|
||||
typedef CertCRLListTemplate<X509List, CRLList> CertCRLList;
|
||||
|
||||
X509Store() : x509_store_(nullptr) {}
|
||||
X509Store()
|
||||
: x509_store_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
explicit X509Store(const CertCRLList& cc)
|
||||
{
|
||||
@ -52,10 +51,10 @@ namespace openvpn {
|
||||
|
||||
// Load cert list
|
||||
{
|
||||
for (X509List::const_iterator i = cc.certs.begin(); i != cc.certs.end(); ++i)
|
||||
for (const auto &e : cc.certs)
|
||||
{
|
||||
if (!X509_STORE_add_cert(x509_store_, (*i)->obj()))
|
||||
throw x509_store_add_cert_error();
|
||||
if (!::X509_STORE_add_cert(x509_store_, e.obj()))
|
||||
throw x509_store_error("X509_STORE_add_cert(");
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,19 +62,22 @@ namespace openvpn {
|
||||
{
|
||||
if (cc.crls.defined())
|
||||
{
|
||||
X509_STORE_set_flags(x509_store_, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
|
||||
for (CRLList::const_iterator i = cc.crls.begin(); i != cc.crls.end(); ++i)
|
||||
::X509_STORE_set_flags(x509_store_, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
|
||||
for (const auto &e : cc.crls)
|
||||
{
|
||||
if (!X509_STORE_add_crl(x509_store_, (*i)->obj()))
|
||||
throw x509_store_add_crl_error();
|
||||
if (!::X509_STORE_add_crl(x509_store_, e.obj()))
|
||||
throw x509_store_error("X509_STORE_add_crl");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
X509_STORE* obj() const { return x509_store_; }
|
||||
X509_STORE* obj() const
|
||||
{
|
||||
return x509_store_;
|
||||
}
|
||||
|
||||
X509_STORE* move()
|
||||
X509_STORE* release()
|
||||
{
|
||||
X509_STORE* ret = x509_store_;
|
||||
x509_store_ = nullptr;
|
||||
@ -85,20 +87,18 @@ namespace openvpn {
|
||||
~X509Store()
|
||||
{
|
||||
if (x509_store_)
|
||||
X509_STORE_free(x509_store_);
|
||||
::X509_STORE_free(x509_store_);
|
||||
}
|
||||
|
||||
private:
|
||||
void init()
|
||||
{
|
||||
x509_store_ = X509_STORE_new();
|
||||
x509_store_ = ::X509_STORE_new();
|
||||
if (!x509_store_)
|
||||
throw x509_store_init_error();
|
||||
throw x509_store_error("X509_STORE_new");
|
||||
}
|
||||
|
||||
X509_STORE* x509_store_;
|
||||
::X509_STORE* x509_store_;
|
||||
};
|
||||
}
|
||||
} // namespace openvpn
|
||||
|
||||
#endif // OPENVPN_OPENSSL_PKI_X509STORE_H
|
||||
}
|
||||
|
@ -194,7 +194,7 @@ namespace openvpn {
|
||||
std::vector<std::string> ret;
|
||||
|
||||
for (auto const& cert : extra_certs)
|
||||
ret.push_back(cert->render_pem());
|
||||
ret.push_back(cert.render_pem());
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -1262,9 +1262,9 @@ namespace openvpn {
|
||||
// chain but shouldn't be included in the verify chain.
|
||||
if (config->extra_certs.defined())
|
||||
{
|
||||
for (OpenSSLPKI::X509List::const_iterator i = config->extra_certs.begin(); i != config->extra_certs.end(); ++i)
|
||||
for (const auto& e : config->extra_certs)
|
||||
{
|
||||
if (SSL_CTX_add_extra_chain_cert(ctx, (*i)->obj_dup()) != 1)
|
||||
if (SSL_CTX_add_extra_chain_cert(ctx, e.obj_dup()) != 1)
|
||||
throw OpenSSLException("OpenSSLContext: SSL_CTX_add_extra_chain_cert failed");
|
||||
}
|
||||
}
|
||||
@ -1303,7 +1303,7 @@ namespace openvpn {
|
||||
void update_trust(const CertCRLList& cc)
|
||||
{
|
||||
OpenSSLPKI::X509Store store(cc);
|
||||
SSL_CTX_set_cert_store(ctx, store.move());
|
||||
SSL_CTX_set_cert_store(ctx, store.release());
|
||||
}
|
||||
|
||||
~OpenSSLContext()
|
||||
|
@ -35,7 +35,7 @@ namespace openvpn {
|
||||
|
||||
// Parse a concatenated list of certs and CRLs (PEM format).
|
||||
// Abstracts CertList and CRLList, so can be used with any crypto lib.
|
||||
// CertList and CRLList must define Item and ItemPtr types.
|
||||
// CertList and CRLList must define Item type.
|
||||
template <typename CertList, typename CRLList>
|
||||
class CertCRLListTemplate
|
||||
{
|
||||
@ -109,8 +109,7 @@ namespace openvpn {
|
||||
if (state == S_IN_CERT && line == cert_end)
|
||||
{
|
||||
try {
|
||||
typename CertList::ItemPtr x509(new typename CertList::Item(item, title));
|
||||
cert_list->push_back(x509);
|
||||
cert_list->emplace_back(item, title);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
@ -122,8 +121,7 @@ namespace openvpn {
|
||||
if (state == S_IN_CRL && line == crl_end)
|
||||
{
|
||||
try {
|
||||
typename CRLList::ItemPtr crl(new typename CRLList::Item(item));
|
||||
crl_list->push_back(crl);
|
||||
crl_list->emplace_back(item);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user