shill: openvpn: Point to default CAs when no CA is specified.
If no CaCert or CaCertNss property is specified, use the --capath
option to point openvpn to the default system CA certificates.
BUG=chrome-os-partner:13785
TEST=unit tests, tested on device that --capath is passed if CA
certificate is default
Change-Id: Ic61d6e69926d77c93804ffd1cd0975713a60db9a
Reviewed-on: https://gerrit.chromium.org/gerrit/34103
Tested-by: Darin Petkov <petkov@chromium.org>
Reviewed-by: Paul Stewart <pstew@chromium.org>
Commit-Ready: Darin Petkov <petkov@chromium.org>
diff --git a/openvpn_driver.cc b/openvpn_driver.cc
index 10a6ca7..59c0500 100644
--- a/openvpn_driver.cc
+++ b/openvpn_driver.cc
@@ -63,6 +63,8 @@
} // namespace
// static
+const char OpenVPNDriver::kDefaultCACertificatesPath[] = "/etc/ssl/certs";
+// static
const char OpenVPNDriver::kOpenVPNPath[] = "/usr/sbin/openvpn";
// static
const char OpenVPNDriver::kOpenVPNScript[] = SCRIPTDIR "/openvpn-script";
@@ -549,7 +551,7 @@
AppendValueOption(flimflam::kOpenVPNServerPollTimeoutProperty,
"--server-poll-timeout", options);
- if (!InitNSSOptions(options, error)) {
+ if (!InitCAOptions(options, error)) {
return;
}
@@ -558,7 +560,6 @@
AppendValueOption(kOpenVPNPingExitProperty, "--ping-exit", options);
AppendValueOption(kOpenVPNPingRestartProperty, "--ping-restart", options);
- AppendValueOption(flimflam::kOpenVPNCaCertProperty, "--ca", options);
AppendValueOption(kOpenVPNCertProperty, "--cert", options);
AppendValueOption(
flimflam::kOpenVPNNsCertTypeProperty, "--ns-cert-type", options);
@@ -620,26 +621,41 @@
options->push_back("openvpn");
}
-bool OpenVPNDriver::InitNSSOptions(vector<string> *options, Error *error) {
+bool OpenVPNDriver::InitCAOptions(vector<string> *options, Error *error) {
string ca_cert =
+ args()->LookupString(flimflam::kOpenVPNCaCertProperty, "");
+ string ca_cert_nss =
args()->LookupString(flimflam::kOpenVPNCaCertNSSProperty, "");
- if (!ca_cert.empty()) {
- if (!args()->LookupString(flimflam::kOpenVPNCaCertProperty, "").empty()) {
- Error::PopulateAndLog(error,
- Error::kInvalidArguments,
- "Can't specify both CACert and CACertNSS.");
- return false;
- }
+ if (ca_cert.empty() && ca_cert_nss.empty()) {
+ // Use default CAs if no CA certificate is provided.
+ options->push_back("--capath");
+ options->push_back(kDefaultCACertificatesPath);
+ return true;
+ }
+ if (!ca_cert.empty() && !ca_cert_nss.empty()) {
+ Error::PopulateAndLog(error,
+ Error::kInvalidArguments,
+ "Can't specify both CACert and CACertNSS.");
+ return false;
+ }
+ options->push_back("--ca");
+ if (!ca_cert_nss.empty()) {
+ DCHECK(ca_cert.empty());
const string &vpnhost = args()->GetString(flimflam::kProviderHostProperty);
vector<char> id(vpnhost.begin(), vpnhost.end());
- FilePath certfile = nss_->GetPEMCertfile(ca_cert, id);
+ FilePath certfile = nss_->GetPEMCertfile(ca_cert_nss, id);
if (certfile.empty()) {
- LOG(ERROR) << "Unable to extract certificate: " << ca_cert;
- } else {
- options->push_back("--ca");
- options->push_back(certfile.value());
+ Error::PopulateAndLog(
+ error,
+ Error::kInvalidArguments,
+ "Unable to extract NSS CA certificate: " + ca_cert_nss);
+ return false;
}
+ options->push_back(certfile.value());
+ return true;
}
+ DCHECK(!ca_cert.empty() && ca_cert_nss.empty());
+ options->push_back(ca_cert);
return true;
}
diff --git a/openvpn_driver.h b/openvpn_driver.h
index 86f7e94..6f788d4 100644
--- a/openvpn_driver.h
+++ b/openvpn_driver.h
@@ -85,10 +85,10 @@
FRIEND_TEST(OpenVPNDriverTest, DeleteInterface);
FRIEND_TEST(OpenVPNDriverTest, Disconnect);
FRIEND_TEST(OpenVPNDriverTest, GetRouteOptionEntry);
+ FRIEND_TEST(OpenVPNDriverTest, InitCAOptions);
FRIEND_TEST(OpenVPNDriverTest, InitEnvironment);
FRIEND_TEST(OpenVPNDriverTest, InitLoggingOptions);
FRIEND_TEST(OpenVPNDriverTest, InitManagementChannelOptions);
- FRIEND_TEST(OpenVPNDriverTest, InitNSSOptions);
FRIEND_TEST(OpenVPNDriverTest, InitOptions);
FRIEND_TEST(OpenVPNDriverTest, InitOptionsHostWithPort);
FRIEND_TEST(OpenVPNDriverTest, InitOptionsNoHost);
@@ -109,6 +109,8 @@
FRIEND_TEST(OpenVPNDriverTest, SplitPortFromHost);
FRIEND_TEST(OpenVPNDriverTest, VerifyPaths);
+ static const char kDefaultCACertificatesPath[];
+
static const char kOpenVPNPath[];
static const char kOpenVPNScript[];
static const Property kProperties[];
@@ -146,7 +148,7 @@
std::string *port);
void InitOptions(std::vector<std::string> *options, Error *error);
- bool InitNSSOptions(std::vector<std::string> *options, Error *error);
+ bool InitCAOptions(std::vector<std::string> *options, Error *error);
void InitPKCS11Options(std::vector<std::string> *options);
bool InitManagementChannelOptions(
std::vector<std::string> *options, Error *error);
diff --git a/openvpn_driver_unittest.cc b/openvpn_driver_unittest.cc
index e7f9345..b86faf4 100644
--- a/openvpn_driver_unittest.cc
+++ b/openvpn_driver_unittest.cc
@@ -448,17 +448,14 @@
TEST_F(OpenVPNDriverTest, InitOptions) {
static const char kHost[] = "192.168.2.254";
static const char kTLSAuthContents[] = "SOME-RANDOM-CONTENTS\n";
- static const char kCaCertNSS[] = "{1234}";
static const char kID[] = "TestPKCS11ID";
FilePath empty_cert;
SetArg(flimflam::kProviderHostProperty, kHost);
SetArg(flimflam::kOpenVPNTLSAuthContentsProperty, kTLSAuthContents);
- SetArg(flimflam::kOpenVPNCaCertNSSProperty, kCaCertNSS);
SetArg(flimflam::kOpenVPNClientCertIdProperty, kID);
driver_->rpc_task_.reset(new RPCTask(&control_, this));
driver_->tunnel_interface_ = kInterfaceName;
EXPECT_CALL(*management_server_, Start(_, _, _)).WillOnce(Return(true));
- EXPECT_CALL(nss_, GetPEMCertfile(kCaCertNSS, _)).WillOnce(Return(empty_cert));
ServiceRefPtr null_service;
EXPECT_CALL(manager_, GetDefaultService()).WillOnce(Return(null_service));
@@ -479,6 +476,7 @@
file_util::ReadFileToString(driver_->tls_auth_file_, &contents));
EXPECT_EQ(kTLSAuthContents, contents);
ExpectInFlags(options, "--pkcs11-id", kID);
+ ExpectInFlags(options, "--capath", OpenVPNDriver::kDefaultCACertificatesPath);
EXPECT_TRUE(std::find(options.begin(), options.end(), "--syslog") !=
options.end());
}
@@ -504,34 +502,49 @@
EXPECT_EQ("1234", *it);
}
-TEST_F(OpenVPNDriverTest, InitNSSOptions) {
+TEST_F(OpenVPNDriverTest, InitCAOptions) {
static const char kHost[] = "192.168.2.254";
+ static const char kCaCert[] = "foo";
static const char kCaCertNSS[] = "{1234}";
static const char kNSSCertfile[] = "/tmp/nss-cert";
+
+ Error error;
+ vector<string> options;
+ EXPECT_TRUE(driver_->InitCAOptions(&options, &error));
+ EXPECT_TRUE(error.IsSuccess());
+ ExpectInFlags(options, "--capath", OpenVPNDriver::kDefaultCACertificatesPath);
+
+ options.clear();
+ SetArg(flimflam::kOpenVPNCaCertProperty, kCaCert);
+ EXPECT_TRUE(driver_->InitCAOptions(&options, &error));
+ ExpectInFlags(options, "--ca", kCaCert);
+ EXPECT_TRUE(error.IsSuccess());
+
+ SetArg(flimflam::kOpenVPNCaCertNSSProperty, kCaCertNSS);
+ EXPECT_FALSE(driver_->InitCAOptions(&options, &error));
+ EXPECT_EQ(Error::kInvalidArguments, error.type());
+ EXPECT_EQ("Can't specify both CACert and CACertNSS.", error.message());
+
+ SetArg(flimflam::kOpenVPNCaCertProperty, "");
+ SetArg(flimflam::kProviderHostProperty, kHost);
FilePath empty_cert;
FilePath nss_cert(kNSSCertfile);
- SetArg(flimflam::kProviderHostProperty, kHost);
- SetArg(flimflam::kOpenVPNCaCertNSSProperty, kCaCertNSS);
EXPECT_CALL(nss_,
GetPEMCertfile(kCaCertNSS,
ElementsAreArray(kHost, arraysize(kHost) - 1)))
.WillOnce(Return(empty_cert))
.WillOnce(Return(nss_cert));
- Error error;
- vector<string> options;
- EXPECT_TRUE(driver_->InitNSSOptions(&options, &error));
- EXPECT_TRUE(error.IsSuccess());
- EXPECT_TRUE(options.empty());
- EXPECT_TRUE(driver_->InitNSSOptions(&options, &error));
+ error.Reset();
+ EXPECT_FALSE(driver_->InitCAOptions(&options, &error));
+ EXPECT_EQ(Error::kInvalidArguments, error.type());
+ EXPECT_EQ("Unable to extract NSS CA certificate: {1234}", error.message());
+
+ error.Reset();
+ options.clear();
+ EXPECT_TRUE(driver_->InitCAOptions(&options, &error));
ExpectInFlags(options, "--ca", kNSSCertfile);
EXPECT_TRUE(error.IsSuccess());
-
- SetArg(flimflam::kOpenVPNCaCertProperty, "foo");
- options.clear();
- EXPECT_FALSE(driver_->InitNSSOptions(&options, &error));
- EXPECT_EQ(Error::kInvalidArguments, error.type());
- EXPECT_EQ("Can't specify both CACert and CACertNSS.", error.message());
}
TEST_F(OpenVPNDriverTest, InitPKCS11Options) {