24#ifdef OPENVPN_PLATFORM_MAC
25#include <CoreFoundation/CFBundle.h>
26#include <ApplicationServices/ApplicationServices.h>
38#ifdef OPENVPN_USE_LOG_BASE_SIMPLE
39#define OPENVPN_LOG_GLOBAL
44#define OPENVPN_CORE_API_VISIBILITY_HIDDEN
47#if defined(OPENVPN_PLATFORM_LINUX) && !defined(OPENVPN_USE_IPROUTE2) && !defined(OPENVPN_USE_SITNL)
48#define OPENVPN_USE_SITNL
68#ifdef OPENVPN_REMOTE_OVERRIDE
72#if defined(USE_MBEDTLS)
74#elif defined(USE_OPENSSL)
75#include <openssl/evp.h>
76#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
77#include <openssl/core_names.h>
81#if defined(OPENVPN_PLATFORM_WIN)
87#include "client/core-client-netcfg.hpp"
90#if defined(OPENVPN_PLATFORM_LINUX)
97#define TUN_CLASS_SETUP TunLinuxSetup::Setup<TUN_LINUX>
99#elif defined(OPENVPN_PLATFORM_MAC)
101#define TUN_CLASS_SETUP TunMac::Setup
110#ifdef USE_TUN_BUILDER
121 tun.reset(
new TUN_CLASS_SETUP());
123 TUN_CLASS_SETUP::Config
config;
126 config.add_bypass_routes_on_establish =
false;
127 return tun->establish(
tbc, &
config,
nullptr, std::cout);
132 const std::string &gateway,
136 return tbc.tun_builder_add_address(
address, prefix_length, gateway,
ipv6, net30);
149 unsigned int flags)
override
162 return tbc.tun_builder_set_session_name(name);
167 std::ostringstream
os;
173 bool socket_protect([[maybe_unused]] openvpn_io::detail::socket_type socket, std::string remote,
bool ipv6)
override
175 std::ostringstream
os;
178 return tun->add_bypass_route(remote,
ipv6,
os);
183 return tbc.tun_builder_set_dns_options(dns);
188 return tbc.tun_builder_set_mtu(mtu);
192 TUN_CLASS_SETUP::Ptr tun =
new TUN_CLASS_SETUP();
201 std::cout <<
"NOT IMPLEMENTED: *** socket_protect " << socket <<
" " << remote << std::endl;
235#if defined(USE_MBEDTLS)
238#elif defined(USE_OPENSSL)
256 std::cout <<
"STATS:" << std::endl;
257 for (
int i = 0; i < n; ++i)
259 const long long value = stats[i];
261 std::cout <<
" " <<
stats_name(i) <<
" : " << value << std::endl;
265#ifdef OPENVPN_REMOTE_OVERRIDE
266 void set_remote_override_cmd(
const std::string &cmd)
268 remote_override_cmd = cmd;
282 if (!ev.
info.empty())
283 std::cout <<
' ' << ev.
info;
285 std::cout <<
" [FATAL-ERR]";
287 std::cout <<
" [ERR]";
288 std::cout << std::endl;
289 if (ev.
name ==
"DYNAMIC_CHALLENGE")
296 std::cout <<
"DYNAMIC CHALLENGE" << std::endl;
297 std::cout <<
"challenge: " << dc.
challenge << std::endl;
298 std::cout <<
"echo: " << dc.
echo << std::endl;
300 std::cout <<
"stateID: " << dc.
stateID << std::endl;
303 else if (ev.
name ==
"PROXY_NEED_CREDS")
305 std::cout <<
"PROXY_NEED_CREDS " << ev.
info << std::endl;
307 else if (ev.
name ==
"INFO")
315 auto extra = ev.
info.substr(9);
316 size_t flagsend = extra.find(
':');
317 if (flagsend != std::string::npos)
319 open_url(extra.substr(flagsend + 1));
324 std::string cr_response;
326 << ev.
info.substr(8) <<
": ";
327 std::getline(std::cin, cr_response);
332 std::cout <<
"Unrecognized INFO/INFO_PRE message: " << ev.
info << std::endl;
337 std::cout <<
"Received event " << ev.
name <<
" " << ev.
info << std::endl;
345 std::cout <<
"ACC CERTCHECK challenge initiated" << std::endl;
351 std::string fakeResponse{R
"({"dpc_response": {
353 "os" : {"type" : "Windows", "version" : "10.0.19045" }
357 std::cout << "ACC DPC1: sending fake client info:" << fakeResponse << std::endl;
362 std::cout <<
"Cannot parse dpc request message:" << acev.
payload << std::endl;
366 std::cout <<
"Cannot parse device posture message:" << acev.
payload << std::endl;
376 if (acev.
protocol ==
"internal:supported_protocols")
378 std::cout <<
"Client/server common app custom control protocols: " << acev.
payload << std::endl;
386 std::cout <<
"received unhandled app custom control message for protocol " << acev.
protocol
387 <<
" msg payload: " << acev.
payload << std::endl;
398 std::cout <<
"ACC CERTCHECK FAILED: MISSING PARAMETERS" << std::endl;
402 std::string clientca_pem =
"";
411 if (!clientca_pem.empty())
436#ifdef OPENVPN_PLATFORM_MAC
437 std::cout <<
"Trying to launch " << url_str << std::endl;
438 std::thread thr([url_str]()
440 CFURLRef
url = CFURLCreateWithBytes(
442 (UInt8*) url_str.c_str(),
444 kCFStringEncodingUTF8,
447 LSOpenCFURLRef(
url, 0);
450#elif defined(OPENVPN_PLATFORM_TYPE_UNIX)
452 if (::getuid() == 0 && ::getenv(
"SUDO_USER"))
454 argv.emplace_back(
"/usr/sbin/runuser");
455 argv.emplace_back(
"-u");
456 argv.emplace_back(::getenv(
"SUDO_USER"));
458 argv.emplace_back(
"/usr/bin/xdg-open");
459 argv.emplace_back(url_str);
462 std::cout <<
"No implementation to launch " << url_str << std::endl;
470 std::cout <<
date_time() <<
' ' <<
log.text << std::flush;
481 std::cout <<
"signal: CT_STOP" << std::endl;
485 std::cout <<
"signal: CT_RECONNECT" << std::endl;
489 std::cout <<
"signal: CT_PAUSE" << std::endl;
490 pause(
"clock-tick pause");
493 std::cout <<
"signal: CT_RESUME" << std::endl;
497 std::cout <<
"signal: CT_STATS" << std::endl;
519 certreq.
error =
true;
520 certreq.
errorText =
"external_pki_cert_request not implemented";
527 using PKEY_CTX_unique_ptr = std::unique_ptr<::EVP_PKEY_CTX,
decltype(&::EVP_PKEY_CTX_free)>;
532 EVP_PKEY *pkey = epki_pkey.
obj();
533 if (signreq.
alias ==
"certcheck")
534 pkey = certcheck_pkey.obj();
536 PKEY_CTX_unique_ptr pkey_ctx(EVP_PKEY_CTX_new(pkey,
nullptr), EVP_PKEY_CTX_free);
539 throw Exception(
"epki_sign failed, error creating PKEY ctx");
542 if ((EVP_PKEY_sign_init(pkey_ctx.get()) < 0))
547 if (signreq.
algorithm ==
"RSA_PKCS1_PSS_PADDING")
549 EVP_PKEY_CTX_set_rsa_padding(pkey_ctx.get(), RSA_PKCS1_PSS_PADDING);
551 else if (signreq.
algorithm ==
"RSA_PKCS1_PADDING")
553 EVP_PKEY_CTX_set_rsa_padding(pkey_ctx.get(), RSA_PKCS1_PADDING);
555 else if (signreq.
algorithm ==
"RSA_NO_PADDING")
557 EVP_PKEY_CTX_set_rsa_padding(pkey_ctx.get(), RSA_NO_PADDING);
563 if ((EVP_PKEY_sign(pkey_ctx.get(),
nullptr, &outlen, signdata.c_data(), signdata.size())) < 0)
570 if ((EVP_PKEY_sign(pkey_ctx.get(), sig.data(), &outlen, signdata.c_data(), signdata.size())) < 0)
575 sig.set_size(outlen);
580#if (OPENSSL_VERSION_NUMBER < 0x30000000L)
588 throw Exception(
"epki_sign failed, digest sign only implemented in OpenSSL 3.0");
593 EVP_PKEY_CTX *pkey_ctx =
nullptr;
597 using MD_unique_ptr = std::unique_ptr<::EVP_MD_CTX,
decltype(&::EVP_MD_CTX_free)>;
599 MD_unique_ptr md(EVP_MD_CTX_new(), EVP_MD_CTX_free);
602 throw Exception(
"epki_sign failed, error creating MD ctx");
609 const char *padding =
"none";
611 if (signreq.
algorithm ==
"RSA_PKCS1_PSS_PADDING")
615 else if (signreq.
algorithm ==
"RSA_PKCS1_PADDING")
619 else if (signreq.
algorithm ==
"RSA_NO_PADDING")
624 EVP_PKEY *pkey = epki_pkey.
obj();
625 if (signreq.
alias ==
"certcheck")
626 pkey = certcheck_pkey.obj();
628 OSSL_PARAM params[6] = {OSSL_PARAM_END};
630 char *hashalg =
const_cast<char *
>(signreq.
hashalg.c_str());
634 params[0] = OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, hashalg, 0);
635 params[1] = OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_PAD_MODE,
const_cast<char *
>(padding), 0);
637 if (EVP_PKEY_get_id(pkey) == EVP_PKEY_RSA && !signreq.
saltlen.empty())
640 char *saltlen =
const_cast<char *
>(signreq.
saltlen.c_str());
641 params[2] = OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, saltlen, 0);
642 params[3] = OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_DIGEST, hashalg, 0);
643 params[4] = OSSL_PARAM_construct_end();
646 EVP_DigestSignInit_ex(md.get(), &pkey_ctx, hashalg,
nullptr,
nullptr, pkey, params);
651 if (EVP_DigestSign(md.get(),
nullptr, &outlen, signdata.data(), signdata.size()) < 0)
658 if (EVP_DigestSign(md.get(), sig.data(), &outlen, signdata.data(), signdata.size()) < 0)
663 sig.set_size(outlen);
673 doOpenSSLSignature(signreq);
677 doOpenSSLDigestSignature(signreq);
684#if defined(USE_MBEDTLS)
704 const int status = mbedtls_pk_sign(epki_ctx.
get(),
709#
if MBEDTLS_VERSION_NUMBER >= 0x03000000
717 if (sig.
size() != sig_size)
718 throw Exception(
"unexpected signature size");
724 catch (
const std::exception &e)
726 signreq.
error =
true;
727 signreq.
errorText = std::string(
"external_pki_sign_request: ") + e.what();
731#elif defined(USE_OPENSSL)
734 || (certcheck_pkey.
defined() && signreq.
alias ==
"certcheck"))
738 doOpenSSLSignRequest(signreq);
740 catch (
const std::exception &e)
742 signreq.
error =
true;
743 signreq.
errorText = std::string(
"external_pki_sign_request: ") + e.what();
749 signreq.
error =
true;
750 signreq.
errorText =
"external_pki_sign_request not implemented";
755 static int rng_callback(
void *arg,
unsigned char *data,
size_t len)
760 self->
rng.
reset(
new SSLLib::RandomAPI());
770#ifdef OPENVPN_REMOTE_OVERRIDE
773 return !remote_override_cmd.empty();
780 argv.emplace_back(remote_override_cmd);
782 const int status =
system_cmd(remote_override_cmd,
793 if (svec.size() == 4)
801 ro.
error =
"cannot parse remote-override, expecting host,ip,port,proto (at least one or both of host and ip must be defined)";
804 ro.
error =
"status=" + std::to_string(status);
813#ifdef OPENVPN_REMOTE_OVERRIDE
814 std::string remote_override_cmd;
824#if !defined(OPENVPN_OVPNCLI_SINGLE_THREAD)
825 openvpn_io::detail::signal_blocker signal_blocker;
829 std::cout <<
"Thread starting..." << std::endl;
831 if (connect_status.
error)
833 std::cout <<
"connect error: ";
834 if (!connect_status.
status.empty())
835 std::cout << connect_status.
status <<
": " << std::endl;
836 std::cout << connect_status.
message << std::endl;
839 catch (
const std::exception &e)
841 std::cout <<
"Connect thread exception: " << e.what() << std::endl;
843 std::cout <<
"Thread finished" << std::endl;
846static std::string
read_profile(
const char *fn,
const std::string *profile_content)
849 return *profile_content;
864#if defined(OPENVPN_PLATFORM_WIN)
869 const std::string title_text =
"F2:Stats F3:Reconnect F4:Stop F5:Pause";
874 std::unique_ptr<std::thread> thread;
875 volatile bool thread_exit =
false;
877 thread.reset(
new std::thread([&thread_exit]()
880 thread_exit =
true; }));
887 const unsigned int c = console.get();
908#elif defined(OPENVPN_OVPNCLI_SINGLE_THREAD)
930 static bool hup =
false;
967 std::cout <<
"received stop signal " << signum << std::endl;
972 std::cout <<
"received reconnect signal " << signum << std::endl;
983 static bool hup =
false;
984 std::cout <<
"received pause/resume toggle signal " << signum << std::endl;
996 std::cout <<
"received unknown signal " << signum << std::endl;
1003 std::unique_ptr<std::thread> thread;
1007 thread.reset(
new std::thread([]()
1024 static const struct option longopts[] = {
1026 {
"username", required_argument,
nullptr,
'u' },
1027 {
"password", required_argument,
nullptr,
'p' },
1028 {
"response", required_argument,
nullptr,
'r' },
1029 {
"dc", required_argument,
nullptr,
'D' },
1030 {
"proto", required_argument,
nullptr,
'P' },
1031 {
"ipv6", required_argument,
nullptr,
'6' },
1032 {
"server", required_argument,
nullptr,
's' },
1033 {
"port", required_argument,
nullptr,
'R' },
1034 {
"timeout", required_argument,
nullptr,
't' },
1035 {
"compress", required_argument,
nullptr,
'c' },
1036 {
"pk-password", required_argument,
nullptr,
'z' },
1037 {
"tvm-override", required_argument,
nullptr,
'M' },
1038 {
"proxy-host", required_argument,
nullptr,
'h' },
1039 {
"proxy-port", required_argument,
nullptr,
'q' },
1040 {
"proxy-username", required_argument,
nullptr,
'U' },
1041 {
"proxy-password", required_argument,
nullptr,
'W' },
1042 {
"peer-info", required_argument,
nullptr,
'I' },
1043 {
"acc-protos", required_argument,
nullptr,
'K' },
1044 {
"gremlin", required_argument,
nullptr,
'G' },
1045 {
"proxy-basic", no_argument,
nullptr,
'B' },
1046 {
"alt-proxy", no_argument,
nullptr,
'A' },
1047#if defined(ENABLE_KOVPN) || defined(ENABLE_OVPNDCO) || defined(ENABLE_OVPNDCOWIN)
1048 {
"no-dco", no_argument,
nullptr,
'd' },
1050 {
"eval", no_argument,
nullptr,
'e' },
1051 {
"self-test", no_argument,
nullptr,
'T' },
1052 {
"cache-password", no_argument,
nullptr,
'C' },
1053 {
"no-cert", no_argument,
nullptr,
'x' },
1054 {
"force-aes-cbc", no_argument,
nullptr,
'f' },
1055 {
"google-dns", no_argument,
nullptr,
'g' },
1056 {
"persist-tun", no_argument,
nullptr,
'j' },
1057 {
"wintun", no_argument,
nullptr,
'w' },
1058 {
"allow-local-dns-resolvers", no_argument,
nullptr,
'l' },
1059 {
"def-keydir", required_argument,
nullptr,
'k' },
1060 {
"merge", no_argument,
nullptr,
'm' },
1061 {
"version", no_argument,
nullptr,
'v' },
1062 {
"auto-sess", no_argument,
nullptr,
'a' },
1063 {
"auth-retry", no_argument,
nullptr,
'Y' },
1064 {
"tcprof-override", required_argument,
nullptr,
'X' },
1065 {
"write-url", required_argument,
nullptr,
'Z' },
1066 {
"sso-methods", required_argument,
nullptr,
'S' },
1067 {
"ssl-debug", required_argument,
nullptr, 1 },
1068 {
"epki-cert", required_argument,
nullptr, 2 },
1069 {
"epki-ca", required_argument,
nullptr, 3 },
1070 {
"epki-key", required_argument,
nullptr, 4 },
1071 {
"legacy-algorithms", no_argument,
nullptr,
'L' },
1072 {
"non-preferred-algorithms", no_argument,
nullptr,
'Q' },
1073#ifdef OPENVPN_REMOTE_OVERRIDE
1074 {
"remote-override",required_argument,
nullptr, 5 },
1076 {
"tbc", no_argument,
nullptr, 6 },
1077 {
"app-custom-protocols", required_argument,
nullptr,
'K' },
1078 {
"certcheck-cert", required_argument,
nullptr,
'o' },
1079 {
"certcheck-pkey", required_argument,
nullptr,
'O' },
1080 {
"certcheck-clientca", required_argument,
nullptr,
'b' },
1081 {
nullptr, 0,
nullptr, 0 }
1093 std::string username;
1094 std::string password;
1095 std::string response;
1096 std::string dynamicChallengeCookie;
1098 std::string allowUnusedAddrFamilies;
1102 std::string compress;
1103 std::string privateKeyPassword;
1104 std::string tlsVersionMinOverride;
1105 std::string tlsCertProfileOverride;
1106 std::string proxyHost;
1107 std::string proxyPort;
1108 std::string proxyUsername;
1109 std::string proxyPassword;
1110 std::string peer_info;
1111 std::string gremlin;
1112 std::string ssoMethods;
1113 std::string appCustomProtocols;
1114 std::string certcheck_cert_fn;
1115 std::string certcheck_pkey_fn;
1116 std::string certcheck_clientca;
1118 bool self_test =
false;
1119 bool disableClientCert =
false;
1120 bool proxyAllowCleartextAuth =
false;
1121 int defaultKeyDirection = -1;
1122 int sslDebugLevel = 0;
1123 bool googleDnsFallback =
false;
1124 bool autologinSessions =
false;
1125 bool retryOnAuthFailed =
false;
1126 bool tunPersist =
false;
1127 bool wintun =
false;
1128 bool allowLocalDnsResolvers =
false;
1129 bool enableLegacyAlgorithms =
false;
1130 bool enableNonPreferredDCO =
false;
1132 bool version =
false;
1133 bool altProxy =
false;
1134#if defined(ENABLE_OVPNDCO) || defined(ENABLE_OVPNDCOWIN)
1139 bool generateTunBuilderCaptureEvent =
false;
1140 std::string epki_cert_fn;
1141 std::string epki_ca_fn;
1142 std::string epki_key_fn;
1144#ifdef OPENVPN_REMOTE_OVERRIDE
1145 std::string remote_override_cmd;
1147 std::string write_url_fn;
1152 while ((ch = getopt_long(argc, argv,
"6:ABCD:G:I:K:LM:P:QR:S:TU:W:X:YZ:ac:degh:o:O:b:jk:lmp:q:r:s:t:u:vwxz:", longopts,
nullptr)) != -1)
1157 sslDebugLevel = ::atoi(optarg);
1160 epki_cert_fn = optarg;
1163 epki_ca_fn = optarg;
1166 epki_key_fn = optarg;
1168#ifdef OPENVPN_REMOTE_OVERRIDE
1170 remote_override_cmd = optarg;
1174 generateTunBuilderCaptureEvent =
true;
1183 disableClientCert =
true;
1198 allowUnusedAddrFamilies = optarg;
1207 ssoMethods = optarg;
1210 timeout = ::atoi(optarg);
1216 privateKeyPassword = optarg;
1219 tlsVersionMinOverride = optarg;
1222 tlsCertProfileOverride = optarg;
1231 enableNonPreferredDCO =
true;
1234 proxyUsername = optarg;
1237 proxyPassword = optarg;
1240 proxyAllowCleartextAuth =
true;
1249 googleDnsFallback =
true;
1252 autologinSessions =
true;
1255 retryOnAuthFailed =
true;
1264 allowLocalDnsResolvers =
true;
1274 const std::string arg = optarg;
1275 if (arg ==
"bi" || arg ==
"bidirectional")
1276 defaultKeyDirection = -1;
1277 else if (arg ==
"0")
1278 defaultKeyDirection = 0;
1279 else if (arg ==
"1")
1280 defaultKeyDirection = 1;
1286 dynamicChallengeCookie = optarg;
1295 appCustomProtocols = optarg;
1298 certcheck_cert_fn = optarg;
1301 certcheck_pkey_fn = optarg;
1304 certcheck_clientca = optarg;
1307 enableLegacyAlgorithms =
true;
1310 write_url_fn = optarg;
1321 std::cout <<
"OpenVPN cli 1.0" << std::endl;
1348#if defined(OPENVPN_PLATFORM_WIN)
1350 auto argvw = CommandLineToArgvW(GetCommandLineW(), &nargs);
1356 for (
int i = 1; i < argc; ++i)
1358 config.content += argv[i];
1361 config.serverOverride = server;
1363 config.protoOverride = proto;
1364 config.connTimeout = timeout;
1365 config.compressionMode = compress;
1366 config.allowUnusedAddrFamilies = allowUnusedAddrFamilies;
1367 config.privateKeyPassword = privateKeyPassword;
1368 config.tlsVersionMinOverride = tlsVersionMinOverride;
1369 config.tlsCertProfileOverride = tlsCertProfileOverride;
1370 config.disableClientCert = disableClientCert;
1371 config.proxyHost = proxyHost;
1372 config.proxyPort = proxyPort;
1373 config.proxyUsername = proxyUsername;
1374 config.proxyPassword = proxyPassword;
1375 config.proxyAllowCleartextAuth = proxyAllowCleartextAuth;
1376 config.altProxy = altProxy;
1378 config.generateTunBuilderCaptureEvent = generateTunBuilderCaptureEvent;
1379 config.defaultKeyDirection = defaultKeyDirection;
1380 config.sslDebugLevel = sslDebugLevel;
1381 config.googleDnsFallback = googleDnsFallback;
1382 config.autologinSessions = autologinSessions;
1383 config.retryOnAuthFailed = retryOnAuthFailed;
1384 config.tunPersist = tunPersist;
1385 config.gremlinConfig = gremlin;
1388 config.allowLocalDnsResolvers = allowLocalDnsResolvers;
1389 config.enableLegacyAlgorithms = enableLegacyAlgorithms;
1390 config.enableNonPreferredDCAlgorithms = enableNonPreferredDCO;
1391 config.ssoMethods = ssoMethods;
1392 config.appCustomProtocols = appCustomProtocols;
1393#if defined(OPENVPN_OVPNCLI_SINGLE_THREAD)
1394 config.clockTickMS = 250;
1397 if (!epki_cert_fn.empty())
1398 config.externalPkiAlias =
"epki";
1405 if (!
config.serverOverride.empty())
1411 if (
config.serverOverride == se.friendlyName)
1413 config.serverOverride = se.server;
1423 std::cout <<
"EVAL PROFILE" << std::endl;
1424 std::cout <<
"error=" << cfg_eval.
error << std::endl;
1425 std::cout <<
"message=" << cfg_eval.
message << std::endl;
1427 std::cout <<
"profileName=" << cfg_eval.
profileName << std::endl;
1428 std::cout <<
"friendlyName=" << cfg_eval.
friendlyName << std::endl;
1429 std::cout <<
"autologin=" << cfg_eval.
autologin << std::endl;
1430 std::cout <<
"externalPki=" << cfg_eval.
externalPki << std::endl;
1431 std::cout <<
"staticChallenge=" << cfg_eval.
staticChallenge << std::endl;
1436 if (!
config.serverOverride.empty())
1437 std::cout <<
"server=" <<
config.serverOverride << std::endl;
1439 for (
size_t i = 0; i < cfg_eval.
serverList.size(); ++i)
1447#if defined(USE_NETCFG)
1448 auto dbus_system = DBus::Connection::Create(DBus::BusType::SYSTEM);
1449 NetCfgTunBuilder<Client> client(dbus_system);
1458 if (!username.empty() || !password.empty())
1459 std::cout <<
"NOTE: creds were not needed" << std::endl;
1462 if (!proxyUsername.empty())
1468 if (creds_status.
error)
1474 if (username.empty())
1477 if (password.empty() && dynamicChallengeCookie.empty())
1486 if (creds_status.
error)
1490 client.certcheck_clientca_fn = certcheck_clientca;
1493 if (!epki_cert_fn.empty())
1496 if (!epki_ca_fn.empty())
1498#if defined(USE_MBEDTLS) || defined(USE_OPENSSL)
1499 if (!epki_key_fn.empty())
1502#if defined(USE_MBEDTLS)
1504 auto mbedrng = std::make_unique<MbedTLSRandom>();
1505 client.epki_ctx.parse(epki_key_txt,
"EPKI", privateKeyPassword, *mbedrng);
1507 client.epki_pkey.parse_pem(epki_key_txt,
"epki private key",
nullptr);
1516 if (!certcheck_cert_fn.empty())
1519 const std::string epki_key_txt =
read_text_utf8(certcheck_pkey_fn);
1521 client.certcheck_pkey.parse_pem(epki_key_txt,
"certcheck private key",
nullptr);
1523 auto mbedrng = std::make_unique<MbedTLSRandom>();
1524 client.certcheck_pkey.parse(epki_key_txt,
"Certcheck", privateKeyPassword, *mbedrng);
1528#ifdef OPENVPN_REMOTE_OVERRIDE
1529 client.set_remote_override_cmd(remote_override_cmd);
1532 client.set_write_url_fn(write_url_fn);
1534 std::cout <<
"CONNECTING..." << std::endl;
1540 if (client.is_dynamic_challenge())
1542 std::cout <<
"ENTER RESPONSE" << std::endl;
1543 std::getline(std::cin, response);
1544 if (!response.empty())
1546 dynamicChallengeCookie = client.dynamic_challenge_cookie();
1553 client.print_stats();
1560 if (ERR_peek_error())
1571 catch (
const usage &)
1573 std::cout <<
"OpenVPN Client (ovpncli)" << std::endl;
1574 std::cout <<
"usage: cli [options] <config-file> [extra-config-directives...]" << std::endl;
1575 std::cout <<
"--version, -v : show version info" << std::endl;
1576 std::cout <<
"--eval, -e : evaluate profile only (standalone)" << std::endl;
1577 std::cout <<
"--merge, -m : merge profile into unified format (standalone)" << std::endl;
1578 std::cout <<
"--username, -u : username" << std::endl;
1579 std::cout <<
"--password, -p : password" << std::endl;
1580 std::cout <<
"--response, -r : static response" << std::endl;
1581 std::cout <<
"--dc, -D : dynamic challenge/response cookie" << std::endl;
1582 std::cout <<
"--proto, -P : protocol override (udp|tcp)" << std::endl;
1583 std::cout <<
"--server, -s : server override" << std::endl;
1584 std::cout <<
"--port, -R : port override" << std::endl;
1585#ifdef OPENVPN_REMOTE_OVERRIDE
1586 std::cout <<
"--remote-override : command to run to generate next remote (returning host,ip,port,proto)" << std::endl;
1588 std::cout <<
"--allowAF, -6 : Allow unused address families (yes|no|default)" << std::endl;
1589 std::cout <<
"--timeout, -t : timeout" << std::endl;
1590 std::cout <<
"--compress, -c : compression mode (yes|no|asym)" << std::endl;
1591 std::cout <<
"--pk-password, -z : private key password" << std::endl;
1592 std::cout <<
"--tvm-override, -M : tls-version-min override (disabled, default, tls_1_x)" << std::endl;
1593 std::cout <<
"--legacy-algorithms, -L: Enable legacy algorithm (OpenSSL legacy provider)" << std::endl;
1594 std::cout <<
"--non-preferred-algorithms, -Q: Enables non preferred data channel algorithms" << std::endl;
1595 std::cout <<
"--tcprof-override, -X : tls-cert-profile override ("
1597#ifdef OPENVPN_ALLOW_INSECURE_CERTPROFILE
1601 "legacy, preferred, etc.)" << std::endl;
1602 std::cout <<
"--proxy-host, -h : HTTP proxy hostname/IP" << std::endl;
1603 std::cout <<
"--proxy-port, -q : HTTP proxy port" << std::endl;
1604 std::cout <<
"--proxy-username, -U : HTTP proxy username" << std::endl;
1605 std::cout <<
"--proxy-password, -W : HTTP proxy password" << std::endl;
1606 std::cout <<
"--proxy-basic, -B : allow HTTP basic auth" << std::endl;
1607 std::cout <<
"--alt-proxy, -A : enable alternative proxy module" << std::endl;
1608#if defined(ENABLE_KOVPN) || defined(ENABLE_OVPNDCO) || defined(ENABLE_OVPNDCOWIN)
1609 std::cout <<
"--no-dco, -d : disable data channel offload" << std::endl;
1611 std::cout <<
"--cache-password, -C : cache password" << std::endl;
1612 std::cout <<
"--no-cert, -x : disable client certificate" << std::endl;
1613 std::cout <<
"--def-keydir, -k : default key direction ('bi', '0', or '1')" << std::endl;
1614 std::cout <<
"--ssl-debug : SSL debug level" << std::endl;
1615 std::cout <<
"--google-dns, -g : enable Google DNS fallback" << std::endl;
1616 std::cout <<
"--auto-sess, -a : request autologin session" << std::endl;
1617 std::cout <<
"--auth-retry, -Y : retry connection on auth failure" << std::endl;
1618 std::cout <<
"--persist-tun, -j : keep TUN interface open across reconnects" << std::endl;
1619 std::cout <<
"--wintun, -w : use WinTun instead of TAP-Windows6 on Windows" << std::endl;
1620 std::cout <<
"--peer-info, -I : peer info key/value list in the form K1=V1,K2=V2,... or @kv.json" << std::endl;
1621 std::cout <<
"--gremlin, -G : gremlin info (send_delay_ms, recv_delay_ms, send_drop_prob, recv_drop_prob)" << std::endl;
1622 std::cout <<
"--epki-ca : simulate external PKI cert supporting intermediate/root certs" << std::endl;
1623 std::cout <<
"--epki-cert : simulate external PKI cert" << std::endl;
1624 std::cout <<
"--epki-key : simulate external PKI private key" << std::endl;
1625 std::cout <<
"--sso-methods : auth pending methods to announce via IV_SSO" << std::endl;
1626 std::cout <<
"--write-url, -Z : write INFO URL to file" << std::endl;
1627 std::cout <<
"--tbc : generate INFO_JSON/TUN_BUILDER_CAPTURE event" << std::endl;
1628 std::cout <<
"--app-custom-protocols, -K : ACC protocols to advertise" << std::endl;
1629 std::cout <<
"--certcheck-cert, -o : path to certificate PEM for certcheck" << std::endl;
1630 std::cout <<
"--certcheck-pkey, -O : path to decrypted pkey PEM for certcheck" << std::endl;
1631 std::cout <<
"--certcheck-clientca, -b : path to decrypted pkey PEM for certcheck CA" << std::endl;
1637#ifndef OPENVPN_OVPNCLI_OMIT_MAIN
1643#ifdef OPENVPN_LOG_LOGBASE_H
1647#if defined(OPENVPN_PLATFORM_WIN)
1648 SetConsoleOutputCP(CP_UTF8);
1655 catch (
const std::exception &e)
1657 std::cout <<
"Main thread exception: " << e.what() << std::endl;
bool socket_protect(openvpn_io::detail::socket_type socket, std::string remote, bool ipv6) override
void handle_dpc1_protocol(const ClientAPI::AppCustomControlMessageEvent &acev)
void handle_certcheck_request()
Begin a cck1 (certcheck) handshake in response to a dpc1 server request.
boolean pause_on_connection_timeout()
void log(ClientAPI_LogInfo loginfo)
std::string certcheck_cert
file name of properly encoded server cert
void open_url(std::string url_str)
std::string dynamic_challenge_cookie()
void acc_event(const openvpn::ClientAPI::AppCustomControlMessageEvent &event) override
volatile ClockTickAction clock_tick_action
static constexpr char certcheck_init_verb[]
void event(const ClientAPI::Event &ev) override
void clock_tick() override
void set_write_url_fn(const std::string &fn)
void external_pki_cert_request(ClientAPI_ExternalPKICertRequest req)
static int rng_callback(void *arg, unsigned char *data, size_t len)
void external_pki_sign_request(ClientAPI_ExternalPKISignRequest req)
bool is_dynamic_challenge() const
std::string certcheck_clientca_fn
file name of properly encoded client ca
void set_clock_tick_action(const ClockTickAction action)
std::string to_string() const
std::string encode(const V &data) const
size_t decode(void *data, size_t len, const std::string &str) const
static std::string copyright()
std::string crypto_self_test()
EvalConfig eval_config(const Config &config)
static std::string platform()
static bool parse_dynamic_challenge(const std::string &cookie, DynamicChallenge &dc)
void send_app_control_channel_msg(const std::string &protocol, const std::string &msg)
void post_cc_msg(const std::string &msg)
void start_cert_check_epki(const std::string &alias, const std::optional< const std::string > &ca)
Start up the cert check handshake using the given epki_alias string.
virtual void remote_override(RemoteOverride &)
std::vector< long long > stats_bundle() const
void start_cert_check(const std::string &client_cert, const std::string &clientkey, const std::optional< const std::string > &ca=std::nullopt)
Start up the cert check handshake using the given certs and key.
virtual bool remote_override_enabled()
static std::string stats_name(int index)
void pause(const std::string &reason)
void reconnect(int seconds)
const T * c_data() const
Returns a const pointer to the start of the buffer.
size_t length() const
Returns the length of the buffer.
size_t size() const
Returns the size of the buffer in T objects.
T * data()
Get a mutable pointer to the start of the array.
mbedtls_pk_context * get() const
std::string render_pem() const
static const char * to_string(const mbedtls_md_type_t t)
T alg_from_prefix(Buffer &buf) const
const std::string & error() const
const char * status_string() const
const std::string & profile_content() const
void reset() noexcept
Points this RCPtr<T> to nullptr safely.
virtual bool rand_bytes_noexcept(unsigned char *buf, size_t size)=0
Fill a buffer with random bytes without throwing exceptions.
virtual bool tun_builder_set_dns_options(const DnsOptions &dns)
Callback to set DNS related options to VPN interface.
virtual bool tun_builder_add_address(const std::string &address, int prefix_length, const std::string &gateway, bool ipv6, bool net30)
Callback to add a network address to the VPN interface.
virtual bool tun_builder_add_route(const std::string &address, int prefix_length, int metric, bool ipv6)
Callback to add a route to the VPN interface.
virtual void tun_builder_teardown(bool disconnect)
Indicates that tunnel is being torn down.
virtual bool tun_builder_reroute_gw(bool ipv4, bool ipv6, unsigned int flags)
Callback to reroute the default gateway to the VPN interface.
virtual int tun_builder_establish()
Callback to establish the VPN tunnel.
virtual bool tun_builder_set_mtu(int mtu)
Callback to set the MTU of the VPN interface.
virtual bool tun_builder_set_remote_address(const std::string &address, bool ipv6)
Callback to set the address of the remote server.
virtual bool tun_builder_set_session_name(const std::string &name)
Sets the session name for the TunBuilder.
virtual bool tun_builder_new()
Callback to construct a new TunBuilder. This function should be called first.
int main(int argc, char *argv[])
static std::string read_profile(const char *fn, const std::string *profile_content)
static Client * the_client
static void handler(int signum)
static void worker_thread()
int openvpn_client(int argc, char *argv[], const std::string *profile_content)
static void start_thread(Client &client)
#define OPENVPN_SIMPLE_EXCEPTION(C)
#define OPENVPN_THROW_EXCEPTION(stuff)
#define OPENVPN_LOG(args)
#define OPENVPN_LOG_STRING(str)
constexpr BufferFlags GROW(1u<< 2)
if enabled, buffer will grow (otherwise buffer_full exception will be thrown)
constexpr BufferFlags ARRAY(1u<< 3)
if enabled, use as array
char * utf8(wchar_t *str)
int strcasecmp(const char *s1, const char *s2)
bool starts_with(const STRING &str, const std::string &prefix)
std::vector< T > split(const T &str, const typename T::value_type sep, const int maxsplit=-1)
std::string first_line(const std::string &str)
std::string render_hex_generic(const V &data, const bool caps=false)
std::string read_text_utf8(const std::string &filename, const std::uint64_t max_size=0)
std::string to_string(const T &t)
Convert a value to a string.
std::string openssl_error()
CleanupType< F > Cleanup(F method) noexcept
void write_string(const std::string &filename, const std::string &str)
std::string get_password(const char *prompt)
int system_cmd(const std::string &cmd, const Argv &argv, RedirectBase *redir, const Environ *env, const sigset_t *sigmask)
Struct containing configuration details parsed from an OpenVPN configuration file.
std::vector< ServerEntry > serverList
std::string userlockedUsername
bool privateKeyPasswordRequired
std::string staticChallenge
std::string supportingChain
std::string http_proxy_pass
std::string http_proxy_user
std::string dynamicChallengeCookie
All DNS options set with the –dns or –dhcp-option directive.
static void parse_flexible(const std::string &src, SET &dest)
const TunBuilderCapture::Ptr tbc(new TunBuilderCapture)
static const char config[]
static std::stringstream out