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 |