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
|
// 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
//
//
#pragma once
#include <openvpn/common/options.hpp>
namespace openvpn {
struct PeerFingerprint
{
PeerFingerprint(const std::string &fp, const std::size_t size)
{
std::istringstream input(fp);
input.setf(std::ios_base::hex, std::ios_base::basefield);
input.unsetf(std::ios_base::skipws);
fingerprint_.reserve(size);
unsigned int val;
if (input >> val && val < 256)
{
fingerprint_.emplace_back(val);
while (input)
{
char sep;
if (input >> sep >> val && sep == ':' && val < 256)
fingerprint_.emplace_back(val);
else
break;
}
}
if (fingerprint_.size() != fingerprint_.capacity())
throw option_error(ERR_INVALID_OPTION_VAL, "malformed peer-fingerprint: " + fp);
}
explicit PeerFingerprint(const std::vector<uint8_t> &fingerprint)
: fingerprint_(fingerprint)
{
}
bool operator==(const PeerFingerprint &that) const
{
return fingerprint_ == that.fingerprint_;
}
std::string str() const
{
std::ostringstream output;
output.setf(std::ios_base::hex, std::ios_base::basefield);
output.fill('0');
output.width(2);
for (const int v : fingerprint_)
output << v << ':';
std::string str(output.str());
if (str.size())
str.erase(str.size() - 1);
return str;
}
protected:
std::vector<uint8_t> fingerprint_;
};
/**
* Parses the --peer-fingerprint configuration option
* and provides the logic to validate an X.509 certificate
* against such an option.
*/
struct PeerFingerprints
{
PeerFingerprints() = default;
PeerFingerprints(const OptionList &opt, const std::size_t fp_size)
{
const auto indices = opt.get_index_ptr("peer-fingerprint");
if (indices == nullptr)
return;
for (const auto i : *indices)
{
std::istringstream fps(opt[i].get(1, Option::MULTILINE));
std::string fp;
opt[i].touch();
while (std::getline(fps, fp))
{
// Ignore empty lines and comments in fingerprint blocks
std::string trimmed = string::trim_copy(fp);
if (trimmed.empty()
|| string::starts_with(trimmed, "#")
|| string::starts_with(trimmed, ";"))
{
continue;
}
fingerprints_.emplace_back(PeerFingerprint(fp, fp_size));
}
}
}
bool match(const PeerFingerprint &fp) const
{
for (const auto &fingerprint : fingerprints_)
{
if (fingerprint == fp)
return true;
}
return false;
}
explicit operator bool()
{
return !fingerprints_.empty();
}
protected:
std::vector<PeerFingerprint> fingerprints_;
};
} // namespace openvpn
|