Chromium Code Reviews| OLD | NEW | 
|---|---|
| 1 // Copyright (c) 2011 The Chromium OS Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium OS Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "vpn-manager/ipsec_manager.h" | 5 #include "vpn-manager/ipsec_manager.h" | 
| 6 | 6 | 
| 7 #include <arpa/inet.h> // for inet_ntop and inet_pton | 7 #include <arpa/inet.h> // for inet_ntop and inet_pton | 
| 8 #include <grp.h> | 8 #include <grp.h> | 
| 9 #include <netdb.h> // for getaddrinfo | 9 #include <netdb.h> // for getaddrinfo | 
| 10 #include <sys/types.h> | 10 #include <sys/types.h> | 
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 46 | 46 | 
| 47 // Give IPsec layer 2 seconds to shut down before killing it. | 47 // Give IPsec layer 2 seconds to shut down before killing it. | 
| 48 const int kTermTimeout = 2; | 48 const int kTermTimeout = 2; | 
| 49 | 49 | 
| 50 using ::chromeos::Process; | 50 using ::chromeos::Process; | 
| 51 using ::chromeos::ProcessImpl; | 51 using ::chromeos::ProcessImpl; | 
| 52 | 52 | 
| 53 IpsecManager::IpsecManager() | 53 IpsecManager::IpsecManager() | 
| 54 : ServiceManager(kIpsecServiceName), | 54 : ServiceManager(kIpsecServiceName), | 
| 55 force_local_address_(NULL), | 55 force_local_address_(NULL), | 
| 56 force_remote_address_(NULL), | |
| 56 output_fd_(-1), | 57 output_fd_(-1), | 
| 57 ike_version_(0), | 58 ike_version_(0), | 
| 58 ipsec_group_(0), | 59 ipsec_group_(0), | 
| 59 stateful_container_(kStatefulContainer), | 60 stateful_container_(kStatefulContainer), | 
| 60 ipsec_run_path_(kIpsecRunPath), | 61 ipsec_run_path_(kIpsecRunPath), | 
| 61 ipsec_up_file_(kIpsecUpFile), | 62 ipsec_up_file_(kIpsecUpFile), | 
| 62 starter_pid_file_(kStarterPidFile), | 63 starter_pid_file_(kStarterPidFile), | 
| 63 starter_(new ProcessImpl) { | 64 starter_(new ProcessImpl) { | 
| 64 } | 65 } | 
| 65 | 66 | 
| 66 bool IpsecManager::Initialize(int ike_version, | 67 bool IpsecManager::Initialize(int ike_version, | 
| 67 const std::string& remote_address, | 68 const std::string& remote_host, | 
| 68 const std::string& psk_file, | 69 const std::string& psk_file, | 
| 69 const std::string& server_ca_file, | 70 const std::string& server_ca_file, | 
| 70 const std::string& client_key_file, | 71 const std::string& client_key_file, | 
| 71 const std::string& client_cert_file) { | 72 const std::string& client_cert_file) { | 
| 72 if (remote_address.empty()) { | 73 if (remote_host.empty()) { | 
| 73 LOG(ERROR) << "Missing remote address to IPsec layer"; | 74 LOG(ERROR) << "Missing remote host to IPsec layer"; | 
| 74 return false; | 75 return false; | 
| 75 } | 76 } | 
| 76 remote_address_ = remote_address; | 77 remote_host_ = remote_host; | 
| 77 | 78 | 
| 78 if (psk_file.empty()) { | 79 if (psk_file.empty()) { | 
| 79 if (server_ca_file.empty() && client_key_file.empty() && | 80 if (server_ca_file.empty() && client_key_file.empty() && | 
| 80 client_cert_file.empty()) { | 81 client_cert_file.empty()) { | 
| 81 LOG(ERROR) << "Must specify either PSK or certificates for IPsec layer"; | 82 LOG(ERROR) << "Must specify either PSK or certificates for IPsec layer"; | 
| 82 return false; | 83 return false; | 
| 83 } | 84 } | 
| 84 | 85 | 
| 85 // Must be a certificate based connection. | 86 // Must be a certificate based connection. | 
| 86 if (!file_util::PathExists(FilePath(server_ca_file))) { | 87 if (!file_util::PathExists(FilePath(server_ca_file))) { | 
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 121 LOG(ERROR) << "Unsupported IKE version" << ike_version; | 122 LOG(ERROR) << "Unsupported IKE version" << ike_version; | 
| 122 return false; | 123 return false; | 
| 123 } | 124 } | 
| 124 ike_version_ = ike_version; | 125 ike_version_ = ike_version; | 
| 125 | 126 | 
| 126 file_util::Delete(FilePath(kIpsecUpFile), false); | 127 file_util::Delete(FilePath(kIpsecUpFile), false); | 
| 127 | 128 | 
| 128 return true; | 129 return true; | 
| 129 } | 130 } | 
| 130 | 131 | 
| 131 bool IpsecManager::GetLocalAddressForRemote( | 132 bool IpsecManager::ConvertSockAddrToIPString(struct sockaddr* socket_address, | 
| 132 const std::string& remote_address_text, | 133 std::string* output) { | 
| 134 // convert local_address to local_address_text. | |
| 
 
petkov
2011/03/24 16:52:22
Convert
 
 | |
| 135 char str[INET6_ADDRSTRLEN] = { 0 }; | |
| 136 switch (socket_address->sa_family) { | |
| 137 case AF_INET: | |
| 138 if (!inet_ntop(AF_INET, &reinterpret_cast<sockaddr_in*>( | |
| 139 socket_address)->sin_addr, str, INET6_ADDRSTRLEN)) { | |
| 140 LOG(ERROR) << "inet_ntop failed"; | |
| 141 return false; | |
| 142 } | |
| 143 break; | |
| 144 case AF_INET6: | |
| 145 if (!inet_ntop(AF_INET6, &reinterpret_cast<sockaddr_in6*>( | |
| 146 socket_address)->sin6_addr, str, INET6_ADDRSTRLEN)) { | |
| 147 LOG(ERROR) << "inet_ntop failed"; | |
| 148 return false; | |
| 149 } | |
| 150 break; | |
| 151 default: | |
| 152 LOG(ERROR) << "Unknown address family"; | |
| 153 return false; | |
| 154 } | |
| 155 *output = str; | |
| 156 return true; | |
| 157 } | |
| 158 | |
| 159 bool IpsecManager::GetAddressesFromRemoteHost( | |
| 160 const std::string& remote_host, | |
| 161 std::string* remote_address_text, | |
| 133 std::string* local_address_text) { | 162 std::string* local_address_text) { | 
| 134 static const char kService[] = "80"; | 163 static const char kService[] = "80"; | 
| 135 if (force_local_address_ != NULL) { | 164 if (force_local_address_ != NULL) { | 
| 136 *local_address_text = force_local_address_; | 165 *local_address_text = force_local_address_; | 
| 166 *remote_address_text = force_remote_address_; | |
| 137 return true; | 167 return true; | 
| 138 } | 168 } | 
| 139 struct addrinfo *remote_address; | 169 struct addrinfo *remote_address; | 
| 140 int s = getaddrinfo(remote_address_text.c_str(), kService, NULL, | 170 int s = getaddrinfo(remote_host.c_str(), kService, NULL, | 
| 141 &remote_address); | 171 &remote_address); | 
| 142 if (s != 0) { | 172 if (s != 0) { | 
| 143 LOG(ERROR) << "getaddrinfo failed: " << gai_strerror(s); | 173 LOG(ERROR) << "getaddrinfo failed: " << gai_strerror(s); | 
| 144 return false; | 174 return false; | 
| 145 } | 175 } | 
| 176 if (!ConvertSockAddrToIPString(remote_address->ai_addr, | |
| 177 remote_address_text)) { | |
| 178 return false; | |
| 179 } | |
| 146 int sock = HANDLE_EINTR(socket(AF_INET, SOCK_DGRAM, 0)); | 180 int sock = HANDLE_EINTR(socket(AF_INET, SOCK_DGRAM, 0)); | 
| 147 if (sock < 0) { | 181 if (sock < 0) { | 
| 148 LOG(ERROR) << "Unable to create socket"; | 182 LOG(ERROR) << "Unable to create socket"; | 
| 149 return false; | 183 return false; | 
| 150 } | 184 } | 
| 151 if (HANDLE_EINTR( | 185 if (HANDLE_EINTR( | 
| 152 connect(sock, remote_address->ai_addr, sizeof(sockaddr))) != 0) { | 186 connect(sock, remote_address->ai_addr, sizeof(sockaddr))) != 0) { | 
| 153 LOG(ERROR) << "Unable to connect"; | 187 LOG(ERROR) << "Unable to connect"; | 
| 154 HANDLE_EINTR(close(sock)); | 188 HANDLE_EINTR(close(sock)); | 
| 155 return false; | 189 return false; | 
| 156 } | 190 } | 
| 157 bool result = false; | 191 bool result = false; | 
| 158 struct sockaddr local_address; | 192 struct sockaddr local_address; | 
| 159 socklen_t addr_len = sizeof(local_address); | 193 socklen_t addr_len = sizeof(local_address); | 
| 160 char str[INET6_ADDRSTRLEN] = { 0 }; | |
| 161 if (getsockname(sock, &local_address, &addr_len) != 0) { | 194 if (getsockname(sock, &local_address, &addr_len) != 0) { | 
| 162 int saved_errno = errno; | 195 int saved_errno = errno; | 
| 163 LOG(ERROR) << "getsockname failed on socket connecting to " | 196 LOG(ERROR) << "getsockname failed on socket connecting to " | 
| 164 << remote_address_text << ": " << saved_errno; | 197 << remote_address_text << ": " << saved_errno; | 
| 165 goto error_label; | 198 goto error_label; | 
| 166 } | 199 } | 
| 167 // convert local_address to local_address_text. | 200 if (!ConvertSockAddrToIPString(&local_address, local_address_text)) | 
| 168 switch (local_address.sa_family) { | 201 goto error_label; | 
| 169 case AF_INET: | |
| 170 if (!inet_ntop(AF_INET, &reinterpret_cast<sockaddr_in*>( | |
| 171 &local_address)->sin_addr, str, INET6_ADDRSTRLEN)) { | |
| 172 LOG(ERROR) << "inet_ntop failed on " << remote_address_text; | |
| 173 goto error_label; | |
| 174 } | |
| 175 break; | |
| 176 case AF_INET6: | |
| 177 if (!inet_ntop(AF_INET6, &reinterpret_cast<sockaddr_in6*>( | |
| 178 &local_address)->sin6_addr, str, INET6_ADDRSTRLEN)) { | |
| 179 LOG(ERROR) << "inet_ntop failed on " << remote_address_text; | |
| 180 goto error_label; | |
| 181 } | |
| 182 break; | |
| 183 default: | |
| 184 LOG(ERROR) << "Unknown address family converting " << remote_address_text; | |
| 185 goto error_label; | |
| 186 } | |
| 187 *local_address_text = str; | |
| 188 LOG(INFO) << "Remote address " << remote_address_text << " has local address " | 202 LOG(INFO) << "Remote address " << remote_address_text << " has local address " | 
| 189 << *local_address_text; | 203 << *local_address_text; | 
| 190 result = true; | 204 result = true; | 
| 191 | 205 | 
| 192 error_label: | 206 error_label: | 
| 193 HANDLE_EINTR(close(sock)); | 207 HANDLE_EINTR(close(sock)); | 
| 194 freeaddrinfo(remote_address); | 208 freeaddrinfo(remote_address); | 
| 195 return result; | 209 return result; | 
| 196 } | 210 } | 
| 197 | 211 | 
| 198 bool IpsecManager::FormatPsk(const FilePath& input_file, | 212 bool IpsecManager::FormatPsk(const FilePath& input_file, | 
| 199 std::string* formatted) { | 213 std::string* formatted) { | 
| 200 std::string psk; | 214 std::string psk; | 
| 201 if (!file_util::ReadFileToString(input_file, &psk)) { | 215 if (!file_util::ReadFileToString(input_file, &psk)) { | 
| 202 LOG(ERROR) << "Unable to read PSK from " << input_file.value(); | 216 LOG(ERROR) << "Unable to read PSK from " << input_file.value(); | 
| 203 return false; | 217 return false; | 
| 204 } | 218 } | 
| 205 std::string local_address; | 219 std::string local_address; | 
| 206 if (!GetLocalAddressForRemote(remote_address_, &local_address)) { | 220 std::string remote_address; | 
| 221 if (!GetAddressesFromRemoteHost(remote_host_, &remote_address, | |
| 222 &local_address)) { | |
| 207 LOG(ERROR) << "Local IP address could not be determined for PSK mode"; | 223 LOG(ERROR) << "Local IP address could not be determined for PSK mode"; | 
| 208 return false; | 224 return false; | 
| 209 } | 225 } | 
| 210 TrimWhitespaceASCII(psk, TRIM_TRAILING, &psk); | 226 TrimWhitespaceASCII(psk, TRIM_TRAILING, &psk); | 
| 211 *formatted = | 227 *formatted = | 
| 212 StringPrintf("%s %s : PSK \"%s\"\n", local_address.c_str(), | 228 StringPrintf("%s %s : PSK \"%s\"\n", local_address.c_str(), | 
| 213 remote_address_.c_str(), psk.c_str()); | 229 remote_address.c_str(), psk.c_str()); | 
| 214 return true; | 230 return true; | 
| 215 } | 231 } | 
| 216 | 232 | 
| 217 void IpsecManager::KillCurrentlyRunning() { | 233 void IpsecManager::KillCurrentlyRunning() { | 
| 218 if (!file_util::PathExists(FilePath(starter_pid_file_))) | 234 if (!file_util::PathExists(FilePath(starter_pid_file_))) | 
| 219 return; | 235 return; | 
| 220 starter_->ResetPidByFile(starter_pid_file_); | 236 starter_->ResetPidByFile(starter_pid_file_); | 
| 221 if (Process::ProcessExists(starter_->pid())) | 237 if (Process::ProcessExists(starter_->pid())) | 
| 222 starter_->Reset(0); | 238 starter_->Reset(0); | 
| 223 else | 239 else | 
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 269 config.append("conn managed\n"); | 285 config.append("conn managed\n"); | 
| 270 AppendStringSetting(&config, "ike", FLAGS_ike); | 286 AppendStringSetting(&config, "ike", FLAGS_ike); | 
| 271 AppendStringSetting(&config, "keyexchange", | 287 AppendStringSetting(&config, "keyexchange", | 
| 272 ike_version_ == 1 ? "ikev1" : "ikev2"); | 288 ike_version_ == 1 ? "ikev1" : "ikev2"); | 
| 273 if (!psk_file_.empty()) AppendStringSetting(&config, "authby", "psk"); | 289 if (!psk_file_.empty()) AppendStringSetting(&config, "authby", "psk"); | 
| 274 AppendBoolSetting(&config, "pfs", FLAGS_pfs); | 290 AppendBoolSetting(&config, "pfs", FLAGS_pfs); | 
| 275 AppendBoolSetting(&config, "rekey", FLAGS_rekey); | 291 AppendBoolSetting(&config, "rekey", FLAGS_rekey); | 
| 276 AppendStringSetting(&config, "left", "%defaultroute"); | 292 AppendStringSetting(&config, "left", "%defaultroute"); | 
| 277 AppendStringSetting(&config, "leftprotoport", FLAGS_leftprotoport); | 293 AppendStringSetting(&config, "leftprotoport", FLAGS_leftprotoport); | 
| 278 AppendStringSetting(&config, "leftupdown", IPSEC_UPDOWN); | 294 AppendStringSetting(&config, "leftupdown", IPSEC_UPDOWN); | 
| 279 AppendStringSetting(&config, "right", remote_address_); | 295 AppendStringSetting(&config, "right", remote_host_); | 
| 280 AppendStringSetting(&config, "rightprotoport", FLAGS_rightprotoport); | 296 AppendStringSetting(&config, "rightprotoport", FLAGS_rightprotoport); | 
| 281 AppendStringSetting(&config, "type", FLAGS_type); | 297 AppendStringSetting(&config, "type", FLAGS_type); | 
| 282 AppendStringSetting(&config, "auto", "start"); | 298 AppendStringSetting(&config, "auto", "start"); | 
| 283 return config; | 299 return config; | 
| 284 } | 300 } | 
| 285 | 301 | 
| 286 bool IpsecManager::SetIpsecGroup(const FilePath& file_path) { | 302 bool IpsecManager::SetIpsecGroup(const FilePath& file_path) { | 
| 287 return chown(file_path.value().c_str(), getuid(), ipsec_group_) == 0; | 303 return chown(file_path.value().c_str(), getuid(), ipsec_group_) == 0; | 
| 288 } | 304 } | 
| 289 | 305 | 
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 407 return; | 423 return; | 
| 408 } | 424 } | 
| 409 | 425 | 
| 410 if (!starter_->Kill(SIGTERM, kTermTimeout)) { | 426 if (!starter_->Kill(SIGTERM, kTermTimeout)) { | 
| 411 starter_->Kill(SIGKILL, 0); | 427 starter_->Kill(SIGKILL, 0); | 
| 412 OnStopped(true); | 428 OnStopped(true); | 
| 413 return; | 429 return; | 
| 414 } | 430 } | 
| 415 OnStopped(false); | 431 OnStopped(false); | 
| 416 } | 432 } | 
| OLD | NEW |