Skip to content

Commit

Permalink
Parse meta options from content_list
Browse files Browse the repository at this point in the history
At the moment meta options are parsed only from
content. This doesn't work well with iOS where
config is imported via content_list. The config might
contain meta options, which currently won't be
recognized as meta and connection won't be established
due to "unknown option" error.

This adds meta options parsing to content_list.

Signed-off-by: Lev Stipakov <[email protected]>
  • Loading branch information
lstipakov authored and dsommers committed Aug 30, 2023
1 parent 0a690f5 commit 7fc0b70
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 6 deletions.
2 changes: 1 addition & 1 deletion openvpn/client/cliopthelper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ class ParseClientConfig
if (content_list)
{
content_list->preprocess();
options.parse_from_key_value_list(*content_list, &limits);
options.parse_from_key_value_list(*content_list, "OVPN_ACCESS_SERVER", &limits);
}
process_setenv_opt(options);
options.update_map();
Expand Down
21 changes: 17 additions & 4 deletions openvpn/common/options.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -710,12 +710,22 @@ class OptionList : public std::vector<Option>, public RCCopyable<thread_unsafe_r
return key.length() + value.length();
}

Option convert_to_option(Limits *lim) const
Option convert_to_option(Limits *lim, const std::string &meta_prefix) const
{
bool newline_present = false;
Option opt;
const std::string unesc_value = unescape(value, newline_present);
opt.push_back(key);

if (string::starts_with(key, meta_prefix))
{
opt.push_back(std::string(key, meta_prefix.length()));
opt.set_meta();
}
else
{
opt.push_back(key);
}

if (newline_present || singular_arg(key))
opt.push_back(unesc_value);
else if (unesc_value != "NOARGS")
Expand Down Expand Up @@ -966,14 +976,17 @@ class OptionList : public std::vector<Option>, public RCCopyable<thread_unsafe_r

// caller may want to call list.preprocess() before this function
// caller should call update_map() after this function
void parse_from_key_value_list(const KeyValueList &list, Limits *lim)
void parse_from_key_value_list(const KeyValueList &list, const std::string &meta_tag, Limits *lim)
{
const std::string meta_prefix = meta_tag + "_";

for (KeyValueList::const_iterator i = list.begin(); i != list.end(); ++i)
{
const KeyValue &kv = **i;
if (lim)
lim->add_bytes(kv.combined_length());
const Option opt = kv.convert_to_option(lim);

Option opt = kv.convert_to_option(lim, meta_prefix);
if (lim)
{
lim->add_opt();
Expand Down
26 changes: 25 additions & 1 deletion test/unittests/test_cliopt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,4 +217,28 @@ TEST(config, onlypullortlsclient)
option_error,
"option_error: Neither 'client' nor both 'tls-client' and 'pull' options declared. OpenVPN3 client only supports --client mode.");
}
}
}

TEST(config, meta_option_in_content)
{
OptionList options;
auto cfg = minimalConfig + "\n# OVPN_ACCESS_SERVER_AAA=BBB";

OptionList::KeyValueList kvl;
kvl.push_back(new OptionList::KeyValue("OVPN_ACCESS_SERVER_CCC", "DDD"));

auto parsed_config = ParseClientConfig::parse(cfg, &kvl, options);

ClientOptions::Config config;
config.dco_compatible = true;
config.proto_context_options.reset(new ProtoContextOptions());
ClientOptions cliopt(options, config);

auto opt = options.get("AAA");
ASSERT_TRUE(opt.meta());
ASSERT_EQ(opt.get(1, 256), "BBB");

opt = options.get("CCC");
ASSERT_TRUE(opt.meta());
ASSERT_EQ(opt.get(1, 256), "DDD");
}

0 comments on commit 7fc0b70

Please sign in to comment.