diff --git a/client/ovpncli.cpp b/client/ovpncli.cpp index ba755267..d4d897e5 100644 --- a/client/ovpncli.cpp +++ b/client/ovpncli.cpp @@ -4,7 +4,7 @@ // packet encryption, packet authentication, and // packet compression. // -// Copyright (C) 2012-2022 OpenVPN Inc. +// Copyright (C) 2012 - 2024 OpenVPN Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License Version 3 @@ -650,6 +650,7 @@ OPENVPN_CLIENT_EXPORT void OpenVPNClientHelper::parse_config(const Config &confi eval.friendlyName = cc.friendlyName(); eval.autologin = cc.autologin(); eval.externalPki = cc.externalPki(); + eval.vpnCa = cc.vpnCa(); eval.staticChallenge = cc.staticChallenge(); eval.staticChallengeEcho = cc.staticChallengeEcho(); eval.privateKeyPasswordRequired = cc.privateKeyPasswordRequired(); diff --git a/client/ovpncli.hpp b/client/ovpncli.hpp index cf543314..7c03f2ed 100644 --- a/client/ovpncli.hpp +++ b/client/ovpncli.hpp @@ -4,7 +4,7 @@ // packet encryption, packet authentication, and // packet compression. // -// Copyright (C) 2012-2022 OpenVPN Inc. +// Copyright (C) 2012 - 2024 OpenVPN Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License Version 3 @@ -53,8 +53,14 @@ struct ServerEntry std::string friendlyName; }; -// return properties of config -// (client reads) +/** + @brief Struct containing configuration details parsed from an OpenVPN configuration file. + @details + This struct holds various properties extracted from an OpenVPN configuration file, such as + error status, profile name, autologin flag, external PKI flag, VPN server CA, static + challenge, private key password requirement, remote host information, list of selectable VPN + servers, Windows driver, and DCO compatibility details. +*/ struct EvalConfig { // true if error @@ -78,6 +84,13 @@ struct EvalConfig // if true, this is an External PKI profile (no cert or key directives) bool externalPki = false; + // VPN server CA in PEM format as given in the configuration. This is the CA, the + // VPN server certificate is checked against. This is not a parsed version so it + // can have extra lines around the actual certificates that an X509 parser would + // ignore. + // Note that this can can be empty if the profile uses --peer-fingerprint instead of traditional PKI check. + std::string vpnCa; + // static challenge, may be empty, ignored if autologin std::string staticChallenge; diff --git a/openvpn/client/cliopthelper.hpp b/openvpn/client/cliopthelper.hpp index 2b065b4a..a0d1b6d5 100644 --- a/openvpn/client/cliopthelper.hpp +++ b/openvpn/client/cliopthelper.hpp @@ -4,7 +4,7 @@ // packet encryption, packet authentication, and // packet compression. // -// Copyright (C) 2012-2022 OpenVPN Inc. +// Copyright (C) 2012 - 2024 OpenVPN Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License Version 3 @@ -224,6 +224,12 @@ class ParseClientConfig } } + { + const Option *o = options.get_ptr("ca"); + if (o) + vpnCa_ = o->get(1, Option::MULTILINE); + } + // profile name { const Option *o = options.get_ptr("PROFILE"); @@ -461,6 +467,11 @@ class ParseClientConfig return externalPki_; } + std::string vpnCa() const + { + return vpnCa_; + } + // static challenge, may be empty, ignored if autologin const std::string &staticChallenge() const { @@ -786,6 +797,7 @@ class ParseClientConfig bool autologin_; bool clientCertEnabled_; bool externalPki_; + std::string vpnCa_; bool pushPeerInfo_; std::string staticChallenge_; bool staticChallengeEcho_; diff --git a/test/unittests/test_cliopt.cpp b/test/unittests/test_cliopt.cpp index ff992d67..014bc1a9 100644 --- a/test/unittests/test_cliopt.cpp +++ b/test/unittests/test_cliopt.cpp @@ -195,6 +195,17 @@ TEST(config, dco_compatibility) } } +TEST(config, server_cert_in_eval) +{ + ClientAPI::Config api_config; + api_config.content = minimalConfig; + + ClientAPI::OpenVPNClientHelper client_helper; + auto eval = client_helper.eval_config(api_config); + + EXPECT_FALSE(eval.vpnCa.empty()); +} + TEST(config, server_options_present_in_error_msg) {