1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
|
// OpenVPN -- An application to securely tunnel IP networks
// over a single port, with support for SSL/TLS-based
// session authentication and key exchange,
// packet encryption, packet authentication, and
// packet compression.
//
// Copyright (C) 2012- OpenVPN Inc.
//
// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
//
#ifndef OPENVPN_PKI_CCLIST_H
#define OPENVPN_PKI_CCLIST_H
#include <string>
#include <sstream>
#include <fstream>
#include <openvpn/common/size.hpp>
#include <openvpn/common/exception.hpp>
#include <openvpn/common/file.hpp>
#include <openvpn/common/string.hpp>
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 type.
template <typename CertList, typename CRLList>
class CertCRLListTemplate
{
public:
OPENVPN_EXCEPTION(parse_cert_crl_error);
CertCRLListTemplate()
{
}
explicit CertCRLListTemplate(const std::string &content, const std::string &title)
{
from_string(content, title, &certs, &crls);
}
void parse_pem(const std::string &content, const std::string &title)
{
from_string(content, title, &certs, &crls);
}
void parse_pem_file(const std::string &filename)
{
from_file(filename, &certs, &crls);
}
std::string render_pem() const
{
return certs.render_pem() + crls.render_pem();
}
static void from_istream(std::istream &in, const std::string &title, CertList *cert_list, CRLList *crl_list)
{
static const char cert_start[] = "-----BEGIN CERTIFICATE-----";
static const char cert_end[] = "-----END CERTIFICATE-----";
static const char crl_start[] = "-----BEGIN X509 CRL-----";
static const char crl_end[] = "-----END X509 CRL-----";
enum
{
S_OUTSIDE, // outside of CERT or CRL block
S_IN_CERT, // in CERT block
S_IN_CRL, // in CRL block
};
std::string line;
int state = S_OUTSIDE;
std::string item = "";
int line_num = 0;
while (std::getline(in, line))
{
line_num++;
string::trim(line);
if (state == S_OUTSIDE)
{
if (line == cert_start)
{
if (!cert_list)
OPENVPN_THROW(parse_cert_crl_error, title << ":" << line_num << " : not expecting a CERT");
state = S_IN_CERT;
}
else if (line == crl_start)
{
if (!crl_list)
OPENVPN_THROW(parse_cert_crl_error, title << ":" << line_num << " : not expecting a CRL");
state = S_IN_CRL;
}
}
if (state != S_OUTSIDE)
{
item += line;
item += "\n";
}
if (state == S_IN_CERT && line == cert_end)
{
try
{
cert_list->emplace_back(item, title);
}
catch (const std::exception &e)
{
OPENVPN_THROW(parse_cert_crl_error, title << ":" << line_num << " : error parsing CERT: " << e.what());
}
state = S_OUTSIDE;
item = "";
}
if (state == S_IN_CRL && line == crl_end)
{
try
{
crl_list->emplace_back(item);
}
catch (const std::exception &e)
{
OPENVPN_THROW(parse_cert_crl_error, title << ":" << line_num << " : error parsing CRL: " << e.what());
}
state = S_OUTSIDE;
item = "";
}
}
if (state != S_OUTSIDE)
OPENVPN_THROW(parse_cert_crl_error, title << " : CERT/CRL content ended unexpectedly without END marker");
}
static void from_string(const std::string &content, const std::string &title, CertList *cert_list, CRLList *crl_list = nullptr)
{
std::stringstream in(content);
from_istream(in, title, cert_list, crl_list);
}
static void from_file(const std::string &filename, CertList *cert_list, CRLList *crl_list = nullptr)
{
std::ifstream ifs(filename.c_str());
if (!ifs)
OPENVPN_THROW(open_file_error, "cannot open CERT/CRL file " << filename);
from_istream(ifs, filename, cert_list, crl_list);
if (ifs.bad())
OPENVPN_THROW(open_file_error, "cannot read CERT/CRL file " << filename);
}
CertList certs;
CRLList crls;
};
} // namespace openvpn
#endif // OPENVPN_PKI_CCLIST_H
|