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;
ObjectID(OpenVPNManagementServer * o)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
OpenVPNManagementServer(OpenVPNDriver * driver)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
~OpenVPNManagementServer()73 OpenVPNManagementServer::~OpenVPNManagementServer() {
74 OpenVPNManagementServer::Stop();
75 }
76
Start(EventDispatcher * dispatcher,Sockets * sockets,vector<vector<string>> * options)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
Stop()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
ReleaseHold()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
Hold()163 void OpenVPNManagementServer::Hold() {
164 SLOG(this, 2) << __func__;
165 hold_release_ = false;
166 }
167
Restart()168 void OpenVPNManagementServer::Restart() {
169 LOG(INFO) << "Restart.";
170 SendSignal("SIGUSR1");
171 }
172
GetServiceRpcIdentifier()173 std::string OpenVPNManagementServer::GetServiceRpcIdentifier() {
174 return driver_->GetServiceRpcIdentifier();
175 }
176
OnReady(int fd)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
OnInput(InputData * data)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
OnInputError(const std::string & error_msg)203 void OpenVPNManagementServer::OnInputError(const std::string& error_msg) {
204 LOG(ERROR) << error_msg;
205 driver_->FailService(Service::kFailureInternal, Service::kErrorDetailsNone);
206 }
207
ProcessMessage(const string & message)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
ProcessInfoMessage(const string & message)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
ProcessNeedPasswordMessage(const string & message)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
ParseSubstring(const string & message,const string & start,const string & end)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
ParsePasswordTag(const string & message)276 string OpenVPNManagementServer::ParsePasswordTag(const string& message) {
277 return ParseSubstring(message, "'", "'");
278 }
279
280 // static
ParsePasswordFailedReason(const string & message)281 string OpenVPNManagementServer::ParsePasswordFailedReason(
282 const string& message) {
283 return ParseSubstring(message, "['", "']");
284 }
285
PerformStaticChallenge(const string & tag)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
PerformAuthentication(const string & tag)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
SupplyTPMToken(const string & tag)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
ProcessFailedPasswordMessage(const string & message)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
ProcessAuthTokenMessage(const string & message)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)
ProcessStateMessage(const string & message)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
ProcessHoldMessage(const string & message)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
ProcessSuccessMessage(const string & message)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
EscapeToQuote(const string & str)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
Send(const string & data)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
SendState(const string & state)442 void OpenVPNManagementServer::SendState(const string& state) {
443 SLOG(this, 2) << __func__ << "(" << state << ")";
444 Send(StringPrintf("state %s\n", state.c_str()));
445 }
446
SendUsername(const string & tag,const string & username)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
SendPassword(const string & tag,const string & password)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
SendSignal(const string & signal)461 void OpenVPNManagementServer::SendSignal(const string& signal) {
462 SLOG(this, 2) << __func__ << "(" << signal << ")";
463 Send(StringPrintf("signal %s\n", signal.c_str()));
464 }
465
SendHoldRelease()466 void OpenVPNManagementServer::SendHoldRelease() {
467 SLOG(this, 2) << __func__;
468 Send("hold release\n");
469 }
470
471 } // namespace shill
472