17#ifndef OPENVPN_OPTIONS_MERGE_H
18#define OPENVPN_OPTIONS_MERGE_H
71 const std::string &
error()
const
100 return "MERGE_UNDEFINED";
102 return "MERGE_SUCCESS";
104 return "MERGE_EXCEPTION";
106 return "MERGE_OVPN_EXT_FAIL";
108 return "MERGE_OVPN_FILE_FAIL";
110 return "MERGE_REF_FAIL";
112 return "MERGE_MULTIPLE_REF_FAIL";
127 const std::string &profile_ext,
128 const std::string &profile_dir_override,
129 const Follow follow_references,
130 const size_t max_line_len,
131 const size_t max_size)
136 size_t total_size = 0;
139 std::string orig_profile_content;
140 std::string profile_dir;
143 profile_dir = !profile_dir_override.empty() ? profile_dir_override :
path::dirname(profile_path);
149 total_size = orig_profile_content.size();
158 catch (
const file_is_binary &e)
161 error_ = std::string(
"ERR_PROFILE_FILE_IS_BINARY: ") + e.what();
164 catch (
const file_too_large &e)
167 error_ = std::string(
"ERR_PROFILE_FILE_TOO_LARGE: ") + e.what();
170 catch (
const std::exception &e)
173 error_ = std::string(
"ERR_PROFILE_GENERIC: ") + e.what();
178 expand_profile(orig_profile_content, profile_dir, follow_references, max_line_len, max_size, total_size);
180 catch (
const std::exception &e)
183 error_ = std::string(
"ERR_PROFILE_GENERIC: ") + e.what();
187 static std::string
merge(
const std::string &profile_path,
188 const std::string &profile_ext,
189 const std::string &profile_dir_override,
190 const Follow follow_references,
191 const size_t max_line_len,
192 const size_t max_size)
196 profile_dir_override,
213 const std::string &profile_dir,
214 const Follow follow_references,
215 const size_t max_line_len,
216 const size_t max_size,
219 if (total_size > max_size)
222 error_ =
"ERR_PROFILE_FILE_TOO_LARGE: file too large";
228 SplitLines in(orig_profile_content, max_line_len);
229 bool in_multiline =
false;
230 bool opaque_multiline =
false;
239 error_ =
"ERR_PROFILE_LINE_TOO_LONG: line too long";
242 const std::string &line = in.
line_ref();
249 in_multiline =
false;
250 opaque_multiline =
false;
255 Option opt = Split::by_space<Option, OptionList::LexComment, SpaceMatch, Split::NullLimit>(line);
261 multiline = std::move(opt);
263 unsigned int flags = 0;
268 unsigned int flags = 0;
269 bool is_fileref = (!opaque_multiline
280 const std::string authfile = opt.
get(3, 256);
281 if (authfile !=
"auto" && authfile !=
"auto-nct"
282 && authfile !=
"basic" && authfile !=
"digest"
283 && authfile !=
"ntlm" && authfile !=
"none")
288 opt.
ref(0) =
"http-proxy-user-pass";
289 opt.
ref(1) = authfile;
303 const std::string fn_str = opt.
get(1, 256);
309 error_ =
"ERR_PROFILE_NO_FILENAME: filename not provided";
315 error_ = std::string(
"ERR_PROFILE_CANT_FOLLOW_LINK: ") + fn;
322 std::string file_content;
329 error_ = std::string(
"ERR_PROFILE_CANT_FOLLOW_LINK: ") + fn +
": cannot follow file reference";
334 total_size += file_content.size();
335 if (total_size > max_size)
338 error_ = std::string(
"ERR_PROFILE_FILE_TOO_LARGE: ") + fn +
": file too large";
343 catch (
const std::exception &e)
347 error_ = std::string(
"ERR_PROFILE_GENERIC: ") + fn +
" : " + e.what();
360 std::string key_direction;
362 key_direction = opt.
get(2, 16);
364 key_direction =
"bidirectional";
370 std::ostringstream os;
371 const std::string &tag = opt.
ref(0);
373 os <<
'<' << tag <<
">\n"
374 << file_content <<
"</" << tag <<
">\n";
399 error_ =
"ERR_PROFILE_GENERIC: ";
416 return d ==
"auth-user-pass";
418 return d ==
"ca" || d ==
"cert" || d ==
"crl-verify";
422 return d ==
"extra-certs";
424 if (d ==
"http-proxy")
442 if (d ==
"relay-extra-ca")
444 if (d ==
"relay-tls-auth")
451 if (d ==
"static-key")
460 if (d ==
"tls-crypt")
462 if (d ==
"tls-crypt-v2")
482 const std::string &ref_dir,
483 const Follow follow_references,
484 const size_t max_line_len,
485 const size_t max_size)
497 catch (
const std::exception &e)
500 error_ = std::string(
"ERR_PROFILE_GENERIC: ") + e.what();
505 const std::string &ref_dir,
506 const Follow follow_references,
507 const size_t max_line_len,
508 const size_t max_size)
static void detect_multiline_breakout(const std::string &opt, const std::string &tag)
static void untag_open_tag(std::string &str)
static bool is_close_tag(const std::string &str, const std::string &tag)
static bool ignore_line(const std::string &line)
static bool is_open_tag(const std::string &str)
const std::string & get(const size_t index, const size_t max_len) const
void resize(const size_t n)
void reserve(const size_t n)
std::string escape(const bool csv) const
const std::string & ref(const size_t i) const
ProfileMergeFromString(const std::string &profile_content, const std::string &ref_dir, const Follow follow_references, const size_t max_line_len, const size_t max_size)
static std::string merge(const std::string &profile_content, const std::string &ref_dir, const Follow follow_references, const size_t max_line_len, const size_t max_size)
void expand_profile(const std::string &orig_profile_content, const std::string &profile_dir, const Follow follow_references, const size_t max_line_len, const size_t max_size, size_t total_size)
const std::string & basename() const
const std::string & error() const
OPENVPN_EXCEPTION(merge_error)
const char * status_string() const
ProfileMerge(const std::string &profile_path, const std::string &profile_ext, const std::string &profile_dir_override, const Follow follow_references, const size_t max_line_len, const size_t max_size)
static bool is_fileref_directive(const std::string &d, unsigned int &flags)
const std::string & profile_content() const
std::vector< std::string > ref_fail_list_
const std::vector< std::string > & ref_path_list() const
std::vector< std::string > ref_succeed_list_
@ MERGE_MULTIPLE_REF_FAIL
@ F_MAY_INCLUDE_KEY_DIRECTION
std::string profile_content_
static std::string merge(const std::string &profile_path, const std::string &profile_ext, const std::string &profile_dir_override, const Follow follow_references, const size_t max_line_len, const size_t max_size)
bool line_overflow() const
#define OPENVPN_THROW(exc, stuff)
std::string ext(const std::string &basename)
std::string dirname(const std::string &path)
std::string basename(const std::string &path)
std::string join(const std::string &p1, const std::string &p2)
bool is_flat(const std::string &path)
int strcasecmp(const char *s1, const char *s2)
void add_trailing(std::string &str, const char c)
Support deferred server-side state creation when client connects.
std::string read_text_utf8(const std::string &filename, const std::uint64_t max_size=0)
void ext(const std::string &path)