OpenVPN 3 Core Library
Loading...
Searching...
No Matches
peerinfo.hpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2012- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11
12// These objects are primary concerned with generating the Peer Info on the
13// client side before transmission to server. For the reverse case (parsing
14// the Peer Info on the server) we normally use an OptionList.
15
16#ifndef OPENVPN_SSL_PEERINFO_H
17#define OPENVPN_SSL_PEERINFO_H
18
19#include <string>
20#include <vector>
21
22#include <openvpn/common/rc.hpp>
28
29#ifdef HAVE_JSON
31#endif
32
34
35OPENVPN_EXCEPTION(peer_info_error);
36
38{
39 KeyValue(const std::string &key_arg, const std::string &value_arg)
40 : key(key_arg),
41 value(value_arg)
42 {
43 }
44
45 std::string key;
46 std::string value;
47
48 std::string to_string() const
49 {
50 return key + '=' + value;
51 }
52};
53
54struct Set : public std::vector<KeyValue>, public RCCopyable<thread_unsafe_refcount>
55{
56 typedef RCPtr<Set> Ptr;
57
58 template <typename SET>
59 static Ptr new_from_foreign_set(const SET &other)
60 {
61 Ptr sp = new Set();
62 for (const auto &kv : other)
63 sp->emplace_back(kv.key, kv.value);
64 return sp;
65 }
66
67 template <typename SET>
68 void append_foreign_set_ptr(const SET *other)
69 {
70 if (other)
71 for (const auto &kv : *other)
72 emplace_back(kv.key, kv.value);
73 }
74
75 template <typename SET>
76 void append_foreign_set_ref(const SET &other)
77 {
78 for (const auto &kv : other)
79 emplace_back(kv.key, kv.value);
80 }
81
82 [[nodiscard]] bool contains_key(const std::string &key)
83 {
84 return std::find_if(begin(), end(), [&](const PeerInfo::KeyValue &kv)
85 { return kv.key == key; })
86 != end();
87 }
88
89 Ptr copy() const
90 {
91 return new Set(*this);
92 }
93
94 // src may be comma-separated key=value pairs or @filename, where
95 // filename contains a JSON dictionary of key/value pairs.
96 template <typename SET>
97 static void parse_flexible(const std::string &src, SET &dest)
98 {
99 if (src.length() >= 1 && src[0] == '@')
100 {
101 const std::string fn = src.substr(1);
102#ifdef OPENVPN_JSON_INTERNAL
103 const Json::Value root = json::parse_from_file(fn);
104 parse_json(root, dest, fn);
105#else
106 OPENVPN_THROW(peer_info_error, fn << ": JSON library not available");
107#endif
108 }
109 else
110 parse_csv(src, dest);
111 }
112
113 // Parse src in the form K1=V1,K2=V2,...
114 template <typename SET>
115 static void parse_csv(const std::string &src, SET &dest)
116 {
117 if (!string::is_empty(src))
118 {
119 if (string::is_multiline(src))
120 OPENVPN_THROW(peer_info_error, "key/value list must be a single line: " << Unicode::utf8_printable(src, 256));
121 const auto list = Split::by_char<std::vector<std::string>, StandardLex, Split::NullLimit>(src, ',', Split::TRIM_LEADING_SPACES | Split::TRIM_SPECIAL);
122 for (const auto &kvstr : list)
123 {
124 const auto kv = Split::by_char<std::vector<std::string>, StandardLex, Split::NullLimit>(kvstr, '=', 0, 1);
125 if (kv.size() == 2)
126 dest.emplace_back(kv[0], kv[1]);
127 else
128 OPENVPN_THROW(peer_info_error, "key/value must be in the form K=V, not: " << Unicode::utf8_printable(kvstr, 256));
129 }
130 }
131 }
132
133#ifdef OPENVPN_JSON_INTERNAL
134 template <typename SET>
135 static void parse_json(const Json::Value &src, SET &dest, const std::string &title)
136 {
137 if (!src.isObject())
138 OPENVPN_THROW(peer_info_error, title << ": top level JSON object must be a dictionary");
139 auto m = src.asObject();
140 for (auto &e : m)
141 {
142 if (e.second.isString())
143 dest.emplace_back(e.first, e.second.asStringRef());
144 else
145 dest.emplace_back(e.first, e.second.toCompactString());
146 }
147 }
148#endif
149
150 std::string to_string() const
151 {
152 std::string ret;
153 ret.reserve(256);
154 for (const auto &kv : *this)
155 {
156 ret += kv.to_string();
157 ret += '\n';
158 }
159 return ret;
160 }
161};
162
163} // namespace openvpn::PeerInfo
164
165#endif
Reference count base class for objects tracked by RCPtr. Allows copying and assignment.
Definition rc.hpp:979
The smart pointer class.
Definition rc.hpp:119
#define OPENVPN_EXCEPTION(C)
#define OPENVPN_THROW(exc, stuff)
@ TRIM_LEADING_SPACES
Definition split.hpp:34
STRING utf8_printable(const STRING &str, size_t max_len_flags)
Definition unicode.hpp:129
Json::Value parse_from_file(const std::string &fn)
bool is_multiline(const std::string &str)
Definition string.hpp:255
bool is_empty(const std::string &str)
Definition string.hpp:448
std::string to_string() const
Definition peerinfo.hpp:48
KeyValue(const std::string &key_arg, const std::string &value_arg)
Definition peerinfo.hpp:39
static void parse_csv(const std::string &src, SET &dest)
Definition peerinfo.hpp:115
std::string to_string() const
Definition peerinfo.hpp:150
bool contains_key(const std::string &key)
Definition peerinfo.hpp:82
static Ptr new_from_foreign_set(const SET &other)
Definition peerinfo.hpp:59
static void parse_flexible(const std::string &src, SET &dest)
Definition peerinfo.hpp:97
void append_foreign_set_ptr(const SET *other)
Definition peerinfo.hpp:68
void append_foreign_set_ref(const SET &other)
Definition peerinfo.hpp:76
std::string ret