Home | History | Annotate | Download | only in vpn
      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 
     40 using base::Bind;
     41 using base::IntToString;
     42 using base::SplitString;
     43 using base::StringPrintf;
     44 using base::Unretained;
     45 using std::string;
     46 using std::vector;
     47 
     48 namespace shill {
     49 
     50 namespace Logging {
     51 static auto kModuleLogScope = ScopeLogger::kVPN;
     52 static string ObjectID(OpenVPNManagementServer* o) {
     53   return o->GetServiceRpcIdentifier();
     54 }
     55 }
     56 
     57 namespace {
     58 const char kPasswordTagAuth[] = "Auth";
     59 }  // namespace
     60 
     61 const char OpenVPNManagementServer::kStateReconnecting[] = "RECONNECTING";
     62 const char OpenVPNManagementServer::kStateResolve[] = "RESOLVE";
     63 
     64 OpenVPNManagementServer::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 
     73 OpenVPNManagementServer::~OpenVPNManagementServer() {
     74   OpenVPNManagementServer::Stop();
     75 }
     76 
     77 bool 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 
    132 void 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 
    152 void 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 
    163 void OpenVPNManagementServer::Hold() {
    164   SLOG(this, 2) << __func__;
    165   hold_release_ = false;
    166 }
    167 
    168 void OpenVPNManagementServer::Restart() {
    169   LOG(INFO) << "Restart.";
    170   SendSignal("SIGUSR1");
    171 }
    172 
    173 std::string OpenVPNManagementServer::GetServiceRpcIdentifier() {
    174   return driver_->GetServiceRpcIdentifier();
    175 }
    176 
    177 void 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 
    192 void 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 
    203 void OpenVPNManagementServer::OnInputError(const std::string& error_msg) {
    204   LOG(ERROR) << error_msg;
    205   driver_->FailService(Service::kFailureInternal, Service::kErrorDetailsNone);
    206 }
    207 
    208 void 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 
    224 bool 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 
    232 bool 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
    257 string 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
    276 string OpenVPNManagementServer::ParsePasswordTag(const string& message) {
    277   return ParseSubstring(message, "'", "'");
    278 }
    279 
    280 // static
    281 string OpenVPNManagementServer::ParsePasswordFailedReason(
    282     const string& message) {
    283   return ParseSubstring(message, "['", "']");
    284 }
    285 
    286 void 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 
    320 void 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 
    335 void 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 
    346 bool 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 
    361 bool 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)
    380 bool 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 
    402 bool 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 
    415 bool 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
    424 string 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 
    435 void 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 
    442 void OpenVPNManagementServer::SendState(const string& state) {
    443   SLOG(this, 2) << __func__ << "(" << state << ")";
    444   Send(StringPrintf("state %s\n", state.c_str()));
    445 }
    446 
    447 void 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 
    453 void 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 
    461 void OpenVPNManagementServer::SendSignal(const string& signal) {
    462   SLOG(this, 2) << __func__ << "(" << signal << ")";
    463   Send(StringPrintf("signal %s\n", signal.c_str()));
    464 }
    465 
    466 void OpenVPNManagementServer::SendHoldRelease() {
    467   SLOG(this, 2) << __func__;
    468   Send("hold release\n");
    469 }
    470 
    471 }  // namespace shill
    472