mirror of
https://github.com/OpenVPN/openvpn3.git
synced 2024-09-20 12:12:15 +02:00
6e8f2a73f8
Signed-off-by: James Yonan <james@openvpn.net>
231 lines
4.8 KiB
C++
231 lines
4.8 KiB
C++
// 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-2017 OpenVPN Technologies, Inc.
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License Version 3
|
|
// as published by the Free Software Foundation.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program in the COPYING file.
|
|
// If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
#ifndef OPENVPN_PKI_X509TRACK_H
|
|
#define OPENVPN_PKI_X509TRACK_H
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include <openvpn/common/exception.hpp>
|
|
#include <openvpn/common/options.hpp>
|
|
#include <openvpn/common/arraysize.hpp>
|
|
#include <openvpn/common/string.hpp>
|
|
#include <openvpn/common/to_string.hpp>
|
|
|
|
namespace openvpn {
|
|
namespace X509Track {
|
|
|
|
enum Type {
|
|
UNDEF=-1,
|
|
SERIAL,
|
|
SERIAL_HEX,
|
|
SHA1,
|
|
CN,
|
|
C,
|
|
L,
|
|
ST,
|
|
O,
|
|
OU,
|
|
EMAIL,
|
|
N_TYPES,
|
|
};
|
|
|
|
static const char *const names[] = { // CONST GLOBAL
|
|
"SERIAL",
|
|
"SERIAL_HEX",
|
|
"SHA1",
|
|
"CN",
|
|
"C",
|
|
"L",
|
|
"ST",
|
|
"O",
|
|
"OU",
|
|
"emailAddress",
|
|
};
|
|
|
|
OPENVPN_EXCEPTION(x509_track_error);
|
|
|
|
inline const char *name(const Type type)
|
|
{
|
|
static_assert(N_TYPES == array_size(names), "x509 names array inconsistency");
|
|
if (type >= 0 && type < N_TYPES)
|
|
return names[type];
|
|
else
|
|
return "UNDEF";
|
|
}
|
|
|
|
inline Type parse_type(const std::string& name)
|
|
{
|
|
for (size_t i = 0; i < N_TYPES; ++i)
|
|
if (name == names[i])
|
|
return Type(i);
|
|
return UNDEF;
|
|
}
|
|
|
|
struct Config
|
|
{
|
|
Config(const Type type_arg, const bool full_chain_arg)
|
|
: type(type_arg),
|
|
full_chain(full_chain_arg)
|
|
{
|
|
}
|
|
|
|
Config(const std::string& spec)
|
|
{
|
|
full_chain = (spec.length() > 0 && spec[0] == '+');
|
|
type = parse_type(spec.substr(full_chain ? 1 : 0));
|
|
if (type == UNDEF)
|
|
throw Exception("cannot parse attribute '" + spec + "'");
|
|
}
|
|
|
|
std::string to_string() const
|
|
{
|
|
std::string ret;
|
|
if (full_chain)
|
|
ret += '+';
|
|
ret += name(type);
|
|
return ret;
|
|
}
|
|
|
|
bool depth_match(const int depth) const
|
|
{
|
|
return !depth || full_chain;
|
|
}
|
|
|
|
Type type;
|
|
bool full_chain;
|
|
};
|
|
|
|
struct ConfigSet : public std::vector<Config>
|
|
{
|
|
ConfigSet() {}
|
|
|
|
ConfigSet(const OptionList& opt,
|
|
const bool include_serial,
|
|
const bool include_serial_hex)
|
|
{
|
|
const auto* xt = opt.get_index_ptr("x509-track");
|
|
if (xt)
|
|
{
|
|
for (const auto &i : *xt)
|
|
{
|
|
try {
|
|
const Option& o = opt[i];
|
|
o.touch();
|
|
emplace_back(o.get(1, 64));
|
|
}
|
|
catch (const std::exception& e)
|
|
{
|
|
throw x509_track_error(e.what());
|
|
}
|
|
}
|
|
}
|
|
|
|
if (include_serial && !exists(SERIAL))
|
|
emplace_back(SERIAL, true);
|
|
if (include_serial_hex && !exists(SERIAL_HEX))
|
|
emplace_back(SERIAL_HEX, true);
|
|
}
|
|
|
|
bool exists(const Type t) const
|
|
{
|
|
for (auto &c : *this)
|
|
if (c.type == t)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
std::string to_string() const
|
|
{
|
|
std::string ret;
|
|
for (auto &c : *this)
|
|
{
|
|
ret += c.to_string();
|
|
ret += '\n';
|
|
}
|
|
return ret;
|
|
}
|
|
};
|
|
|
|
struct KeyValue
|
|
{
|
|
KeyValue(const Type type_arg,
|
|
const int depth_arg,
|
|
std::string value_arg)
|
|
: type(type_arg),
|
|
depth(depth_arg),
|
|
value(std::move(value_arg))
|
|
{
|
|
}
|
|
|
|
std::string to_string(const bool omi_form) const
|
|
{
|
|
std::string ret;
|
|
ret.reserve(128);
|
|
if (omi_form)
|
|
ret += ">CLIENT:ENV,";
|
|
ret += key_name();
|
|
ret += '=';
|
|
ret += string::reduce_spaces(value, ' ');
|
|
return ret;
|
|
}
|
|
|
|
std::string key_name() const
|
|
{
|
|
switch (type)
|
|
{
|
|
case SERIAL:
|
|
return "tls_serial_" + openvpn::to_string(depth);
|
|
case SERIAL_HEX:
|
|
return "tls_serial_hex_" + openvpn::to_string(depth);
|
|
default:
|
|
return "X509_" + openvpn::to_string(depth) + '_' + name(type);
|
|
}
|
|
}
|
|
|
|
Type type = UNDEF;
|
|
int depth = 0;
|
|
std::string value;
|
|
};
|
|
|
|
struct Set : public std::vector<KeyValue>
|
|
{
|
|
std::string to_string(const bool omi_form) const
|
|
{
|
|
std::string ret;
|
|
ret.reserve(512);
|
|
for (auto &kv : *this)
|
|
{
|
|
ret += kv.to_string(omi_form);
|
|
if (omi_form)
|
|
ret += '\r';
|
|
ret += '\n';
|
|
}
|
|
return ret;
|
|
}
|
|
};
|
|
|
|
}
|
|
}
|
|
|
|
#endif
|