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"),
127 struct addrinfo hints, *result, *rp;
131 memset(&hints, 0, sizeof(struct addrinfo));
132 hints.ai_family = AF_UNSPEC;
133 hints.ai_socktype = SOCK_STREAM;
134 hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV;
135 hints.ai_protocol = 0;
136 hints.ai_canonname = NULL;
137 hints.ai_addr = NULL;
138 hints.ai_next = NULL;
140 /* The 'port' variable is a string because it's easier
141 this way than if we pass NULL to getaddrinfo() and
142 then try to fill in the numeric value into
143 different types of returned sockaddr_in{6,}. */
145 if (vpninfo->proxy_factory) {
150 free(vpninfo->proxy_type);
151 vpninfo->proxy_type = NULL;
152 free(vpninfo->proxy);
153 vpninfo->proxy = NULL;
155 if (vpninfo->port == 443)
156 i = asprintf(&url, "https://%s/%s", vpninfo->hostname,
157 vpninfo->urlpath?:"");
159 i = asprintf(&url, "https://%s:%d/%s", vpninfo->hostname,
160 vpninfo->port, vpninfo->urlpath?:"");
164 proxies = px_proxy_factory_get_proxies(vpninfo->proxy_factory,
168 while (proxies && proxies[i]) {
169 if (!vpninfo->proxy &&
170 (!strncmp(proxies[i], "http://", 7) ||
171 !strncmp(proxies[i], "socks://", 8) ||
172 !strncmp(proxies[i], "socks5://", 9)))
173 internal_parse_url(proxies[i], &vpninfo->proxy_type,
174 &vpninfo->proxy, &vpninfo->proxy_port,
181 vpn_progress(vpninfo, PRG_TRACE,
182 _("Proxy from libproxy: %s://%s:%d/\n"),
183 vpninfo->proxy_type, vpninfo->proxy, vpninfo->port);
186 if (vpninfo->proxy) {
187 hostname = vpninfo->proxy;
188 snprintf(port, 6, "%d", vpninfo->proxy_port);
190 hostname = vpninfo->hostname;
191 snprintf(port, 6, "%d", vpninfo->port);
194 if (hostname[0] == '[' && hostname[strlen(hostname)-1] == ']') {
195 /* Solaris has no strndup(). */
196 int len = strlen(hostname) - 2;
197 char *new_hostname = malloc(len + 1);
200 memcpy(new_hostname, hostname + 1, len);
201 new_hostname[len] = 0;
203 hostname = new_hostname;
204 hints.ai_flags |= AI_NUMERICHOST;
207 err = getaddrinfo(hostname, port, &hints, &result);
210 vpn_progress(vpninfo, PRG_ERR,
211 _("getaddrinfo failed for host '%s': %s\n"),
212 hostname, gai_strerror(err));
213 if (hints.ai_flags & AI_NUMERICHOST)
217 if (hints.ai_flags & AI_NUMERICHOST)
220 for (rp = result; rp ; rp = rp->ai_next) {
223 if (!getnameinfo(rp->ai_addr, rp->ai_addrlen, host,
224 sizeof(host), NULL, 0, NI_NUMERICHOST))
225 vpn_progress(vpninfo, PRG_INFO, vpninfo->proxy_type?
226 _("Attempting to connect to proxy %s%s%s:%s\n"):
227 _("Attempting to connect to server %s%s%s:%s\n"),
228 rp->ai_family == AF_INET6?"[":"",
230 rp->ai_family == AF_INET6?"]":"",
233 ssl_sock = socket(rp->ai_family, rp->ai_socktype,
237 if (cancellable_connect(vpninfo, ssl_sock, rp->ai_addr, rp->ai_addrlen) >= 0) {
238 /* Store the peer address we actually used, so that DTLS can
239 use it again later */
240 vpninfo->peer_addr = malloc(rp->ai_addrlen);
241 if (!vpninfo->peer_addr) {
242 vpn_progress(vpninfo, PRG_ERR,
243 _("Failed to allocate sockaddr storage\n"));
247 vpninfo->peer_addrlen = rp->ai_addrlen;
248 memcpy(vpninfo->peer_addr, rp->ai_addr, rp->ai_addrlen);
254 freeaddrinfo(result);
257 vpn_progress(vpninfo, PRG_ERR,
258 _("Failed to connect to host %s\n"),
259 vpninfo->proxy?:vpninfo->hostname);
264 if (vpninfo->proxy) {
265 err = process_proxy(vpninfo, ssl_sock);
275 int __attribute__ ((format (printf, 2, 3)))
276 openconnect_SSL_printf(struct openconnect_info *vpninfo, const char *fmt, ...)
284 vsnprintf(buf, 1023, fmt, args);
286 return openconnect_SSL_write(vpninfo, buf, strlen(buf));
290 int request_passphrase(struct openconnect_info *vpninfo, const char *label,
291 char **response, const char *fmt, ...)
293 struct oc_auth_form f;
294 struct oc_form_opt o;
299 if (!vpninfo->process_auth_form)
303 memset(&f, 0, sizeof(f));
305 vsnprintf(buf, 1023, fmt, args);
308 f.auth_id = (char *)label;
312 o.type = OC_FORM_OPT_PASSWORD;
313 o.name = (char *)label;
317 ret = vpninfo->process_auth_form(vpninfo->cbdata, &f);
326 #if defined(__sun__) || defined(__NetBSD__) || defined(__DragonFly__)
327 int openconnect_passphrase_from_fsid(struct openconnect_info *vpninfo)
331 if (statvfs(vpninfo->sslkey, &buf)) {
333 vpn_progress(vpninfo, PRG_ERR, _("statvfs: %s\n"),
337 if (asprintf(&vpninfo->cert_password, "%lx", buf.f_fsid))
342 int openconnect_passphrase_from_fsid(struct openconnect_info *vpninfo)
345 unsigned *fsid = (unsigned *)&buf.f_fsid;
346 unsigned long long fsid64;
348 if (statfs(vpninfo->sslkey, &buf)) {
350 vpn_progress(vpninfo, PRG_ERR, _("statfs: %s\n"),
354 fsid64 = ((unsigned long long)fsid[0] << 32) | fsid[1];
356 if (asprintf(&vpninfo->cert_password, "%llx", fsid64))
362 #if defined(OPENCONNECT_OPENSSL) || defined (DTLS_OPENSSL)
363 /* We put this here rather than in openssl.c because it might be needed
364 for OpenSSL DTLS support even when GnuTLS is being used for HTTPS */
365 int openconnect_print_err_cb(const char *str, size_t len, void *ptr)
367 struct openconnect_info *vpninfo = ptr;
369 vpn_progress(vpninfo, PRG_ERR, "%s", str);
374 #ifdef FAKE_ANDROID_KEYSTORE
375 char *keystore_strerror(int err)
377 return (char *)strerror(-err);
380 int keystore_fetch(const char *key, unsigned char **result)
387 fd = open(key, O_RDONLY);
391 if (fstat(fd, &st)) {
396 data = malloc(st.st_size + 1);
402 if (read(fd, data, st.st_size) != st.st_size) {
408 data[st.st_size] = 0;
415 #elif defined (ANDROID_KEYSTORE)
416 #include <cutils/sockets.h>
417 #include <keystore.h>
418 char *keystore_strerror(int err)
421 case NO_ERROR: return _("No error");
422 case LOCKED: return _("Keystore ocked");
423 case UNINITIALIZED: return _("Keystore uninitialized");
424 case SYSTEM_ERROR: return _("System error");
425 case PROTOCOL_ERROR: return _("Protocol error");
426 case PERMISSION_DENIED: return _("Permission denied");
427 case KEY_NOT_FOUND: return _("Key not found");
428 case VALUE_CORRUPTED: return _("Value corrupted");
429 case UNDEFINED_ACTION: return _("Undefined action");
430 case WRONG_PASSWORD_0:
431 case WRONG_PASSWORD_1:
432 case WRONG_PASSWORD_2:
433 case WRONG_PASSWORD_3: return _("Wrong password");
434 default: return _("Unknown error");
438 /* Returns length, or a negative errno in its own namespace (handled by its
439 own strerror function above). The numbers are from Android's keystore.h */
440 int keystore_fetch(const char *key, unsigned char **result)
442 unsigned char *data, *p;
443 unsigned char buf[3];
445 int ret = -SYSTEM_ERROR;
447 fd = socket_local_client("keystore",
448 ANDROID_SOCKET_NAMESPACE_RESERVED,
451 return -SYSTEM_ERROR;
458 if (send(fd, buf, 3, 0) != 3 || send(fd, key, len, 0) != len ||
459 shutdown(fd, SHUT_WR) || recv(fd, buf, 1, 0) != 1)
462 if (buf[0] != NO_ERROR) {
463 /* Should never be zero */
464 ret = buf[0] ? -buf[0] : -PROTOCOL_ERROR;
467 if (recv(fd, buf, 2, 0) != 2)
469 len = (buf[0] << 8) + buf[1];
476 int got = recv(fd, p, len, 0);
479 ret = -PROTOCOL_ERROR;