1// 2// Copyright (C) 2012 The Android Open Source Project 3// 4// Licensed under the Apache License, Version 2.0 (the "License"); 5// you may not use this file except in compliance with the License. 6// You may obtain a copy of the License at 7// 8// http://www.apache.org/licenses/LICENSE-2.0 9// 10// Unless required by applicable law or agreed to in writing, software 11// distributed under the License is distributed on an "AS IS" BASIS, 12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13// See the License for the specific language governing permissions and 14// limitations under the License. 15// 16 17#include "shill/vpn/openvpn_management_server.h" 18 19#include <arpa/inet.h> 20#include <netinet/in.h> 21 22#include <base/bind.h> 23#include <base/strings/string_number_conversions.h> 24#include <base/strings/string_split.h> 25#include <base/strings/string_util.h> 26#include <base/strings/stringprintf.h> 27#include <brillo/data_encoding.h> 28#if defined(__ANDROID__) 29#include <dbus/service_constants.h> 30#else 31#include <chromeos/dbus/service_constants.h> 32#endif // __ANDROID__ 33 34#include "shill/error.h" 35#include "shill/event_dispatcher.h" 36#include "shill/logging.h" 37#include "shill/net/sockets.h" 38#include "shill/vpn/openvpn_driver.h" 39 40using base::Bind; 41using base::IntToString; 42using base::SplitString; 43using base::StringPrintf; 44using base::Unretained; 45using std::string; 46using std::vector; 47 48namespace shill { 49 50namespace Logging { 51static auto kModuleLogScope = ScopeLogger::kVPN; 52static string ObjectID(OpenVPNManagementServer* o) { 53 return o->GetServiceRpcIdentifier(); 54} 55} 56 57namespace { 58const char kPasswordTagAuth[] = "Auth"; 59} // namespace 60 61const char OpenVPNManagementServer::kStateReconnecting[] = "RECONNECTING"; 62const char OpenVPNManagementServer::kStateResolve[] = "RESOLVE"; 63 64OpenVPNManagementServer::OpenVPNManagementServer(OpenVPNDriver* driver) 65 : driver_(driver), 66 sockets_(nullptr), 67 socket_(-1), 68 dispatcher_(nullptr), 69 connected_socket_(-1), 70 hold_waiting_(false), 71 hold_release_(false) {} 72 73OpenVPNManagementServer::~OpenVPNManagementServer() { 74 OpenVPNManagementServer::Stop(); 75} 76 77bool OpenVPNManagementServer::Start(EventDispatcher* dispatcher, 78 Sockets* sockets, 79 vector<vector<string>>* options) { 80 SLOG(this, 2) << __func__; 81 if (IsStarted()) { 82 return true; 83 } 84 85 int socket = sockets->Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 86 if (socket < 0) { 87 PLOG(ERROR) << "Unable to create management server socket."; 88 return false; 89 } 90 91 struct sockaddr_in addr; 92 socklen_t addrlen = sizeof(addr); 93 memset(&addr, 0, sizeof(addr)); 94 addr.sin_family = AF_INET; 95 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 96 if (sockets->Bind( 97 socket, reinterpret_cast<struct sockaddr*>(&addr), addrlen) < 0 || 98 sockets->Listen(socket, 1) < 0 || 99 sockets->GetSockName( 100 socket, reinterpret_cast<struct sockaddr*>(&addr), &addrlen) < 0) { 101 PLOG(ERROR) << "Socket setup failed."; 102 sockets->Close(socket); 103 return false; 104 } 105 106 SLOG(this, 2) << "Listening socket: " << socket; 107 sockets_ = sockets; 108 socket_ = socket; 109 ready_handler_.reset( 110 dispatcher->CreateReadyHandler( 111 socket, IOHandler::kModeInput, 112 Bind(&OpenVPNManagementServer::OnReady, Unretained(this)))); 113 dispatcher_ = dispatcher; 114 115 // Append openvpn management API options. 116 driver_->AppendOption("management", inet_ntoa(addr.sin_addr), 117 IntToString(ntohs(addr.sin_port)), options); 118 driver_->AppendOption("management-client", options); 119 driver_->AppendOption("management-hold", options); 120 hold_release_ = false; 121 hold_waiting_ = false; 122 123 driver_->AppendOption("management-query-passwords", options); 124 if (driver_->AppendValueOption(kOpenVPNStaticChallengeProperty, 125 "static-challenge", 126 options)) { 127 options->back().push_back("1"); // Force echo. 128 } 129 return true; 130} 131 132void OpenVPNManagementServer::Stop() { 133 SLOG(this, 2) << __func__; 134 if (!IsStarted()) { 135 return; 136 } 137 state_.clear(); 138 input_handler_.reset(); 139 if (connected_socket_ >= 0) { 140 sockets_->Close(connected_socket_); 141 connected_socket_ = -1; 142 } 143 dispatcher_ = nullptr; 144 ready_handler_.reset(); 145 if (socket_ >= 0) { 146 sockets_->Close(socket_); 147 socket_ = -1; 148 } 149 sockets_ = nullptr; 150} 151 152void OpenVPNManagementServer::ReleaseHold() { 153 SLOG(this, 2) << __func__; 154 hold_release_ = true; 155 if (!hold_waiting_) { 156 return; 157 } 158 LOG(INFO) << "Releasing hold."; 159 hold_waiting_ = false; 160 SendHoldRelease(); 161} 162 163void OpenVPNManagementServer::Hold() { 164 SLOG(this, 2) << __func__; 165 hold_release_ = false; 166} 167 168void OpenVPNManagementServer::Restart() { 169 LOG(INFO) << "Restart."; 170 SendSignal("SIGUSR1"); 171} 172 173std::string OpenVPNManagementServer::GetServiceRpcIdentifier() { 174 return driver_->GetServiceRpcIdentifier(); 175} 176 177void OpenVPNManagementServer::OnReady(int fd) { 178 SLOG(this, 2) << __func__ << "(" << fd << ")"; 179 connected_socket_ = sockets_->Accept(fd, nullptr, nullptr); 180 if (connected_socket_ < 0) { 181 PLOG(ERROR) << "Connected socket accept failed."; 182 return; 183 } 184 ready_handler_.reset(); 185 input_handler_.reset(dispatcher_->CreateInputHandler( 186 connected_socket_, 187 Bind(&OpenVPNManagementServer::OnInput, Unretained(this)), 188 Bind(&OpenVPNManagementServer::OnInputError, Unretained(this)))); 189 SendState("on"); 190} 191 192void OpenVPNManagementServer::OnInput(InputData* data) { 193 SLOG(this, 2) << __func__ << "(" << data->len << ")"; 194 vector<string> messages = SplitString( 195 string(reinterpret_cast<char*>(data->buf), data->len), "\n", 196 base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); 197 for (vector<string>::const_iterator it = messages.begin(); 198 it != messages.end() && IsStarted(); ++it) { 199 ProcessMessage(*it); 200 } 201} 202 203void OpenVPNManagementServer::OnInputError(const std::string& error_msg) { 204 LOG(ERROR) << error_msg; 205 driver_->FailService(Service::kFailureInternal, Service::kErrorDetailsNone); 206} 207 208void OpenVPNManagementServer::ProcessMessage(const string& message) { 209 SLOG(this, 2) << __func__ << "(" << message << ")"; 210 if (message.empty()) { 211 return; 212 } 213 if (!ProcessInfoMessage(message) && 214 !ProcessNeedPasswordMessage(message) && 215 !ProcessFailedPasswordMessage(message) && 216 !ProcessAuthTokenMessage(message) && 217 !ProcessStateMessage(message) && 218 !ProcessHoldMessage(message) && 219 !ProcessSuccessMessage(message)) { 220 LOG(WARNING) << "Message ignored: " << message; 221 } 222} 223 224bool OpenVPNManagementServer::ProcessInfoMessage(const string& message) { 225 if (!base::StartsWith(message, ">INFO:", base::CompareCase::SENSITIVE)) { 226 return false; 227 } 228 LOG(INFO) << message; 229 return true; 230} 231 232bool OpenVPNManagementServer::ProcessNeedPasswordMessage( 233 const string& message) { 234 if (!base::StartsWith(message, ">PASSWORD:Need ", 235 base::CompareCase::SENSITIVE)) { 236 return false; 237 } 238 LOG(INFO) << "Processing need-password message."; 239 string tag = ParsePasswordTag(message); 240 if (tag == kPasswordTagAuth) { 241 if (message.find("SC:") != string::npos) { 242 PerformStaticChallenge(tag); 243 } else { 244 PerformAuthentication(tag); 245 } 246 } else if (base::StartsWith(tag, "User-Specific TPM Token", 247 base::CompareCase::SENSITIVE)) { 248 SupplyTPMToken(tag); 249 } else { 250 NOTIMPLEMENTED() << ": Unsupported need-password message: " << message; 251 driver_->FailService(Service::kFailureInternal, Service::kErrorDetailsNone); 252 } 253 return true; 254} 255 256// static 257string OpenVPNManagementServer::ParseSubstring(const string& message, 258 const string& start, 259 const string& end) { 260 SLOG(VPN, nullptr, 2) << __func__ << "(" << message 261 << ", " << start << ", " << end << ")"; 262 DCHECK(!start.empty() && !end.empty()); 263 size_t start_pos = message.find(start); 264 if (start_pos == string::npos) { 265 return string(); 266 } 267 size_t end_pos = message.find(end, start_pos + start.size()); 268 if (end_pos == string::npos) { 269 return string(); 270 } 271 return message.substr(start_pos + start.size(), 272 end_pos - start_pos - start.size()); 273} 274 275// static 276string OpenVPNManagementServer::ParsePasswordTag(const string& message) { 277 return ParseSubstring(message, "'", "'"); 278} 279 280// static 281string OpenVPNManagementServer::ParsePasswordFailedReason( 282 const string& message) { 283 return ParseSubstring(message, "['", "']"); 284} 285 286void OpenVPNManagementServer::PerformStaticChallenge(const string& tag) { 287 LOG(INFO) << "Perform static challenge: " << tag; 288 string user = driver_->args()->LookupString(kOpenVPNUserProperty, ""); 289 string password = driver_->args()->LookupString(kOpenVPNPasswordProperty, ""); 290 string otp = driver_->args()->LookupString(kOpenVPNOTPProperty, ""); 291 string token = driver_->args()->LookupString(kOpenVPNTokenProperty, ""); 292 if (user.empty() || (token.empty() && (password.empty() || otp.empty()))) { 293 NOTIMPLEMENTED() << ": Missing credentials:" 294 << (user.empty() ? " no-user" : "") 295 << (token.empty() ? " no-token" : "") 296 << (password.empty() ? " no-password" : "") 297 << (otp.empty() ? " no-otp" : ""); 298 driver_->FailService(Service::kFailureInternal, Service::kErrorDetailsNone); 299 return; 300 } 301 302 string password_encoded; 303 if (!token.empty()) { 304 password_encoded = token; 305 // Don't reuse token. 306 driver_->args()->RemoveString(kOpenVPNTokenProperty); 307 } else { 308 string b64_password(brillo::data_encoding::Base64Encode(password)); 309 string b64_otp(brillo::data_encoding::Base64Encode(otp)); 310 password_encoded = StringPrintf("SCRV1:%s:%s", 311 b64_password.c_str(), 312 b64_otp.c_str()); 313 // Don't reuse OTP. 314 driver_->args()->RemoveString(kOpenVPNOTPProperty); 315 } 316 SendUsername(tag, user); 317 SendPassword(tag, password_encoded); 318} 319 320void OpenVPNManagementServer::PerformAuthentication(const string& tag) { 321 LOG(INFO) << "Perform authentication: " << tag; 322 string user = driver_->args()->LookupString(kOpenVPNUserProperty, ""); 323 string password = driver_->args()->LookupString(kOpenVPNPasswordProperty, ""); 324 if (user.empty() || password.empty()) { 325 NOTIMPLEMENTED() << ": Missing credentials:" 326 << (user.empty() ? " no-user" : "") 327 << (password.empty() ? " no-password" : ""); 328 driver_->FailService(Service::kFailureInternal, Service::kErrorDetailsNone); 329 return; 330 } 331 SendUsername(tag, user); 332 SendPassword(tag, password); 333} 334 335void OpenVPNManagementServer::SupplyTPMToken(const string& tag) { 336 SLOG(this, 2) << __func__ << "(" << tag << ")"; 337 string pin = driver_->args()->LookupString(kOpenVPNPinProperty, ""); 338 if (pin.empty()) { 339 NOTIMPLEMENTED() << ": Missing PIN."; 340 driver_->FailService(Service::kFailureInternal, Service::kErrorDetailsNone); 341 return; 342 } 343 SendPassword(tag, pin); 344} 345 346bool OpenVPNManagementServer::ProcessFailedPasswordMessage( 347 const string& message) { 348 if (!base::StartsWith(message, ">PASSWORD:Verification Failed:", 349 base::CompareCase::SENSITIVE)) { 350 return false; 351 } 352 LOG(INFO) << message; 353 string reason; 354 if (ParsePasswordTag(message) == kPasswordTagAuth) { 355 reason = ParsePasswordFailedReason(message); 356 } 357 driver_->FailService(Service::kFailureConnect, reason); 358 return true; 359} 360 361bool OpenVPNManagementServer::ProcessAuthTokenMessage(const string& message) { 362 if (!base::StartsWith(message, ">PASSWORD:Auth-Token:", 363 base::CompareCase::SENSITIVE)) { 364 return false; 365 } 366 LOG(INFO) << "Auth-Token message ignored."; 367 return true; 368} 369 370// >STATE:* message support. State messages are of the form: 371// >STATE:<date>,<state>,<detail>,<local-ip>,<remote-ip> 372// where: 373// <date> is the current time (since epoch) in seconds 374// <state> is one of: 375// INITIAL, CONNECTING, WAIT, AUTH, GET_CONFIG, ASSIGN_IP, ADD_ROUTES, 376// CONNECTED, RECONNECTING, EXITING, RESOLVE, TCP_CONNECT 377// <detail> is a free-form string giving details about the state change 378// <local-ip> is a dotted-quad for the local IPv4 address (when available) 379// <remote-ip> is a dotted-quad for the remote IPv4 address (when available) 380bool OpenVPNManagementServer::ProcessStateMessage(const string& message) { 381 if (!base::StartsWith(message, ">STATE:", base::CompareCase::SENSITIVE)) { 382 return false; 383 } 384 vector<string> details = SplitString(message, ",", base::TRIM_WHITESPACE, 385 base::SPLIT_WANT_ALL); 386 if (details.size() > 1) { 387 state_ = details[1]; 388 LOG(INFO) << "OpenVPN state: " << state_; 389 if (state_ == kStateReconnecting) { 390 OpenVPNDriver::ReconnectReason reason = 391 OpenVPNDriver::kReconnectReasonUnknown; 392 if (details.size() > 2 && details[2] == "tls-error") { 393 reason = OpenVPNDriver::kReconnectReasonTLSError; 394 } 395 driver_->OnReconnecting(reason); 396 } 397 } 398 399 return true; 400} 401 402bool OpenVPNManagementServer::ProcessHoldMessage(const string& message) { 403 if (!base::StartsWith(message, ">HOLD:Waiting for hold release", 404 base::CompareCase::SENSITIVE)) { 405 return false; 406 } 407 LOG(INFO) << "Client waiting for hold release."; 408 hold_waiting_ = true; 409 if (hold_release_) { 410 ReleaseHold(); 411 } 412 return true; 413} 414 415bool OpenVPNManagementServer::ProcessSuccessMessage(const string& message) { 416 if (!base::StartsWith(message, "SUCCESS: ", base::CompareCase::SENSITIVE)) { 417 return false; 418 } 419 LOG(INFO) << message; 420 return true; 421} 422 423// static 424string OpenVPNManagementServer::EscapeToQuote(const string& str) { 425 string escaped; 426 for (string::const_iterator it = str.begin(); it != str.end(); ++it) { 427 if (*it == '\\' || *it == '"') { 428 escaped += '\\'; 429 } 430 escaped += *it; 431 } 432 return escaped; 433} 434 435void OpenVPNManagementServer::Send(const string& data) { 436 SLOG(this, 2) << __func__; 437 ssize_t len = sockets_->Send(connected_socket_, data.data(), data.size(), 0); 438 PLOG_IF(ERROR, len < 0 || static_cast<size_t>(len) != data.size()) 439 << "Send failed."; 440} 441 442void OpenVPNManagementServer::SendState(const string& state) { 443 SLOG(this, 2) << __func__ << "(" << state << ")"; 444 Send(StringPrintf("state %s\n", state.c_str())); 445} 446 447void OpenVPNManagementServer::SendUsername(const string& tag, 448 const string& username) { 449 SLOG(this, 2) << __func__; 450 Send(StringPrintf("username \"%s\" %s\n", tag.c_str(), username.c_str())); 451} 452 453void OpenVPNManagementServer::SendPassword(const string& tag, 454 const string& password) { 455 SLOG(this, 2) << __func__; 456 Send(StringPrintf("password \"%s\" \"%s\"\n", 457 tag.c_str(), 458 EscapeToQuote(password).c_str())); 459} 460 461void OpenVPNManagementServer::SendSignal(const string& signal) { 462 SLOG(this, 2) << __func__ << "(" << signal << ")"; 463 Send(StringPrintf("signal %s\n", signal.c_str())); 464} 465 466void OpenVPNManagementServer::SendHoldRelease() { 467 SLOG(this, 2) << __func__; 468 Send("hold release\n"); 469} 470 471} // namespace shill 472