2 * OpenConnect (SSL + DTLS) VPN client
4 * Copyright © 2008-2012 Intel Corporation.
6 * Author: David Woodhouse <dwmw2@infradead.org>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * version 2.1, as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to:
20 * Free Software Foundation, Inc.
21 * 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301 USA
25 #include <sys/types.h>
26 #include <sys/socket.h>
28 #include <netinet/in.h>
29 #include <arpa/inet.h>
38 #if defined(__linux__) || defined(ANDROID)
40 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__APPLE__)
41 #include <sys/param.h>
42 #include <sys/mount.h>
43 #elif defined (__sun__) || defined(__NetBSD__) || defined(__DragonFly__)
44 #include <sys/statvfs.h>
45 #elif defined (__GNU__)
46 #include <sys/statfs.h>
49 #include "openconnect-internal.h"
51 /* OSX < 1.6 doesn't have AI_NUMERICSERV */
52 #ifndef AI_NUMERICSERV
53 #define AI_NUMERICSERV 0
56 static int cancellable_connect(struct openconnect_info *vpninfo, int sockfd,
57 const struct sockaddr *addr, socklen_t addrlen)
59 struct sockaddr_storage peer;
60 socklen_t peerlen = sizeof(peer);
61 fd_set wr_set, rd_set;
64 fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK);
66 if (connect(sockfd, addr, addrlen) < 0 && errno != EINPROGRESS)
71 FD_SET(sockfd, &wr_set);
72 if (vpninfo->cancel_fd != -1) {
73 FD_SET(vpninfo->cancel_fd, &rd_set);
74 if (vpninfo->cancel_fd > sockfd)
75 maxfd = vpninfo->cancel_fd;
78 /* Later we'll render this whole exercise non-pointless by
79 including a 'cancelfd' here too. */
80 select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
81 if (vpninfo->cancel_fd != -1 && FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
82 vpn_progress(vpninfo, PRG_ERR, _("Socket connect cancelled\n"));
87 /* Check whether connect() succeeded or failed by using
88 getpeername(). See http://cr.yp.to/docs/connect.html */
89 return getpeername(sockfd, (void *)&peer, &peerlen);
92 int connect_https_socket(struct openconnect_info *vpninfo)
100 if (vpninfo->peer_addr) {
102 ssl_sock = socket(vpninfo->peer_addr->sa_family, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_IP);
106 ssl_sock = socket(vpninfo->peer_addr->sa_family, SOCK_STREAM, IPPROTO_IP);
109 fcntl(ssl_sock, F_SETFD, fcntl(ssl_sock, F_GETFD) | FD_CLOEXEC);
111 if (cancellable_connect(vpninfo, ssl_sock, vpninfo->peer_addr, vpninfo->peer_addrlen)) {
113 if (vpninfo->proxy) {
114 vpn_progress(vpninfo, PRG_ERR,
115 _("Failed to reconnect to proxy %s\n"),
118 vpn_progress(vpninfo, PRG_ERR,
119 _("Failed to reconnect to host %s\n"),
126 struct addrinfo hints, *result, *rp;
130 memset(&hints, 0, sizeof(struct addrinfo));
131 hints.ai_family = AF_UNSPEC;
132 hints.ai_socktype = SOCK_STREAM;
133 hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV;
134 hints.ai_protocol = 0;
135 hints.ai_canonname = NULL;
136 hints.ai_addr = NULL;
137 hints.ai_next = NULL;
139 /* The 'port' variable is a string because it's easier
140 this way than if we pass NULL to getaddrinfo() and
141 then try to fill in the numeric value into
142 different types of returned sockaddr_in{6,}. */
144 if (vpninfo->proxy_factory) {
149 free(vpninfo->proxy_type);
150 vpninfo->proxy_type = NULL;
151 free(vpninfo->proxy);
152 vpninfo->proxy = NULL;
154 if (vpninfo->port == 443)
155 i = asprintf(&url, "https://%s/%s", vpninfo->hostname,
156 vpninfo->urlpath?:"");
158 i = asprintf(&url, "https://%s:%d/%s", vpninfo->hostname,
159 vpninfo->port, vpninfo->urlpath?:"");
163 proxies = px_proxy_factory_get_proxies(vpninfo->proxy_factory,
167 while (proxies && proxies[i]) {
168 if (!vpninfo->proxy &&
169 (!strncmp(proxies[i], "http://", 7) ||
170 !strncmp(proxies[i], "socks://", 8) ||
171 !strncmp(proxies[i], "socks5://", 9)))
172 internal_parse_url(proxies[i], &vpninfo->proxy_type,
173 &vpninfo->proxy, &vpninfo->proxy_port,
180 vpn_progress(vpninfo, PRG_TRACE,
181 _("Proxy from libproxy: %s://%s:%d/\n"),
182 vpninfo->proxy_type, vpninfo->proxy, vpninfo->port);
185 if (vpninfo->proxy) {
186 hostname = vpninfo->proxy;
187 snprintf(port, 6, "%d", vpninfo->proxy_port);
189 hostname = vpninfo->hostname;
190 snprintf(port, 6, "%d", vpninfo->port);
193 if (hostname[0] == '[' && hostname[strlen(hostname)-1] == ']') {
194 /* Solaris has no strndup(). */
195 int len = strlen(hostname) - 2;
196 char *new_hostname = malloc(len + 1);
199 memcpy(new_hostname, hostname + 1, len);
200 new_hostname[len] = 0;
202 hostname = new_hostname;
203 hints.ai_flags |= AI_NUMERICHOST;
206 err = getaddrinfo(hostname, port, &hints, &result);
207 if (hints.ai_flags & AI_NUMERICHOST)
211 vpn_progress(vpninfo, PRG_ERR,
212 _("getaddrinfo failed for host '%s': %s\n"),
213 hostname, gai_strerror(err));
217 for (rp = result; rp ; rp = rp->ai_next) {
220 if (!getnameinfo(rp->ai_addr, rp->ai_addrlen, host,
221 sizeof(host), NULL, 0, NI_NUMERICHOST))
222 vpn_progress(vpninfo, PRG_INFO, vpninfo->proxy_type?
223 _("Attempting to connect to proxy %s%s%s:%s\n"):
224 _("Attempting to connect to server %s%s%s:%s\n"),
225 rp->ai_family == AF_INET6?"[":"",
227 rp->ai_family == AF_INET6?"]":"",
230 ssl_sock = socket(rp->ai_family, rp->ai_socktype,
234 if (cancellable_connect(vpninfo, ssl_sock, rp->ai_addr, rp->ai_addrlen) >= 0) {
235 /* Store the peer address we actually used, so that DTLS can
236 use it again later */
237 vpninfo->peer_addr = malloc(rp->ai_addrlen);
238 if (!vpninfo->peer_addr) {
239 vpn_progress(vpninfo, PRG_ERR,
240 _("Failed to allocate sockaddr storage\n"));
244 vpninfo->peer_addrlen = rp->ai_addrlen;
245 memcpy(vpninfo->peer_addr, rp->ai_addr, rp->ai_addrlen);
251 freeaddrinfo(result);
254 vpn_progress(vpninfo, PRG_ERR,
255 _("Failed to connect to host %s\n"),
256 vpninfo->proxy?:vpninfo->hostname);
261 if (vpninfo->proxy) {
262 err = process_proxy(vpninfo, ssl_sock);
272 int __attribute__ ((format (printf, 2, 3)))
273 openconnect_SSL_printf(struct openconnect_info *vpninfo, const char *fmt, ...)
281 vsnprintf(buf, 1023, fmt, args);
283 return openconnect_SSL_write(vpninfo, buf, strlen(buf));
287 int request_passphrase(struct openconnect_info *vpninfo, const char *label,
288 char **response, const char *fmt, ...)
290 struct oc_auth_form f;
291 struct oc_form_opt o;
296 if (!vpninfo->process_auth_form)
300 memset(&f, 0, sizeof(f));
302 vsnprintf(buf, 1023, fmt, args);
305 f.auth_id = (char *)label;
309 o.type = OC_FORM_OPT_PASSWORD;
310 o.name = (char *)label;
314 ret = vpninfo->process_auth_form(vpninfo->cbdata, &f);
323 #if defined(__sun__) || defined(__NetBSD__) || defined(__DragonFly__)
324 int openconnect_passphrase_from_fsid(struct openconnect_info *vpninfo)
328 if (statvfs(vpninfo->sslkey, &buf)) {
330 vpn_progress(vpninfo, PRG_ERR, _("statvfs: %s\n"),
334 if (asprintf(&vpninfo->cert_password, "%lx", buf.f_fsid))
339 int openconnect_passphrase_from_fsid(struct openconnect_info *vpninfo)
342 unsigned *fsid = (unsigned *)&buf.f_fsid;
343 unsigned long long fsid64;
345 if (statfs(vpninfo->sslkey, &buf)) {
347 vpn_progress(vpninfo, PRG_ERR, _("statfs: %s\n"),
351 fsid64 = ((unsigned long long)fsid[0] << 32) | fsid[1];
353 if (asprintf(&vpninfo->cert_password, "%llx", fsid64))
359 #if defined(OPENCONNECT_OPENSSL) || defined (DTLS_OPENSSL)
360 /* We put this here rather than in openssl.c because it might be needed
361 for OpenSSL DTLS support even when GnuTLS is being used for HTTPS */
362 int openconnect_print_err_cb(const char *str, size_t len, void *ptr)
364 struct openconnect_info *vpninfo = ptr;
366 vpn_progress(vpninfo, PRG_ERR, "%s", str);
371 #ifdef FAKE_ANDROID_KEYSTORE
372 char *keystore_strerror(int err)
374 return (char *)strerror(-err);
377 int keystore_fetch(const char *key, unsigned char **result)
384 fd = open(key, O_RDONLY);
388 if (fstat(fd, &st)) {
393 data = malloc(st.st_size + 1);
399 if (read(fd, data, st.st_size) != st.st_size) {
405 data[st.st_size] = 0;
412 #elif defined (ANDROID_KEYSTORE)
413 #include <cutils/sockets.h>
414 #include <keystore.h>
415 char *keystore_strerror(int err)
418 case NO_ERROR: return _("No error");
419 case LOCKED: return _("Keystore ocked");
420 case UNINITIALIZED: return _("Keystore uninitialized");
421 case SYSTEM_ERROR: return _("System error");
422 case PROTOCOL_ERROR: return _("Protocol error");
423 case PERMISSION_DENIED: return _("Permission denied");
424 case KEY_NOT_FOUND: return _("Key not found");
425 case VALUE_CORRUPTED: return _("Value corrupted");
426 case UNDEFINED_ACTION: return _("Undefined action");
427 case WRONG_PASSWORD_0:
428 case WRONG_PASSWORD_1:
429 case WRONG_PASSWORD_2:
430 case WRONG_PASSWORD_3: return _("Wrong password");
431 default: return _("Unknown error");
435 /* Returns length, or a negative errno in its own namespace (handled by its
436 own strerror function above). The numbers are from Android's keystore.h */
437 int keystore_fetch(const char *key, unsigned char **result)
439 unsigned char *data, *p;
440 unsigned char buf[3];
442 int ret = -SYSTEM_ERROR;
444 fd = socket_local_client("keystore",
445 ANDROID_SOCKET_NAMESPACE_RESERVED,
448 return -SYSTEM_ERROR;
455 if (send(fd, buf, 3, 0) != 3 || send(fd, key, len, 0) != len ||
456 shutdown(fd, SHUT_WR) || recv(fd, buf, 1, 0) != 1)
459 if (buf[0] != NO_ERROR) {
460 /* Should never be zero */
461 ret = buf[0] ? -buf[0] : -PROTOCOL_ERROR;
464 if (recv(fd, buf, 2, 0) != 2)
466 len = (buf[0] << 8) + buf[1];
473 int got = recv(fd, p, len, 0);
476 ret = -PROTOCOL_ERROR;