1c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
2c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Copyright (C) 2012 The Android Open Source Project
3c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
4c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Licensed under the Apache License, Version 2.0 (the "License");
5c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// you may not use this file except in compliance with the License.
6c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// You may obtain a copy of the License at
7c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
8c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//      http://www.apache.org/licenses/LICENSE-2.0
9c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
10c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Unless required by applicable law or agreed to in writing, software
11c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// distributed under the License is distributed on an "AS IS" BASIS,
12c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// See the License for the specific language governing permissions and
14c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// limitations under the License.
15c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
161c1152030c1bab9f91450b508777feac8c162e60Darin Petkov
172240e8c03451c6b6f21eb8944d8a1c0747ac10b3Ben Chan#ifndef SHILL_VPN_OPENVPN_MANAGEMENT_SERVER_H_
182240e8c03451c6b6f21eb8944d8a1c0747ac10b3Ben Chan#define SHILL_VPN_OPENVPN_MANAGEMENT_SERVER_H_
191c1152030c1bab9f91450b508777feac8c162e60Darin Petkov
20d5dce94ec196e160c0d4bfeeb5ab8d4eb021ef15Ben Chan#include <memory>
214646302299227516f4979bb27b46ce6249f6ec2fDarin Petkov#include <string>
224646302299227516f4979bb27b46ce6249f6ec2fDarin Petkov#include <vector>
234646302299227516f4979bb27b46ce6249f6ec2fDarin Petkov
24cc67c52a2c00f90e877971d552208dd99825d84eBen Chan#include <base/macros.h>
25271fe5247103d0b76c48796c6f10ba45c6db59c4Darin Petkov#include <gtest/gtest_prod.h>  // for FRIEND_TEST
261c1152030c1bab9f91450b508777feac8c162e60Darin Petkov
271c1152030c1bab9f91450b508777feac8c162e60Darin Petkovnamespace shill {
281c1152030c1bab9f91450b508777feac8c162e60Darin Petkov
293273da7039841d15fc160cc69c036e3124803744Darin Petkovclass Error;
3078f6326aeee06b6684ac545e956e35facbd4b2faDarin Petkovclass EventDispatcher;
31f4baef2e49c144b8dad650562c60e03b8407ef17Liam McLoughlinstruct InputData;
3278f6326aeee06b6684ac545e956e35facbd4b2faDarin Petkovclass IOHandler;
331c1152030c1bab9f91450b508777feac8c162e60Darin Petkovclass OpenVPNDriver;
3478f6326aeee06b6684ac545e956e35facbd4b2faDarin Petkovclass Sockets;
351c1152030c1bab9f91450b508777feac8c162e60Darin Petkov
361c1152030c1bab9f91450b508777feac8c162e60Darin Petkovclass OpenVPNManagementServer {
371c1152030c1bab9f91450b508777feac8c162e60Darin Petkov public:
381c049c794175356e5b6c2b6bbb5ef4a12fbfe9a3Darin Petkov  static const char kStateReconnecting[];
391c049c794175356e5b6c2b6bbb5ef4a12fbfe9a3Darin Petkov  static const char kStateResolve[];
401c049c794175356e5b6c2b6bbb5ef4a12fbfe9a3Darin Petkov
41bad1c10ffd2d4ac14f7bd9f4ef6a8982e711f566mukesh agrawal  explicit OpenVPNManagementServer(OpenVPNDriver* driver);
421c1152030c1bab9f91450b508777feac8c162e60Darin Petkov  virtual ~OpenVPNManagementServer();
431c1152030c1bab9f91450b508777feac8c162e60Darin Petkov
444646302299227516f4979bb27b46ce6249f6ec2fDarin Petkov  // Returns false on failure. On success, returns true and appends management
454646302299227516f4979bb27b46ce6249f6ec2fDarin Petkov  // interface openvpn options to |options|.
46e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart  virtual bool Start(EventDispatcher* dispatcher,
47e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart                     Sockets* sockets,
48e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart                     std::vector<std::vector<std::string>>* options);
4978f6326aeee06b6684ac545e956e35facbd4b2faDarin Petkov
504646302299227516f4979bb27b46ce6249f6ec2fDarin Petkov  virtual void Stop();
511c1152030c1bab9f91450b508777feac8c162e60Darin Petkov
52a5e07ef0402aad0635a5e7a0932740b9dfbf46d1Darin Petkov  // Releases openvpn's hold if it's waiting for a hold release (i.e., if
53a5e07ef0402aad0635a5e7a0932740b9dfbf46d1Darin Petkov  // |hold_waiting_| is true). Otherwise, sets |hold_release_| to true
54a5e07ef0402aad0635a5e7a0932740b9dfbf46d1Darin Petkov  // indicating that the hold can be released as soon as openvpn requests.
55a5e07ef0402aad0635a5e7a0932740b9dfbf46d1Darin Petkov  virtual void ReleaseHold();
56a5e07ef0402aad0635a5e7a0932740b9dfbf46d1Darin Petkov
57a5e07ef0402aad0635a5e7a0932740b9dfbf46d1Darin Petkov  // Holds openvpn so that it doesn't connect or reconnect automatically (i.e.,
58a5e07ef0402aad0635a5e7a0932740b9dfbf46d1Darin Petkov  // sets |hold_release_| to false). Note that this method neither drops an
59a5e07ef0402aad0635a5e7a0932740b9dfbf46d1Darin Petkov  // existing connection, nor sends any commands to the openvpn client.
60a5e07ef0402aad0635a5e7a0932740b9dfbf46d1Darin Petkov  virtual void Hold();
61a5e07ef0402aad0635a5e7a0932740b9dfbf46d1Darin Petkov
62a42afe3a1621b8262d5404ecfaf200d3d76bd454Darin Petkov  // Restarts openvpn causing a disconnect followed by a reconnect attempt.
63a42afe3a1621b8262d5404ecfaf200d3d76bd454Darin Petkov  virtual void Restart();
64a42afe3a1621b8262d5404ecfaf200d3d76bd454Darin Petkov
651c049c794175356e5b6c2b6bbb5ef4a12fbfe9a3Darin Petkov  // OpenVPN client state.
66e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart  const std::string& state() const { return state_; }
671c049c794175356e5b6c2b6bbb5ef4a12fbfe9a3Darin Petkov
68c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein  // Method to get service identifier for logging.
69c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein  virtual std::string GetServiceRpcIdentifier();
70c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein
711c1152030c1bab9f91450b508777feac8c162e60Darin Petkov private:
721c049c794175356e5b6c2b6bbb5ef4a12fbfe9a3Darin Petkov  friend class OpenVPNDriverTest;
73271fe5247103d0b76c48796c6f10ba45c6db59c4Darin Petkov  friend class OpenVPNManagementServerTest;
74daaa553671f46e46dd5737eb67bfbc7c12c89dc2Darin Petkov  FRIEND_TEST(OpenVPNManagementServerTest, EscapeToQuote);
75a5e07ef0402aad0635a5e7a0932740b9dfbf46d1Darin Petkov  FRIEND_TEST(OpenVPNManagementServerTest, Hold);
76e08084d3bc985fe937e7afb8e6fd08463cb9c792Darin Petkov  FRIEND_TEST(OpenVPNManagementServerTest, OnInputStop);
77271fe5247103d0b76c48796c6f10ba45c6db59c4Darin Petkov  FRIEND_TEST(OpenVPNManagementServerTest, OnReady);
78271fe5247103d0b76c48796c6f10ba45c6db59c4Darin Petkov  FRIEND_TEST(OpenVPNManagementServerTest, OnReadyAcceptFail);
79daaa553671f46e46dd5737eb67bfbc7c12c89dc2Darin Petkov  FRIEND_TEST(OpenVPNManagementServerTest, PerformAuthentication);
80daaa553671f46e46dd5737eb67bfbc7c12c89dc2Darin Petkov  FRIEND_TEST(OpenVPNManagementServerTest, PerformAuthenticationNoCreds);
81683942b7e07f1c27a0d89267d5344c2bde7b2b86Darin Petkov  FRIEND_TEST(OpenVPNManagementServerTest, PerformStaticChallengeNoCreds);
82b57682315ba47f8c567b6673f5aa7b87f367a4edPaul Stewart  FRIEND_TEST(OpenVPNManagementServerTest, PerformStaticChallengeOTP);
83b57682315ba47f8c567b6673f5aa7b87f367a4edPaul Stewart  FRIEND_TEST(OpenVPNManagementServerTest, PerformStaticChallengeToken);
840440b9b420d3a532af111b86c5c7c6cb87bc269aDarin Petkov  FRIEND_TEST(OpenVPNManagementServerTest, ProcessFailedPasswordMessage);
85a5e07ef0402aad0635a5e7a0932740b9dfbf46d1Darin Petkov  FRIEND_TEST(OpenVPNManagementServerTest, ProcessHoldMessage);
86271fe5247103d0b76c48796c6f10ba45c6db59c4Darin Petkov  FRIEND_TEST(OpenVPNManagementServerTest, ProcessInfoMessage);
87daaa553671f46e46dd5737eb67bfbc7c12c89dc2Darin Petkov  FRIEND_TEST(OpenVPNManagementServerTest, ProcessNeedPasswordMessageAuth);
88683942b7e07f1c27a0d89267d5344c2bde7b2b86Darin Petkov  FRIEND_TEST(OpenVPNManagementServerTest, ProcessNeedPasswordMessageAuthSC);
89e0d5dd1ef481599ece78f8ff4a84485eb1134b85Darin Petkov  FRIEND_TEST(OpenVPNManagementServerTest, ProcessNeedPasswordMessageTPMToken);
90e0d5dd1ef481599ece78f8ff4a84485eb1134b85Darin Petkov  FRIEND_TEST(OpenVPNManagementServerTest, ProcessNeedPasswordMessageUnknown);
91271fe5247103d0b76c48796c6f10ba45c6db59c4Darin Petkov  FRIEND_TEST(OpenVPNManagementServerTest, Send);
92a5e07ef0402aad0635a5e7a0932740b9dfbf46d1Darin Petkov  FRIEND_TEST(OpenVPNManagementServerTest, SendHoldRelease);
93683942b7e07f1c27a0d89267d5344c2bde7b2b86Darin Petkov  FRIEND_TEST(OpenVPNManagementServerTest, SendPassword);
94271fe5247103d0b76c48796c6f10ba45c6db59c4Darin Petkov  FRIEND_TEST(OpenVPNManagementServerTest, SendState);
95683942b7e07f1c27a0d89267d5344c2bde7b2b86Darin Petkov  FRIEND_TEST(OpenVPNManagementServerTest, SendUsername);
96271fe5247103d0b76c48796c6f10ba45c6db59c4Darin Petkov  FRIEND_TEST(OpenVPNManagementServerTest, Start);
97271fe5247103d0b76c48796c6f10ba45c6db59c4Darin Petkov  FRIEND_TEST(OpenVPNManagementServerTest, Stop);
98e0d5dd1ef481599ece78f8ff4a84485eb1134b85Darin Petkov  FRIEND_TEST(OpenVPNManagementServerTest, SupplyTPMToken);
99e0d5dd1ef481599ece78f8ff4a84485eb1134b85Darin Petkov  FRIEND_TEST(OpenVPNManagementServerTest, SupplyTPMTokenNoPIN);
100271fe5247103d0b76c48796c6f10ba45c6db59c4Darin Petkov
10178f6326aeee06b6684ac545e956e35facbd4b2faDarin Petkov  // IO handler callbacks.
10278f6326aeee06b6684ac545e956e35facbd4b2faDarin Petkov  void OnReady(int fd);
103e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart  void OnInput(InputData* data);
104e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart  void OnInputError(const std::string& error_msg);
10578f6326aeee06b6684ac545e956e35facbd4b2faDarin Petkov
106e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart  void Send(const std::string& data);
107e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart  void SendState(const std::string& state);
108e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart  void SendUsername(const std::string& tag, const std::string& username);
109e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart  void SendPassword(const std::string& tag, const std::string& password);
110a5e07ef0402aad0635a5e7a0932740b9dfbf46d1Darin Petkov  void SendHoldRelease();
111e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart  void SendSignal(const std::string& signal);
11278f6326aeee06b6684ac545e956e35facbd4b2faDarin Petkov
113e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart  void ProcessMessage(const std::string& message);
114e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart  bool ProcessInfoMessage(const std::string& message);
115e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart  bool ProcessNeedPasswordMessage(const std::string& message);
116e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart  bool ProcessFailedPasswordMessage(const std::string& message);
117e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart  bool ProcessAuthTokenMessage(const std::string& message);
118e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart  bool ProcessStateMessage(const std::string& message);
119e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart  bool ProcessHoldMessage(const std::string& message);
120e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart  bool ProcessSuccessMessage(const std::string& message);
12178f6326aeee06b6684ac545e956e35facbd4b2faDarin Petkov
122e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart  void PerformStaticChallenge(const std::string& tag);
123e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart  void PerformAuthentication(const std::string& tag);
124e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart  void SupplyTPMToken(const std::string& tag);
125e0d5dd1ef481599ece78f8ff4a84485eb1134b85Darin Petkov
126aba893217c9cf1dd0d39c4dee89a23d3b1a3f4c1Darin Petkov  // Returns the first substring in |message| enclosed by the |start| and |end|
127aba893217c9cf1dd0d39c4dee89a23d3b1a3f4c1Darin Petkov  // substrings. Note that the first |end| substring after the position of
128aba893217c9cf1dd0d39c4dee89a23d3b1a3f4c1Darin Petkov  // |start| is matched.
129e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart  static std::string ParseSubstring(const std::string& message,
130e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart                                    const std::string& start,
131e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart                                    const std::string& end);
132aba893217c9cf1dd0d39c4dee89a23d3b1a3f4c1Darin Petkov
133aba893217c9cf1dd0d39c4dee89a23d3b1a3f4c1Darin Petkov  // Password messages come in two forms:
134aba893217c9cf1dd0d39c4dee89a23d3b1a3f4c1Darin Petkov  //
135aba893217c9cf1dd0d39c4dee89a23d3b1a3f4c1Darin Petkov  // >PASSWORD:Need 'AUTH_TYPE' ...
136aba893217c9cf1dd0d39c4dee89a23d3b1a3f4c1Darin Petkov  // >PASSWORD:Verification Failed: 'AUTH_TYPE' ['REASON_STRING']
137aba893217c9cf1dd0d39c4dee89a23d3b1a3f4c1Darin Petkov  //
138aba893217c9cf1dd0d39c4dee89a23d3b1a3f4c1Darin Petkov  // ParsePasswordTag parses AUTH_TYPE out of a password |message| and returns
139aba893217c9cf1dd0d39c4dee89a23d3b1a3f4c1Darin Petkov  // it. ParsePasswordFailedReason parses REASON_STRING, if any, out of a
140aba893217c9cf1dd0d39c4dee89a23d3b1a3f4c1Darin Petkov  // password |message| and returns it.
141e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart  static std::string ParsePasswordTag(const std::string& message);
142e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart  static std::string ParsePasswordFailedReason(const std::string& message);
143683942b7e07f1c27a0d89267d5344c2bde7b2b86Darin Petkov
144daaa553671f46e46dd5737eb67bfbc7c12c89dc2Darin Petkov  // Escapes |str| per OpenVPN's command parsing rules assuming |str| will be
145daaa553671f46e46dd5737eb67bfbc7c12c89dc2Darin Petkov  // sent over the management interface quoted (i.e., whitespace is not
146daaa553671f46e46dd5737eb67bfbc7c12c89dc2Darin Petkov  // escaped).
147e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart  static std::string EscapeToQuote(const std::string& str);
148daaa553671f46e46dd5737eb67bfbc7c12c89dc2Darin Petkov
149e08084d3bc985fe937e7afb8e6fd08463cb9c792Darin Petkov  bool IsStarted() const { return sockets_; }
150e08084d3bc985fe937e7afb8e6fd08463cb9c792Darin Petkov
151e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart  OpenVPNDriver* driver_;
15278f6326aeee06b6684ac545e956e35facbd4b2faDarin Petkov
153e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart  Sockets* sockets_;
15478f6326aeee06b6684ac545e956e35facbd4b2faDarin Petkov  int socket_;
155d5dce94ec196e160c0d4bfeeb5ab8d4eb021ef15Ben Chan  std::unique_ptr<IOHandler> ready_handler_;
156e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart  EventDispatcher* dispatcher_;
15778f6326aeee06b6684ac545e956e35facbd4b2faDarin Petkov  int connected_socket_;
158d5dce94ec196e160c0d4bfeeb5ab8d4eb021ef15Ben Chan  std::unique_ptr<IOHandler> input_handler_;
1591c1152030c1bab9f91450b508777feac8c162e60Darin Petkov
1601c049c794175356e5b6c2b6bbb5ef4a12fbfe9a3Darin Petkov  std::string state_;
1611c049c794175356e5b6c2b6bbb5ef4a12fbfe9a3Darin Petkov
162a5e07ef0402aad0635a5e7a0932740b9dfbf46d1Darin Petkov  bool hold_waiting_;
163a5e07ef0402aad0635a5e7a0932740b9dfbf46d1Darin Petkov  bool hold_release_;
164a5e07ef0402aad0635a5e7a0932740b9dfbf46d1Darin Petkov
1651c1152030c1bab9f91450b508777feac8c162e60Darin Petkov  DISALLOW_COPY_AND_ASSIGN(OpenVPNManagementServer);
1661c1152030c1bab9f91450b508777feac8c162e60Darin Petkov};
1671c1152030c1bab9f91450b508777feac8c162e60Darin Petkov
1681c1152030c1bab9f91450b508777feac8c162e60Darin Petkov}  // namespace shill
1691c1152030c1bab9f91450b508777feac8c162e60Darin Petkov
1702240e8c03451c6b6f21eb8944d8a1c0747ac10b3Ben Chan#endif  // SHILL_VPN_OPENVPN_MANAGEMENT_SERVER_H_
171