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#if defined(OPENVPN_PLATFORM_ANDROID)
62#endif
63
64#if defined(OPENVPN_EXTERNAL_TRANSPORT_FACTORY)
67#endif
68
69#if defined(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#if defined(USE_TUN_BUILDER)
184 TunBuilderBase *builder = nullptr;
185#endif
186
187#if defined(OPENVPN_EXTERNAL_TUN_FACTORY)
188 ExternalTun::Factory *extern_tun_factory = nullptr;
189#endif
190
191#if defined(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 autologin(false),
209 autologin_sessions(false),
210 creds_locked(false),
213#ifdef OPENVPN_EXTERNAL_TRANSPORT_FACTORY
214 ,
215 extern_transport_factory(config.extern_transport_factory)
216#endif
217 {
218 // parse general client options
219 const ParseClientConfig pcc(opt);
220
221 // creds
223 autologin = pcc.autologin();
225
226 // digest factory
228
229 // initialize RNG/PRNG
230 rng.reset(new SSLLib::RandomAPI());
231 prng.reset(new MTRand(time(nullptr)));
232
233 // frame
234 // get tun-mtu and tun-mtu-max parameter from config
235 const unsigned int tun_mtu = parse_tun_mtu(opt, 0);
236 const unsigned int tun_mtu_max = std::max(parse_tun_mtu_max(opt, TUN_MTU_DEFAULT + 100), tun_mtu);
237
238 const MSSCtrlParms mc(opt);
239 frame = frame_init(true, tun_mtu_max, mc.mssfix_ctrl, true);
240
241 // TCP queue limit
242 tcp_queue_limit = opt.get_num<decltype(tcp_queue_limit)>("tcp-queue-limit", 1, tcp_queue_limit, 1, 65536);
243
244 // route-nopull
246
247 // OpenVPN Protocol context (including SSL)
248 cp_main = proto_config(opt, config, pcc, false);
249 cp_relay = proto_config(opt, config, pcc, true); // may be null
250
251 CryptoAlgs::allow_default_dc_algs<SSLLib::CryptoAPI>(cp_main->ssl_factory->libctx(),
252 !config.clientconf.enableNonPreferredDCAlgorithms,
253 config.clientconf.enableLegacyAlgorithms);
254
255#if (defined(ENABLE_KOVPN) || defined(ENABLE_OVPNDCO) || defined(ENABLE_OVPNDCOWIN)) && !defined(OPENVPN_FORCE_TUN_NULL) && !defined(OPENVPN_EXTERNAL_TUN_FACTORY)
256 if (config.clientconf.dco)
257#if defined(USE_TUN_BUILDER)
258 dco = DCOTransport::new_controller(config.builder);
259#else
260 dco = DCOTransport::new_controller(nullptr);
261#endif
262#endif
263
264 layer = cp_main->layer;
265
266#ifdef PRIVATE_TUNNEL_PROXY
267 if (config.alt_proxy && !dco)
268 alt_proxy = PTProxy::new_proxy(opt, rng);
269#endif
270
271 // If HTTP proxy parameters are not supplied by API, try to get them from config
274
275 // load remote list
276 if (config.remote_override)
277 {
278 remote_list.reset(new RemoteList(config.remote_override));
280 }
281 else
283 if (!remote_list->defined())
284 throw option_error(ERR_INVALID_CONFIG, "no remote option specified");
285
286 // If running in tun_persist mode, we need to do basic DNS caching so that
287 // we can avoid emitting DNS requests while the tunnel is blocked during
288 // reconnections.
289 remote_list->set_enable_cache(config.clientconf.tunPersist);
290
291 // process server/port/family overrides
292 remote_list->set_server_override(config.clientconf.serverOverride);
293 remote_list->set_port_override(config.clientconf.portOverride);
294 remote_list->set_proto_version_override(config.clientconf.proto_version_override);
295
296 // process protocol override, should be called after set_enable_cache
297 remote_list->handle_proto_override(config.clientconf.proto_override,
299
300 // process remote-random
301 if (opt.exists("remote-random"))
303
304 // get "float" option
305 server_addr_float = opt.exists("float");
306
307 // special remote cache handling for proxies
308 if (alt_proxy)
309 {
310 remote_list->set_enable_cache(false); // remote server addresses will be resolved by proxy
311 alt_proxy->set_enable_cache(config.clientconf.tunPersist);
312 }
313 else if (http_proxy_options)
314 {
315 remote_list->set_enable_cache(false); // remote server addresses will be resolved by proxy
316 http_proxy_options->proxy_server_set_enable_cache(config.clientconf.tunPersist);
317 }
318
320
321 // throw an exception if dco is requested but config/options are dco-incompatible
322 bool dco_compatible = false;
323 std::tie(dco_compatible, std::ignore) = check_dco_compatibility(clientconf, opt);
324 if (config.clientconf.dco && !dco_compatible)
325 {
326 throw option_error(ERR_INVALID_CONFIG, "dco_compatibility: config/options are not compatible with dco");
327 }
328
329#ifdef OPENVPN_PLATFORM_UWP
330 // workaround for OVPN3-62 Busy loop in win_event.hpp
332#endif
333
334 synchronous_dns_lookup = config.synchronous_dns_lookup;
335
336#ifdef OPENVPN_TLS_LINK
337 if (opt.exists("tls-ca"))
338 {
339 tls_ca = opt.cat("tls-ca");
340 }
341#endif
342
343 // init transport config
344 const std::string session_name = load_transport_config();
345
346 // initialize tun/tap
347 if (dco)
348 {
349 DCO::TunConfig tunconf;
350#if defined(OPENVPN_COMMAND_AGENT) && defined(OPENVPN_PLATFORM_WIN)
351 tunconf.setup_factory = WinCommandAgent::new_agent(opt);
352#endif
353 tunconf.tun_prop.layer = layer;
354 tunconf.tun_prop.session_name = session_name;
355 if (tun_mtu)
356 tunconf.tun_prop.mtu = tun_mtu;
357 tunconf.tun_prop.mtu_max = tun_mtu_max;
358 tunconf.tun_prop.google_dns_fallback = config.clientconf.googleDnsFallback;
359 tunconf.tun_prop.dhcp_search_domains_as_split_domains = config.clientconf.dhcpSearchDomainsAsSplitDomains;
361 tunconf.stop = config.stop;
362 tunconf.allow_local_dns_resolvers = config.clientconf.allowLocalDnsResolvers;
363#if defined(OPENVPN_PLATFORM_WIN)
364 if (config.clientconf.tunPersist)
365 tunconf.tun_persist.reset(new TunWin::DcoTunPersist(true, TunWrapObjRetain::NO_RETAIN_NO_REPLACE, nullptr));
366#endif
367 tun_factory = dco->new_tun_factory(tunconf, opt);
368 }
369 else
370 {
371#if defined(OPENVPN_EXTERNAL_TUN_FACTORY)
372 {
373 ExternalTun::Config tunconf;
374 tunconf.tun_prop.layer = layer;
375 tunconf.tun_prop.session_name = session_name;
376 tunconf.tun_prop.google_dns_fallback = config.clientconf.googleDnsFallback;
377 tunconf.tun_prop.dhcp_search_domains_as_split_domains = config.clientconf.dhcpSearchDomainsAsSplitDomains;
378 if (tun_mtu)
379 tunconf.tun_prop.mtu = tun_mtu;
380 tunconf.tun_prop.mtu_max = tun_mtu_max;
381 tunconf.frame = frame;
382 tunconf.stats = cli_stats;
384 tunconf.tun_persist = config.clientconf.tunPersist;
385 tunconf.stop = config.stop;
386 tun_factory.reset(config.extern_tun_factory->new_tun_factory(tunconf, opt));
387 if (!tun_factory)
388 throw option_error(ERR_INVALID_CONFIG, "OPENVPN_EXTERNAL_TUN_FACTORY: no tun factory");
389 }
390#elif defined(USE_TUN_BUILDER)
391 {
393 tunconf->builder = config.builder;
394 tunconf->tun_prop.session_name = session_name;
395 tunconf->tun_prop.google_dns_fallback = config.clientconf.googleDnsFallback;
396 tunconf->tun_prop.dhcp_search_domains_as_split_domains = config.clientconf.dhcpSearchDomainsAsSplitDomains;
397 tunconf->tun_prop.allow_local_lan_access = config.clientconf.allowLocalLanAccess;
398 if (tun_mtu)
399 tunconf->tun_prop.mtu = tun_mtu;
400 tunconf->tun_prop.mtu_max = tun_mtu_max;
401 tunconf->frame = frame;
402 tunconf->stats = cli_stats;
403 tunconf->tun_prop.remote_list = remote_list;
404 tun_factory = tunconf;
405#if defined(OPENVPN_PLATFORM_IPHONE)
406 tunconf->retain_sd = true;
407 tunconf->tun_prefix = true;
408 if (config.clientconf.tunPersist)
409 tunconf->tun_prop.remote_bypass = true;
410#endif
411#if defined(OPENVPN_PLATFORM_ANDROID)
412 // Android VPN API only supports excluded IP prefixes starting with Android 13/API 33,
413 // so we must emulate them for earlier platforms
414 if (config.enable_route_emulation)
415 {
416 tunconf->eer_factory.reset(new EmulateExcludeRouteFactoryImpl(false));
417 }
418 else
419 {
420 tunconf->eer_factory.reset(nullptr);
421 }
422#endif
423#if defined(OPENVPN_PLATFORM_MAC)
424 tunconf->tun_prefix = true;
425#endif
426 if (config.clientconf.tunPersist)
427 tunconf->tun_persist.reset(new TunBuilderClient::TunPersist(true, tunconf->retain_sd ? TunWrapObjRetain::RETAIN : TunWrapObjRetain::NO_RETAIN, config.builder));
428 tun_factory = tunconf;
429 }
430#elif defined(OPENVPN_PLATFORM_LINUX) && !defined(OPENVPN_FORCE_TUN_NULL)
431 {
433 tunconf->tun_prop.layer = layer;
434 tunconf->tun_prop.session_name = session_name;
435 if (tun_mtu)
436 tunconf->tun_prop.mtu = tun_mtu;
437 tunconf->tun_prop.mtu_max = tun_mtu_max;
438 tunconf->tun_prop.google_dns_fallback = config.clientconf.googleDnsFallback;
439 tunconf->tun_prop.dhcp_search_domains_as_split_domains = config.clientconf.dhcpSearchDomainsAsSplitDomains;
440 tunconf->generate_tun_builder_capture_event = config.clientconf.generateTunBuilderCaptureEvent;
441 tunconf->tun_prop.remote_list = remote_list;
442 tunconf->frame = frame;
443 tunconf->stats = cli_stats;
444 if (config.clientconf.tunPersist)
445 tunconf->tun_persist.reset(new TunLinux::TunPersist(true, TunWrapObjRetain::NO_RETAIN, nullptr));
446 tunconf->load(opt);
447 tun_factory = tunconf;
448 }
449#elif defined(OPENVPN_PLATFORM_MAC) && !defined(OPENVPN_FORCE_TUN_NULL)
450 {
452 tunconf->tun_prop.layer = layer;
453 tunconf->tun_prop.session_name = session_name;
454 tunconf->tun_prop.google_dns_fallback = config.clientconf.googleDnsFallback;
455 tunconf->tun_prop.dhcp_search_domains_as_split_domains = config.clientconf.dhcpSearchDomainsAsSplitDomains;
456 if (tun_mtu)
457 tunconf->tun_prop.mtu = tun_mtu;
458 tunconf->tun_prop.mtu_max = tun_mtu_max;
459 tunconf->frame = frame;
460 tunconf->stats = cli_stats;
461 tunconf->stop = config.stop;
462 if (config.clientconf.tunPersist)
463 {
464 tunconf->tun_persist.reset(new TunMac::TunPersist(true, TunWrapObjRetain::NO_RETAIN, nullptr));
465#ifndef OPENVPN_COMMAND_AGENT
466 /* remote_list is required by remote_bypass to work */
467 tunconf->tun_prop.remote_bypass = true;
468 tunconf->tun_prop.remote_list = remote_list;
469#endif
470 }
472#ifdef OPENVPN_COMMAND_AGENT
473 tunconf->tun_setup_factory = UnixCommandAgent::new_agent(opt);
474#endif
475 tun_factory = tunconf;
476 }
477#elif defined(OPENVPN_PLATFORM_WIN) && !defined(OPENVPN_FORCE_TUN_NULL)
478 {
480 tunconf->tun_prop.layer = layer;
481 tunconf->tun_prop.session_name = session_name;
482 tunconf->tun_prop.google_dns_fallback = config.clientconf.googleDnsFallback;
483 tunconf->tun_prop.dhcp_search_domains_as_split_domains = config.clientconf.dhcpSearchDomainsAsSplitDomains;
484 if (tun_mtu)
485 tunconf->tun_prop.mtu = tun_mtu;
486 tunconf->tun_prop.mtu_max = tun_mtu_max;
487 tunconf->frame = frame;
488 tunconf->stats = cli_stats;
489 tunconf->stop = config.stop;
490 tunconf->tun_type = config.clientconf.wintun ? TunWin::Wintun : TunWin::TapWindows6;
491 tunconf->allow_local_dns_resolvers = config.clientconf.allowLocalDnsResolvers;
492 if (config.clientconf.tunPersist)
493 {
494 tunconf->tun_persist.reset(new TunWin::TunPersist(true, TunWrapObjRetain::NO_RETAIN, nullptr));
495#ifndef OPENVPN_COMMAND_AGENT
496 /* remote_list is required by remote_bypass to work */
497 tunconf->tun_prop.remote_bypass = true;
498 tunconf->tun_prop.remote_list = remote_list;
499#endif
500 }
501#ifdef OPENVPN_COMMAND_AGENT
502 tunconf->tun_setup_factory = WinCommandAgent::new_agent(opt);
503#endif
504 tun_factory = tunconf;
505 }
506#else
507 {
509 tunconf->frame = frame;
510 tunconf->stats = cli_stats;
511 tun_factory = tunconf;
512 }
513#endif
514 }
515
516 // The Core Library itself does not handle TAP/OSI_LAYER_2 currently,
517 // so we bail out early whenever someone tries to use TAP configurations
519 throw ErrorCode(Error::TAP_NOT_SUPPORTED, true, "OSI layer 2 tunnels are not currently supported");
520
521 // server-poll-timeout
522 {
523 const Option *o = opt.get_ptr("server-poll-timeout");
524 if (o)
525 server_poll_timeout_ = parse_number_throw<unsigned int>(o->get(1, 16), "server-poll-timeout");
526 }
527
528 // create default creds object in case submit_creds is not called,
529 // and populate it with embedded creds, if available
530 {
531 ClientCreds::Ptr cc = new ClientCreds();
532 if (pcc.hasEmbeddedPassword())
533 {
536 submit_creds(cc);
537 creds_locked = true;
538 }
539 else if (autologin_sessions)
540 {
541 submit_creds(cc);
542 creds_locked = true;
543 }
544 else
545 {
546 submit_creds(cc);
547 }
548 }
549
550 // configure push_base, a set of base options that will be combined with
551 // options pushed by server.
552 {
554
555 // base options where multiple options of the same type can aggregate
556 push_base->multi.extend(opt, "route");
557 push_base->multi.extend(opt, "route-ipv6");
558 push_base->multi.extend(opt, "redirect-gateway");
559 push_base->multi.extend(opt, "redirect-private");
560 push_base->multi.extend(opt, "dhcp-option");
561
562 // base options which need to be merged, not just aggregated
563 push_base->merge.extend(opt, "dns");
564
565 // base options where only a single instance of each option makes sense
566 push_base->singleton.extend(opt, "redirect-dns");
567 push_base->singleton.extend(opt, "inactive");
568 push_base->singleton.extend(opt, "route-metric");
569
570 // IPv6
571 {
572 const unsigned int n6 = push_base->singleton.extend(opt, "block-ipv6");
573 const unsigned int n4 = push_base->singleton.extend(opt, "block-ipv4");
574
575 if (!n6 && config.clientconf.allowUnusedAddrFamilies() == TriStateSetting::No)
576 {
577 push_base->singleton.emplace_back("block-ipv6");
578 }
579 if (!n4 && config.clientconf.allowUnusedAddrFamilies() == TriStateSetting::No)
580 {
581 push_base->singleton.emplace_back("block-ipv4");
582 }
583 }
584 }
585
587 }
588
589 // If those options are present, dco cannot be used
590 inline static std::unordered_set<std::string> dco_incompatible_opts = {
591 "http-proxy",
592 "compress",
593 "comp-lzo"};
594
595
599 static std::tuple<bool, std::string> check_dco_compatibility(const ClientAPI::ConfigCommon &config, const OptionList &opt)
600 {
601#if defined(ENABLE_KOVPN)
602 // only care about dco/dco-win
603 return std::make_tuple(true, "");
604#else
605
606 std::vector<std::string> reasons;
607
608 for (auto &optname : dco_incompatible_opts)
609 {
610 if (opt.exists(optname))
611 {
612 reasons.push_back("option " + optname + " is not compatible with dco");
613 }
614 }
615
616 if (config.enableLegacyAlgorithms)
617 {
618 reasons.emplace_back("legacy algorithms are not compatible with dco");
619 }
620
621 if (config.enableNonPreferredDCAlgorithms)
622 {
623 reasons.emplace_back("non-preferred data channel algorithms are not compatible with dco");
624 }
625
626 if (!config.proxyHost.empty())
627 {
628 reasons.emplace_back("proxyHost config setting is not compatible with dco");
629 }
630
631 if (reasons.empty())
632 {
633 return std::make_tuple(true, "");
634 }
635 else
636 {
637 return std::make_tuple(false, string::join(reasons, "\n"));
638 }
639#endif
640 }
641
643 {
644 // secret option not supported
645 if (opt.exists("secret"))
646 throw option_error(ERR_INVALID_OPTION_CRYPTO, "sorry, static key encryption mode (non-SSL/TLS) is not supported");
647
648 // fragment option not supported
649 if (opt.exists("fragment"))
650 throw option_error(ERR_INVALID_OPTION_VAL, "sorry, 'fragment' directive is not supported, nor is connecting to a server that uses 'fragment' directive");
651
652 if (!opt.exists("client"))
653 throw option_error(ERR_INVALID_CONFIG, "Neither 'client' nor both 'tls-client' and 'pull' options declared. OpenVPN3 client only supports --client mode.");
654
655 // Only p2p mode accept
656 if (opt.exists("mode"))
657 {
658 const auto &mode = opt.get("mode");
659 if (mode.size() != 2 || mode.get(1, 128) != "p2p")
660 {
661 throw option_error(ERR_INVALID_CONFIG, "Only 'mode p2p' supported");
662 }
663 }
664
665 // key-method 2 is the only thing that 2.5+ and 3.x support
666 if (opt.exists("key-method"))
667 {
668 auto keymethod = opt.get("key-method");
669 if (keymethod.size() != 2 || keymethod.get(1, 128) != "2")
670 {
671 throw option_error(ERR_INVALID_OPTION_VAL, "Only 'key-method 2' is supported: " + keymethod.get(1, 128));
672 }
673 }
674 }
675
676 std::unordered_set<std::string> settings_ignoreWithWarning = {
677 "allow-compression", /* TODO: maybe check against our client option compression setting? */
678 "allow-recursive-routing",
679 "auth-retry",
680 "compat-mode",
681 "connect-retry",
682 "connect-retry-max",
683 "connect-timeout", /* TODO: this should be really implemented */
684 "data-ciphers", /* TODO: maybe add more special warning that checks it against our supported ciphers */
685 "data-ciphers-fallback",
686 "disable-dco", /* TODO: maybe throw an error if DCO is active? */
687 "disable-occ",
688 "engine",
689 "explicit-exit-notify", /* ignoring it in config does not break connection or functionality */
690 "group",
691 "ifconfig-nowarn", /* v3 does not do OCC checks */
692 "ip-win32",
693 "keepalive", /* A push only feature (ping/ping-restart) in v3. Ignore with warning since often present in configs too */
694 "link-mtu",
695 "machine-readable-output", /* would be set by a CliOptions */
696 "mark", /* enables SO_MARK */
697 "mute",
698 "ncp-ciphers",
699 "nice",
700 "opt-verify",
701 "passtos",
702 "persist-key",
703 "persist-tun",
704 "preresolve",
705 "providers", /* Done via client options */
706 "remap-usr1",
707 "reneg-bytes",
708 "reneg-pkts",
709 "replay-window",
710 "resolv-retry",
711 "route-method", /* Windows specific fine tuning option */
712 "route-delay",
713 "show-net-up",
714 "socket-flags",
715 "suppress-timestamps", /* harmless to ignore */
716 "tcp-nodelay",
717 "tls-version-max", /* We don't allow restricting max version */
718 "tun-mtu-extra", /* (only really used in tap in OpenVPN 2.x)*/
719 "udp-mtu", /* Alias for link-mtu */
720 "user",
721 };
722
723 std::unordered_set<std::string> settings_serverOnlyOptions = {
724 "auth-gen-token",
725 "auth-gen-token-secret",
726 "auth-user-pass-optional",
727 "auth-user-pass-verify",
728 "bcast-buffers",
729 "ccd-exclusive",
730 "client-config-dir",
731 "client-connect",
732 "client-disconnect",
733 "client-to-client",
734 "connect-freq",
735 "dh",
736 "disable",
737 "duplicate-cn",
738 "hash-size",
739 "ifconfig-ipv6-pool",
740 "ifconfig-pool",
741 "ifconfig-pool-persist",
742 "ifconfig-push",
743 "ifconfig-push-constraint",
744 "iroute",
745 "iroute-ipv6",
746 "max-clients",
747 "max-routes-per-client",
748 "push",
749 "push-remove",
750 "push-reset",
751 "server",
752 "server-bridge",
753 "server-ipv6",
754 "stale-routes-check",
755 "tls-crypt-v2-verify",
756 "username-as-common-name",
757 "verify-client-cert",
758 "vlan-accept",
759 "vlan-pvid",
760 "vlan-tagging",
761 };
762
763 /* Features not implemented and not safe to ignore */
764 std::unordered_set<std::string> settings_feature_not_implemented_fatal = {
765 "askpass",
766 "capath",
767 "cd",
768 "chroot",
769 "client-nat",
770 "cryptoapicert",
771 "daemon",
772 "daemon",
773 "errors-to-stderr",
774 "gremlin",
775 "lladdr",
776 "log",
777 "log",
778 "log-append",
779 "management",
780 "memstats",
781 "msg-channel", /* (Windows service in v2) */
782 "ping-timer-rem",
783 "single-session", /* This option is quite obscure but changes behaviour enough to not ignore it */
784 "socks-proxy",
785 "status",
786 "status-version",
787 "syslog",
788 "tls-server", /* No p2p mode in v3 */
789 "verify-hash",
790 "win-sys",
791 "writepid",
792 "x509-username-field",
793 };
794
795 /* Features not implemented but safe enough to ignore */
796 std::unordered_set<std::string> settings_feature_not_implemented_warn = {
797 "allow-pull-fqdn",
798 "bind",
799 "local",
800 "lport",
801 "mlock",
802 "mtu-disc",
803 "mtu-test",
804 "persist-local-ip",
805 "persist-remote-ip",
806 "shaper",
807 "tls-exit",
808 };
809
810 /* Push only options (some are allowed in the config in OpenVPN 2
811 * but really push only options) */
812 std::unordered_set<std::string> settings_pushonlyoptions = {
813 "auth-token",
814 "auth-token-user",
815 "echo",
816 "parameter",
817 "ping",
818 "ping-exit",
819 "ping-restart", /* ping related options are pull only in v3, v2 needs them in the config for pure p2p */
820 "key-derivation",
821 "peer-id",
822 "protocol-flags",
823 "ifconfig",
824 "ifconfig-ipv6",
825 "topology",
826 "route-gateway"};
827
828 /* Features related to scripts/plugins */
829 std::unordered_set<std::string> settings_script_plugin_feature = {
830 "down",
831 "down-pre",
832 "ifconfig-noexec",
833 "ipchange",
834 "learn-address",
835 "plugin",
836 "route-noexec",
837 "route-pre-down",
838 "route-up",
839 "setenv-safe",
840 "tls-export-cert",
841 "tls-verify",
842 "up",
843 "up-delay",
844 "x509-track"};
845
846 /* Standalone OpenVPN v2 modes */
847 std::unordered_set<std::string> settings_standalone_options = {
848 "genkey",
849 "mktun",
850 "rmtun",
851 "show-ciphers",
852 "show-curves",
853 "show-digests",
854 "show-engines",
855 "show-groups",
856 "show-tls",
857 "test-crypto"};
858
859 /* Deprecated/throwing error in OpenVPN 2.x already: */
860 std::unordered_set<std::string> settings_removedOptions = {
861 "mtu-dynamic", "no-replay", "no-name-remapping", "compat-names", "ncp-disable", "no-iv"};
862
863 std::unordered_set<std::string> settings_ignoreSilently = {
864 "ecdh-curve", /* Deprecated in v2, not needed with modern OpenSSL */
865 "fast-io",
866 "max-routes",
867 "mute-replay-warnings",
868 "nobind", /* only behaviour in v3 client anyway */
869 "prng",
870 "rcvbuf", /* present in many configs */
871 "replay-persist", /* Makes little sense in TLS mode */
872 "script-security",
873 "sndbuf",
874 "tmp-dir",
875 "tun-ipv6", /* ignored in v2 as well */
876 "txqueuelen", /* so platforms evaluate that in tun, some do not, do not warn about that */
877 "verb"};
878
880 {
881 public:
882 void add_failed_opt(const Option &o, const std::string &message, bool fatal_arg)
883 {
884 if (!options_per_category.contains(message))
885 {
887 }
888
889 fatal |= fatal_arg;
890 options_per_category[message].push_back(o);
891 }
892
894 {
895 std::ostringstream os;
896
897 for (const auto &[category, options] : options_per_category)
898 {
899 if (!options.empty())
900 {
901 OPENVPN_LOG(category);
902
903 os << category << ": ";
904 std::vector<std::string> opts;
905 for (size_t i = 0; i < options.size(); ++i)
906 {
907 auto &o = options[i];
908 OPENVPN_LOG(std::to_string(i) << ' ' << o.render(Option::RENDER_BRACKET | Option::RENDER_TRUNC_64));
909 opts.push_back(o.get(0, 64));
910 }
911
912 os << string::join(opts, ",") << std::endl;
913 }
914 }
915
916 if (fatal)
917 {
918 throw ErrorCode(Error::UNUSED_OPTIONS, true, os.str());
919 }
920 }
921
922 private:
923 std::map<std::string, std::vector<Option>> options_per_category;
924 bool fatal = false;
925 };
926
937 {
938 /* Meta options that AS profiles often have that we do not parse and
939 * can ignore without warning */
940 std::unordered_set<std::string> ignoreMetaOptions = {
941 "CLI_PREF_ALLOW_WEB_IMPORT",
942 "CLI_PREF_BASIC_CLIENT",
943 "CLI_PREF_ENABLE_CONNECT",
944 "CLI_PREF_ENABLE_XD_PROXY",
945 "WSHOST",
946 "WEB_CA_BUNDLE",
947 "IS_OPENVPN_WEB_CA",
948 "NO_WEB",
949 "ORGANIZATION"};
950
951 std::unordered_set<std::string> ignore_unknown_option_list;
952
953 if (opt.exists("ignore-unknown-option"))
954 {
955 auto igOptlist = opt.get_index("ignore-unknown-option");
956 for (auto igUnOptIdx : igOptlist)
957 {
958 const Option &o = opt[igUnOptIdx];
959 for (size_t i = 1; i < o.size(); i++)
960 {
961 const auto &optionToIgnore = o.get(i, 0);
962
963 ignore_unknown_option_list.insert(optionToIgnore);
964 }
965 o.touch();
966 }
967 }
968
969 for (const auto &o : opt)
970 {
971 if (!o.meta() && settings_ignoreSilently.contains(o.get(0, 0)))
972 {
973 o.touch();
974 }
975 if (o.meta() && ignoreMetaOptions.contains(o.get(0, 0)))
976 {
977 o.touch();
978 }
979 }
980
981 /* Mark all options that will not trigger any kind of message
982 * as touched to avoid an empty message with unused options */
983 if (opt.n_unused() == 0)
984 return;
985
986 OPENVPN_LOG_NTNL("NOTE: This configuration contains options that were not used:" << std::endl);
987
988 OptionErrors errors{};
989
990 /* Go through all options and check all options that have not been
991 * touched (parsed) yet */
992 showUnusedOptionsByList(opt, settings_removedOptions, "Removed deprecated option", true, errors);
993 showUnusedOptionsByList(opt, settings_serverOnlyOptions, "Server only option", true, errors);
994 showUnusedOptionsByList(opt, settings_standalone_options, "OpenVPN 2.x command line operation", true, errors);
995 showUnusedOptionsByList(opt, settings_feature_not_implemented_warn, "Feature not implemented (option ignored)", false, errors);
996 showUnusedOptionsByList(opt, settings_pushonlyoptions, "Option allowed only to be pushed by the server", true, errors);
997 showUnusedOptionsByList(opt, settings_script_plugin_feature, "Ignored (no script/plugin support)", false, errors);
998 showUnusedOptionsByList(opt, ignore_unknown_option_list, "Ignored by option 'ignore-unknown-option'", false, errors);
999 showUnusedOptionsByList(opt, settings_ignoreWithWarning, "Unsupported option (ignored)", false, errors);
1000
1001 auto ignoredBySetenvOpt = [](const Option &option)
1002 { return !option.touched() && option.warnonlyunknown(); };
1003 showOptionsByFunction(opt, ignoredBySetenvOpt, "Ignored options prefixed with 'setenv opt'", false, errors);
1004
1005 auto unusedMetaOpt = [](const Option &option)
1006 { return !option.touched() && option.meta(); };
1007 showOptionsByFunction(opt, unusedMetaOpt, "Unused ignored meta options", false, errors);
1008
1009 auto managmentOpt = [](const Option &option)
1010 { return !option.touched() && option.get(0, 0).rfind("management", 0) == 0; };
1011 showOptionsByFunction(opt, managmentOpt, "OpenVPN management interface is not supported by this client", true, errors);
1012
1013 // If we still have options that are unaccounted for, we print them and throw an error or just warn about them
1014 auto onlyLightlyTouchedOptions = [](const Option &option)
1015 { return option.touched_lightly(); };
1016 showOptionsByFunction(opt, onlyLightlyTouchedOptions, "Unused options, probably specified multiple times in the configuration file", false, errors);
1017
1018 auto nonTouchedOptions = [](const Option &option)
1019 { return !option.touched() && !option.touched_lightly(); };
1020 showOptionsByFunction(opt, nonTouchedOptions, OPENVPN_UNUSED_OPTIONS, true, errors);
1021
1022 errors.print_option_errors();
1023 }
1024
1025 void showUnusedOptionsByList(const OptionList &optlist, std::unordered_set<std::string> option_set, const std::string &message, bool fatal, OptionErrors &errors)
1026 {
1027 auto func = [&option_set](const Option &opt)
1028 { return !opt.touched() && option_set.contains(opt.get(0, 0)); };
1029 showOptionsByFunction(optlist, func, message, fatal, errors);
1030 }
1031
1032 /* lambda expression that capture variables have complex signatures, avoid these by letting the compiler
1033 * itself figure it out with a template */
1034 template <typename T>
1035 void showOptionsByFunction(const OptionList &opt, T func, const std::string &message, bool fatal, OptionErrors &errors)
1036 {
1037 for (size_t i = 0; i < opt.size(); ++i)
1038 {
1039 auto &o = opt[i];
1040 if (func(o))
1041 {
1042 o.touch();
1043
1044 errors.add_failed_opt(o, message, fatal);
1045 }
1046 }
1047 }
1048
1050 {
1052
1053 // autologin sessions
1055 pi->emplace_back("IV_AUTO_SESS", "1");
1056
1057 if (pcc.pushPeerInfo())
1058 {
1059 /* If we override the HWADDR, we add it at this time statically. If we need to
1060 * dynamically discover it from the transport it will be added in
1061 * \c build_connect_time_peer_info_string instead */
1062 if (!config.clientconf.hwAddrOverride.empty())
1063 {
1064 pi->emplace_back("IV_HWADDR", config.clientconf.hwAddrOverride);
1065 }
1066
1067 pi->emplace_back("IV_SSL", get_ssl_library_version());
1068
1069 if (!config.clientconf.platformVersion.empty())
1070 pi->emplace_back("IV_PLAT_VER", config.clientconf.platformVersion);
1071
1072 /* ensure that we use only one variable with the same name */
1073 std::unordered_map<std::string, std::string> extra_values;
1074
1075 if (pcc.peerInfoUV())
1076 {
1077 for (auto const &kv : *pcc.peerInfoUV())
1078 {
1079 extra_values[kv.key] = kv.value;
1080 }
1081 }
1082
1083 /* Config::peerInfo takes precedence */
1084 if (config.extra_peer_info.get())
1085 {
1086 for (auto const &kv : *config.extra_peer_info.get())
1087 {
1088 extra_values[kv.key] = kv.value;
1089 }
1090 }
1091
1092 for (auto kv : extra_values)
1093 {
1094 pi->emplace_back(kv.first, kv.second);
1095 }
1096 }
1097
1098 // UI version
1099 if (!config.clientconf.guiVersion.empty())
1100 pi->emplace_back("IV_GUI_VER", config.clientconf.guiVersion);
1101
1102 // Supported SSO methods
1103 if (!config.clientconf.ssoMethods.empty())
1104 pi->emplace_back("IV_SSO", config.clientconf.ssoMethods);
1105
1106 if (!config.clientconf.appCustomProtocols.empty())
1107 pi->emplace_back("IV_ACC", "2048,6:A," + config.clientconf.appCustomProtocols);
1108
1109 return pi;
1110 }
1111
1113 {
1114 bool omit_next = false;
1115
1116 if (alt_proxy)
1117 omit_next = alt_proxy->next();
1118 if (!omit_next)
1119 remote_list->next(type);
1121 }
1122
1127
1129 {
1130 if (reconnect_notify)
1132 else
1133 return false;
1134 }
1135
1137 {
1139 }
1140
1148 Client::Config::Ptr client_config(const bool relay_mode)
1149 {
1150 Client::Config::Ptr cli_config = new Client::Config;
1151
1152 // Copy ProtoConfig so that modifications due to server push will
1153 // not persist across client instantiations.
1154 cli_config->proto_context_config.reset(new ProtoContext::ProtoConfig(proto_config_cached(relay_mode)));
1155
1156 cli_config->proto_context_options = proto_context_options;
1157 cli_config->push_base = push_base;
1158 cli_config->transport_factory = transport_factory;
1159 cli_config->tun_factory = tun_factory;
1160 cli_config->cli_stats = cli_stats;
1161 cli_config->cli_events = cli_events;
1162 cli_config->creds = creds;
1163 cli_config->pushed_options_filter = pushed_options_filter;
1164 cli_config->tcp_queue_limit = tcp_queue_limit;
1165 cli_config->echo = clientconf.echo;
1166 cli_config->info = clientconf.info;
1167 cli_config->autologin_sessions = autologin_sessions;
1168
1169 // if the previous client instance had session-id, it must be used by the new instance too
1170 if (creds && creds->session_id_defined())
1171 {
1172 cli_config->proto_context_config->set_xmit_creds(true);
1173 }
1174
1175 return cli_config;
1176 }
1177
1178 bool need_creds() const
1179 {
1180 return !autologin;
1181 }
1182
1183 void submit_creds(const ClientCreds::Ptr &creds_arg)
1184 {
1185 if (!creds_arg)
1186 return;
1187
1188 // Override HTTP proxy credentials if provided dynamically
1190 http_proxy_options->username = creds_arg->get_http_proxy_username();
1192 http_proxy_options->password = creds_arg->get_http_proxy_password();
1193
1194 if (!creds_locked)
1195 {
1196 // if no username is defined in creds and userlocked_username is defined
1197 // in profile, set the creds username to be the userlocked_username
1198 if (!creds_arg->username_defined() && !userlocked_username.empty())
1199 {
1201 creds_arg->save_username_for_session_id();
1202 }
1203 creds = creds_arg;
1204 }
1205 }
1206
1208 {
1209 return !http_proxy_options;
1210 }
1211
1212 Time::Duration server_poll_timeout() const
1213 {
1214 return Time::Duration::seconds(server_poll_timeout_);
1215 }
1216
1218 {
1219 return *cli_stats;
1220 }
1222 {
1223 return cli_stats;
1224 }
1226 {
1227 return *cli_events;
1228 }
1230 {
1231 return client_lifecycle.get();
1232 }
1233
1234 int conn_timeout() const
1235 {
1236 return clientconf.connTimeout;
1237 }
1238
1240 {
1241 return asio_work_always_on_;
1242 }
1243
1245 {
1247 if (alt_proxy)
1248 {
1249 alt_proxy->precache(r);
1250 if (r)
1251 return r;
1252 }
1254 {
1255 http_proxy_options->proxy_server_precache(r);
1256 if (r)
1257 return r;
1258 }
1259 return remote_list;
1260 }
1261
1263 {
1264 now_.update();
1265 }
1266
1267 void finalize(const bool disconnected)
1268 {
1269 if (tun_factory)
1270 tun_factory->finalize(disconnected);
1271 }
1272
1273 private:
1275 {
1276 if (relay_mode && cp_relay)
1277 return *cp_relay;
1278 else
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:130
void set_username(const std::string &username_arg)
Definition clicreds.hpp:37
std::string get_http_proxy_username() const
Definition clicreds.hpp:120
bool http_proxy_password_defined() const
Definition clicreds.hpp:145
std::string get_http_proxy_password() const
Definition clicreds.hpp:125
bool session_id_defined() const
Definition clicreds.hpp:150
void set_password(const std::string &password_arg)
Definition clicreds.hpp:42
bool http_proxy_username_defined() const
Definition clicreds.hpp:140
void save_username_for_session_id()
Definition clicreds.hpp:169
std::map< std::string, std::vector< Option > > options_per_category
Definition cliopt.hpp:923
void add_failed_opt(const Option &o, const std::string &message, bool fatal_arg)
Definition cliopt.hpp:882
ClientCreds::Ptr creds
Definition cliopt.hpp:1465
void check_for_incompatible_options(const OptionList &opt)
Definition cliopt.hpp:642
std::unordered_set< std::string > settings_standalone_options
Definition cliopt.hpp:847
void showOptionsByFunction(const OptionList &opt, T func, const std::string &message, bool fatal, OptionErrors &errors)
Definition cliopt.hpp:1035
ReconnectNotify * reconnect_notify
Definition cliopt.hpp:1462
const SessionStats::Ptr & stats_ptr() const
Definition cliopt.hpp:1221
int conn_timeout() const
Definition cliopt.hpp:1234
ProtoContext::ProtoConfig & proto_config_cached(const bool relay_mode)
Definition cliopt.hpp:1274
void showUnusedOptionsByList(const OptionList &optlist, std::unordered_set< std::string > option_set, const std::string &message, bool fatal, OptionErrors &errors)
Definition cliopt.hpp:1025
std::unordered_set< std::string > settings_ignoreSilently
Definition cliopt.hpp:863
std::unordered_set< std::string > settings_feature_not_implemented_warn
Definition cliopt.hpp:796
void handle_unused_options(const OptionList &opt)
Definition cliopt.hpp:936
ProtoContext::ProtoConfig::Ptr cp_main
Definition cliopt.hpp:1455
ClientProto::Session Client
Definition cliopt.hpp:149
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:599
std::unordered_set< std::string > settings_ignoreWithWarning
Definition cliopt.hpp:676
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:1178
std::unordered_set< std::string > settings_removedOptions
Definition cliopt.hpp:860
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:1267
unsigned int tcp_queue_limit
Definition cliopt.hpp:1467
std::unordered_set< std::string > settings_script_plugin_feature
Definition cliopt.hpp:829
static PeerInfo::Set::Ptr build_peer_info(const Config &config, const ParseClientConfig &pcc, const bool autologin_sessions)
Definition cliopt.hpp:1049
std::unordered_set< std::string > settings_serverOnlyOptions
Definition cliopt.hpp:723
RCPtr< ClientOptions > Ptr
Definition cliopt.hpp:147
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:1207
RemoteList::Ptr remote_list
Definition cliopt.hpp:1457
bool asio_work_always_on() const
Definition cliopt.hpp:1239
ClientConfigParsed clientconf
Definition cliopt.hpp:1448
SessionStats & stats()
Definition cliopt.hpp:1217
bool pause_on_connection_timeout()
Definition cliopt.hpp:1128
void next(RemoteList::Advance type)
Definition cliopt.hpp:1112
static std::unordered_set< std::string > dco_incompatible_opts
Definition cliopt.hpp:590
ClientEvent::Queue & events()
Definition cliopt.hpp:1225
OptionList::FilterBase::Ptr pushed_options_filter
Definition cliopt.hpp:1480
ClientLifeCycle * lifecycle()
Definition cliopt.hpp:1229
std::unordered_set< std::string > settings_pushonlyoptions
Definition cliopt.hpp:812
Time::Duration server_poll_timeout() const
Definition cliopt.hpp:1212
bool retry_on_auth_failed() const
Definition cliopt.hpp:1136
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:1183
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:764
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:1244
Client::Config::Ptr client_config(const bool relay_mode)
Definition cliopt.hpp:1148
static Ptr parse(const OptionList &opt)
Definition httpcli.hpp:103
std::string cat(const std::string &name) const
Definition options.hpp:1286
void extend(const OptionList &other, FilterBase *filt=nullptr)
Definition options.hpp:1123
const IndexList & get_index(const std::string &name) const
Definition options.hpp:1265
T get_num(const std::string &name, const size_t idx, const T default_value) const
Definition options.hpp:1416
void touch(const std::string &name) const
Definition options.hpp:1456
const Option & get(const std::string &name) const
Definition options.hpp:1254
size_t n_unused(bool ignore_meta=false) const
Definition options.hpp:1512
const Option * get_ptr(const std::string &name) const
Definition options.hpp:1186
bool exists(const std::string &name) const
Definition options.hpp:1325
void touch(bool lightly=false) const
Definition options.hpp:385
const std::string & get(const size_t index, const size_t max_len) const
Definition options.hpp:187
size_t size() const
Definition options.hpp:327
const std::string & embeddedPassword() const
const PeerInfo::Set * peerInfoUV() const
const std::string & userlockedUsername() const
RCPtr< ProtoConfig > Ptr
Definition proto.hpp:338
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
The smart pointer class.
Definition rc.hpp:119
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:912
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:85
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:521
unsigned int parse_tun_mtu_max(const OptionList &opt, unsigned int default_value)
Definition tunmtu.hpp:28
@ TUN_MTU_DEFAULT
Definition tunmtu.hpp:20
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:1679
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:75
TunProp::Config tun_prop
Definition dco.hpp:72
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:85
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
std::ostringstream os
static const char config[]
const char message[]
const std::string optname