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 |