blob: 3ac15d8c3e620cf160fb8803ebc99b13d0da6027 [file] [log] [blame]
Darin Petkov1c115202012-03-22 15:35:47 +01001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Darin Petkova42afe32013-02-05 16:53:52 +01005#ifndef SHILL_OPENVPN_MANAGEMENT_SERVER_H_
6#define SHILL_OPENVPN_MANAGEMENT_SERVER_H_
Darin Petkov1c115202012-03-22 15:35:47 +01007
Darin Petkov46463022012-03-29 14:57:32 +02008#include <string>
9#include <vector>
10
Darin Petkov1c115202012-03-22 15:35:47 +010011#include <base/basictypes.h>
Darin Petkov3273da72013-02-13 11:50:25 +010012#include <base/memory/scoped_ptr.h>
Darin Petkov271fe522012-03-27 13:47:29 +020013#include <gtest/gtest_prod.h> // for FRIEND_TEST
Darin Petkov1c115202012-03-22 15:35:47 +010014
15namespace shill {
16
Darin Petkov3273da72013-02-13 11:50:25 +010017class Error;
Darin Petkov78f63262012-03-26 01:30:24 +020018class EventDispatcher;
Darin Petkov683942b2012-03-27 18:00:04 +020019class GLib;
Liam McLoughlinf4baef22012-08-01 19:08:25 -070020struct InputData;
Darin Petkov78f63262012-03-26 01:30:24 +020021class IOHandler;
Darin Petkov1c115202012-03-22 15:35:47 +010022class OpenVPNDriver;
Darin Petkov78f63262012-03-26 01:30:24 +020023class Sockets;
Darin Petkov1c115202012-03-22 15:35:47 +010024
25class OpenVPNManagementServer {
26 public:
Darin Petkov1c049c72013-03-21 13:15:45 +010027 static const char kStateReconnecting[];
28 static const char kStateResolve[];
29
Darin Petkov683942b2012-03-27 18:00:04 +020030 OpenVPNManagementServer(OpenVPNDriver *driver, GLib *glib);
Darin Petkov1c115202012-03-22 15:35:47 +010031 virtual ~OpenVPNManagementServer();
32
Darin Petkov46463022012-03-29 14:57:32 +020033 // Returns false on failure. On success, returns true and appends management
34 // interface openvpn options to |options|.
35 virtual bool Start(EventDispatcher *dispatcher,
36 Sockets *sockets,
Paul Stewart406c4732013-08-01 09:30:12 -070037 std::vector<std::vector<std::string>> *options);
Darin Petkov78f63262012-03-26 01:30:24 +020038
Darin Petkov46463022012-03-29 14:57:32 +020039 virtual void Stop();
Darin Petkov1c115202012-03-22 15:35:47 +010040
Darin Petkova5e07ef2012-07-09 14:27:57 +020041 // Releases openvpn's hold if it's waiting for a hold release (i.e., if
42 // |hold_waiting_| is true). Otherwise, sets |hold_release_| to true
43 // indicating that the hold can be released as soon as openvpn requests.
44 virtual void ReleaseHold();
45
46 // Holds openvpn so that it doesn't connect or reconnect automatically (i.e.,
47 // sets |hold_release_| to false). Note that this method neither drops an
48 // existing connection, nor sends any commands to the openvpn client.
49 virtual void Hold();
50
Darin Petkova42afe32013-02-05 16:53:52 +010051 // Restarts openvpn causing a disconnect followed by a reconnect attempt.
52 virtual void Restart();
53
Darin Petkov1c049c72013-03-21 13:15:45 +010054 // OpenVPN client state.
55 const std::string &state() const { return state_; }
56
Darin Petkov1c115202012-03-22 15:35:47 +010057 private:
Darin Petkov1c049c72013-03-21 13:15:45 +010058 friend class OpenVPNDriverTest;
Darin Petkov271fe522012-03-27 13:47:29 +020059 friend class OpenVPNManagementServerTest;
Darin Petkovdaaa5532012-07-24 15:37:55 +020060 FRIEND_TEST(OpenVPNManagementServerTest, EscapeToQuote);
Darin Petkova5e07ef2012-07-09 14:27:57 +020061 FRIEND_TEST(OpenVPNManagementServerTest, Hold);
Darin Petkove08084d2012-06-11 13:19:35 +020062 FRIEND_TEST(OpenVPNManagementServerTest, OnInputStop);
Darin Petkov271fe522012-03-27 13:47:29 +020063 FRIEND_TEST(OpenVPNManagementServerTest, OnReady);
64 FRIEND_TEST(OpenVPNManagementServerTest, OnReadyAcceptFail);
Darin Petkovdaaa5532012-07-24 15:37:55 +020065 FRIEND_TEST(OpenVPNManagementServerTest, PerformAuthentication);
66 FRIEND_TEST(OpenVPNManagementServerTest, PerformAuthenticationNoCreds);
Darin Petkov683942b2012-03-27 18:00:04 +020067 FRIEND_TEST(OpenVPNManagementServerTest, PerformStaticChallenge);
68 FRIEND_TEST(OpenVPNManagementServerTest, PerformStaticChallengeNoCreds);
Darin Petkov0440b9b2012-04-17 16:11:56 +020069 FRIEND_TEST(OpenVPNManagementServerTest, ProcessFailedPasswordMessage);
Darin Petkova5e07ef2012-07-09 14:27:57 +020070 FRIEND_TEST(OpenVPNManagementServerTest, ProcessHoldMessage);
Darin Petkov271fe522012-03-27 13:47:29 +020071 FRIEND_TEST(OpenVPNManagementServerTest, ProcessInfoMessage);
Darin Petkovdaaa5532012-07-24 15:37:55 +020072 FRIEND_TEST(OpenVPNManagementServerTest, ProcessNeedPasswordMessageAuth);
Darin Petkov683942b2012-03-27 18:00:04 +020073 FRIEND_TEST(OpenVPNManagementServerTest, ProcessNeedPasswordMessageAuthSC);
Darin Petkove0d5dd12012-04-04 16:10:48 +020074 FRIEND_TEST(OpenVPNManagementServerTest, ProcessNeedPasswordMessageTPMToken);
75 FRIEND_TEST(OpenVPNManagementServerTest, ProcessNeedPasswordMessageUnknown);
Darin Petkov271fe522012-03-27 13:47:29 +020076 FRIEND_TEST(OpenVPNManagementServerTest, Send);
Darin Petkova5e07ef2012-07-09 14:27:57 +020077 FRIEND_TEST(OpenVPNManagementServerTest, SendHoldRelease);
Darin Petkov683942b2012-03-27 18:00:04 +020078 FRIEND_TEST(OpenVPNManagementServerTest, SendPassword);
Darin Petkov271fe522012-03-27 13:47:29 +020079 FRIEND_TEST(OpenVPNManagementServerTest, SendState);
Darin Petkov683942b2012-03-27 18:00:04 +020080 FRIEND_TEST(OpenVPNManagementServerTest, SendUsername);
Darin Petkov271fe522012-03-27 13:47:29 +020081 FRIEND_TEST(OpenVPNManagementServerTest, Start);
82 FRIEND_TEST(OpenVPNManagementServerTest, Stop);
Darin Petkove0d5dd12012-04-04 16:10:48 +020083 FRIEND_TEST(OpenVPNManagementServerTest, SupplyTPMToken);
84 FRIEND_TEST(OpenVPNManagementServerTest, SupplyTPMTokenNoPIN);
Darin Petkov271fe522012-03-27 13:47:29 +020085
Darin Petkov78f63262012-03-26 01:30:24 +020086 // IO handler callbacks.
87 void OnReady(int fd);
88 void OnInput(InputData *data);
Darin Petkov3273da72013-02-13 11:50:25 +010089 void OnInputError(const Error &error);
Darin Petkov78f63262012-03-26 01:30:24 +020090
91 void Send(const std::string &data);
92 void SendState(const std::string &state);
Darin Petkov683942b2012-03-27 18:00:04 +020093 void SendUsername(const std::string &tag, const std::string &username);
94 void SendPassword(const std::string &tag, const std::string &password);
Darin Petkova5e07ef2012-07-09 14:27:57 +020095 void SendHoldRelease();
Darin Petkova42afe32013-02-05 16:53:52 +010096 void SendSignal(const std::string &signal);
Darin Petkov78f63262012-03-26 01:30:24 +020097
98 void ProcessMessage(const std::string &message);
Darin Petkov271fe522012-03-27 13:47:29 +020099 bool ProcessInfoMessage(const std::string &message);
100 bool ProcessNeedPasswordMessage(const std::string &message);
101 bool ProcessFailedPasswordMessage(const std::string &message);
Darin Petkov16e70322013-03-07 15:54:23 +0100102 bool ProcessAuthTokenMessage(const std::string &message);
Darin Petkov271fe522012-03-27 13:47:29 +0200103 bool ProcessStateMessage(const std::string &message);
Darin Petkova5e07ef2012-07-09 14:27:57 +0200104 bool ProcessHoldMessage(const std::string &message);
Darin Petkova42afe32013-02-05 16:53:52 +0100105 bool ProcessSuccessMessage(const std::string &message);
Darin Petkov78f63262012-03-26 01:30:24 +0200106
Darin Petkove0d5dd12012-04-04 16:10:48 +0200107 void PerformStaticChallenge(const std::string &tag);
Darin Petkovdaaa5532012-07-24 15:37:55 +0200108 void PerformAuthentication(const std::string &tag);
Darin Petkove0d5dd12012-04-04 16:10:48 +0200109 void SupplyTPMToken(const std::string &tag);
110
Darin Petkovaba89322013-03-11 14:48:22 +0100111 // Returns the first substring in |message| enclosed by the |start| and |end|
112 // substrings. Note that the first |end| substring after the position of
113 // |start| is matched.
114 static std::string ParseSubstring(const std::string &message,
115 const std::string &start,
116 const std::string &end);
117
118 // Password messages come in two forms:
119 //
120 // >PASSWORD:Need 'AUTH_TYPE' ...
121 // >PASSWORD:Verification Failed: 'AUTH_TYPE' ['REASON_STRING']
122 //
123 // ParsePasswordTag parses AUTH_TYPE out of a password |message| and returns
124 // it. ParsePasswordFailedReason parses REASON_STRING, if any, out of a
125 // password |message| and returns it.
126 static std::string ParsePasswordTag(const std::string &message);
127 static std::string ParsePasswordFailedReason(const std::string &message);
Darin Petkov683942b2012-03-27 18:00:04 +0200128
Darin Petkovdaaa5532012-07-24 15:37:55 +0200129 // Escapes |str| per OpenVPN's command parsing rules assuming |str| will be
130 // sent over the management interface quoted (i.e., whitespace is not
131 // escaped).
132 static std::string EscapeToQuote(const std::string &str);
133
Darin Petkove08084d2012-06-11 13:19:35 +0200134 bool IsStarted() const { return sockets_; }
135
Darin Petkov1c115202012-03-22 15:35:47 +0100136 OpenVPNDriver *driver_;
Darin Petkov683942b2012-03-27 18:00:04 +0200137 GLib *glib_;
Darin Petkov78f63262012-03-26 01:30:24 +0200138
139 Sockets *sockets_;
140 int socket_;
141 scoped_ptr<IOHandler> ready_handler_;
142 EventDispatcher *dispatcher_;
143 int connected_socket_;
144 scoped_ptr<IOHandler> input_handler_;
Darin Petkov1c115202012-03-22 15:35:47 +0100145
Darin Petkov1c049c72013-03-21 13:15:45 +0100146 std::string state_;
147
Darin Petkova5e07ef2012-07-09 14:27:57 +0200148 bool hold_waiting_;
149 bool hold_release_;
150
Darin Petkov1c115202012-03-22 15:35:47 +0100151 DISALLOW_COPY_AND_ASSIGN(OpenVPNManagementServer);
152};
153
154} // namespace shill
155
Darin Petkova42afe32013-02-05 16:53:52 +0100156#endif // SHILL_OPENVPN_MANAGEMENT_SERVER_H_