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)
142 ret = SSL_read(vpninfo->https_ssl, buf + i, 1);
144 if (buf[i] == '\n') {
146 if (i && buf[i-1] == '\r') {
159 fd_set rd_set, wr_set;
160 int maxfd = vpninfo->ssl_fd;
165 ret = SSL_get_error(vpninfo->https_ssl, ret);
166 if (ret == SSL_ERROR_WANT_READ)
167 FD_SET(vpninfo->ssl_fd, &rd_set);
168 else if (ret == SSL_ERROR_WANT_WRITE)
169 FD_SET(vpninfo->ssl_fd, &wr_set);
171 vpn_progress(vpninfo, PRG_ERR, _("Failed to read from SSL socket\n"));
172 report_ssl_errors(vpninfo);
176 if (vpninfo->cancel_fd != -1) {
177 FD_SET(vpninfo->cancel_fd, &rd_set);
178 if (vpninfo->cancel_fd > vpninfo->ssl_fd)
179 maxfd = vpninfo->cancel_fd;
181 select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
182 if (vpninfo->cancel_fd != -1 &&
183 FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
184 vpn_progress(vpninfo, PRG_ERR, _("SSL read cancelled\n"));
194 static int pem_pw_cb(char *buf, int len, int w, void *v)
196 struct openconnect_info *vpninfo = v;
198 /* Only try the provided password once... */
199 SSL_CTX_set_default_passwd_cb(vpninfo->https_ctx, NULL);
200 SSL_CTX_set_default_passwd_cb_userdata(vpninfo->https_ctx, NULL);
202 if (len <= strlen(vpninfo->cert_password)) {
203 vpn_progress(vpninfo, PRG_ERR,
204 _("PEM password too long (%zd >= %d)\n"),
205 strlen(vpninfo->cert_password), len);
208 strcpy(buf, vpninfo->cert_password);
209 return strlen(vpninfo->cert_password);
212 static int load_pkcs12_certificate(struct openconnect_info *vpninfo, PKCS12 *p12)
214 EVP_PKEY *pkey = NULL;
218 char pass[PEM_BUFSIZE];
221 /* We do this every time round the loop, to work around a bug in
222 OpenSSL < 1.0.0-beta2 -- where the stack at *ca will be freed
223 when PKCS12_parse() returns an error, but *ca is left pointing
224 to the freed memory. */
226 if (!vpninfo->cert_password) {
227 if (EVP_read_pw_string(pass, PEM_BUFSIZE,
228 "Enter PKCS#12 pass phrase:", 0))
231 if (!PKCS12_parse(p12, vpninfo->cert_password?:pass, &pkey, &cert, &ca)) {
232 unsigned long err = ERR_peek_error();
234 report_ssl_errors(vpninfo);
236 if (ERR_GET_LIB(err) == ERR_LIB_PKCS12 &&
237 ERR_GET_FUNC(err) == PKCS12_F_PKCS12_PARSE &&
238 ERR_GET_REASON(err) == PKCS12_R_MAC_VERIFY_FAILURE) {
239 vpn_progress(vpninfo, PRG_ERR,
240 _("Parse PKCS#12 failed (wrong passphrase?)\n"));
241 vpninfo->cert_password = NULL;
245 vpn_progress(vpninfo, PRG_ERR,
246 _("Parse PKCS#12 failed (see above errors)\n"));
251 vpninfo->cert_x509 = cert;
252 SSL_CTX_use_certificate(vpninfo->https_ctx, cert);
254 vpn_progress(vpninfo, PRG_ERR,
255 _("PKCS#12 contained no certificate!"));
260 SSL_CTX_use_PrivateKey(vpninfo->https_ctx, pkey);
263 vpn_progress(vpninfo, PRG_ERR,
264 _("PKCS#12 contained no private key!"));
268 /* Only include supporting certificates which are actually necessary */
272 for (i = 0; i < sk_X509_num(ca); i++) {
273 X509 *cert2 = sk_X509_value(ca, i);
274 if (X509_check_issued(cert2, cert) == X509_V_OK) {
280 X509_NAME_oneline(X509_get_subject_name(cert2),
282 vpn_progress(vpninfo, PRG_DEBUG,
283 _("Extra cert from PKCS#12: '%s'\n"), buf);
284 CRYPTO_add(&cert2->references, 1, CRYPTO_LOCK_X509);
285 SSL_CTX_add_extra_chain_cert(vpninfo->https_ctx, cert2);
290 sk_X509_pop_free(ca, X509_free);
298 static int load_tpm_certificate(struct openconnect_info *vpninfo)
302 ENGINE_load_builtin_engines();
304 e = ENGINE_by_id("tpm");
306 vpn_progress(vpninfo, PRG_ERR, _("Can't load TPM engine.\n"));
307 report_ssl_errors(vpninfo);
310 if (!ENGINE_init(e) || !ENGINE_set_default_RSA(e) ||
311 !ENGINE_set_default_RAND(e)) {
312 vpn_progress(vpninfo, PRG_ERR, _("Failed to init TPM engine\n"));
313 report_ssl_errors(vpninfo);
318 if (vpninfo->cert_password) {
319 if (!ENGINE_ctrl_cmd(e, "PIN", strlen(vpninfo->cert_password),
320 vpninfo->cert_password, NULL, 0)) {
321 vpn_progress(vpninfo, PRG_ERR,
322 _("Failed to set TPM SRK password\n"));
323 report_ssl_errors(vpninfo);
326 key = ENGINE_load_private_key(e, vpninfo->sslkey, NULL, NULL);
328 vpn_progress(vpninfo, PRG_ERR,
329 _("Failed to load TPM private key\n"));
330 report_ssl_errors(vpninfo);
335 if (!SSL_CTX_use_PrivateKey(vpninfo->https_ctx, key)) {
336 vpn_progress(vpninfo, PRG_ERR, _("Add key from TPM failed\n"));
337 report_ssl_errors(vpninfo);
345 static int load_tpm_certificate(struct openconnect_info *vpninfo)
347 vpn_progress(vpninfo, PRG_ERR,
348 _("This version of OpenConnect was built without TPM support\n"));
353 static int reload_pem_cert(struct openconnect_info *vpninfo)
355 BIO *b = BIO_new(BIO_s_file_internal());
360 if (BIO_read_filename(b, vpninfo->cert) <= 0) {
363 vpn_progress(vpninfo, PRG_ERR,
364 _("Failed to reload X509 cert for expiry check\n"));
365 report_ssl_errors(vpninfo);
368 vpninfo->cert_x509 = PEM_read_bio_X509_AUX(b, NULL, NULL, NULL);
369 if (!vpninfo->cert_x509)
375 static int load_certificate(struct openconnect_info *vpninfo)
377 vpn_progress(vpninfo, PRG_TRACE,
378 _("Using certificate file %s\n"), vpninfo->cert);
380 if (vpninfo->cert_type == CERT_TYPE_PKCS12 ||
381 vpninfo->cert_type == CERT_TYPE_UNKNOWN) {
385 f = fopen(vpninfo->cert, "r");
387 vpn_progress(vpninfo, PRG_ERR,
388 _("Failed to open certificate file %s: %s\n"),
389 vpninfo->cert, strerror(errno));
392 p12 = d2i_PKCS12_fp(f, NULL);
395 return load_pkcs12_certificate(vpninfo, p12);
398 if (vpninfo->cert_type == CERT_TYPE_PKCS12) {
399 vpn_progress(vpninfo, PRG_ERR, _("Read PKCS#12 failed\n"));
400 report_ssl_errors(vpninfo);
403 /* Clear error and fall through to see if it's a PEM file... */
407 /* It's PEM or TPM now, and either way we need to load the plain cert: */
408 if (!SSL_CTX_use_certificate_chain_file(vpninfo->https_ctx,
410 vpn_progress(vpninfo, PRG_ERR,
411 _("Loading certificate failed\n"));
412 report_ssl_errors(vpninfo);
416 /* Ew, we can't get it back from the OpenSSL CTX in any sane fashion */
417 reload_pem_cert(vpninfo);
419 if (vpninfo->cert_type == CERT_TYPE_UNKNOWN) {
420 FILE *f = fopen(vpninfo->sslkey, "r");
424 vpn_progress(vpninfo, PRG_ERR,
425 _("Failed to open private key file %s: %s\n"),
426 vpninfo->cert, strerror(errno));
431 while (fgets(buf, 255, f)) {
432 if (!strcmp(buf, "-----BEGIN TSS KEY BLOB-----\n")) {
433 vpninfo->cert_type = CERT_TYPE_TPM;
435 } else if (!strcmp(buf, "-----BEGIN RSA PRIVATE KEY-----\n") ||
436 !strcmp(buf, "-----BEGIN DSA PRIVATE KEY-----\n") ||
437 !strcmp(buf, "-----BEGIN ENCRYPTED PRIVATE KEY-----\n")) {
438 vpninfo->cert_type = CERT_TYPE_PEM;
443 if (vpninfo->cert_type == CERT_TYPE_UNKNOWN) {
444 vpn_progress(vpninfo, PRG_ERR,
445 _("Failed to identify private key type in '%s'\n"),
451 if (vpninfo->cert_type == CERT_TYPE_TPM)
452 return load_tpm_certificate(vpninfo);
454 /* Standard PEM certificate */
455 if (vpninfo->cert_password) {
456 SSL_CTX_set_default_passwd_cb(vpninfo->https_ctx,
458 SSL_CTX_set_default_passwd_cb_userdata(vpninfo->https_ctx,
462 if (!SSL_CTX_use_RSAPrivateKey_file(vpninfo->https_ctx, vpninfo->sslkey,
464 unsigned long err = ERR_peek_error();
466 report_ssl_errors(vpninfo);
468 #ifndef EVP_F_EVP_DECRYPTFINAL_EX
469 #define EVP_F_EVP_DECRYPTFINAL_EX EVP_F_EVP_DECRYPTFINAL
471 /* If the user fat-fingered the passphrase, try again */
472 if (ERR_GET_LIB(err) == ERR_LIB_EVP &&
473 ERR_GET_FUNC(err) == EVP_F_EVP_DECRYPTFINAL_EX &&
474 ERR_GET_REASON(err) == EVP_R_BAD_DECRYPT) {
475 vpn_progress(vpninfo, PRG_ERR,
476 _("Loading private key failed (wrong passphrase?)\n"));
480 vpn_progress(vpninfo, PRG_ERR,
481 _("Loading private key failed (see above errors)\n"));
487 static int get_cert_fingerprint(struct openconnect_info *vpninfo,
488 X509 *cert, const EVP_MD *type,
491 unsigned char md[EVP_MAX_MD_SIZE];
494 if (!X509_digest(cert, type, md, &n))
497 for (i=0; i < n; i++)
498 sprintf(&buf[i*2], "%02X", md[i]);
503 int get_cert_md5_fingerprint(struct openconnect_info *vpninfo,
504 X509 *cert, char *buf)
506 return get_cert_fingerprint(vpninfo, cert, EVP_md5(), buf);
509 int openconnect_get_cert_sha1(struct openconnect_info *vpninfo,
510 X509 *cert, char *buf)
512 return get_cert_fingerprint(vpninfo, cert, EVP_sha1(), buf);
515 static int check_server_cert(struct openconnect_info *vpninfo, X509 *cert)
517 char fingerprint[EVP_MAX_MD_SIZE * 2 + 1];
520 ret = openconnect_get_cert_sha1(vpninfo, cert, fingerprint);
524 if (strcasecmp(vpninfo->servercert, fingerprint)) {
525 vpn_progress(vpninfo, PRG_ERR,
526 _("Server SSL certificate didn't match: %s\n"), fingerprint);
532 static int match_hostname_elem(const char *hostname, int helem_len,
533 const char *match, int melem_len)
535 if (!helem_len && !melem_len)
538 if (!helem_len || !melem_len)
542 if (match[0] == '*') {
545 for (i = 1 ; i <= helem_len; i++) {
546 if (!match_hostname_elem(hostname + i, helem_len - i,
547 match + 1, melem_len - 1))
553 /* From the NetBSD (5.1) man page for ctype(3):
554 Values of type char or signed char must first be cast to unsigned char,
555 to ensure that the values are within the correct range. The result
556 should then be cast to int to avoid warnings from some compilers.
557 We do indeed get warning "array subscript has type 'char'" without
559 if (toupper((int)(unsigned char)hostname[0]) ==
560 toupper((int)(unsigned char)match[0]))
561 return match_hostname_elem(hostname + 1, helem_len - 1,
562 match + 1, melem_len - 1);
567 static int match_hostname(const char *hostname, const char *match)
570 const char *h_dot, *m_dot;
571 int helem_len, melem_len;
573 h_dot = strchr(hostname, '.');
574 m_dot = strchr(match, '.');
576 if (h_dot && m_dot) {
577 helem_len = h_dot - hostname + 1;
578 melem_len = m_dot - match + 1;
579 } else if (!h_dot && !m_dot) {
580 helem_len = strlen(hostname);
581 melem_len = strlen(match);
586 if (match_hostname_elem(hostname, helem_len,
590 hostname += helem_len;
599 /* cf. RFC2818 and RFC2459 */
600 static int match_cert_hostname(struct openconnect_info *vpninfo, X509 *peer_cert)
602 STACK_OF(GENERAL_NAME) *altnames;
604 ASN1_STRING *subjasn1;
605 char *subjstr = NULL;
608 char addrbuf[sizeof(struct in6_addr)];
611 /* Allow GEN_IP in the certificate only if we actually connected
612 by IP address rather than by name. */
613 if (inet_pton(AF_INET, vpninfo->hostname, addrbuf) > 0)
615 else if (inet_pton(AF_INET6, vpninfo->hostname, addrbuf) > 0)
617 else if (vpninfo->hostname[0] == '[' &&
618 vpninfo->hostname[strlen(vpninfo->hostname)-1] == ']') {
619 char *p = &vpninfo->hostname[strlen(vpninfo->hostname)-1];
621 if (inet_pton(AF_INET6, vpninfo->hostname + 1, addrbuf) > 0)
626 altnames = X509_get_ext_d2i(peer_cert, NID_subject_alt_name,
628 for (i = 0; i < sk_GENERAL_NAME_num(altnames); i++) {
629 const GENERAL_NAME *this = sk_GENERAL_NAME_value(altnames, i);
631 if (this->type == GEN_DNS) {
634 int len = ASN1_STRING_to_UTF8((void *)&str, this->d.ia5);
640 /* We don't like names with embedded NUL */
641 if (strlen(str) != len)
644 if (!match_hostname(vpninfo->hostname, str)) {
645 vpn_progress(vpninfo, PRG_TRACE,
646 _("Matched DNS altname '%s'\n"),
648 GENERAL_NAMES_free(altnames);
652 vpn_progress(vpninfo, PRG_TRACE,
653 _("No match for altname '%s'\n"),
657 } else if (this->type == GEN_IPADD && addrlen) {
661 if (this->d.ip->length == 4) {
663 } else if (this->d.ip->length == 16) {
666 vpn_progress(vpninfo, PRG_ERR,
667 _("Certificate has GEN_IPADD altname with bogus length %d\n"),
672 /* We only do this for the debug messages */
673 inet_ntop(family, this->d.ip->data, host, sizeof(host));
675 if (this->d.ip->length == addrlen &&
676 !memcmp(addrbuf, this->d.ip->data, addrlen)) {
677 vpn_progress(vpninfo, PRG_TRACE,
678 _("Matched %s address '%s'\n"),
679 (family == AF_INET6)?"IPv6":"IPv4",
681 GENERAL_NAMES_free(altnames);
684 vpn_progress(vpninfo, PRG_TRACE,
685 _("No match for %s address '%s'\n"),
686 (family == AF_INET6)?"IPv6":"IPv4",
689 } else if (this->type == GEN_URI) {
691 char *url_proto, *url_host, *url_path, *url_host2;
693 int len = ASN1_STRING_to_UTF8((void *)&str, this->d.ia5);
698 /* We don't like names with embedded NUL */
699 if (strlen(str) != len)
702 if (internal_parse_url(str, &url_proto, &url_host, &url_port, &url_path, 0)) {
707 if (!url_proto || strcasecmp(url_proto, "https"))
710 if (url_port != vpninfo->port)
713 /* Leave url_host as it was so that it can be freed */
714 url_host2 = url_host;
715 if (addrlen == 16 && vpninfo->hostname[0] != '[' &&
716 url_host[0] == '[' && url_host[strlen(url_host)-1] == ']') {
717 /* Cope with https://[IPv6]/ when the hostname is bare IPv6 */
718 url_host[strlen(url_host)-1] = 0;
722 if (strcasecmp(vpninfo->hostname, url_host2))
726 vpn_progress(vpninfo, PRG_TRACE,
727 _("URI '%s' has non-empty path; ignoring\n"),
729 goto no_uri_match_silent;
731 vpn_progress(vpninfo, PRG_TRACE,
732 _("Matched URI '%s'\n"),
738 GENERAL_NAMES_free(altnames);
742 vpn_progress(vpninfo, PRG_TRACE,
743 _("No match for URI '%s'\n"),
752 GENERAL_NAMES_free(altnames);
754 /* According to RFC2818, we don't use the legacy subject name if
755 there was an altname with DNS type. */
757 vpn_progress(vpninfo, PRG_ERR,
758 _("No altname in peer cert matched '%s'\n"),
763 subjname = X509_get_subject_name(peer_cert);
765 vpn_progress(vpninfo, PRG_ERR,
766 _("No subject name in peer cert!\n"));
770 /* Find the _last_ (most specific) commonName */
773 int j = X509_NAME_get_index_by_NID(subjname, NID_commonName, i);
780 subjasn1 = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subjname, i));
782 i = ASN1_STRING_to_UTF8((void *)&subjstr, subjasn1);
784 if (!subjstr || strlen(subjstr) != i) {
785 vpn_progress(vpninfo, PRG_ERR,
786 _("Failed to parse subject name in peer cert\n"));
791 if (match_hostname(vpninfo->hostname, subjstr)) {
792 vpn_progress(vpninfo, PRG_ERR,
793 _("Peer cert subject mismatch ('%s' != '%s')\n"),
794 subjstr, vpninfo->hostname);
797 vpn_progress(vpninfo, PRG_TRACE,
798 _("Matched peer certificate subject name '%s'\n"),
802 OPENSSL_free(subjstr);
806 static int verify_peer(struct openconnect_info *vpninfo, SSL *https_ssl)
811 peer_cert = SSL_get_peer_certificate(https_ssl);
813 if (vpninfo->servercert) {
814 /* If given a cert fingerprint on the command line, that's
816 ret = check_server_cert(vpninfo, peer_cert);
818 int vfy = SSL_get_verify_result(https_ssl);
819 const char *err_string = NULL;
821 if (vfy != X509_V_OK)
822 err_string = X509_verify_cert_error_string(vfy);
823 else if (match_cert_hostname(vpninfo, peer_cert))
824 err_string = _("certificate does not match hostname");
827 vpn_progress(vpninfo, PRG_INFO,
828 _("Server certificate verify failed: %s\n"),
831 if (vpninfo->validate_peer_cert)
832 ret = vpninfo->validate_peer_cert(vpninfo->cbdata,
841 X509_free(peer_cert);
846 static void workaround_openssl_certchain_bug(struct openconnect_info *vpninfo,
849 /* OpenSSL has problems with certificate chains -- if there are
850 multiple certs with the same name, it doesn't necessarily
851 choose the _right_ one. (RT#1942)
852 Pick the right ones for ourselves and add them manually. */
853 X509 *cert = SSL_get_certificate(ssl);
855 X509_STORE *store = SSL_CTX_get_cert_store(vpninfo->https_ctx);
861 /* If we already have 'supporting' certs, don't add them again */
862 if (vpninfo->https_ctx->extra_certs)
865 if (!X509_STORE_CTX_init(&ctx, store, NULL, NULL))
868 while (ctx.get_issuer(&cert2, &ctx, cert) == 1) {
873 X509_NAME_oneline(X509_get_subject_name(cert),
875 vpn_progress(vpninfo, PRG_DEBUG,
876 _("Extra cert from cafile: '%s'\n"), buf);
877 SSL_CTX_add_extra_chain_cert(vpninfo->https_ctx, cert);
879 X509_STORE_CTX_cleanup(&ctx);
882 #if OPENSSL_VERSION_NUMBER >= 0x00908000
883 static int ssl_app_verify_callback(X509_STORE_CTX *ctx, void *arg)
885 /* We've seen certificates in the wild which don't have the
886 purpose fields filled in correctly */
887 X509_VERIFY_PARAM_set_purpose(ctx->param, X509_PURPOSE_ANY);
888 return X509_verify_cert(ctx);
892 static int check_certificate_expiry(struct openconnect_info *vpninfo)
895 const char *reason = NULL;
899 if (!vpninfo->cert_x509)
903 notAfter = X509_get_notAfter(vpninfo->cert_x509);
904 i = X509_cmp_time(notAfter, &t);
906 vpn_progress(vpninfo, PRG_ERR,
907 _("Error in client cert notAfter field\n"));
910 reason = _("Client certificate has expired at");
912 t += vpninfo->cert_expire_warning;
913 i = X509_cmp_time(notAfter, &t);
915 reason = _("Client certificate expires soon at");
919 BIO *bp = BIO_new(BIO_s_mem());
921 const char *expiry = _("<error>");
925 ASN1_TIME_print(bp, notAfter);
926 BIO_write(bp, &zero, 1);
927 BIO_get_mem_ptr(bp, &bm);
930 vpn_progress(vpninfo, PRG_ERR, "%s: %s\n", reason, expiry);
937 static int cancellable_connect(struct openconnect_info *vpninfo, int sockfd,
938 const struct sockaddr *addr, socklen_t addrlen)
940 struct sockaddr_storage peer;
941 socklen_t peerlen = sizeof(peer);
942 fd_set wr_set, rd_set;
945 fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK);
947 if (connect(sockfd, addr, addrlen) < 0 && errno != EINPROGRESS)
952 FD_SET(sockfd, &wr_set);
953 if (vpninfo->cancel_fd != -1) {
954 FD_SET(vpninfo->cancel_fd, &rd_set);
955 if (vpninfo->cancel_fd > sockfd)
956 maxfd = vpninfo->cancel_fd;
959 /* Later we'll render this whole exercise non-pointless by
960 including a 'cancelfd' here too. */
961 select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
962 if (vpninfo->cancel_fd != -1 && FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
963 vpninfo->progress(vpninfo, PRG_ERR, _("Socket connect cancelled\n"));
968 /* Check whether connect() succeeded or failed by using
969 getpeername(). See http://cr.yp.to/docs/connect.html */
970 return getpeername(sockfd, (void *)&peer, &peerlen);
973 int openconnect_open_https(struct openconnect_info *vpninfo)
975 method_const SSL_METHOD *ssl3_method;
984 if (vpninfo->peer_addr) {
985 ssl_sock = socket(vpninfo->peer_addr->sa_family, SOCK_STREAM, IPPROTO_IP);
988 if (vpninfo->proxy) {
989 vpn_progress(vpninfo, PRG_ERR,
990 _("Failed to reconnect to proxy %s\n"),
993 vpn_progress(vpninfo, PRG_ERR,
994 _("Failed to reconnect to host %s\n"),
999 if (cancellable_connect(vpninfo, ssl_sock, vpninfo->peer_addr, vpninfo->peer_addrlen))
1003 struct addrinfo hints, *result, *rp;
1007 memset(&hints, 0, sizeof(struct addrinfo));
1008 hints.ai_family = AF_UNSPEC;
1009 hints.ai_socktype = SOCK_STREAM;
1010 hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV;
1011 hints.ai_protocol = 0;
1012 hints.ai_canonname = NULL;
1013 hints.ai_addr = NULL;
1014 hints.ai_next = NULL;
1016 /* The 'port' variable is a string because it's easier
1017 this way than if we pass NULL to getaddrinfo() and
1018 then try to fill in the numeric value into
1019 different types of returned sockaddr_in{6,}. */
1021 if (vpninfo->proxy_factory) {
1026 free(vpninfo->proxy_type);
1027 vpninfo->proxy_type = NULL;
1028 free(vpninfo->proxy);
1029 vpninfo->proxy = NULL;
1031 if (vpninfo->port == 443)
1032 i = asprintf(&url, "https://%s/%s", vpninfo->hostname,
1033 vpninfo->urlpath?:"");
1035 i = asprintf(&url, "https://%s:%d/%s", vpninfo->hostname,
1036 vpninfo->port, vpninfo->urlpath?:"");
1040 proxies = px_proxy_factory_get_proxies(vpninfo->proxy_factory,
1044 while (proxies && proxies[i]) {
1045 if (!vpninfo->proxy &&
1046 (!strncmp(proxies[i], "http://", 7) ||
1047 !strncmp(proxies[i], "socks://", 8) ||
1048 !strncmp(proxies[i], "socks5://", 9)))
1049 internal_parse_url(proxies[i], &vpninfo->proxy_type,
1050 &vpninfo->proxy, &vpninfo->proxy_port,
1057 vpn_progress(vpninfo, PRG_TRACE,
1058 _("Proxy from libproxy: %s://%s:%d/\n"),
1059 vpninfo->proxy_type, vpninfo->proxy, vpninfo->port);
1062 if (vpninfo->proxy) {
1063 hostname = vpninfo->proxy;
1064 snprintf(port, 6, "%d", vpninfo->proxy_port);
1066 hostname = vpninfo->hostname;
1067 snprintf(port, 6, "%d", vpninfo->port);
1070 if (hostname[0] == '[' && hostname[strlen(hostname)-1] == ']') {
1071 /* Solaris has no strndup(). */
1072 int len = strlen(hostname) - 2;
1073 char *new_hostname = malloc(len + 1);
1076 memcpy(new_hostname, hostname + 1, len);
1077 new_hostname[len] = 0;
1079 hostname = new_hostname;
1080 hints.ai_flags |= AI_NUMERICHOST;
1083 err = getaddrinfo(hostname, port, &hints, &result);
1084 if (hints.ai_flags & AI_NUMERICHOST)
1088 vpn_progress(vpninfo, PRG_ERR,
1089 _("getaddrinfo failed for host '%s': %s\n"),
1090 hostname, gai_strerror(err));
1094 for (rp = result; rp ; rp = rp->ai_next) {
1097 if (!getnameinfo(rp->ai_addr, rp->ai_addrlen, host,
1098 sizeof(host), NULL, 0, NI_NUMERICHOST))
1099 vpn_progress(vpninfo, PRG_INFO,
1100 _("Attempting to connect to %s%s%s:%s\n"),
1101 rp->ai_family == AF_INET6?"[":"",
1103 rp->ai_family == AF_INET6?"]":"",
1106 ssl_sock = socket(rp->ai_family, rp->ai_socktype,
1110 if (cancellable_connect(vpninfo, ssl_sock, rp->ai_addr, rp->ai_addrlen) >= 0) {
1111 /* Store the peer address we actually used, so that DTLS can
1112 use it again later */
1113 vpninfo->peer_addr = malloc(rp->ai_addrlen);
1114 if (!vpninfo->peer_addr) {
1115 vpn_progress(vpninfo, PRG_ERR,
1116 _("Failed to allocate sockaddr storage\n"));
1120 vpninfo->peer_addrlen = rp->ai_addrlen;
1121 memcpy(vpninfo->peer_addr, rp->ai_addr, rp->ai_addrlen);
1127 freeaddrinfo(result);
1130 vpn_progress(vpninfo, PRG_ERR,
1131 _("Failed to connect to host %s\n"),
1132 vpninfo->proxy?:vpninfo->hostname);
1136 fcntl(ssl_sock, F_SETFD, FD_CLOEXEC);
1138 if (vpninfo->proxy) {
1139 err = process_proxy(vpninfo, ssl_sock);
1146 ssl3_method = TLSv1_client_method();
1147 if (!vpninfo->https_ctx) {
1148 vpninfo->https_ctx = SSL_CTX_new(ssl3_method);
1150 /* Some servers (or their firewalls) really don't like seeing
1152 #ifdef SSL_OP_NO_TICKET
1153 SSL_CTX_set_options (vpninfo->https_ctx, SSL_OP_NO_TICKET);
1156 if (vpninfo->cert) {
1157 err = load_certificate(vpninfo);
1159 vpn_progress(vpninfo, PRG_ERR,
1160 _("Loading certificate failed. Aborting.\n"));
1163 check_certificate_expiry(vpninfo);
1166 /* We just want to do:
1167 SSL_CTX_set_purpose(vpninfo->https_ctx, X509_PURPOSE_ANY);
1168 ... but it doesn't work with OpenSSL < 0.9.8k because of
1169 problems with inheritance (fixed in v1.1.4.6 of
1170 crypto/x509/x509_vpm.c) so we have to play silly buggers
1171 instead. This trick doesn't work _either_ in < 0.9.7 but
1172 I don't know of _any_ workaround which will, and can't
1173 be bothered to find out either. */
1174 #if OPENSSL_VERSION_NUMBER >= 0x00908000
1175 SSL_CTX_set_cert_verify_callback(vpninfo->https_ctx,
1176 ssl_app_verify_callback, NULL);
1178 SSL_CTX_set_default_verify_paths(vpninfo->https_ctx);
1180 if (vpninfo->cafile) {
1181 if (!SSL_CTX_load_verify_locations(vpninfo->https_ctx, vpninfo->cafile, NULL)) {
1182 vpn_progress(vpninfo, PRG_ERR,
1183 _("Failed to open CA file '%s'\n"),
1185 report_ssl_errors(vpninfo);
1192 https_ssl = SSL_new(vpninfo->https_ctx);
1193 workaround_openssl_certchain_bug(vpninfo, https_ssl);
1195 https_bio = BIO_new_socket(ssl_sock, BIO_NOCLOSE);
1196 SSL_set_bio(https_ssl, https_bio, https_bio);
1198 vpn_progress(vpninfo, PRG_INFO, _("SSL negotiation with %s\n"),
1201 while ((err = SSL_connect(https_ssl)) <= 0) {
1202 fd_set wr_set, rd_set;
1203 int maxfd = ssl_sock;
1208 err = SSL_get_error(https_ssl, err);
1209 if (err == SSL_ERROR_WANT_READ)
1210 FD_SET(ssl_sock, &rd_set);
1211 else if (err == SSL_ERROR_WANT_WRITE)
1212 FD_SET(ssl_sock, &wr_set);
1214 vpn_progress(vpninfo, PRG_ERR, _("SSL connection failure\n"));
1215 report_ssl_errors(vpninfo);
1216 SSL_free(https_ssl);
1221 if (vpninfo->cancel_fd != -1) {
1222 FD_SET(vpninfo->cancel_fd, &rd_set);
1223 if (vpninfo->cancel_fd > ssl_sock)
1224 maxfd = vpninfo->cancel_fd;
1226 select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
1227 if (vpninfo->cancel_fd != -1 &&
1228 FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
1229 vpn_progress(vpninfo, PRG_ERR, _("SSL connection cancelled\n"));
1230 SSL_free(https_ssl);
1236 if (verify_peer(vpninfo, https_ssl)) {
1237 SSL_free(https_ssl);
1242 vpninfo->ssl_fd = ssl_sock;
1243 vpninfo->https_ssl = https_ssl;
1245 vpn_progress(vpninfo, PRG_INFO, _("Connected to HTTPS on %s\n"),
1251 void openconnect_close_https(struct openconnect_info *vpninfo)
1253 SSL_free(vpninfo->https_ssl);
1254 vpninfo->https_ssl = NULL;
1255 close(vpninfo->ssl_fd);
1256 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_rfds);
1257 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_wfds);
1258 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_efds);
1259 vpninfo->ssl_fd = -1;
1262 void openconnect_init_openssl(void)
1264 SSL_library_init ();
1266 SSL_load_error_strings ();
1267 OpenSSL_add_all_algorithms ();
1270 #if defined(__sun__) || defined(__NetBSD__) || defined(__DragonFly__)
1271 int openconnect_passphrase_from_fsid(struct openconnect_info *vpninfo)
1275 if (statvfs(vpninfo->sslkey, &buf)) {
1277 vpn_progress(vpninfo, PRG_ERR, _("statvfs: %s\n"),
1281 if (asprintf(&vpninfo->cert_password, "%lx", buf.f_fsid))
1286 int openconnect_passphrase_from_fsid(struct openconnect_info *vpninfo)
1289 unsigned *fsid = (unsigned *)&buf.f_fsid;
1290 unsigned long long fsid64;
1292 if (statfs(vpninfo->sslkey, &buf)) {
1294 vpn_progress(vpninfo, PRG_ERR, _("statfs: %s\n"),
1298 fsid64 = ((unsigned long long)fsid[0] << 32) | fsid[1];
1300 if (asprintf(&vpninfo->cert_password, "%llx", fsid64))