shill: openvpn: Support no-OTP user/password authentication.
This also fixes a flimflam bug where passwords were sent unescaped, so \ and "
weren't legal password characters in no-OTP authentication mode.
BUG=chromium:137970
TEST=unit tests
Change-Id: I0caad371a5db91739eaf83fc587ad88df1433c77
Reviewed-on: https://gerrit.chromium.org/gerrit/28266
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_management_server.cc b/openvpn_management_server.cc
index e667733..cc0aba4 100644
--- a/openvpn_management_server.cc
+++ b/openvpn_management_server.cc
@@ -200,9 +200,7 @@
if (message.find("SC:") != string::npos) {
PerformStaticChallenge(tag);
} else {
- NOTIMPLEMENTED()
- << ": User/password (no-OTP) authentication not implemented.";
- driver_->Cleanup(Service::kStateFailure);
+ PerformAuthentication(tag);
}
} else if (StartsWithASCII(tag, "User-Specific TPM Token", true)) {
SupplyTPMToken(tag);
@@ -261,6 +259,23 @@
driver_->args()->RemoveString(flimflam::kOpenVPNOTPProperty);
}
+void OpenVPNManagementServer::PerformAuthentication(const string &tag) {
+ LOG(INFO) << "Perform authentication: " << tag;
+ string user =
+ driver_->args()->LookupString(flimflam::kOpenVPNUserProperty, "");
+ string password =
+ driver_->args()->LookupString(flimflam::kOpenVPNPasswordProperty, "");
+ if (user.empty() || password.empty()) {
+ NOTIMPLEMENTED() << ": Missing credentials:"
+ << (user.empty() ? " no-user" : "")
+ << (password.empty() ? " no-password" : "");
+ driver_->Cleanup(Service::kStateFailure);
+ return;
+ }
+ SendUsername(tag, user);
+ SendPassword(tag, password);
+}
+
void OpenVPNManagementServer::SupplyTPMToken(const string &tag) {
SLOG(VPN, 2) << __func__ << "(" << tag << ")";
string pin = driver_->args()->LookupString(flimflam::kOpenVPNPinProperty, "");
@@ -320,6 +335,18 @@
return true;
}
+// static
+string OpenVPNManagementServer::EscapeToQuote(const string &str) {
+ string escaped;
+ for (string::const_iterator it = str.begin(); it != str.end(); ++it) {
+ if (*it == '\\' || *it == '"') {
+ escaped += '\\';
+ }
+ escaped += *it;
+ }
+ return escaped;
+}
+
void OpenVPNManagementServer::Send(const string &data) {
SLOG(VPN, 2) << __func__;
ssize_t len = sockets_->Send(connected_socket_, data.data(), data.size(), 0);
@@ -341,7 +368,9 @@
void OpenVPNManagementServer::SendPassword(const string &tag,
const string &password) {
SLOG(VPN, 2) << __func__;
- Send(StringPrintf("password \"%s\" \"%s\"\n", tag.c_str(), password.c_str()));
+ Send(StringPrintf("password \"%s\" \"%s\"\n",
+ tag.c_str(),
+ EscapeToQuote(password).c_str()));
}
void OpenVPNManagementServer::SendHoldRelease() {