OpenVPN 3 Core Library
Loading...
Searching...
No Matches
cliopt.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 classes encapsulate the basic setup of the various objects needed to
13// create an OpenVPN client session. The basic idea here is to look at both
14// compile time settings (i.e. crypto/SSL/random libraries), and run-time
15// (such as transport layer using UDP, TCP, or HTTP-proxy), and
16// build the actual objects that will be used to construct a client session.
17
18#ifndef OPENVPN_CLIENT_CLIOPT_H
19#define OPENVPN_CLIENT_CLIOPT_H
20
21#include <string>
22#include <tuple>
23#include <unordered_set>
24#include <map>
25#include <set>
26
28
41
53
55
56#ifdef OPENVPN_GREMLIN
58#endif
59
60#ifdef OPENVPN_PLATFORM_ANDROID
62#endif
63
64#ifdef OPENVPN_EXTERNAL_TRANSPORT_FACTORY
67#endif
68
69#ifdef OPENVPN_EXTERNAL_TUN_FACTORY
70// requires that client implements ExternalTun::Factory::new_tun_factory
72#elif defined(USE_TUN_BUILDER)
74#elif defined(OPENVPN_PLATFORM_LINUX) && !defined(OPENVPN_FORCE_TUN_NULL)
76#ifdef OPENVPN_COMMAND_AGENT
78#endif
79#elif defined(OPENVPN_PLATFORM_MAC) && !defined(OPENVPN_FORCE_TUN_NULL)
82#ifdef OPENVPN_COMMAND_AGENT
84#endif
85#elif defined(OPENVPN_PLATFORM_WIN) && !defined(OPENVPN_FORCE_TUN_NULL)
87#ifdef OPENVPN_COMMAND_AGENT
89#endif
90#else
92#endif
93
94#ifdef PRIVATE_TUNNEL_PROXY
95#include <openvpn/pt/ptproxy.hpp>
96#endif
97
98#if defined(ENABLE_KOVPN) || defined(ENABLE_OVPNDCO) || defined(ENABLE_OVPNDCOWIN)
100#endif
101
102#ifndef OPENVPN_UNUSED_OPTIONS
103#define OPENVPN_UNUSED_OPTIONS "UNKNOWN/UNSUPPORTED OPTIONS"
104#endif
105
106namespace openvpn {
107
109{
110
116 {
117 /* explicitly allow slicing to only copy the settings that
118 * are in the common base class \c ConfigCommon */
119 ClientAPI::ConfigCommon::operator=(config);
120
121 if (!config.protoOverride.empty())
123
124 if (config.protoVersionOverride == 4)
126 else if (config.protoVersionOverride == 6)
128
129 if (!config.allowUnusedAddrFamilies.empty())
130 allowUnusedAddrFamilies = TriStateSetting::parse(config.allowUnusedAddrFamilies);
131 }
132
134
136
138
139 /* from eval config */
141};
142
143
144class ClientOptions : public RC<thread_unsafe_refcount>
145{
146 public:
148
150
151 struct Config
152 {
153 /* Options set by the client application.
154 * This class only uses a subset. For simplicity
155 * we keep all client settings here instead of creating a new
156 * subset class of configuration options */
158
164 bool alt_proxy = false;
167
169#ifdef OPENVPN_PLATFORM_ANDROID
170 bool enable_route_emulation = true;
171#endif
172#ifdef OPENVPN_GREMLIN
173 Gremlin::Config::Ptr gremlin_config;
174#endif
175 Stop *stop = nullptr;
176
177 // callbacks -- must remain in scope for lifetime of ClientOptions object
182
183#ifdef USE_TUN_BUILDER
184 TunBuilderBase *builder = nullptr;
185#endif
186
187#ifdef OPENVPN_EXTERNAL_TUN_FACTORY
188 ExternalTun::Factory *extern_tun_factory = nullptr;
189#endif
190
191#ifdef OPENVPN_EXTERNAL_TRANSPORT_FACTORY
192 ExternalTransport::Factory *extern_transport_factory = nullptr;
193#endif
194 };
195
196 ClientOptions(const OptionList &opt, // only needs to remain in scope for duration of constructor call
197 const Config &config)
199 server_addr_float(false),
205 tcp_queue_limit(64),
208#ifdef OPENVPN_GREMLIN
209 gremlin_config(config.gremlin_config),
210#endif
211 autologin(false),
212 autologin_sessions(false),
213 creds_locked(false),
216#ifdef OPENVPN_EXTERNAL_TRANSPORT_FACTORY
217 ,
218 extern_transport_factory(config.extern_transport_factory)
219#endif
220 {
221 // parse general client options
222 const ParseClientConfig pcc(opt);
223
224 // creds
226 autologin = pcc.autologin();
228
229 // digest factory
231
232 // initialize RNG/PRNG
233 rng.reset(new SSLLib::RandomAPI());
234 prng.reset(new MTRand(time(nullptr)));
235
236 // frame
237 // get tun-mtu and tun-mtu-max parameter from config
238 const unsigned int tun_mtu = parse_tun_mtu(opt, 0);
239 const unsigned int tun_mtu_max = std::max(parse_tun_mtu_max(opt, TUN_MTU_DEFAULT + 100), tun_mtu);
240
241 const MSSCtrlParms mc(opt);
242 frame = frame_init(true, tun_mtu_max, mc.mssfix_ctrl, true);
243
244 // TCP queue limit
245 tcp_queue_limit = opt.get_num<decltype(tcp_queue_limit)>("tcp-queue-limit", 1, tcp_queue_limit, 1, 65536);
246
247 // route-nopull
249
250 // OpenVPN Protocol context (including SSL)
251 cp_main = proto_config(opt, config, pcc, false);
252 cp_relay = proto_config(opt, config, pcc, true); // may be null
253
254 CryptoAlgs::allow_default_dc_algs<SSLLib::CryptoAPI>(cp_main->ssl_factory->libctx(),
255 !config.clientconf.enableNonPreferredDCAlgorithms,
256 config.clientconf.enableLegacyAlgorithms);
257
258#if (defined(ENABLE_KOVPN) || defined(ENABLE_OVPNDCO) || defined(ENABLE_OVPNDCOWIN)) && !defined(OPENVPN_FORCE_TUN_NULL) && !defined(OPENVPN_EXTERNAL_TUN_FACTORY)
259 if (config.clientconf.dco)
260#if defined(USE_TUN_BUILDER)
261 dco = DCOTransport::new_controller(config.builder);
262#else
263 dco = DCOTransport::new_controller(nullptr);
264#endif
265#endif
266
267 layer = cp_main->layer;
268
269#ifdef PRIVATE_TUNNEL_PROXY
270 if (config.alt_proxy && !dco)
271 alt_proxy = PTProxy::new_proxy(opt, rng);
272#endif
273
274 // If HTTP proxy parameters are not supplied by API, try to get them from config
277
278 // load remote list
279 if (config.remote_override)
280 {
281 remote_list.reset(new RemoteList(config.remote_override));
283 }
284 else
286 if (!remote_list->defined())
287 throw option_error(ERR_INVALID_CONFIG, "no remote option specified");
288
289 // If running in tun_persist mode, we need to do basic DNS caching so that
290 // we can avoid emitting DNS requests while the tunnel is blocked during
291 // reconnections.
292 remote_list->set_enable_cache(config.clientconf.tunPersist);
293
294 // process server/port/family overrides
295 remote_list->set_server_override(config.clientconf.serverOverride);
296 remote_list->set_port_override(config.clientconf.portOverride);
297 remote_list->set_proto_version_override(config.clientconf.proto_version_override);
298
299 // process protocol override, should be called after set_enable_cache
300 remote_list->handle_proto_override(config.clientconf.proto_override,
302
303 // process remote-random
304 if (opt.exists("remote-random"))
306
307 // get "float" option
308 server_addr_float = opt.exists("float");
309
310 // special remote cache handling for proxies
311 if (alt_proxy)
312 {
313 remote_list->set_enable_cache(false); // remote server addresses will be resolved by proxy
314 alt_proxy->set_enable_cache(config.clientconf.tunPersist);
315 }
316 else if (http_proxy_options)
317 {
318 remote_list->set_enable_cache(false); // remote server addresses will be resolved by proxy
319 http_proxy_options->proxy_server_set_enable_cache(config.clientconf.tunPersist);
320 }
321
323
324 // throw an exception if dco is requested but config/options are dco-incompatible
325 bool dco_compatible = false;
326 std::tie(dco_compatible, std::ignore) = check_dco_compatibility(clientconf, opt);
327 if (config.clientconf.dco && !dco_compatible)
328 {
329 throw option_error(ERR_INVALID_CONFIG, "dco_compatibility: config/options are not compatible with dco");
330 }
331
332#ifdef OPENVPN_PLATFORM_UWP
333 // workaround for OVPN3-62 Busy loop in win_event.hpp
335#endif
336
337 synchronous_dns_lookup = config.synchronous_dns_lookup;
338
339#ifdef OPENVPN_TLS_LINK
340 if (opt.exists("tls-ca"))
341 {
342 tls_ca = opt.cat("tls-ca");
343 }
344#endif
345
346 // init transport config
347 const std::string session_name = load_transport_config();
348
349 // initialize tun/tap
350 if (dco)
351 {
352 DCO::TunConfig tunconf;
353#if defined(OPENVPN_COMMAND_AGENT) && defined(OPENVPN_PLATFORM_WIN)
354 tunconf.setup_factory = WinCommandAgent::new_agent(opt);
355#endif
356 tunconf.tun_prop.layer = layer;
357 tunconf.tun_prop.session_name = session_name;
358 if (tun_mtu)
359 tunconf.tun_prop.mtu = tun_mtu;
360 tunconf.tun_prop.mtu_max = tun_mtu_max;
361 tunconf.tun_prop.google_dns_fallback = config.clientconf.googleDnsFallback;
362 tunconf.tun_prop.dhcp_search_domains_as_split_domains = config.clientconf.dhcpSearchDomainsAsSplitDomains;
364 tunconf.stop = config.stop;
365 tunconf.allow_local_dns_resolvers = config.clientconf.allowLocalDnsResolvers;
366#ifdef OPENVPN_PLATFORM_WIN
367 if (config.clientconf.tunPersist)
368 tunconf.tun_persist.reset(new TunWin::DcoTunPersist(true, TunWrapObjRetain::NO_RETAIN_NO_REPLACE, nullptr));
369#endif
370 tun_factory = dco->new_tun_factory(tunconf, opt);
371 }
372 else
373 {
374#ifdef OPENVPN_EXTERNAL_TUN_FACTORY
375 {
376 ExternalTun::Config tunconf;
377 tunconf.tun_prop.layer = layer;
378 tunconf.tun_prop.session_name = session_name;
379 tunconf.tun_prop.google_dns_fallback = config.clientconf.googleDnsFallback;
380 tunconf.tun_prop.dhcp_search_domains_as_split_domains = config.clientconf.dhcpSearchDomainsAsSplitDomains;
381 if (tun_mtu)
382 tunconf.tun_prop.mtu = tun_mtu;
383 tunconf.tun_prop.mtu_max = tun_mtu_max;
384 tunconf.frame = frame;
385 tunconf.stats = cli_stats;
387 tunconf.tun_persist = config.clientconf.tunPersist;
388 tunconf.stop = config.stop;
389 tun_factory.reset(config.extern_tun_factory->new_tun_factory(tunconf, opt));
390 if (!tun_factory)
391 throw option_error(ERR_INVALID_CONFIG, "OPENVPN_EXTERNAL_TUN_FACTORY: no tun factory");
392 }
393#elif defined(USE_TUN_BUILDER)
394 {
396 tunconf->builder = config.builder;
397 tunconf->tun_prop.session_name = session_name;
398 tunconf->tun_prop.google_dns_fallback = config.clientconf.googleDnsFallback;
399 tunconf->tun_prop.dhcp_search_domains_as_split_domains = config.clientconf.dhcpSearchDomainsAsSplitDomains;
400 tunconf->tun_prop.allow_local_lan_access = config.clientconf.allowLocalLanAccess;
401 if (tun_mtu)
402 tunconf->tun_prop.mtu = tun_mtu;
403 tunconf->tun_prop.mtu_max = tun_mtu_max;
404 tunconf->frame = frame;
405 tunconf->stats = cli_stats;
406 tunconf->tun_prop.remote_list = remote_list;
407 tun_factory = tunconf;
408#if defined(OPENVPN_PLATFORM_IPHONE)
409 tunconf->retain_sd = true;
410 tunconf->tun_prefix = true;
411 if (config.clientconf.tunPersist)
412 tunconf->tun_prop.remote_bypass = true;
413#endif
414#if defined(OPENVPN_PLATFORM_ANDROID)
415 // Android VPN API only supports excluded IP prefixes starting with Android 13/API 33,
416 // so we must emulate them for earlier platforms
417 if (config.enable_route_emulation)
418 {
419 tunconf->eer_factory.reset(new EmulateExcludeRouteFactoryImpl(false));
420 }
421 else
422 {
423 tunconf->eer_factory.reset(nullptr);
424 }
425#endif
426#if defined(OPENVPN_PLATFORM_MAC)
427 tunconf->tun_prefix = true;
428#endif
429 if (config.clientconf.tunPersist)
430 tunconf->tun_persist.reset(new TunBuilderClient::TunPersist(true, tunconf->retain_sd ? TunWrapObjRetain::RETAIN : TunWrapObjRetain::NO_RETAIN, config.builder));
431 tun_factory = tunconf;
432 }
433#elif defined(OPENVPN_PLATFORM_LINUX) && !defined(OPENVPN_FORCE_TUN_NULL)
434 {
436 tunconf->tun_prop.layer = layer;
437 tunconf->tun_prop.session_name = session_name;
438 if (tun_mtu)
439 tunconf->tun_prop.mtu = tun_mtu;
440 tunconf->tun_prop.mtu_max = tun_mtu_max;
441 tunconf->tun_prop.google_dns_fallback = config.clientconf.googleDnsFallback;
442 tunconf->tun_prop.dhcp_search_domains_as_split_domains = config.clientconf.dhcpSearchDomainsAsSplitDomains;
443 tunconf->generate_tun_builder_capture_event = config.clientconf.generateTunBuilderCaptureEvent;
444 tunconf->tun_prop.remote_list = remote_list;
445 tunconf->frame = frame;
446 tunconf->stats = cli_stats;
447 if (config.clientconf.tunPersist)
448 tunconf->tun_persist.reset(new TunLinux::TunPersist(true, TunWrapObjRetain::NO_RETAIN, nullptr));
449 tunconf->load(opt);
450 tun_factory = tunconf;
451 }
452#elif defined(OPENVPN_PLATFORM_MAC) && !defined(OPENVPN_FORCE_TUN_NULL)
453 {
455 tunconf->tun_prop.layer = layer;
456 tunconf->tun_prop.session_name = session_name;
457 tunconf->tun_prop.google_dns_fallback = config.clientconf.googleDnsFallback;
458 tunconf->tun_prop.dhcp_search_domains_as_split_domains = config.clientconf.dhcpSearchDomainsAsSplitDomains;
459 if (tun_mtu)
460 tunconf->tun_prop.mtu = tun_mtu;
461 tunconf->tun_prop.mtu_max = tun_mtu_max;
462 tunconf->frame = frame;
463 tunconf->stats = cli_stats;
464 tunconf->stop = config.stop;
465 if (config.clientconf.tunPersist)
466 {
467 tunconf->tun_persist.reset(new TunMac::TunPersist(true, TunWrapObjRetain::NO_RETAIN, nullptr));
468#ifndef OPENVPN_COMMAND_AGENT
469 /* remote_list is required by remote_bypass to work */
470 tunconf->tun_prop.remote_bypass = true;
471 tunconf->tun_prop.remote_list = remote_list;
472#endif
473 }
475#ifdef OPENVPN_COMMAND_AGENT
476 tunconf->tun_setup_factory = UnixCommandAgent::new_agent(opt);
477#endif
478 tun_factory = tunconf;
479 }
480#elif defined(OPENVPN_PLATFORM_WIN) && !defined(OPENVPN_FORCE_TUN_NULL)
481 {
483 tunconf->tun_prop.layer = layer;
484 tunconf->tun_prop.session_name = session_name;
485 tunconf->tun_prop.google_dns_fallback = config.clientconf.googleDnsFallback;
486 tunconf->tun_prop.dhcp_search_domains_as_split_domains = config.clientconf.dhcpSearchDomainsAsSplitDomains;
487 if (tun_mtu)
488 tunconf->tun_prop.mtu = tun_mtu;
489 tunconf->tun_prop.mtu_max = tun_mtu_max;
490 tunconf->frame = frame;
491 tunconf->stats = cli_stats;
492 tunconf->stop = config.stop;
493 tunconf->tun_type = config.clientconf.wintun ? TunWin::Wintun : TunWin::TapWindows6;
494 tunconf->allow_local_dns_resolvers = config.clientconf.allowLocalDnsResolvers;
495 if (config.clientconf.tunPersist)
496 {
497 tunconf->tun_persist.reset(new TunWin::TunPersist(true, TunWrapObjRetain::NO_RETAIN, nullptr));
498#ifndef OPENVPN_COMMAND_AGENT
499 /* remote_list is required by remote_bypass to work */
500 tunconf->tun_prop.remote_bypass = true;
501 tunconf->tun_prop.remote_list = remote_list;
502#endif
503 }
504#ifdef OPENVPN_COMMAND_AGENT
505 tunconf->tun_setup_factory = WinCommandAgent::new_agent(opt);
506#endif
507 tun_factory = tunconf;
508 }
509#else
510 {
512 tunconf->frame = frame;
513 tunconf->stats = cli_stats;
514 tun_factory = tunconf;
515 }
516#endif
517 }
518
519 // The Core Library itself does not handle TAP/OSI_LAYER_2 currently,
520 // so we bail out early whenever someone tries to use TAP configurations
522 throw ErrorCode(Error::TAP_NOT_SUPPORTED, true, "OSI layer 2 tunnels are not currently supported");
523
524 // server-poll-timeout
525 {
526 const Option *o = opt.get_ptr("server-poll-timeout");
527 if (o)
528 server_poll_timeout_ = parse_number_throw<unsigned int>(o->get(1, 16), "server-poll-timeout");
529 }
530
531 // create default creds object in case submit_creds is not called,
532 // and populate it with embedded creds, if available
533 {
534 ClientCreds::Ptr cc = new ClientCreds();
535 if (pcc.hasEmbeddedPassword())
536 {
539 submit_creds(cc);
540 creds_locked = true;
541 }
542 else if (autologin_sessions)
543 {
544 submit_creds(cc);
545 creds_locked = true;
546 }
547 else
548 {
549 submit_creds(cc);
550 }
551 }
552
553 // configure push_base, a set of base options that will be combined with
554 // options pushed by server.
555 {
557
558 // base options where multiple options of the same type can aggregate
559 push_base->multi.extend(opt, "route");
560 push_base->multi.extend(opt, "route-ipv6");
561 push_base->multi.extend(opt, "redirect-gateway");
562 push_base->multi.extend(opt, "redirect-private");
563 push_base->multi.extend(opt, "dhcp-option");
564
565 // base options which need to be merged, not just aggregated
566 push_base->merge.extend(opt, "dns");
567
568 // base options where only a single instance of each option makes sense
569 push_base->singleton.extend(opt, "redirect-dns");
570 push_base->singleton.extend(opt, "inactive");
571 push_base->singleton.extend(opt, "route-metric");
572
573 // IPv6
574 {
575 const unsigned int n6 = push_base->singleton.extend(opt, "block-ipv6");
576 const unsigned int n4 = push_base->singleton.extend(opt, "block-ipv4");
577
578 if (!n6 && config.clientconf.allowUnusedAddrFamilies() == TriStateSetting::No)
579 {
580 push_base->singleton.emplace_back("block-ipv6");
581 }
582 if (!n4 && config.clientconf.allowUnusedAddrFamilies() == TriStateSetting::No)
583 {
584 push_base->singleton.emplace_back("block-ipv4");
585 }
586 }
587 }
588
590 }
591
592 // If those options are present, dco cannot be used
593 inline static std::unordered_set<std::string> dco_incompatible_opts = {
594 "http-proxy",
595 "compress",
596 "comp-lzo"};
597
598
602 static std::tuple<bool, std::string> check_dco_compatibility(const ClientAPI::ConfigCommon &config, const OptionList &opt)
603 {
604#ifdef ENABLE_KOVPN
605 // only care about dco/dco-win
606 return std::make_tuple(true, "");
607#else
608
609 std::vector<std::string> reasons;
610
611 for (auto &optname : dco_incompatible_opts)
612 {
613 if (opt.exists(optname))
614 {
615 reasons.push_back("option " + optname + " is not compatible with dco");
616 }
617 }
618
619 if (config.enableLegacyAlgorithms)
620 {
621 reasons.emplace_back("legacy algorithms are not compatible with dco");
622 }
623
624 if (config.enableNonPreferredDCAlgorithms)
625 {
626 reasons.emplace_back("non-preferred data channel algorithms are not compatible with dco");
627 }
628
629 if (!config.proxyHost.empty())
630 {
631 reasons.emplace_back("proxyHost config setting is not compatible with dco");
632 }
633
634 if (reasons.empty())
635 {
636 return std::make_tuple(true, "");
637 }
638
639 return std::make_tuple(false, string::join(reasons, "\n"));
640
641#endif
642 }
643
645 {
646 // secret option not supported
647 if (opt.exists("secret"))
648 throw option_error(ERR_INVALID_OPTION_CRYPTO, "sorry, static key encryption mode (non-SSL/TLS) is not supported");
649
650 // fragment option not supported
651 if (opt.exists("fragment"))
652 throw option_error(ERR_INVALID_OPTION_VAL, "sorry, 'fragment' directive is not supported, nor is connecting to a server that uses 'fragment' directive");
653
654 if (!opt.exists("client"))
655 throw option_error(ERR_INVALID_CONFIG, "Neither 'client' nor both 'tls-client' and 'pull' options declared. OpenVPN3 client only supports --client mode.");
656
657 // Only p2p mode accept
658 if (opt.exists("mode"))
659 {
660 const auto &mode = opt.get("mode");
661 if (mode.size() != 2 || mode.get(1, 128) != "p2p")
662 {
663 throw option_error(ERR_INVALID_CONFIG, "Only 'mode p2p' supported");
664 }
665 }
666
667 // key-method 2 is the only thing that 2.5+ and 3.x support
668 if (opt.exists("key-method"))
669 {
670 auto keymethod = opt.get("key-method");
671 if (keymethod.size() != 2 || keymethod.get(1, 128) != "2")
672 {
673 throw option_error(ERR_INVALID_OPTION_VAL, "Only 'key-method 2' is supported: " + keymethod.get(1, 128));
674 }
675 }
676 }
677
678 std::unordered_set<std::string> settings_ignoreWithWarning = {
679 "allow-compression", /* TODO: maybe check against our client option compression setting? */
680 "allow-recursive-routing",
681 "auth-retry",
682 "compat-mode",
683 "connect-retry",
684 "connect-retry-max",
685 "connect-timeout", /* TODO: this should be really implemented */
686 "data-ciphers", /* TODO: maybe add more special warning that checks it against our supported ciphers */
687 "data-ciphers-fallback",
688 "disable-dco", /* TODO: maybe throw an error if DCO is active? */
689 "disable-occ",
690 "engine",
691 "explicit-exit-notify", /* ignoring it in config does not break connection or functionality */
692 "group",
693 "ifconfig-nowarn", /* v3 does not do OCC checks */
694 "ip-win32",
695 "keepalive", /* A push only feature (ping/ping-restart) in v3. Ignore with warning since often present in configs too */
696 "link-mtu",
697 "machine-readable-output", /* would be set by a CliOptions */
698 "mark", /* enables SO_MARK */
699 "mute",
700 "ncp-ciphers",
701 "nice",
702 "opt-verify",
703 "passtos",
704 "persist-key",
705 "persist-tun",
706 "preresolve",
707 "providers", /* Done via client options */
708 "remap-usr1",
709 "reneg-bytes",
710 "reneg-pkts",
711 "replay-window",
712 "resolv-retry",
713 "route-method", /* Windows specific fine tuning option */
714 "route-delay",
715 "show-net-up",
716 "socket-flags",
717 "suppress-timestamps", /* harmless to ignore */
718 "tcp-nodelay",
719 "tls-version-max", /* We don't allow restricting max version */
720 "tun-mtu-extra", /* (only really used in tap in OpenVPN 2.x)*/
721 "udp-mtu", /* Alias for link-mtu */
722 "user",
723 };
724
725 std::unordered_set<std::string> settings_serverOnlyOptions = {
726 "auth-gen-token",
727 "auth-gen-token-secret",
728 "auth-user-pass-optional",
729 "auth-user-pass-verify",
730 "bcast-buffers",
731 "ccd-exclusive",
732 "client-config-dir",
733 "client-connect",
734 "client-disconnect",
735 "client-to-client",
736 "connect-freq",
737 "dh",
738 "disable",
739 "duplicate-cn",
740 "hash-size",
741 "ifconfig-ipv6-pool",
742 "ifconfig-pool",
743 "ifconfig-pool-persist",
744 "ifconfig-push",
745 "ifconfig-push-constraint",
746 "iroute",
747 "iroute-ipv6",
748 "max-clients",
749 "max-routes-per-client",
750 "push",
751 "push-remove",
752 "push-reset",
753 "server",
754 "server-bridge",
755 "server-ipv6",
756 "stale-routes-check",
757 "tls-crypt-v2-verify",
758 "username-as-common-name",
759 "verify-client-cert",
760 "vlan-accept",
761 "vlan-pvid",
762 "vlan-tagging",
763 };
764
765 /* Features not implemented and not safe to ignore */
766 std::unordered_set<std::string> settings_feature_not_implemented_fatal = {
767 "askpass",
768 "capath",
769 "cd",
770 "chroot",
771 "client-nat",
772 "cryptoapicert",
773 "daemon",
774 "daemon",
775 "errors-to-stderr",
776 "gremlin",
777 "lladdr",
778 "log",
779 "log",
780 "log-append",
781 "management",
782 "memstats",
783 "msg-channel", /* (Windows service in v2) */
784 "ping-timer-rem",
785 "single-session", /* This option is quite obscure but changes behaviour enough to not ignore it */
786 "socks-proxy",
787 "status",
788 "status-version",
789 "syslog",
790 "tls-server", /* No p2p mode in v3 */
791 "verify-hash",
792 "win-sys",
793 "writepid",
794 "x509-username-field",
795 };
796
797 /* Features not implemented but safe enough to ignore */
798 std::unordered_set<std::string> settings_feature_not_implemented_warn = {
799 "allow-pull-fqdn",
800 "bind",
801 "local",
802 "lport",
803 "mlock",
804 "mtu-disc",
805 "mtu-test",
806 "persist-local-ip",
807 "persist-remote-ip",
808 "shaper",
809 "tls-exit",
810 };
811
812 /* Push only options (some are allowed in the config in OpenVPN 2
813 * but really push only options) */
814 std::unordered_set<std::string> settings_pushonlyoptions = {
815 "auth-token",
816 "auth-token-user",
817 "echo",
818 "parameter",
819 "ping",
820 "ping-exit",
821 "ping-restart", /* ping related options are pull only in v3, v2 needs them in the config for pure p2p */
822 "key-derivation",
823 "peer-id",
824 "protocol-flags",
825 "ifconfig",
826 "ifconfig-ipv6",
827 "topology",
828 "route-gateway"};
829
830 /* Features related to scripts/plugins */
831 std::unordered_set<std::string> settings_script_plugin_feature = {
832 "down",
833 "down-pre",
834 "ifconfig-noexec",
835 "ipchange",
836 "learn-address",
837 "plugin",
838 "route-noexec",
839 "route-pre-down",
840 "route-up",
841 "setenv-safe",
842 "tls-export-cert",
843 "tls-verify",
844 "up",
845 "up-delay",
846 "x509-track"};
847
848 /* Standalone OpenVPN v2 modes */
849 std::unordered_set<std::string> settings_standalone_options = {
850 "genkey",
851 "mktun",
852 "rmtun",
853 "show-ciphers",
854 "show-curves",
855 "show-digests",
856 "show-engines",
857 "show-groups",
858 "show-tls",
859 "test-crypto"};
860
861 /* Deprecated/throwing error in OpenVPN 2.x already: */
862 std::unordered_set<std::string> settings_removedOptions = {
863 "mtu-dynamic", "no-replay", "no-name-remapping", "compat-names", "ncp-disable", "no-iv"};
864
865 std::unordered_set<std::string> settings_ignoreSilently = {
866 "ecdh-curve", /* Deprecated in v2, not needed with modern OpenSSL */
867 "fast-io",
868 "max-routes",
869 "mute-replay-warnings",
870 "nobind", /* only behaviour in v3 client anyway */
871 "prng",
872 "rcvbuf", /* present in many configs */
873 "replay-persist", /* Makes little sense in TLS mode */
874 "script-security",
875 "sndbuf",
876 "tmp-dir",
877 "tun-ipv6", /* ignored in v2 as well */
878 "txqueuelen", /* so platforms evaluate that in tun, some do not, do not warn about that */
879 "verb"};
880
882 {
883 public:
884 void add_failed_opt(const Option &o, const std::string &message, bool fatal_arg)
885 {
886 if (!options_per_category.contains(message))
887 {
889 }
890
891 fatal |= fatal_arg;
892 options_per_category[message].push_back(o);
893 }
894
896 {
897 std::ostringstream os;
898
899 for (const auto &[category, options] : options_per_category)
900 {
901 if (!options.empty())
902 {
903 OPENVPN_LOG(category);
904
905 os << category << ": ";
906 std::vector<std::string> opts;
907 for (size_t i = 0; i < options.size(); ++i)
908 {
909 auto &o = options[i];
910 OPENVPN_LOG(std::to_string(i) << ' ' << o.render(Option::RENDER_BRACKET | Option::RENDER_TRUNC_64));
911 opts.push_back(o.get(0, 64));
912 }
913
914 os << string::join(opts, ",") << '\n';
915 }
916 }
917
918 if (fatal)
919 {
920 throw ErrorCode(Error::UNUSED_OPTIONS, true, os.str());
921 }
922 }
923
924 private:
925 std::map<std::string, std::vector<Option>> options_per_category;
926 bool fatal = false;
927 };
928
939 {
940 /* Meta options that AS profiles often have that we do not parse and
941 * can ignore without warning */
942 std::unordered_set<std::string> ignoreMetaOptions = {
943 "CLI_PREF_ALLOW_WEB_IMPORT",
944 "CLI_PREF_BASIC_CLIENT",
945 "CLI_PREF_ENABLE_CONNECT",
946 "CLI_PREF_ENABLE_XD_PROXY",
947 "WSHOST",
948 "WEB_CA_BUNDLE",
949 "IS_OPENVPN_WEB_CA",
950 "NO_WEB",
951 "ORGANIZATION"};
952
953 std::unordered_set<std::string> ignore_unknown_option_list;
954
955 if (opt.exists("ignore-unknown-option"))
956 {
957 auto igOptlist = opt.get_index("ignore-unknown-option");
958 for (auto igUnOptIdx : igOptlist)
959 {
960 const Option &o = opt[igUnOptIdx];
961 for (size_t i = 1; i < o.size(); i++)
962 {
963 const auto &optionToIgnore = o.get(i, 0);
964
965 ignore_unknown_option_list.insert(optionToIgnore);
966 }
967 o.touch();
968 }
969 }
970
971 for (const auto &o : opt)
972 {
973 if (!o.meta() && settings_ignoreSilently.contains(o.get(0, 0)))
974 {
975 o.touch();
976 }
977 if (o.meta() && ignoreMetaOptions.contains(o.get(0, 0)))
978 {
979 o.touch();
980 }
981 }
982
983 /* Mark all options that will not trigger any kind of message
984 * as touched to avoid an empty message with unused options */
985 if (opt.n_unused() == 0)
986 return;
987
988 OPENVPN_LOG_NTNL("NOTE: This configuration contains options that were not used:\n");
989
990 OptionErrors errors{};
991
992 /* Go through all options and check all options that have not been
993 * touched (parsed) yet */
994 showUnusedOptionsByList(opt, settings_removedOptions, "Removed deprecated option", true, errors);
995 showUnusedOptionsByList(opt, settings_serverOnlyOptions, "Server only option", true, errors);
996 showUnusedOptionsByList(opt, settings_standalone_options, "OpenVPN 2.x command line operation", true, errors);
997 showUnusedOptionsByList(opt, settings_feature_not_implemented_warn, "Feature not implemented (option ignored)", false, errors);
998 showUnusedOptionsByList(opt, settings_pushonlyoptions, "Option allowed only to be pushed by the server", true, errors);
999 showUnusedOptionsByList(opt, settings_script_plugin_feature, "Ignored (no script/plugin support)", false, errors);
1000 showUnusedOptionsByList(opt, ignore_unknown_option_list, "Ignored by option 'ignore-unknown-option'", false, errors);
1001 showUnusedOptionsByList(opt, settings_ignoreWithWarning, "Unsupported option (ignored)", false, errors);
1002
1003 auto ignoredBySetenvOpt = [](const Option &option)
1004 { return !option.touched() && option.warnonlyunknown(); };
1005 showOptionsByFunction(opt, ignoredBySetenvOpt, "Ignored options prefixed with 'setenv opt'", false, errors);
1006
1007 auto unusedMetaOpt = [](const Option &option)
1008 { return !option.touched() && option.meta(); };
1009 showOptionsByFunction(opt, unusedMetaOpt, "Unused ignored meta options", false, errors);
1010
1011 auto managmentOpt = [](const Option &option)
1012 { return !option.touched() && option.get(0, 0).rfind("management", 0) == 0; };
1013 showOptionsByFunction(opt, managmentOpt, "OpenVPN management interface is not supported by this client", true, errors);
1014
1015 // If we still have options that are unaccounted for, we print them and throw an error or just warn about them
1016 auto onlyLightlyTouchedOptions = [](const Option &option)
1017 { return option.touched_lightly(); };
1018 showOptionsByFunction(opt, onlyLightlyTouchedOptions, "Unused options, probably specified multiple times in the configuration file", false, errors);
1019
1020 auto nonTouchedOptions = [](const Option &option)
1021 { return !option.touched() && !option.touched_lightly(); };
1022 showOptionsByFunction(opt, nonTouchedOptions, OPENVPN_UNUSED_OPTIONS, true, errors);
1023
1024 errors.print_option_errors();
1025 }
1026
1027 void showUnusedOptionsByList(const OptionList &optlist, std::unordered_set<std::string> option_set, const std::string &message, bool fatal, OptionErrors &errors)
1028 {
1029 auto func = [&option_set](const Option &opt)
1030 { return !opt.touched() && option_set.contains(opt.get(0, 0)); };
1031 showOptionsByFunction(optlist, func, message, fatal, errors);
1032 }
1033
1034 /* lambda expression that capture variables have complex signatures, avoid these by letting the compiler
1035 * itself figure it out with a template */
1036 template <typename T>
1037 void showOptionsByFunction(const OptionList &opt, T func, const std::string &message, bool fatal, OptionErrors &errors)
1038 {
1039 for (size_t i = 0; i < opt.size(); ++i)
1040 {
1041 auto &o = opt[i];
1042 if (func(o))
1043 {
1044 o.touch();
1045
1046 errors.add_failed_opt(o, message, fatal);
1047 }
1048 }
1049 }
1050
1052 {
1054
1055 // autologin sessions
1057 pi->emplace_back("IV_AUTO_SESS", "1");
1058
1059 if (pcc.pushPeerInfo())
1060 {
1061 /* If we override the HWADDR, we add it at this time statically. If we need to
1062 * dynamically discover it from the transport it will be added in
1063 * \c build_connect_time_peer_info_string instead */
1064 if (!config.clientconf.hwAddrOverride.empty())
1065 {
1066 pi->emplace_back("IV_HWADDR", config.clientconf.hwAddrOverride);
1067 }
1068
1069 pi->emplace_back("IV_SSL", get_ssl_library_version());
1070
1071 if (!config.clientconf.platformVersion.empty())
1072 pi->emplace_back("IV_PLAT_VER", config.clientconf.platformVersion);
1073
1074 /* ensure that we use only one variable with the same name */
1075 std::unordered_map<std::string, std::string> extra_values;
1076
1077 if (pcc.peerInfoUV())
1078 {
1079 for (const auto &kv : *pcc.peerInfoUV())
1080 {
1081 extra_values[kv.key] = kv.value;
1082 }
1083 }
1084
1085 /* Config::peerInfo takes precedence */
1086 if (config.extra_peer_info.get())
1087 {
1088 for (const auto &kv : *config.extra_peer_info.get())
1089 {
1090 extra_values[kv.key] = kv.value;
1091 }
1092 }
1093
1094 for (auto kv : extra_values)
1095 {
1096 pi->emplace_back(kv.first, kv.second);
1097 }
1098 }
1099
1100 // UI version
1101 if (!config.clientconf.guiVersion.empty())
1102 pi->emplace_back("IV_GUI_VER", config.clientconf.guiVersion);
1103
1104 // Supported SSO methods
1105 if (!config.clientconf.ssoMethods.empty())
1106 pi->emplace_back("IV_SSO", config.clientconf.ssoMethods);
1107
1108 if (!config.clientconf.appCustomProtocols.empty())
1109 pi->emplace_back("IV_ACC", "2048,6:A," + config.clientconf.appCustomProtocols);
1110
1111 return pi;
1112 }
1113
1115 {
1116 bool omit_next = false;
1117
1118 if (alt_proxy)
1119 omit_next = alt_proxy->next();
1120 if (!omit_next)
1121 remote_list->next(type);
1123 }
1124
1129
1131 {
1132 if (reconnect_notify)
1134 return false;
1135 }
1136
1138 {
1140 }
1141
1149 Client::Config::Ptr client_config(const bool relay_mode)
1150 {
1151 Client::Config::Ptr cli_config = new Client::Config;
1152
1153 // Copy ProtoConfig so that modifications due to server push will
1154 // not persist across client instantiations.
1155 cli_config->proto_context_config.reset(new ProtoContext::ProtoConfig(proto_config_cached(relay_mode)));
1156
1157 cli_config->proto_context_options = proto_context_options;
1158 cli_config->push_base = push_base;
1159 cli_config->transport_factory = transport_factory;
1160 cli_config->tun_factory = tun_factory;
1161 cli_config->cli_stats = cli_stats;
1162 cli_config->cli_events = cli_events;
1163 cli_config->creds = creds;
1164 cli_config->pushed_options_filter = pushed_options_filter;
1165 cli_config->tcp_queue_limit = tcp_queue_limit;
1166 cli_config->echo = clientconf.echo;
1167 cli_config->info = clientconf.info;
1168 cli_config->autologin_sessions = autologin_sessions;
1169
1170 // if the previous client instance had session-id, it must be used by the new instance too
1171 if (creds && creds->session_id_defined())
1172 {
1173 cli_config->proto_context_config->set_xmit_creds(true);
1174 }
1175
1176 return cli_config;
1177 }
1178
1179 bool need_creds() const
1180 {
1181 return !autologin;
1182 }
1183
1184 void submit_creds(const ClientCreds::Ptr &creds_arg)
1185 {
1186 if (!creds_arg)
1187 return;
1188
1189 // Override HTTP proxy credentials if provided dynamically
1191 http_proxy_options->username = creds_arg->get_http_proxy_username();
1193 http_proxy_options->password = creds_arg->get_http_proxy_password();
1194
1195 if (!creds_locked)
1196 {
1197 // if no username is defined in creds and userlocked_username is defined
1198 // in profile, set the creds username to be the userlocked_username
1199 if (!creds_arg->username_defined() && !userlocked_username.empty())
1200 {
1202 creds_arg->save_username_for_session_id();
1203 }
1204 creds = creds_arg;
1205 }
1206 }
1207
1209 {
1210 return !http_proxy_options;
1211 }
1212
1213 Time::Duration server_poll_timeout() const
1214 {
1215 return Time::Duration::seconds(server_poll_timeout_);
1216 }
1217
1219 {
1220 return *cli_stats;
1221 }
1223 {
1224 return cli_stats;
1225 }
1227 {
1228 return *cli_events;
1229 }
1231 {
1232 return client_lifecycle.get();
1233 }
1234
1235 int conn_timeout() const
1236 {
1237 return clientconf.connTimeout;
1238 }
1239
1241 {
1242 return asio_work_always_on_;
1243 }
1244
1246 {
1248 if (alt_proxy)
1249 {
1250 alt_proxy->precache(r);
1251 if (r)
1252 return r;
1253 }
1255 {
1256 http_proxy_options->proxy_server_precache(r);
1257 if (r)
1258 return r;
1259 }
1260 return remote_list;
1261 }
1262
1264 {
1265 now_.update();
1266 }
1267
1268 void finalize(const bool disconnected)
1269 {
1270 if (tun_factory)
1271 tun_factory->finalize(disconnected);
1272 }
1273
1274 private:
1276 {
1277 if (relay_mode && cp_relay)
1278 return *cp_relay;
1279 return *cp_main;
1280 }
1281
1283 const Config &config,
1284 const ParseClientConfig &pcc,
1285 const bool relay_mode)
1286 {
1287 // relay mode is null unless one of the below directives is defined
1288 if (relay_mode && !opt.exists("relay-mode"))
1290
1291 // load flags
1292 unsigned int lflags = SSLConfigAPI::LF_PARSE_MODE;
1293 if (relay_mode)
1295
1296 // client SSL config
1297 SSLLib::SSLAPI::Config::Ptr cc(new SSLLib::SSLAPI::Config());
1298 cc->set_external_pki_callback(config.external_pki, config.clientconf.external_pki_alias);
1299 cc->set_frame(frame);
1300 cc->set_flags(SSLConst::LOG_VERIFY_STATUS);
1301 cc->set_debug_level(config.clientconf.sslDebugLevel);
1302 cc->set_rng(rng);
1303 cc->set_local_cert_enabled(pcc.clientCertEnabled() && !config.clientconf.disableClientCert);
1304 /* load depends on private key password and legacy algorithms */
1305 cc->enable_legacy_algorithms(config.clientconf.enableLegacyAlgorithms);
1306 cc->set_private_key_password(config.clientconf.privateKeyPassword);
1307 cc->load(opt, lflags);
1308 cc->set_tls_version_min_override(config.clientconf.tlsVersionMinOverride);
1309 cc->set_tls_cert_profile_override(config.clientconf.tlsCertProfileOverride);
1310 cc->set_tls_cipher_list(config.clientconf.tlsCipherList);
1311 cc->set_tls_ciphersuite_list(config.clientconf.tlsCiphersuitesList);
1312
1313 // client ProtoContext config
1315 cp->ssl_factory = cc->new_factory();
1316 cp->relay_mode = relay_mode;
1317 cp->dc.set_factory(new CryptoDCSelect<SSLLib::CryptoAPI>(cp->ssl_factory->libctx(), frame, cli_stats, rng));
1318 cp->dc_deferred = true; // defer data channel setup until after options pull
1319 cp->tls_auth_factory.reset(new CryptoOvpnHMACFactory<SSLLib::CryptoAPI>());
1320 cp->tls_crypt_factory.reset(new CryptoTLSCryptFactory<SSLLib::CryptoAPI>());
1321 cp->tls_crypt_metadata_factory.reset(new CryptoTLSCryptMetadataFactory());
1322 cp->tlsprf_factory.reset(new CryptoTLSPRFFactory<SSLLib::CryptoAPI>());
1323 cp->load(opt, *proto_context_options, config.default_key_direction, false);
1324 cp->set_xmit_creds(!autologin || pcc.hasEmbeddedPassword() || autologin_sessions);
1325 cp->extra_peer_info = build_peer_info(config, pcc, autologin_sessions);
1326 cp->extra_peer_info_push_peerinfo = pcc.pushPeerInfo();
1327 cp->frame = frame;
1328 cp->now = &now_;
1329 cp->rng = rng;
1330 cp->prng = prng;
1331
1332 return cp;
1333 }
1334
1336 {
1337 // get current transport protocol
1338 const Protocol &transport_protocol = remote_list->current_transport_protocol();
1339
1340 // If we are connecting over a proxy, and TCP protocol is required, but current
1341 // transport protocol is NOT TCP, we will throw an internal error because this
1342 // should have been caught earlier in RemoteList::handle_proto_override.
1343
1344 // construct transport object
1345#ifdef OPENVPN_EXTERNAL_TRANSPORT_FACTORY
1346 ExternalTransport::Config transconf;
1347 transconf.remote_list = remote_list;
1348 transconf.frame = frame;
1349 transconf.stats = cli_stats;
1350 transconf.socket_protect = socket_protect;
1353 transconf.protocol = transport_protocol;
1354 transport_factory = extern_transport_factory->new_transport_factory(transconf);
1355#ifdef OPENVPN_GREMLIN
1356 udpconf->gremlin_config = gremlin_config;
1357#endif
1358
1359#else
1360 if (dco)
1361 {
1362 DCO::TransportConfig transconf;
1363 transconf.protocol = transport_protocol;
1364 transconf.remote_list = remote_list;
1365 transconf.frame = frame;
1366 transconf.stats = cli_stats;
1368 transconf.socket_protect = socket_protect;
1370 }
1371 else if (alt_proxy)
1372 {
1373 if (alt_proxy->requires_tcp() && !transport_protocol.is_tcp())
1374 throw option_error(ERR_INVALID_CONFIG, "internal error: no TCP server entries for " + alt_proxy->name() + " transport");
1375 AltProxy::Config conf;
1376 conf.remote_list = remote_list;
1377 conf.frame = frame;
1378 conf.stats = cli_stats;
1381 conf.rng = rng;
1383 }
1384 else if (http_proxy_options)
1385 {
1386 if (!transport_protocol.is_tcp())
1387 throw option_error(ERR_INVALID_CONFIG, "internal error: no TCP server entries for HTTP proxy transport");
1388
1389 // HTTP Proxy transport
1391 httpconf->remote_list = remote_list;
1392 httpconf->frame = frame;
1393 httpconf->stats = cli_stats;
1394 httpconf->digest_factory.reset(new CryptoDigestFactory<SSLLib::CryptoAPI>(cp_main->ssl_factory->libctx()));
1395 httpconf->socket_protect = socket_protect;
1396 httpconf->http_proxy_options = http_proxy_options;
1397 httpconf->rng = rng;
1398#ifdef PRIVATE_TUNNEL_PROXY
1399 httpconf->skip_html = true;
1400#endif
1401 transport_factory = httpconf;
1402 }
1403 else
1404 {
1405 if (transport_protocol.is_udp())
1406 {
1407 // UDP transport
1409 udpconf->remote_list = remote_list;
1410 udpconf->frame = frame;
1411 udpconf->stats = cli_stats;
1412 udpconf->socket_protect = socket_protect;
1413 udpconf->server_addr_float = server_addr_float;
1414#ifdef OPENVPN_GREMLIN
1415 udpconf->gremlin_config = gremlin_config;
1416#endif
1417 transport_factory = udpconf;
1418 }
1419 else if (transport_protocol.is_tcp()
1420#ifdef OPENVPN_TLS_LINK
1421 || transport_protocol.is_tls()
1422#endif
1423 )
1424 {
1425 // TCP transport
1427 tcpconf->remote_list = remote_list;
1428 tcpconf->frame = frame;
1429 tcpconf->stats = cli_stats;
1430 tcpconf->socket_protect = socket_protect;
1431#ifdef OPENVPN_TLS_LINK
1432 if (transport_protocol.is_tls())
1433 tcpconf->use_tls = true;
1434 tcpconf->tls_ca = tls_ca;
1435#endif
1436#ifdef OPENVPN_GREMLIN
1437 tcpconf->gremlin_config = gremlin_config;
1438#endif
1439 transport_factory = tcpconf;
1440 }
1441 else
1442 throw option_error(ERR_INVALID_OPTION_VAL, "internal error: unknown transport protocol");
1443 }
1444#endif // OPENVPN_EXTERNAL_TRANSPORT_FACTORY
1446 }
1447 // General client options.
1449
1450 Time now_; // current time
1467 unsigned int tcp_queue_limit;
1470#ifdef OPENVPN_GREMLIN
1471 Gremlin::Config::Ptr gremlin_config;
1472#endif
1484#ifdef OPENVPN_EXTERNAL_TRANSPORT_FACTORY
1485 ExternalTransport::Factory *extern_transport_factory;
1486#endif
1487#ifdef OPENVPN_TLS_LINK
1488 std::string tls_ca;
1489#endif
1490};
1491} // namespace openvpn
1492
1493#endif
bool username_defined() const
Definition clicreds.hpp:125
void set_username(const std::string &username_arg)
Definition clicreds.hpp:35
std::string get_http_proxy_username() const
Definition clicreds.hpp:115
bool http_proxy_password_defined() const
Definition clicreds.hpp:140
std::string get_http_proxy_password() const
Definition clicreds.hpp:120
bool session_id_defined() const
Definition clicreds.hpp:145
void set_password(const std::string &password_arg)
Definition clicreds.hpp:40
bool http_proxy_username_defined() const
Definition clicreds.hpp:135
void save_username_for_session_id()
Definition clicreds.hpp:164
std::map< std::string, std::vector< Option > > options_per_category
Definition cliopt.hpp:925
void add_failed_opt(const Option &o, const std::string &message, bool fatal_arg)
Definition cliopt.hpp:884
ClientCreds::Ptr creds
Definition cliopt.hpp:1465
void check_for_incompatible_options(const OptionList &opt)
Definition cliopt.hpp:644
std::unordered_set< std::string > settings_standalone_options
Definition cliopt.hpp:849
void showOptionsByFunction(const OptionList &opt, T func, const std::string &message, bool fatal, OptionErrors &errors)
Definition cliopt.hpp:1037
ReconnectNotify * reconnect_notify
Definition cliopt.hpp:1462
const SessionStats::Ptr & stats_ptr() const
Definition cliopt.hpp:1222
int conn_timeout() const
Definition cliopt.hpp:1235
ProtoContext::ProtoConfig & proto_config_cached(const bool relay_mode)
Definition cliopt.hpp:1275
void showUnusedOptionsByList(const OptionList &optlist, std::unordered_set< std::string > option_set, const std::string &message, bool fatal, OptionErrors &errors)
Definition cliopt.hpp:1027
std::unordered_set< std::string > settings_ignoreSilently
Definition cliopt.hpp:865
std::unordered_set< std::string > settings_feature_not_implemented_warn
Definition cliopt.hpp:798
void handle_unused_options(const OptionList &opt)
Definition cliopt.hpp:938
ProtoContext::ProtoConfig::Ptr cp_main
Definition cliopt.hpp:1455
PushOptionsBase::Ptr push_base
Definition cliopt.hpp:1479
static std::tuple< bool, std::string > check_dco_compatibility(const ClientAPI::ConfigCommon &config, const OptionList &opt)
Definition cliopt.hpp:602
std::unordered_set< std::string > settings_ignoreWithWarning
Definition cliopt.hpp:678
TransportClientFactory::Ptr transport_factory
Definition cliopt.hpp:1459
ClientEvent::Queue::Ptr cli_events
Definition cliopt.hpp:1464
HTTPProxyTransport::Options::Ptr http_proxy_options
Definition cliopt.hpp:1469
bool need_creds() const
Definition cliopt.hpp:1179
std::unordered_set< std::string > settings_removedOptions
Definition cliopt.hpp:862
unsigned int server_poll_timeout_
Definition cliopt.hpp:1466
ClientLifeCycle::Ptr client_lifecycle
Definition cliopt.hpp:1481
TunClientFactory::Ptr tun_factory
Definition cliopt.hpp:1460
void finalize(const bool disconnected)
Definition cliopt.hpp:1268
unsigned int tcp_queue_limit
Definition cliopt.hpp:1467
std::unordered_set< std::string > settings_script_plugin_feature
Definition cliopt.hpp:831
static PeerInfo::Set::Ptr build_peer_info(const Config &config, const ParseClientConfig &pcc, const bool autologin_sessions)
Definition cliopt.hpp:1051
std::unordered_set< std::string > settings_serverOnlyOptions
Definition cliopt.hpp:725
SocketProtect * socket_protect
Definition cliopt.hpp:1461
ProtoContext::ProtoConfig::Ptr cp_relay
Definition cliopt.hpp:1456
SessionStats::Ptr cli_stats
Definition cliopt.hpp:1463
bool server_poll_timeout_enabled() const
Definition cliopt.hpp:1208
RemoteList::Ptr remote_list
Definition cliopt.hpp:1457
bool asio_work_always_on() const
Definition cliopt.hpp:1240
ClientConfigParsed clientconf
Definition cliopt.hpp:1448
SessionStats & stats()
Definition cliopt.hpp:1218
bool pause_on_connection_timeout()
Definition cliopt.hpp:1130
void next(RemoteList::Advance type)
Definition cliopt.hpp:1114
static std::unordered_set< std::string > dco_incompatible_opts
Definition cliopt.hpp:593
ClientEvent::Queue & events()
Definition cliopt.hpp:1226
OptionList::FilterBase::Ptr pushed_options_filter
Definition cliopt.hpp:1480
ClientLifeCycle * lifecycle()
Definition cliopt.hpp:1230
std::unordered_set< std::string > settings_pushonlyoptions
Definition cliopt.hpp:814
Time::Duration server_poll_timeout() const
Definition cliopt.hpp:1213
bool retry_on_auth_failed() const
Definition cliopt.hpp:1137
ClientOptions(const OptionList &opt, const Config &config)
Definition cliopt.hpp:196
RandomAPI::Ptr prng
Definition cliopt.hpp:1452
std::string userlocked_username
Definition cliopt.hpp:1473
void submit_creds(const ClientCreds::Ptr &creds_arg)
Definition cliopt.hpp:1184
std::string load_transport_config()
Definition cliopt.hpp:1335
ProtoContext::ProtoConfig::Ptr proto_config(const OptionList &opt, const Config &config, const ParseClientConfig &pcc, const bool relay_mode)
Definition cliopt.hpp:1282
std::unordered_set< std::string > settings_feature_not_implemented_fatal
Definition cliopt.hpp:766
StrongRandomAPI::Ptr rng
Definition cliopt.hpp:1451
AltProxy::Ptr alt_proxy
Definition cliopt.hpp:1482
ProtoContextCompressionOptions::Ptr proto_context_options
Definition cliopt.hpp:1468
RemoteList::Ptr remote_list_precache() const
Definition cliopt.hpp:1245
Client::Config::Ptr client_config(const bool relay_mode)
Definition cliopt.hpp:1149
static Ptr parse(const OptionList &opt)
Definition httpcli.hpp:103
std::string cat(const std::string &name) const
Definition options.hpp:1269
void extend(const OptionList &other, FilterBase *filt=nullptr)
Definition options.hpp:1111
const IndexList & get_index(const std::string &name) const
Definition options.hpp:1250
T get_num(const std::string &name, const size_t idx, const T default_value) const
Definition options.hpp:1395
void touch(const std::string &name) const
Definition options.hpp:1435
const Option & get(const std::string &name) const
Definition options.hpp:1240
size_t n_unused(bool ignore_meta=false) const
Definition options.hpp:1491
const Option * get_ptr(const std::string &name) const
Definition options.hpp:1174
bool exists(const std::string &name) const
Definition options.hpp:1308
void touch(bool lightly=false) const
Definition options.hpp:378
const std::string & get(const size_t index, const size_t max_len) const
Definition options.hpp:184
size_t size() const
Definition options.hpp:320
const std::string & embeddedPassword() const
const PeerInfo::Set * peerInfoUV() const
const std::string & userlockedUsername() const
RCPtr< ProtoConfig > Ptr
Definition proto.hpp:339
bool is_udp() const
Definition protocol.hpp:75
bool is_tls() const
Definition protocol.hpp:83
static Protocol parse(const std::string &str, const AllowSuffix allow_suffix, const char *title=nullptr)
Definition protocol.hpp:157
bool is_tcp() const
Definition protocol.hpp:79
void reset() noexcept
Points this RCPtr<T> to nullptr safely.
Definition rc.hpp:290
T * get() const noexcept
Returns the raw pointer to the object T, or nullptr.
Definition rc.hpp:321
Reference count base class for objects tracked by RCPtr. Disallows copying and assignment.
Definition rc.hpp:908
virtual bool pause_on_connection_timeout()=0
void set_server_override(const std::string &server_override)
void next(Advance type=Advance::Addr)
void handle_proto_override(const Protocol &proto_override, const bool tcp_proxy_enabled)
bool defined() const
void set_enable_cache(const bool enable_cache_arg)
void set_random(const RandomAPI::Ptr &rng_arg)
void set_proto_version_override(const IP::Addr::Version v)
void set_port_override(const std::string &port_override)
const Protocol & current_transport_protocol() const
std::string current_server_host() const
void stop()
Definition stop.hpp:83
static TriStateSetting parse(const std::string &str)
TunBuilder methods, loosely based on the Android VpnService.Builder abstraction.
Definition base.hpp:42
static TunBuilderSetup::Factory::Ptr new_agent(const OptionList &opt)
Definition cmdagent.hpp:45
static TunWin::SetupFactory::Ptr new_agent(const OptionList &opt)
Definition cmdagent.hpp:42
#define OPENVPN_UNUSED_OPTIONS
Definition cliopt.hpp:103
#define OPENVPN_LOG_NTNL(args)
#define OPENVPN_LOG(args)
@ TAP_NOT_SUPPORTED
Definition error.hpp:45
auto join(const T &strings, const typename T::value_type &delim, const bool tail=false)
Definition string.hpp:481
@ TUN_MTU_DEFAULT
Definition tunmtu.hpp:20
unsigned int parse_tun_mtu_max(const OptionList &opt, unsigned int default_value)
Definition tunmtu.hpp:28
Frame::Ptr frame_init(const bool align_adjust_3_1, const size_t tun_mtu_max, const size_t control_channel_payload, const bool verbose)
unsigned int parse_tun_mtu(const OptionList &opt, unsigned int default_value)
Definition tunmtu.hpp:23
const std::string get_ssl_library_version()
Definition sslctx.hpp:1701
SocketProtect * socket_protect
Definition altproxy.hpp:42
StrongRandomAPI::Ptr rng
Definition altproxy.hpp:39
SessionStats::Ptr stats
Definition altproxy.hpp:37
DigestFactory::Ptr digest_factory
Definition altproxy.hpp:40
RemoteList::Ptr remote_list
Definition altproxy.hpp:34
virtual TransportClientFactory::Ptr new_transport_client_factory(const Config &)=0
virtual std::string name() const =0
virtual bool next()=0
virtual void precache(RemoteList::Ptr &r)=0
virtual bool requires_tcp() const =0
virtual void set_enable_cache(const bool enable_cache)=0
TriStateSetting allowUnusedAddrFamilies
Definition cliopt.hpp:137
std::string external_pki_alias
Definition cliopt.hpp:140
IP::Addr::Version proto_version_override
Definition cliopt.hpp:133
void import_client_settings(const ClientAPI::Config &config)
Definition cliopt.hpp:115
ReconnectNotify * reconnect_notify
Definition cliopt.hpp:180
ClientEvent::Queue::Ptr cli_events
Definition cliopt.hpp:161
ClientConfigParsed clientconf
Definition cliopt.hpp:157
PeerInfo::Set::Ptr extra_peer_info
Definition cliopt.hpp:168
RemoteList::RemoteOverride * remote_override
Definition cliopt.hpp:181
ExternalPKIBase * external_pki
Definition cliopt.hpp:178
SessionStats::Ptr cli_stats
Definition cliopt.hpp:160
ProtoContextCompressionOptions::Ptr proto_context_options
Definition cliopt.hpp:162
HTTPProxyTransport::Options::Ptr http_proxy_options
Definition cliopt.hpp:163
SocketProtect * socket_protect
Definition cliopt.hpp:179
RemoteList::Ptr remote_list
Definition dco.hpp:47
SessionStats::Ptr stats
Definition dco.hpp:50
SocketProtect * socket_protect
Definition dco.hpp:51
bool allow_local_dns_resolvers
Definition dco.hpp:73
TunProp::Config tun_prop
Definition dco.hpp:70
virtual TunClientFactory::Ptr new_tun_factory(const TunConfig &conf, const OptionList &opt)=0
virtual TransportClientFactory::Ptr new_transport_factory(const TransportConfig &conf)=0
TunProp::Config tun_prop
Definition config.hpp:26
SessionStats::Ptr stats
Definition config.hpp:28
unsigned int mssfix_ctrl
Definition mssparms.hpp:84
virtual void finalize(const bool disconnected)
Definition tunbase.hpp:126
RemoteList::Ptr remote_list
Definition tunprop.hpp:74
bool dhcp_search_domains_as_split_domains
Definition tunprop.hpp:60
std::string session_name
Definition tunprop.hpp:53
static const char config[]
const char message[]
const std::string optname