2 * OpenConnect (SSL + DTLS) VPN client
4 * Copyright © 2008-2010 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>
33 #include <netinet/in.h>
34 #include <arpa/inet.h>
35 #if defined(__linux__)
37 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__APPLE__)
38 #include <sys/param.h>
39 #include <sys/mount.h>
40 #elif defined (__sun__) || defined(__NetBSD__) || defined(__DragonFly__)
41 #include <sys/statvfs.h>
42 #elif defined (__GNU__)
43 #include <sys/statfs.h>
46 #include <openssl/ssl.h>
47 #include <openssl/err.h>
48 #include <openssl/engine.h>
49 #include <openssl/evp.h>
50 #include <openssl/pkcs12.h>
51 #include <openssl/x509v3.h>
53 #include "openconnect-internal.h"
55 /* OSX < 1.6 doesn't have AI_NUMERICSERV */
56 #ifndef AI_NUMERICSERV
57 #define AI_NUMERICSERV 0
60 /* Helper functions for reading/writing lines over SSL.
61 We could use cURL for the HTTP stuff, but it's overkill */
63 int openconnect_SSL_write(struct openconnect_info *vpninfo, char *buf, size_t len)
65 size_t orig_len = len;
68 int done = SSL_write(vpninfo->https_ssl, buf, len);
73 int err = SSL_get_error(vpninfo->https_ssl, done);
74 fd_set wr_set, rd_set;
75 int maxfd = vpninfo->ssl_fd;
80 if (err == SSL_ERROR_WANT_READ)
81 FD_SET(vpninfo->ssl_fd, &rd_set);
82 else if (err == SSL_ERROR_WANT_WRITE)
83 FD_SET(vpninfo->ssl_fd, &wr_set);
85 vpn_progress(vpninfo, PRG_ERR, _("Failed to write to SSL socket"));
86 report_ssl_errors(vpninfo);
89 if (vpninfo->cancel_fd != -1) {
90 FD_SET(vpninfo->cancel_fd, &rd_set);
91 if (vpninfo->cancel_fd > vpninfo->ssl_fd)
92 maxfd = vpninfo->cancel_fd;
94 select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
95 if (vpninfo->cancel_fd != -1 &&
96 FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
97 vpn_progress(vpninfo, PRG_ERR, _("SSL write cancelled\n"));
105 int __attribute__ ((format (printf, 2, 3)))
106 openconnect_SSL_printf(struct openconnect_info *vpninfo, const char *fmt, ...)
114 vsnprintf(buf, 1023, fmt, args);
116 return openconnect_SSL_write(vpninfo, buf, strlen(buf));
120 static int print_err(const char *str, size_t len, void *ptr)
122 struct openconnect_info *vpninfo = ptr;
124 vpn_progress(vpninfo, PRG_ERR, "%s", str);
128 void report_ssl_errors(struct openconnect_info *vpninfo)
130 ERR_print_errors_cb(print_err, vpninfo);
133 int openconnect_SSL_gets(struct openconnect_info *vpninfo, char *buf, size_t len)
141 while ( (ret = SSL_read(vpninfo->https_ssl, buf + i, 1)) == 1) {
142 if (buf[i] == '\n') {
144 if (i && buf[i-1] == '\r') {
158 ret = -SSL_get_error(vpninfo->https_ssl, ret);
164 static int pem_pw_cb(char *buf, int len, int w, void *v)
166 struct openconnect_info *vpninfo = v;
168 /* Only try the provided password once... */
169 SSL_CTX_set_default_passwd_cb(vpninfo->https_ctx, NULL);
170 SSL_CTX_set_default_passwd_cb_userdata(vpninfo->https_ctx, NULL);
172 if (len <= strlen(vpninfo->cert_password)) {
173 vpn_progress(vpninfo, PRG_ERR,
174 _("PEM password too long (%zd >= %d)\n"),
175 strlen(vpninfo->cert_password), len);
178 strcpy(buf, vpninfo->cert_password);
179 return strlen(vpninfo->cert_password);
182 static int load_pkcs12_certificate(struct openconnect_info *vpninfo, PKCS12 *p12)
184 EVP_PKEY *pkey = NULL;
188 char pass[PEM_BUFSIZE];
191 /* We do this every time round the loop, to work around a bug in
192 OpenSSL < 1.0.0-beta2 -- where the stack at *ca will be freed
193 when PKCS12_parse() returns an error, but *ca is left pointing
194 to the freed memory. */
196 if (!vpninfo->cert_password) {
197 if (EVP_read_pw_string(pass, PEM_BUFSIZE,
198 "Enter PKCS#12 pass phrase:", 0))
201 if (!PKCS12_parse(p12, vpninfo->cert_password?:pass, &pkey, &cert, &ca)) {
202 unsigned long err = ERR_peek_error();
204 report_ssl_errors(vpninfo);
206 if (ERR_GET_LIB(err) == ERR_LIB_PKCS12 &&
207 ERR_GET_FUNC(err) == PKCS12_F_PKCS12_PARSE &&
208 ERR_GET_REASON(err) == PKCS12_R_MAC_VERIFY_FAILURE) {
209 vpn_progress(vpninfo, PRG_ERR,
210 _("Parse PKCS#12 failed (wrong passphrase?)\n"));
211 vpninfo->cert_password = NULL;
215 vpn_progress(vpninfo, PRG_ERR,
216 _("Parse PKCS#12 failed (see above errors)\n"));
221 vpninfo->cert_x509 = cert;
222 SSL_CTX_use_certificate(vpninfo->https_ctx, cert);
224 vpn_progress(vpninfo, PRG_ERR,
225 _("PKCS#12 contained no certificate!"));
230 SSL_CTX_use_PrivateKey(vpninfo->https_ctx, pkey);
233 vpn_progress(vpninfo, PRG_ERR,
234 _("PKCS#12 contained no private key!"));
238 /* Only include supporting certificates which are actually necessary */
242 for (i = 0; i < sk_X509_num(ca); i++) {
243 X509 *cert2 = sk_X509_value(ca, i);
244 if (X509_check_issued(cert2, cert) == X509_V_OK) {
250 X509_NAME_oneline(X509_get_subject_name(cert2),
252 vpn_progress(vpninfo, PRG_DEBUG,
253 _("Extra cert from PKCS#12: '%s'\n"), buf);
254 CRYPTO_add(&cert2->references, 1, CRYPTO_LOCK_X509);
255 SSL_CTX_add_extra_chain_cert(vpninfo->https_ctx, cert2);
260 sk_X509_pop_free(ca, X509_free);
268 static int load_tpm_certificate(struct openconnect_info *vpninfo)
272 ENGINE_load_builtin_engines();
274 e = ENGINE_by_id("tpm");
276 vpn_progress(vpninfo, PRG_ERR, _("Can't load TPM engine.\n"));
277 report_ssl_errors(vpninfo);
280 if (!ENGINE_init(e) || !ENGINE_set_default_RSA(e) ||
281 !ENGINE_set_default_RAND(e)) {
282 vpn_progress(vpninfo, PRG_ERR, _("Failed to init TPM engine\n"));
283 report_ssl_errors(vpninfo);
288 if (vpninfo->cert_password) {
289 if (!ENGINE_ctrl_cmd(e, "PIN", strlen(vpninfo->cert_password),
290 vpninfo->cert_password, NULL, 0)) {
291 vpn_progress(vpninfo, PRG_ERR,
292 _("Failed to set TPM SRK password\n"));
293 report_ssl_errors(vpninfo);
296 key = ENGINE_load_private_key(e, vpninfo->sslkey, NULL, NULL);
298 vpn_progress(vpninfo, PRG_ERR,
299 _("Failed to load TPM private key\n"));
300 report_ssl_errors(vpninfo);
305 if (!SSL_CTX_use_PrivateKey(vpninfo->https_ctx, key)) {
306 vpn_progress(vpninfo, PRG_ERR, _("Add key from TPM failed\n"));
307 report_ssl_errors(vpninfo);
315 static int load_tpm_certificate(struct openconnect_info *vpninfo)
317 vpn_progress(vpninfo, PRG_ERR,
318 _("This version of OpenConnect was built without TPM support\n"));
323 static int reload_pem_cert(struct openconnect_info *vpninfo)
325 BIO *b = BIO_new(BIO_s_file_internal());
330 if (BIO_read_filename(b, vpninfo->cert) <= 0) {
333 vpn_progress(vpninfo, PRG_ERR,
334 _("Failed to reload X509 cert for expiry check\n"));
335 report_ssl_errors(vpninfo);
338 vpninfo->cert_x509 = PEM_read_bio_X509_AUX(b, NULL, NULL, NULL);
339 if (!vpninfo->cert_x509)
345 static int load_certificate(struct openconnect_info *vpninfo)
347 vpn_progress(vpninfo, PRG_TRACE,
348 _("Using certificate file %s\n"), vpninfo->cert);
350 if (vpninfo->cert_type == CERT_TYPE_PKCS12 ||
351 vpninfo->cert_type == CERT_TYPE_UNKNOWN) {
355 f = fopen(vpninfo->cert, "r");
357 vpn_progress(vpninfo, PRG_ERR,
358 _("Failed to open certificate file %s: %s\n"),
359 vpninfo->cert, strerror(errno));
362 p12 = d2i_PKCS12_fp(f, NULL);
365 return load_pkcs12_certificate(vpninfo, p12);
368 if (vpninfo->cert_type == CERT_TYPE_PKCS12) {
369 vpn_progress(vpninfo, PRG_ERR, _("Read PKCS#12 failed\n"));
370 report_ssl_errors(vpninfo);
373 /* Clear error and fall through to see if it's a PEM file... */
377 /* It's PEM or TPM now, and either way we need to load the plain cert: */
378 if (!SSL_CTX_use_certificate_chain_file(vpninfo->https_ctx,
380 vpn_progress(vpninfo, PRG_ERR,
381 _("Loading certificate failed\n"));
382 report_ssl_errors(vpninfo);
386 /* Ew, we can't get it back from the OpenSSL CTX in any sane fashion */
387 reload_pem_cert(vpninfo);
389 if (vpninfo->cert_type == CERT_TYPE_UNKNOWN) {
390 FILE *f = fopen(vpninfo->sslkey, "r");
394 vpn_progress(vpninfo, PRG_ERR,
395 _("Failed to open private key file %s: %s\n"),
396 vpninfo->cert, strerror(errno));
401 while (fgets(buf, 255, f)) {
402 if (!strcmp(buf, "-----BEGIN TSS KEY BLOB-----\n")) {
403 vpninfo->cert_type = CERT_TYPE_TPM;
405 } else if (!strcmp(buf, "-----BEGIN RSA PRIVATE KEY-----\n") ||
406 !strcmp(buf, "-----BEGIN DSA PRIVATE KEY-----\n") ||
407 !strcmp(buf, "-----BEGIN ENCRYPTED PRIVATE KEY-----\n")) {
408 vpninfo->cert_type = CERT_TYPE_PEM;
413 if (vpninfo->cert_type == CERT_TYPE_UNKNOWN) {
414 vpn_progress(vpninfo, PRG_ERR,
415 _("Failed to identify private key type in '%s'\n"),
421 if (vpninfo->cert_type == CERT_TYPE_TPM)
422 return load_tpm_certificate(vpninfo);
424 /* Standard PEM certificate */
425 if (vpninfo->cert_password) {
426 SSL_CTX_set_default_passwd_cb(vpninfo->https_ctx,
428 SSL_CTX_set_default_passwd_cb_userdata(vpninfo->https_ctx,
432 if (!SSL_CTX_use_RSAPrivateKey_file(vpninfo->https_ctx, vpninfo->sslkey,
434 unsigned long err = ERR_peek_error();
436 report_ssl_errors(vpninfo);
438 #ifndef EVP_F_EVP_DECRYPTFINAL_EX
439 #define EVP_F_EVP_DECRYPTFINAL_EX EVP_F_EVP_DECRYPTFINAL
441 /* If the user fat-fingered the passphrase, try again */
442 if (ERR_GET_LIB(err) == ERR_LIB_EVP &&
443 ERR_GET_FUNC(err) == EVP_F_EVP_DECRYPTFINAL_EX &&
444 ERR_GET_REASON(err) == EVP_R_BAD_DECRYPT) {
445 vpn_progress(vpninfo, PRG_ERR,
446 _("Loading private key failed (wrong passphrase?)\n"));
450 vpn_progress(vpninfo, PRG_ERR,
451 _("Loading private key failed (see above errors)\n"));
457 static int get_cert_fingerprint(struct openconnect_info *vpninfo,
458 X509 *cert, const EVP_MD *type,
461 unsigned char md[EVP_MAX_MD_SIZE];
464 if (!X509_digest(cert, type, md, &n))
467 for (i=0; i < n; i++)
468 sprintf(&buf[i*2], "%02X", md[i]);
473 int get_cert_md5_fingerprint(struct openconnect_info *vpninfo,
474 X509 *cert, char *buf)
476 return get_cert_fingerprint(vpninfo, cert, EVP_md5(), buf);
479 int openconnect_get_cert_sha1(struct openconnect_info *vpninfo,
480 X509 *cert, char *buf)
482 return get_cert_fingerprint(vpninfo, cert, EVP_sha1(), buf);
485 static int check_server_cert(struct openconnect_info *vpninfo, X509 *cert)
487 char fingerprint[EVP_MAX_MD_SIZE * 2 + 1];
490 ret = openconnect_get_cert_sha1(vpninfo, cert, fingerprint);
494 if (strcasecmp(vpninfo->servercert, fingerprint)) {
495 vpn_progress(vpninfo, PRG_ERR,
496 _("Server SSL certificate didn't match: %s\n"), fingerprint);
502 static int match_hostname_elem(const char *hostname, int helem_len,
503 const char *match, int melem_len)
505 if (!helem_len && !melem_len)
508 if (!helem_len || !melem_len)
512 if (match[0] == '*') {
515 for (i = 1 ; i <= helem_len; i++) {
516 if (!match_hostname_elem(hostname + i, helem_len - i,
517 match + 1, melem_len - 1))
523 /* From the NetBSD (5.1) man page for ctype(3):
524 Values of type char or signed char must first be cast to unsigned char,
525 to ensure that the values are within the correct range. The result
526 should then be cast to int to avoid warnings from some compilers.
527 We do indeed get warning "array subscript has type 'char'" without
529 if (toupper((int)(unsigned char)hostname[0]) ==
530 toupper((int)(unsigned char)match[0]))
531 return match_hostname_elem(hostname + 1, helem_len - 1,
532 match + 1, melem_len - 1);
537 static int match_hostname(const char *hostname, const char *match)
540 const char *h_dot, *m_dot;
541 int helem_len, melem_len;
543 h_dot = strchr(hostname, '.');
544 m_dot = strchr(match, '.');
546 if (h_dot && m_dot) {
547 helem_len = h_dot - hostname + 1;
548 melem_len = m_dot - match + 1;
549 } else if (!h_dot && !m_dot) {
550 helem_len = strlen(hostname);
551 melem_len = strlen(match);
556 if (match_hostname_elem(hostname, helem_len,
560 hostname += helem_len;
569 /* cf. RFC2818 and RFC2459 */
570 static int match_cert_hostname(struct openconnect_info *vpninfo, X509 *peer_cert)
572 STACK_OF(GENERAL_NAME) *altnames;
574 ASN1_STRING *subjasn1;
575 char *subjstr = NULL;
578 char addrbuf[sizeof(struct in6_addr)];
581 /* Allow GEN_IP in the certificate only if we actually connected
582 by IP address rather than by name. */
583 if (inet_pton(AF_INET, vpninfo->hostname, addrbuf) > 0)
585 else if (inet_pton(AF_INET6, vpninfo->hostname, addrbuf) > 0)
587 else if (vpninfo->hostname[0] == '[' &&
588 vpninfo->hostname[strlen(vpninfo->hostname)-1] == ']') {
589 char *p = &vpninfo->hostname[strlen(vpninfo->hostname)-1];
591 if (inet_pton(AF_INET6, vpninfo->hostname + 1, addrbuf) > 0)
596 altnames = X509_get_ext_d2i(peer_cert, NID_subject_alt_name,
598 for (i = 0; i < sk_GENERAL_NAME_num(altnames); i++) {
599 const GENERAL_NAME *this = sk_GENERAL_NAME_value(altnames, i);
601 if (this->type == GEN_DNS) {
604 int len = ASN1_STRING_to_UTF8((void *)&str, this->d.ia5);
610 /* We don't like names with embedded NUL */
611 if (strlen(str) != len)
614 if (!match_hostname(vpninfo->hostname, str)) {
615 vpn_progress(vpninfo, PRG_TRACE,
616 _("Matched DNS altname '%s'\n"),
618 GENERAL_NAMES_free(altnames);
622 vpn_progress(vpninfo, PRG_TRACE,
623 _("No match for altname '%s'\n"),
627 } else if (this->type == GEN_IPADD && addrlen) {
631 if (this->d.ip->length == 4) {
633 } else if (this->d.ip->length == 16) {
636 vpn_progress(vpninfo, PRG_ERR,
637 _("Certificate has GEN_IPADD altname with bogus length %d\n"),
642 /* We only do this for the debug messages */
643 inet_ntop(family, this->d.ip->data, host, sizeof(host));
645 if (this->d.ip->length == addrlen &&
646 !memcmp(addrbuf, this->d.ip->data, addrlen)) {
647 vpn_progress(vpninfo, PRG_TRACE,
648 _("Matched %s address '%s'\n"),
649 (family == AF_INET6)?"IPv6":"IPv4",
651 GENERAL_NAMES_free(altnames);
654 vpn_progress(vpninfo, PRG_TRACE,
655 _("No match for %s address '%s'\n"),
656 (family == AF_INET6)?"IPv6":"IPv4",
659 } else if (this->type == GEN_URI) {
661 char *url_proto, *url_host, *url_path, *url_host2;
663 int len = ASN1_STRING_to_UTF8((void *)&str, this->d.ia5);
668 /* We don't like names with embedded NUL */
669 if (strlen(str) != len)
672 if (internal_parse_url(str, &url_proto, &url_host, &url_port, &url_path, 0)) {
677 if (!url_proto || strcasecmp(url_proto, "https"))
680 if (url_port != vpninfo->port)
683 /* Leave url_host as it was so that it can be freed */
684 url_host2 = url_host;
685 if (addrlen == 16 && vpninfo->hostname[0] != '[' &&
686 url_host[0] == '[' && url_host[strlen(url_host)-1] == ']') {
687 /* Cope with https://[IPv6]/ when the hostname is bare IPv6 */
688 url_host[strlen(url_host)-1] = 0;
692 if (strcasecmp(vpninfo->hostname, url_host2))
696 vpn_progress(vpninfo, PRG_TRACE,
697 _("URI '%s' has non-empty path; ignoring\n"),
699 goto no_uri_match_silent;
701 vpn_progress(vpninfo, PRG_TRACE,
702 _("Matched URI '%s'\n"),
708 GENERAL_NAMES_free(altnames);
712 vpn_progress(vpninfo, PRG_TRACE,
713 _("No match for URI '%s'\n"),
722 GENERAL_NAMES_free(altnames);
724 /* According to RFC2818, we don't use the legacy subject name if
725 there was an altname with DNS type. */
727 vpn_progress(vpninfo, PRG_ERR,
728 _("No altname in peer cert matched '%s'\n"),
733 subjname = X509_get_subject_name(peer_cert);
735 vpn_progress(vpninfo, PRG_ERR,
736 _("No subject name in peer cert!\n"));
740 /* Find the _last_ (most specific) commonName */
743 int j = X509_NAME_get_index_by_NID(subjname, NID_commonName, i);
750 subjasn1 = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subjname, i));
752 i = ASN1_STRING_to_UTF8((void *)&subjstr, subjasn1);
754 if (!subjstr || strlen(subjstr) != i) {
755 vpn_progress(vpninfo, PRG_ERR,
756 _("Failed to parse subject name in peer cert\n"));
761 if (match_hostname(vpninfo->hostname, subjstr)) {
762 vpn_progress(vpninfo, PRG_ERR,
763 _("Peer cert subject mismatch ('%s' != '%s')\n"),
764 subjstr, vpninfo->hostname);
767 vpn_progress(vpninfo, PRG_TRACE,
768 _("Matched peer certificate subject name '%s'\n"),
772 OPENSSL_free(subjstr);
776 static int verify_peer(struct openconnect_info *vpninfo, SSL *https_ssl)
781 peer_cert = SSL_get_peer_certificate(https_ssl);
783 if (vpninfo->servercert) {
784 /* If given a cert fingerprint on the command line, that's
786 ret = check_server_cert(vpninfo, peer_cert);
788 int vfy = SSL_get_verify_result(https_ssl);
789 const char *err_string = NULL;
791 if (vfy != X509_V_OK)
792 err_string = X509_verify_cert_error_string(vfy);
793 else if (match_cert_hostname(vpninfo, peer_cert))
794 err_string = _("certificate does not match hostname");
797 vpn_progress(vpninfo, PRG_INFO,
798 _("Server certificate verify failed: %s\n"),
801 if (vpninfo->validate_peer_cert)
802 ret = vpninfo->validate_peer_cert(vpninfo->cbdata,
811 X509_free(peer_cert);
816 static void workaround_openssl_certchain_bug(struct openconnect_info *vpninfo,
819 /* OpenSSL has problems with certificate chains -- if there are
820 multiple certs with the same name, it doesn't necessarily
821 choose the _right_ one. (RT#1942)
822 Pick the right ones for ourselves and add them manually. */
823 X509 *cert = SSL_get_certificate(ssl);
825 X509_STORE *store = SSL_CTX_get_cert_store(vpninfo->https_ctx);
831 /* If we already have 'supporting' certs, don't add them again */
832 if (vpninfo->https_ctx->extra_certs)
835 if (!X509_STORE_CTX_init(&ctx, store, NULL, NULL))
838 while (ctx.get_issuer(&cert2, &ctx, cert) == 1) {
843 X509_NAME_oneline(X509_get_subject_name(cert),
845 vpn_progress(vpninfo, PRG_DEBUG,
846 _("Extra cert from cafile: '%s'\n"), buf);
847 SSL_CTX_add_extra_chain_cert(vpninfo->https_ctx, cert);
849 X509_STORE_CTX_cleanup(&ctx);
852 #if OPENSSL_VERSION_NUMBER >= 0x00908000
853 static int ssl_app_verify_callback(X509_STORE_CTX *ctx, void *arg)
855 /* We've seen certificates in the wild which don't have the
856 purpose fields filled in correctly */
857 X509_VERIFY_PARAM_set_purpose(ctx->param, X509_PURPOSE_ANY);
858 return X509_verify_cert(ctx);
862 static int check_certificate_expiry(struct openconnect_info *vpninfo)
865 const char *reason = NULL;
869 if (!vpninfo->cert_x509)
873 notAfter = X509_get_notAfter(vpninfo->cert_x509);
874 i = X509_cmp_time(notAfter, &t);
876 vpn_progress(vpninfo, PRG_ERR,
877 _("Error in client cert notAfter field\n"));
880 reason = _("Client certificate has expired at");
882 t += vpninfo->cert_expire_warning;
883 i = X509_cmp_time(notAfter, &t);
885 reason = _("Client certificate expires soon at");
889 BIO *bp = BIO_new(BIO_s_mem());
891 const char *expiry = _("<error>");
895 ASN1_TIME_print(bp, notAfter);
896 BIO_write(bp, &zero, 1);
897 BIO_get_mem_ptr(bp, &bm);
900 vpn_progress(vpninfo, PRG_ERR, "%s: %s\n", reason, expiry);
907 static int cancellable_connect(struct openconnect_info *vpninfo, int sockfd,
908 const struct sockaddr *addr, socklen_t addrlen)
910 struct sockaddr_storage peer;
911 socklen_t peerlen = sizeof(peer);
912 fd_set wr_set, rd_set;
915 fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK);
917 if (connect(sockfd, addr, addrlen) < 0 && errno != EINPROGRESS)
922 FD_SET(sockfd, &wr_set);
923 if (vpninfo->cancel_fd != -1) {
924 FD_SET(vpninfo->cancel_fd, &rd_set);
925 if (vpninfo->cancel_fd > sockfd)
926 maxfd = vpninfo->cancel_fd;
929 /* Later we'll render this whole exercise non-pointless by
930 including a 'cancelfd' here too. */
931 select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
932 if (vpninfo->cancel_fd != -1 && FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
933 vpninfo->progress(vpninfo, PRG_ERR, _("Socket connect cancelled\n"));
938 /* Check whether connect() succeeded or failed by using
939 getpeername(). See http://cr.yp.to/docs/connect.html */
940 return getpeername(sockfd, (void *)&peer, &peerlen);
943 int openconnect_open_https(struct openconnect_info *vpninfo)
945 method_const SSL_METHOD *ssl3_method;
954 if (vpninfo->peer_addr) {
955 ssl_sock = socket(vpninfo->peer_addr->sa_family, SOCK_STREAM, IPPROTO_IP);
958 if (vpninfo->proxy) {
959 vpn_progress(vpninfo, PRG_ERR,
960 _("Failed to reconnect to proxy %s\n"),
963 vpn_progress(vpninfo, PRG_ERR,
964 _("Failed to reconnect to host %s\n"),
969 if (cancellable_connect(vpninfo, ssl_sock, vpninfo->peer_addr, vpninfo->peer_addrlen))
973 struct addrinfo hints, *result, *rp;
977 memset(&hints, 0, sizeof(struct addrinfo));
978 hints.ai_family = AF_UNSPEC;
979 hints.ai_socktype = SOCK_STREAM;
980 hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV;
981 hints.ai_protocol = 0;
982 hints.ai_canonname = NULL;
983 hints.ai_addr = NULL;
984 hints.ai_next = NULL;
986 /* The 'port' variable is a string because it's easier
987 this way than if we pass NULL to getaddrinfo() and
988 then try to fill in the numeric value into
989 different types of returned sockaddr_in{6,}. */
991 if (vpninfo->proxy_factory) {
996 free(vpninfo->proxy_type);
997 vpninfo->proxy_type = NULL;
998 free(vpninfo->proxy);
999 vpninfo->proxy = NULL;
1001 if (vpninfo->port == 443)
1002 i = asprintf(&url, "https://%s/%s", vpninfo->hostname,
1003 vpninfo->urlpath?:"");
1005 i = asprintf(&url, "https://%s:%d/%s", vpninfo->hostname,
1006 vpninfo->port, vpninfo->urlpath?:"");
1010 proxies = px_proxy_factory_get_proxies(vpninfo->proxy_factory,
1014 while (proxies && proxies[i]) {
1015 if (!vpninfo->proxy &&
1016 (!strncmp(proxies[i], "http://", 7) ||
1017 !strncmp(proxies[i], "socks://", 8) ||
1018 !strncmp(proxies[i], "socks5://", 9)))
1019 internal_parse_url(proxies[i], &vpninfo->proxy_type,
1020 &vpninfo->proxy, &vpninfo->proxy_port,
1027 vpn_progress(vpninfo, PRG_TRACE,
1028 _("Proxy from libproxy: %s://%s:%d/\n"),
1029 vpninfo->proxy_type, vpninfo->proxy, vpninfo->port);
1032 if (vpninfo->proxy) {
1033 hostname = vpninfo->proxy;
1034 snprintf(port, 6, "%d", vpninfo->proxy_port);
1036 hostname = vpninfo->hostname;
1037 snprintf(port, 6, "%d", vpninfo->port);
1040 if (hostname[0] == '[' && hostname[strlen(hostname)-1] == ']') {
1041 /* Solaris has no strndup(). */
1042 int len = strlen(hostname) - 2;
1043 char *new_hostname = malloc(len + 1);
1046 memcpy(new_hostname, hostname + 1, len);
1047 new_hostname[len] = 0;
1049 hostname = new_hostname;
1050 hints.ai_flags |= AI_NUMERICHOST;
1053 err = getaddrinfo(hostname, port, &hints, &result);
1054 if (hints.ai_flags & AI_NUMERICHOST)
1058 vpn_progress(vpninfo, PRG_ERR,
1059 _("getaddrinfo failed for host '%s': %s\n"),
1060 hostname, gai_strerror(err));
1064 for (rp = result; rp ; rp = rp->ai_next) {
1067 if (!getnameinfo(rp->ai_addr, rp->ai_addrlen, host,
1068 sizeof(host), NULL, 0, NI_NUMERICHOST))
1069 vpn_progress(vpninfo, PRG_INFO,
1070 _("Attempting to connect to %s%s%s:%s\n"),
1071 rp->ai_family == AF_INET6?"[":"",
1073 rp->ai_family == AF_INET6?"]":"",
1076 ssl_sock = socket(rp->ai_family, rp->ai_socktype,
1080 if (cancellable_connect(vpninfo, ssl_sock, rp->ai_addr, rp->ai_addrlen) >= 0) {
1081 /* Store the peer address we actually used, so that DTLS can
1082 use it again later */
1083 vpninfo->peer_addr = malloc(rp->ai_addrlen);
1084 if (!vpninfo->peer_addr) {
1085 vpn_progress(vpninfo, PRG_ERR,
1086 _("Failed to allocate sockaddr storage\n"));
1090 vpninfo->peer_addrlen = rp->ai_addrlen;
1091 memcpy(vpninfo->peer_addr, rp->ai_addr, rp->ai_addrlen);
1097 freeaddrinfo(result);
1100 vpn_progress(vpninfo, PRG_ERR,
1101 _("Failed to connect to host %s\n"),
1102 vpninfo->proxy?:vpninfo->hostname);
1106 fcntl(ssl_sock, F_SETFD, FD_CLOEXEC);
1108 if (vpninfo->proxy) {
1109 err = process_proxy(vpninfo, ssl_sock);
1116 ssl3_method = TLSv1_client_method();
1117 if (!vpninfo->https_ctx) {
1118 vpninfo->https_ctx = SSL_CTX_new(ssl3_method);
1120 /* Some servers (or their firewalls) really don't like seeing
1122 #ifdef SSL_OP_NO_TICKET
1123 SSL_CTX_set_options (vpninfo->https_ctx, SSL_OP_NO_TICKET);
1126 if (vpninfo->cert) {
1127 err = load_certificate(vpninfo);
1129 vpn_progress(vpninfo, PRG_ERR,
1130 _("Loading certificate failed. Aborting.\n"));
1133 check_certificate_expiry(vpninfo);
1136 /* We just want to do:
1137 SSL_CTX_set_purpose(vpninfo->https_ctx, X509_PURPOSE_ANY);
1138 ... but it doesn't work with OpenSSL < 0.9.8k because of
1139 problems with inheritance (fixed in v1.1.4.6 of
1140 crypto/x509/x509_vpm.c) so we have to play silly buggers
1141 instead. This trick doesn't work _either_ in < 0.9.7 but
1142 I don't know of _any_ workaround which will, and can't
1143 be bothered to find out either. */
1144 #if OPENSSL_VERSION_NUMBER >= 0x00908000
1145 SSL_CTX_set_cert_verify_callback(vpninfo->https_ctx,
1146 ssl_app_verify_callback, NULL);
1148 SSL_CTX_set_default_verify_paths(vpninfo->https_ctx);
1150 if (vpninfo->cafile) {
1151 if (!SSL_CTX_load_verify_locations(vpninfo->https_ctx, vpninfo->cafile, NULL)) {
1152 vpn_progress(vpninfo, PRG_ERR,
1153 _("Failed to open CA file '%s'\n"),
1155 report_ssl_errors(vpninfo);
1162 https_ssl = SSL_new(vpninfo->https_ctx);
1163 workaround_openssl_certchain_bug(vpninfo, https_ssl);
1165 https_bio = BIO_new_socket(ssl_sock, BIO_NOCLOSE);
1166 SSL_set_bio(https_ssl, https_bio, https_bio);
1168 vpn_progress(vpninfo, PRG_INFO, _("SSL negotiation with %s\n"),
1171 while ((err = SSL_connect(https_ssl)) <= 0) {
1172 fd_set wr_set, rd_set;
1173 int maxfd = ssl_sock;
1178 err = SSL_get_error(https_ssl, err);
1179 if (err == SSL_ERROR_WANT_READ)
1180 FD_SET(ssl_sock, &rd_set);
1181 else if (err == SSL_ERROR_WANT_WRITE)
1182 FD_SET(ssl_sock, &wr_set);
1184 vpn_progress(vpninfo, PRG_ERR, _("SSL connection failure\n"));
1185 report_ssl_errors(vpninfo);
1186 SSL_free(https_ssl);
1191 if (vpninfo->cancel_fd != -1) {
1192 FD_SET(vpninfo->cancel_fd, &rd_set);
1193 if (vpninfo->cancel_fd > ssl_sock)
1194 maxfd = vpninfo->cancel_fd;
1196 select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
1197 if (vpninfo->cancel_fd != -1 &&
1198 FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
1199 vpn_progress(vpninfo, PRG_ERR, _("SSL connection cancelled\n"));
1200 SSL_free(https_ssl);
1206 if (verify_peer(vpninfo, https_ssl)) {
1207 SSL_free(https_ssl);
1212 vpninfo->ssl_fd = ssl_sock;
1213 vpninfo->https_ssl = https_ssl;
1215 vpn_progress(vpninfo, PRG_INFO, _("Connected to HTTPS on %s\n"),
1221 void openconnect_close_https(struct openconnect_info *vpninfo)
1223 SSL_free(vpninfo->https_ssl);
1224 vpninfo->https_ssl = NULL;
1225 close(vpninfo->ssl_fd);
1226 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_rfds);
1227 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_wfds);
1228 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_efds);
1229 vpninfo->ssl_fd = -1;
1232 void openconnect_init_openssl(void)
1234 SSL_library_init ();
1236 SSL_load_error_strings ();
1237 OpenSSL_add_all_algorithms ();
1240 #if defined(__sun__) || defined(__NetBSD__) || defined(__DragonFly__)
1241 int openconnect_passphrase_from_fsid(struct openconnect_info *vpninfo)
1245 if (statvfs(vpninfo->sslkey, &buf)) {
1247 vpn_progress(vpninfo, PRG_ERR, _("statvfs: %s\n"),
1251 if (asprintf(&vpninfo->cert_password, "%lx", buf.f_fsid))
1256 int openconnect_passphrase_from_fsid(struct openconnect_info *vpninfo)
1259 unsigned *fsid = (unsigned *)&buf.f_fsid;
1260 unsigned long long fsid64;
1262 if (statfs(vpninfo->sslkey, &buf)) {
1264 vpn_progress(vpninfo, PRG_ERR, _("statfs: %s\n"),
1268 fsid64 = ((unsigned long long)fsid[0] << 32) | fsid[1];
1270 if (asprintf(&vpninfo->cert_password, "%llx", fsid64))