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