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#ifndef SHILL_VPN_OPENVPN_MANAGEMENT_SERVER_H_
18#define SHILL_VPN_OPENVPN_MANAGEMENT_SERVER_H_
19
20#include <memory>
21#include <string>
22#include <vector>
23
24#include <base/macros.h>
25#include <gtest/gtest_prod.h>  // for FRIEND_TEST
26
27namespace shill {
28
29class Error;
30class EventDispatcher;
31struct InputData;
32class IOHandler;
33class OpenVPNDriver;
34class Sockets;
35
36class OpenVPNManagementServer {
37 public:
38  static const char kStateReconnecting[];
39  static const char kStateResolve[];
40
41  explicit OpenVPNManagementServer(OpenVPNDriver* driver);
42  virtual ~OpenVPNManagementServer();
43
44  // Returns false on failure. On success, returns true and appends management
45  // interface openvpn options to |options|.
46  virtual bool Start(EventDispatcher* dispatcher,
47                     Sockets* sockets,
48                     std::vector<std::vector<std::string>>* options);
49
50  virtual void Stop();
51
52  // Releases openvpn's hold if it's waiting for a hold release (i.e., if
53  // |hold_waiting_| is true). Otherwise, sets |hold_release_| to true
54  // indicating that the hold can be released as soon as openvpn requests.
55  virtual void ReleaseHold();
56
57  // Holds openvpn so that it doesn't connect or reconnect automatically (i.e.,
58  // sets |hold_release_| to false). Note that this method neither drops an
59  // existing connection, nor sends any commands to the openvpn client.
60  virtual void Hold();
61
62  // Restarts openvpn causing a disconnect followed by a reconnect attempt.
63  virtual void Restart();
64
65  // OpenVPN client state.
66  const std::string& state() const { return state_; }
67
68  // Method to get service identifier for logging.
69  virtual std::string GetServiceRpcIdentifier();
70
71 private:
72  friend class OpenVPNDriverTest;
73  friend class OpenVPNManagementServerTest;
74  FRIEND_TEST(OpenVPNManagementServerTest, EscapeToQuote);
75  FRIEND_TEST(OpenVPNManagementServerTest, Hold);
76  FRIEND_TEST(OpenVPNManagementServerTest, OnInputStop);
77  FRIEND_TEST(OpenVPNManagementServerTest, OnReady);
78  FRIEND_TEST(OpenVPNManagementServerTest, OnReadyAcceptFail);
79  FRIEND_TEST(OpenVPNManagementServerTest, PerformAuthentication);
80  FRIEND_TEST(OpenVPNManagementServerTest, PerformAuthenticationNoCreds);
81  FRIEND_TEST(OpenVPNManagementServerTest, PerformStaticChallengeNoCreds);
82  FRIEND_TEST(OpenVPNManagementServerTest, PerformStaticChallengeOTP);
83  FRIEND_TEST(OpenVPNManagementServerTest, PerformStaticChallengeToken);
84  FRIEND_TEST(OpenVPNManagementServerTest, ProcessFailedPasswordMessage);
85  FRIEND_TEST(OpenVPNManagementServerTest, ProcessHoldMessage);
86  FRIEND_TEST(OpenVPNManagementServerTest, ProcessInfoMessage);
87  FRIEND_TEST(OpenVPNManagementServerTest, ProcessNeedPasswordMessageAuth);
88  FRIEND_TEST(OpenVPNManagementServerTest, ProcessNeedPasswordMessageAuthSC);
89  FRIEND_TEST(OpenVPNManagementServerTest, ProcessNeedPasswordMessageTPMToken);
90  FRIEND_TEST(OpenVPNManagementServerTest, ProcessNeedPasswordMessageUnknown);
91  FRIEND_TEST(OpenVPNManagementServerTest, Send);
92  FRIEND_TEST(OpenVPNManagementServerTest, SendHoldRelease);
93  FRIEND_TEST(OpenVPNManagementServerTest, SendPassword);
94  FRIEND_TEST(OpenVPNManagementServerTest, SendState);
95  FRIEND_TEST(OpenVPNManagementServerTest, SendUsername);
96  FRIEND_TEST(OpenVPNManagementServerTest, Start);
97  FRIEND_TEST(OpenVPNManagementServerTest, Stop);
98  FRIEND_TEST(OpenVPNManagementServerTest, SupplyTPMToken);
99  FRIEND_TEST(OpenVPNManagementServerTest, SupplyTPMTokenNoPIN);
100
101  // IO handler callbacks.
102  void OnReady(int fd);
103  void OnInput(InputData* data);
104  void OnInputError(const std::string& error_msg);
105
106  void Send(const std::string& data);
107  void SendState(const std::string& state);
108  void SendUsername(const std::string& tag, const std::string& username);
109  void SendPassword(const std::string& tag, const std::string& password);
110  void SendHoldRelease();
111  void SendSignal(const std::string& signal);
112
113  void ProcessMessage(const std::string& message);
114  bool ProcessInfoMessage(const std::string& message);
115  bool ProcessNeedPasswordMessage(const std::string& message);
116  bool ProcessFailedPasswordMessage(const std::string& message);
117  bool ProcessAuthTokenMessage(const std::string& message);
118  bool ProcessStateMessage(const std::string& message);
119  bool ProcessHoldMessage(const std::string& message);
120  bool ProcessSuccessMessage(const std::string& message);
121
122  void PerformStaticChallenge(const std::string& tag);
123  void PerformAuthentication(const std::string& tag);
124  void SupplyTPMToken(const std::string& tag);
125
126  // Returns the first substring in |message| enclosed by the |start| and |end|
127  // substrings. Note that the first |end| substring after the position of
128  // |start| is matched.
129  static std::string ParseSubstring(const std::string& message,
130                                    const std::string& start,
131                                    const std::string& end);
132
133  // Password messages come in two forms:
134  //
135  // >PASSWORD:Need 'AUTH_TYPE' ...
136  // >PASSWORD:Verification Failed: 'AUTH_TYPE' ['REASON_STRING']
137  //
138  // ParsePasswordTag parses AUTH_TYPE out of a password |message| and returns
139  // it. ParsePasswordFailedReason parses REASON_STRING, if any, out of a
140  // password |message| and returns it.
141  static std::string ParsePasswordTag(const std::string& message);
142  static std::string ParsePasswordFailedReason(const std::string& message);
143
144  // Escapes |str| per OpenVPN's command parsing rules assuming |str| will be
145  // sent over the management interface quoted (i.e., whitespace is not
146  // escaped).
147  static std::string EscapeToQuote(const std::string& str);
148
149  bool IsStarted() const { return sockets_; }
150
151  OpenVPNDriver* driver_;
152
153  Sockets* sockets_;
154  int socket_;
155  std::unique_ptr<IOHandler> ready_handler_;
156  EventDispatcher* dispatcher_;
157  int connected_socket_;
158  std::unique_ptr<IOHandler> input_handler_;
159
160  std::string state_;
161
162  bool hold_waiting_;
163  bool hold_release_;
164
165  DISALLOW_COPY_AND_ASSIGN(OpenVPNManagementServer);
166};
167
168}  // namespace shill
169
170#endif  // SHILL_VPN_OPENVPN_MANAGEMENT_SERVER_H_
171