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,
223 _("Attempting to connect to %s%s%s:%s\n"),
224 rp->ai_family == AF_INET6?"[":"",
226 rp->ai_family == AF_INET6?"]":"",
229 ssl_sock = socket(rp->ai_family, rp->ai_socktype,
233 if (cancellable_connect(vpninfo, ssl_sock, rp->ai_addr, rp->ai_addrlen) >= 0) {
234 /* Store the peer address we actually used, so that DTLS can
235 use it again later */
236 vpninfo->peer_addr = malloc(rp->ai_addrlen);
237 if (!vpninfo->peer_addr) {
238 vpn_progress(vpninfo, PRG_ERR,
239 _("Failed to allocate sockaddr storage\n"));
243 vpninfo->peer_addrlen = rp->ai_addrlen;
244 memcpy(vpninfo->peer_addr, rp->ai_addr, rp->ai_addrlen);
250 freeaddrinfo(result);
253 vpn_progress(vpninfo, PRG_ERR,
254 _("Failed to connect to host %s\n"),
255 vpninfo->proxy?:vpninfo->hostname);
260 if (vpninfo->proxy) {
261 err = process_proxy(vpninfo, ssl_sock);
271 int __attribute__ ((format (printf, 2, 3)))
272 openconnect_SSL_printf(struct openconnect_info *vpninfo, const char *fmt, ...)
280 vsnprintf(buf, 1023, fmt, args);
282 return openconnect_SSL_write(vpninfo, buf, strlen(buf));
286 int request_passphrase(struct openconnect_info *vpninfo, const char *label,
287 char **response, const char *fmt, ...)
289 struct oc_auth_form f;
290 struct oc_form_opt o;
295 if (!vpninfo->process_auth_form)
299 memset(&f, 0, sizeof(f));
301 vsnprintf(buf, 1023, fmt, args);
304 f.auth_id = (char *)label;
308 o.type = OC_FORM_OPT_PASSWORD;
309 o.name = (char *)label;
313 ret = vpninfo->process_auth_form(vpninfo->cbdata, &f);
322 #if defined(__sun__) || defined(__NetBSD__) || defined(__DragonFly__)
323 int openconnect_passphrase_from_fsid(struct openconnect_info *vpninfo)
327 if (statvfs(vpninfo->sslkey, &buf)) {
329 vpn_progress(vpninfo, PRG_ERR, _("statvfs: %s\n"),
333 if (asprintf(&vpninfo->cert_password, "%lx", buf.f_fsid))
338 int openconnect_passphrase_from_fsid(struct openconnect_info *vpninfo)
341 unsigned *fsid = (unsigned *)&buf.f_fsid;
342 unsigned long long fsid64;
344 if (statfs(vpninfo->sslkey, &buf)) {
346 vpn_progress(vpninfo, PRG_ERR, _("statfs: %s\n"),
350 fsid64 = ((unsigned long long)fsid[0] << 32) | fsid[1];
352 if (asprintf(&vpninfo->cert_password, "%llx", fsid64))
358 #if defined(OPENCONNECT_OPENSSL) || defined (DTLS_OPENSSL)
359 /* We put this here rather than in openssl.c because it might be needed
360 for OpenSSL DTLS support even when GnuTLS is being used for HTTPS */
361 int openconnect_print_err_cb(const char *str, size_t len, void *ptr)
363 struct openconnect_info *vpninfo = ptr;
365 vpn_progress(vpninfo, PRG_ERR, "%s", str);
370 #ifdef FAKE_ANDROID_KEYSTORE
371 char *keystore_strerror(int err)
373 return (char *)strerror(-err);
376 int keystore_fetch(const char *key, unsigned char **result)
383 fd = open(key, O_RDONLY);
387 if (fstat(fd, &st)) {
392 data = malloc(st.st_size);
398 if (read(fd, data, st.st_size) != st.st_size) {
409 #elif defined (ANDROID_KEYSTORE)
410 #include <cutils/sockets.h>
411 #include <keystore.h>
412 char *keystore_strerror(int err)
415 case NO_ERROR: return _("No error");
416 case LOCKED: return _("Keystore ocked");
417 case UNINITIALIZED: return _("Keystore uninitialized");
418 case SYSTEM_ERROR: return _("System error");
419 case PROTOCOL_ERROR: return _("Protocol error");
420 case PERMISSION_DENIED: return _("Permission denied");
421 case KEY_NOT_FOUND: return _("Key not found");
422 case VALUE_CORRUPTED: return _("Value corrupted");
423 case UNDEFINED_ACTION: return _("Undefined action");
424 case WRONG_PASSWORD_0:
425 case WRONG_PASSWORD_1:
426 case WRONG_PASSWORD_2:
427 case WRONG_PASSWORD_3: return _("Wrong password");
428 default: return _("Unknown error");
432 /* Returns length, or a negative errno in its own namespace (handled by its
433 own strerror function above). The numbers are from Android's keystore.h */
434 int keystore_fetch(const char *key, unsigned char **result)
436 unsigned char *data, *p;
437 unsigned char buf[3];
439 int ret = -SYSTEM_ERROR;
441 fd = socket_local_client("keystore",
442 ANDROID_SOCKET_NAMESPACE_RESERVED,
445 return -SYSTEM_ERROR;
452 if (send(fd, buf, 3, 0) != 3 || send(fd, key, len, 0) != len ||
453 shutdown(fd, SHUT_WR) || recv(fd, buf, 1, 0) != 1)
456 if (buf[0] != NO_ERROR) {
457 /* Should never be zero */
458 ret = buf[0] ? -buf[0] : -PROTOCOL_ERROR;
461 if (recv(fd, buf, 2, 0) != 2)
463 len = (buf[0] << 8) + buf[1];
470 int got = recv(fd, p, len, 0);
473 ret = -PROTOCOL_ERROR;