// // Copyright (C) 2012 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef SHILL_VPN_OPENVPN_MANAGEMENT_SERVER_H_ #define SHILL_VPN_OPENVPN_MANAGEMENT_SERVER_H_ #include <memory> #include <string> #include <vector> #include <base/macros.h> #include <gtest/gtest_prod.h> // for FRIEND_TEST namespace shill { class Error; class EventDispatcher; struct InputData; class IOHandler; class OpenVPNDriver; class Sockets; class OpenVPNManagementServer { public: static const char kStateReconnecting[]; static const char kStateResolve[]; explicit OpenVPNManagementServer(OpenVPNDriver* driver); virtual ~OpenVPNManagementServer(); // Returns false on failure. On success, returns true and appends management // interface openvpn options to |options|. virtual bool Start(EventDispatcher* dispatcher, Sockets* sockets, std::vector<std::vector<std::string>>* options); virtual void Stop(); // Releases openvpn's hold if it's waiting for a hold release (i.e., if // |hold_waiting_| is true). Otherwise, sets |hold_release_| to true // indicating that the hold can be released as soon as openvpn requests. virtual void ReleaseHold(); // Holds openvpn so that it doesn't connect or reconnect automatically (i.e., // sets |hold_release_| to false). Note that this method neither drops an // existing connection, nor sends any commands to the openvpn client. virtual void Hold(); // Restarts openvpn causing a disconnect followed by a reconnect attempt. virtual void Restart(); // OpenVPN client state. const std::string& state() const { return state_; } // Method to get service identifier for logging. virtual std::string GetServiceRpcIdentifier(); private: friend class OpenVPNDriverTest; friend class OpenVPNManagementServerTest; FRIEND_TEST(OpenVPNManagementServerTest, EscapeToQuote); FRIEND_TEST(OpenVPNManagementServerTest, Hold); FRIEND_TEST(OpenVPNManagementServerTest, OnInputStop); FRIEND_TEST(OpenVPNManagementServerTest, OnReady); FRIEND_TEST(OpenVPNManagementServerTest, OnReadyAcceptFail); FRIEND_TEST(OpenVPNManagementServerTest, PerformAuthentication); FRIEND_TEST(OpenVPNManagementServerTest, PerformAuthenticationNoCreds); FRIEND_TEST(OpenVPNManagementServerTest, PerformStaticChallengeNoCreds); FRIEND_TEST(OpenVPNManagementServerTest, PerformStaticChallengeOTP); FRIEND_TEST(OpenVPNManagementServerTest, PerformStaticChallengeToken); FRIEND_TEST(OpenVPNManagementServerTest, ProcessFailedPasswordMessage); FRIEND_TEST(OpenVPNManagementServerTest, ProcessHoldMessage); FRIEND_TEST(OpenVPNManagementServerTest, ProcessInfoMessage); FRIEND_TEST(OpenVPNManagementServerTest, ProcessNeedPasswordMessageAuth); FRIEND_TEST(OpenVPNManagementServerTest, ProcessNeedPasswordMessageAuthSC); FRIEND_TEST(OpenVPNManagementServerTest, ProcessNeedPasswordMessageTPMToken); FRIEND_TEST(OpenVPNManagementServerTest, ProcessNeedPasswordMessageUnknown); FRIEND_TEST(OpenVPNManagementServerTest, Send); FRIEND_TEST(OpenVPNManagementServerTest, SendHoldRelease); FRIEND_TEST(OpenVPNManagementServerTest, SendPassword); FRIEND_TEST(OpenVPNManagementServerTest, SendState); FRIEND_TEST(OpenVPNManagementServerTest, SendUsername); FRIEND_TEST(OpenVPNManagementServerTest, Start); FRIEND_TEST(OpenVPNManagementServerTest, Stop); FRIEND_TEST(OpenVPNManagementServerTest, SupplyTPMToken); FRIEND_TEST(OpenVPNManagementServerTest, SupplyTPMTokenNoPIN); // IO handler callbacks. void OnReady(int fd); void OnInput(InputData* data); void OnInputError(const std::string& error_msg); void Send(const std::string& data); void SendState(const std::string& state); void SendUsername(const std::string& tag, const std::string& username); void SendPassword(const std::string& tag, const std::string& password); void SendHoldRelease(); void SendSignal(const std::string& signal); void ProcessMessage(const std::string& message); bool ProcessInfoMessage(const std::string& message); bool ProcessNeedPasswordMessage(const std::string& message); bool ProcessFailedPasswordMessage(const std::string& message); bool ProcessAuthTokenMessage(const std::string& message); bool ProcessStateMessage(const std::string& message); bool ProcessHoldMessage(const std::string& message); bool ProcessSuccessMessage(const std::string& message); void PerformStaticChallenge(const std::string& tag); void PerformAuthentication(const std::string& tag); void SupplyTPMToken(const std::string& tag); // Returns the first substring in |message| enclosed by the |start| and |end| // substrings. Note that the first |end| substring after the position of // |start| is matched. static std::string ParseSubstring(const std::string& message, const std::string& start, const std::string& end); // Password messages come in two forms: // // >PASSWORD:Need 'AUTH_TYPE' ... // >PASSWORD:Verification Failed: 'AUTH_TYPE' ['REASON_STRING'] // // ParsePasswordTag parses AUTH_TYPE out of a password |message| and returns // it. ParsePasswordFailedReason parses REASON_STRING, if any, out of a // password |message| and returns it. static std::string ParsePasswordTag(const std::string& message); static std::string ParsePasswordFailedReason(const std::string& message); // Escapes |str| per OpenVPN's command parsing rules assuming |str| will be // sent over the management interface quoted (i.e., whitespace is not // escaped). static std::string EscapeToQuote(const std::string& str); bool IsStarted() const { return sockets_; } OpenVPNDriver* driver_; Sockets* sockets_; int socket_; std::unique_ptr<IOHandler> ready_handler_; EventDispatcher* dispatcher_; int connected_socket_; std::unique_ptr<IOHandler> input_handler_; std::string state_; bool hold_waiting_; bool hold_release_; DISALLOW_COPY_AND_ASSIGN(OpenVPNManagementServer); }; } // namespace shill #endif // SHILL_VPN_OPENVPN_MANAGEMENT_SERVER_H_