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
26 #include <sys/types.h>
27 #include <netinet/in.h>
28 #include <arpa/inet.h>
31 #include <openssl/ssl.h>
32 #include <openssl/err.h>
33 #include <openssl/engine.h>
34 #include <openssl/evp.h>
35 #include <openssl/rand.h>
36 #include <openssl/pkcs12.h>
37 #include <openssl/x509v3.h>
38 #include <openssl/x509.h>
39 #include <openssl/bio.h>
41 #include "openconnect-internal.h"
43 int openconnect_sha1(unsigned char *result, void *data, int len)
48 EVP_Digest(data, len, result, NULL, EVP_sha1(), NULL);
49 EVP_MD_CTX_cleanup(&c);
54 int openconnect_get_cert_DER(struct openconnect_info *vpninfo,
55 OPENCONNECT_X509 *cert, unsigned char **buf)
57 BIO *bp = BIO_new(BIO_s_mem());
61 if (!i2d_X509_bio(bp, cert)) {
66 BIO_get_mem_ptr(bp, &certinfo);
73 memcpy(*buf, certinfo->data, l);
78 int openconnect_random(void *bytes, int len)
80 if (RAND_bytes(bytes, len) != 1)
85 /* Helper functions for reading/writing lines over SSL.
86 We could use cURL for the HTTP stuff, but it's overkill */
88 int openconnect_SSL_write(struct openconnect_info *vpninfo, char *buf, size_t len)
90 size_t orig_len = len;
93 int done = SSL_write(vpninfo->https_ssl, buf, len);
98 int err = SSL_get_error(vpninfo->https_ssl, done);
99 fd_set wr_set, rd_set;
100 int maxfd = vpninfo->ssl_fd;
105 if (err == SSL_ERROR_WANT_READ)
106 FD_SET(vpninfo->ssl_fd, &rd_set);
107 else if (err == SSL_ERROR_WANT_WRITE)
108 FD_SET(vpninfo->ssl_fd, &wr_set);
110 vpn_progress(vpninfo, PRG_ERR, _("Failed to write to SSL socket"));
111 openconnect_report_ssl_errors(vpninfo);
114 if (vpninfo->cancel_fd != -1) {
115 FD_SET(vpninfo->cancel_fd, &rd_set);
116 if (vpninfo->cancel_fd > vpninfo->ssl_fd)
117 maxfd = vpninfo->cancel_fd;
119 select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
120 if (vpninfo->cancel_fd != -1 &&
121 FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
122 vpn_progress(vpninfo, PRG_ERR, _("SSL write cancelled\n"));
130 int openconnect_SSL_read(struct openconnect_info *vpninfo, char *buf, size_t len)
134 while ((done = SSL_read(vpninfo->https_ssl, buf, len)) == -1) {
135 int err = SSL_get_error(vpninfo->https_ssl, done);
136 fd_set wr_set, rd_set;
137 int maxfd = vpninfo->ssl_fd;
142 if (err == SSL_ERROR_WANT_READ)
143 FD_SET(vpninfo->ssl_fd, &rd_set);
144 else if (err == SSL_ERROR_WANT_WRITE)
145 FD_SET(vpninfo->ssl_fd, &wr_set);
147 vpn_progress(vpninfo, PRG_ERR, _("Failed to read from SSL socket"));
148 openconnect_report_ssl_errors(vpninfo);
151 if (vpninfo->cancel_fd != -1) {
152 FD_SET(vpninfo->cancel_fd, &rd_set);
153 if (vpninfo->cancel_fd > vpninfo->ssl_fd)
154 maxfd = vpninfo->cancel_fd;
156 select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
157 if (vpninfo->cancel_fd != -1 &&
158 FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
159 vpn_progress(vpninfo, PRG_ERR, _("SSL read cancelled\n"));
166 static int print_err(const char *str, size_t len, void *ptr)
168 struct openconnect_info *vpninfo = ptr;
170 vpn_progress(vpninfo, PRG_ERR, "%s", str);
174 void openconnect_report_ssl_errors(struct openconnect_info *vpninfo)
176 ERR_print_errors_cb(print_err, vpninfo);
179 int openconnect_SSL_gets(struct openconnect_info *vpninfo, char *buf, size_t len)
188 ret = SSL_read(vpninfo->https_ssl, buf + i, 1);
190 if (buf[i] == '\n') {
192 if (i && buf[i-1] == '\r') {
205 fd_set rd_set, wr_set;
206 int maxfd = vpninfo->ssl_fd;
211 ret = SSL_get_error(vpninfo->https_ssl, ret);
212 if (ret == SSL_ERROR_WANT_READ)
213 FD_SET(vpninfo->ssl_fd, &rd_set);
214 else if (ret == SSL_ERROR_WANT_WRITE)
215 FD_SET(vpninfo->ssl_fd, &wr_set);
217 vpn_progress(vpninfo, PRG_ERR, _("Failed to read from SSL socket\n"));
218 openconnect_report_ssl_errors(vpninfo);
222 if (vpninfo->cancel_fd != -1) {
223 FD_SET(vpninfo->cancel_fd, &rd_set);
224 if (vpninfo->cancel_fd > vpninfo->ssl_fd)
225 maxfd = vpninfo->cancel_fd;
227 select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
228 if (vpninfo->cancel_fd != -1 &&
229 FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
230 vpn_progress(vpninfo, PRG_ERR, _("SSL read cancelled\n"));
241 /* UI handling. All this just to handle the PIN callback from the TPM ENGINE,
242 and turn it into a call to our ->process_auth_form function */
245 struct openconnect_info *vpninfo;
246 struct oc_form_opt **last_opt;
247 struct oc_auth_form form;
251 struct oc_form_opt opt;
255 /* Ick. But there is no way to pass this sanely through OpenSSL */
256 static struct openconnect_info *ui_vpninfo;
258 static int ui_open(UI *ui)
260 struct openconnect_info *vpninfo = ui_vpninfo; /* Ick */
261 struct ui_data *ui_data;
263 if (!vpninfo || !vpninfo->process_auth_form)
266 ui_data = malloc(sizeof(*ui_data));
270 memset(ui_data, 0, sizeof(*ui_data));
271 ui_data->last_opt = &ui_data->form.opts;
272 ui_data->vpninfo = vpninfo;
273 UI_add_user_data(ui, ui_data);
278 static int ui_write(UI *ui, UI_STRING *uis)
280 struct ui_data *ui_data = UI_get0_user_data(ui);
281 struct ui_form_opt *opt;
283 switch(UI_get_string_type(uis)) {
285 ui_data->form.error = (char *)UI_get0_output_string(uis);
288 ui_data->form.message = (char *)UI_get0_output_string(uis);
291 opt = malloc(sizeof(*opt));
294 memset(opt, 0, sizeof(*opt));
296 opt->opt.label = opt->opt.name = (char *)UI_get0_output_string(uis);
297 if (UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO)
298 opt->opt.type = OC_FORM_OPT_TEXT;
300 opt->opt.type = OC_FORM_OPT_PASSWORD;
301 *(ui_data->last_opt) = &opt->opt;
302 ui_data->last_opt = &opt->opt.next;
306 fprintf(stderr, "Unhandled SSL UI request type %d\n",
307 UI_get_string_type(uis));
313 static int ui_flush(UI *ui)
315 struct ui_data *ui_data = UI_get0_user_data(ui);
316 struct openconnect_info *vpninfo = ui_data->vpninfo;
317 struct ui_form_opt *opt;
320 ret = vpninfo->process_auth_form(vpninfo->cbdata, &ui_data->form);
324 for (opt = (struct ui_form_opt *)ui_data->form.opts; opt;
325 opt = (struct ui_form_opt *)opt->opt.next) {
326 if (opt->opt.value && opt->uis)
327 UI_set_result(ui, opt->uis, opt->opt.value);
332 static int ui_close(UI *ui)
334 struct ui_data *ui_data = UI_get0_user_data(ui);
335 struct ui_form_opt *opt, *next_opt;
337 opt = (struct ui_form_opt *)ui_data->form.opts;
339 next_opt = (struct ui_form_opt *)opt->opt.next;
341 free(opt->opt.value);
346 UI_add_user_data(ui, NULL);
351 static UI_METHOD *create_openssl_ui(struct openconnect_info *vpninfo)
353 UI_METHOD *ui_method = UI_create_method((char *)"AnyConnect VPN UI");
355 /* There is a race condition here because of the use of the
356 static ui_vpninfo pointer. This sucks, but it's OpenSSL's
357 fault and in practice it's *never* going to hurt us.
359 This UI is only used for loading certificates from a TPM; for
360 PKCS#12 and PEM files we hook the passphrase request differently.
361 The ui_vpninfo variable is set here, and is used from ui_open()
362 when the TPM ENGINE decides it needs to ask the user for a PIN.
364 The race condition exists because theoretically, there
365 could be more than one thread using libopenconnect and
366 trying to authenticate to a VPN server, within the *same*
367 process. And if *both* are using certificates from the TPM,
368 and *both* manage to be within that short window of time
369 between setting ui_vpninfo and invoking ui_open() to fetch
370 the PIN, then one connection's ->process_auth_form() could
371 get a PIN request for the *other* connection.
373 However, the only thing that ever does run libopenconnect more
374 than once from the same process is KDE's NetworkManager support,
375 and NetworkManager doesn't *support* having more than one VPN
376 connected anyway, so first that would have to be fixed and then
377 you'd have to connect to two VPNs simultaneously by clicking
378 'connect' on both at *exactly* the same time and then getting
381 Oh, and the KDE support won't be using OpenSSL anyway because of
382 licensing conflicts... so although this sucks, I'm not going to
385 ui_vpninfo = vpninfo;
387 /* Set up a UI method of our own for password/passphrase requests */
388 UI_method_set_opener(ui_method, ui_open);
389 UI_method_set_writer(ui_method, ui_write);
390 UI_method_set_flusher(ui_method, ui_flush);
391 UI_method_set_closer(ui_method, ui_close);
396 static int pem_pw_cb(char *buf, int len, int w, void *v)
398 struct openconnect_info *vpninfo = v;
402 if (vpninfo->cert_password) {
403 pass = vpninfo->cert_password;
404 vpninfo->cert_password = NULL;
405 } else if (request_passphrase(vpninfo, &pass,
406 _("Enter PEM pass phrase:")))
412 vpn_progress(vpninfo, PRG_ERR,
413 _("PEM password too long (%d >= %d)\n"),
419 memcpy(buf, pass, plen+1);
424 static int load_pkcs12_certificate(struct openconnect_info *vpninfo, PKCS12 *p12)
426 EVP_PKEY *pkey = NULL;
432 pass = vpninfo->cert_password;
433 vpninfo->cert_password = NULL;
435 /* We do this every time round the loop, to work around a bug in
436 OpenSSL < 1.0.0-beta2 -- where the stack at *ca will be freed
437 when PKCS12_parse() returns an error, but *ca is left pointing
438 to the freed memory. */
440 if (!pass && request_passphrase(vpninfo, &pass,
441 _("Enter PKCS#12 pass phrase:")) < 0) {
445 if (!PKCS12_parse(p12, pass, &pkey, &cert, &ca)) {
446 unsigned long err = ERR_peek_error();
448 openconnect_report_ssl_errors(vpninfo);
450 if (ERR_GET_LIB(err) == ERR_LIB_PKCS12 &&
451 ERR_GET_FUNC(err) == PKCS12_F_PKCS12_PARSE &&
452 ERR_GET_REASON(err) == PKCS12_R_MAC_VERIFY_FAILURE) {
453 vpn_progress(vpninfo, PRG_ERR,
454 _("Parse PKCS#12 failed (wrong passphrase?)\n"));
460 vpn_progress(vpninfo, PRG_ERR,
461 _("Parse PKCS#12 failed (see above errors)\n"));
466 vpninfo->cert_x509 = cert;
467 SSL_CTX_use_certificate(vpninfo->https_ctx, cert);
469 vpn_progress(vpninfo, PRG_ERR,
470 _("PKCS#12 contained no certificate!"));
475 SSL_CTX_use_PrivateKey(vpninfo->https_ctx, pkey);
478 vpn_progress(vpninfo, PRG_ERR,
479 _("PKCS#12 contained no private key!"));
483 /* Only include supporting certificates which are actually necessary */
487 for (i = 0; i < sk_X509_num(ca); i++) {
488 X509 *cert2 = sk_X509_value(ca, i);
489 if (X509_check_issued(cert2, cert) == X509_V_OK) {
494 if (X509_check_issued(cert2, cert2) == X509_V_OK)
497 X509_NAME_oneline(X509_get_subject_name(cert2),
499 vpn_progress(vpninfo, PRG_DEBUG,
500 _("Extra cert from PKCS#12: '%s'\n"), buf);
501 CRYPTO_add(&cert2->references, 1, CRYPTO_LOCK_X509);
502 SSL_CTX_add_extra_chain_cert(vpninfo->https_ctx, cert2);
507 sk_X509_pop_free(ca, X509_free);
515 static int load_tpm_certificate(struct openconnect_info *vpninfo)
519 UI_METHOD *meth = NULL;
520 ENGINE_load_builtin_engines();
522 e = ENGINE_by_id("tpm");
524 vpn_progress(vpninfo, PRG_ERR, _("Can't load TPM engine.\n"));
525 openconnect_report_ssl_errors(vpninfo);
528 if (!ENGINE_init(e) || !ENGINE_set_default_RSA(e) ||
529 !ENGINE_set_default_RAND(e)) {
530 vpn_progress(vpninfo, PRG_ERR, _("Failed to init TPM engine\n"));
531 openconnect_report_ssl_errors(vpninfo);
536 if (vpninfo->cert_password) {
537 if (!ENGINE_ctrl_cmd(e, "PIN", strlen(vpninfo->cert_password),
538 vpninfo->cert_password, NULL, 0)) {
539 vpn_progress(vpninfo, PRG_ERR,
540 _("Failed to set TPM SRK password\n"));
541 openconnect_report_ssl_errors(vpninfo);
544 /* Provide our own UI method to handle the PIN callback. */
545 meth = create_openssl_ui(vpninfo);
547 key = ENGINE_load_private_key(e, vpninfo->sslkey, meth, NULL);
549 UI_destroy_method(meth);
551 vpn_progress(vpninfo, PRG_ERR,
552 _("Failed to load TPM private key\n"));
553 openconnect_report_ssl_errors(vpninfo);
558 if (!SSL_CTX_use_PrivateKey(vpninfo->https_ctx, key)) {
559 vpn_progress(vpninfo, PRG_ERR, _("Add key from TPM failed\n"));
560 openconnect_report_ssl_errors(vpninfo);
568 static int load_tpm_certificate(struct openconnect_info *vpninfo)
570 vpn_progress(vpninfo, PRG_ERR,
571 _("This version of OpenConnect was built without TPM support\n"));
576 static int reload_pem_cert(struct openconnect_info *vpninfo)
578 BIO *b = BIO_new(BIO_s_file_internal());
583 if (BIO_read_filename(b, vpninfo->cert) <= 0) {
586 vpn_progress(vpninfo, PRG_ERR,
587 _("Failed to reload X509 cert for expiry check\n"));
588 openconnect_report_ssl_errors(vpninfo);
591 vpninfo->cert_x509 = PEM_read_bio_X509_AUX(b, NULL, NULL, NULL);
592 if (!vpninfo->cert_x509)
598 static int load_certificate(struct openconnect_info *vpninfo)
600 vpn_progress(vpninfo, PRG_TRACE,
601 _("Using certificate file %s\n"), vpninfo->cert);
603 if (vpninfo->cert_type == CERT_TYPE_PKCS12 ||
604 vpninfo->cert_type == CERT_TYPE_UNKNOWN) {
608 f = fopen(vpninfo->cert, "r");
610 vpn_progress(vpninfo, PRG_ERR,
611 _("Failed to open certificate file %s: %s\n"),
612 vpninfo->cert, strerror(errno));
615 p12 = d2i_PKCS12_fp(f, NULL);
618 return load_pkcs12_certificate(vpninfo, p12);
621 if (vpninfo->cert_type == CERT_TYPE_PKCS12) {
622 vpn_progress(vpninfo, PRG_ERR, _("Read PKCS#12 failed\n"));
623 openconnect_report_ssl_errors(vpninfo);
626 /* Clear error and fall through to see if it's a PEM file... */
630 /* It's PEM or TPM now, and either way we need to load the plain cert: */
631 if (!SSL_CTX_use_certificate_chain_file(vpninfo->https_ctx,
633 vpn_progress(vpninfo, PRG_ERR,
634 _("Loading certificate failed\n"));
635 openconnect_report_ssl_errors(vpninfo);
639 /* Ew, we can't get it back from the OpenSSL CTX in any sane fashion */
640 reload_pem_cert(vpninfo);
642 if (vpninfo->cert_type == CERT_TYPE_UNKNOWN) {
643 FILE *f = fopen(vpninfo->sslkey, "r");
647 vpn_progress(vpninfo, PRG_ERR,
648 _("Failed to open private key file %s: %s\n"),
649 vpninfo->cert, strerror(errno));
654 while (fgets(buf, 255, f)) {
655 if (!strcmp(buf, "-----BEGIN TSS KEY BLOB-----\n")) {
656 vpninfo->cert_type = CERT_TYPE_TPM;
658 } else if (!strcmp(buf, "-----BEGIN RSA PRIVATE KEY-----\n") ||
659 !strcmp(buf, "-----BEGIN DSA PRIVATE KEY-----\n") ||
660 !strcmp(buf, "-----BEGIN ENCRYPTED PRIVATE KEY-----\n")) {
661 vpninfo->cert_type = CERT_TYPE_PEM;
666 if (vpninfo->cert_type == CERT_TYPE_UNKNOWN) {
667 vpn_progress(vpninfo, PRG_ERR,
668 _("Failed to identify private key type in '%s'\n"),
674 if (vpninfo->cert_type == CERT_TYPE_TPM)
675 return load_tpm_certificate(vpninfo);
677 /* Standard PEM certificate */
678 SSL_CTX_set_default_passwd_cb(vpninfo->https_ctx, pem_pw_cb);
679 SSL_CTX_set_default_passwd_cb_userdata(vpninfo->https_ctx, vpninfo);
681 if (!SSL_CTX_use_RSAPrivateKey_file(vpninfo->https_ctx, vpninfo->sslkey,
683 unsigned long err = ERR_peek_error();
685 openconnect_report_ssl_errors(vpninfo);
687 #ifndef EVP_F_EVP_DECRYPTFINAL_EX
688 #define EVP_F_EVP_DECRYPTFINAL_EX EVP_F_EVP_DECRYPTFINAL
690 /* If the user fat-fingered the passphrase, try again */
691 if (ERR_GET_LIB(err) == ERR_LIB_EVP &&
692 ERR_GET_FUNC(err) == EVP_F_EVP_DECRYPTFINAL_EX &&
693 ERR_GET_REASON(err) == EVP_R_BAD_DECRYPT) {
694 vpn_progress(vpninfo, PRG_ERR,
695 _("Loading private key failed (wrong passphrase?)\n"));
699 vpn_progress(vpninfo, PRG_ERR,
700 _("Loading private key failed (see above errors)\n"));
706 static int get_cert_fingerprint(struct openconnect_info *vpninfo,
707 OPENCONNECT_X509 *cert, const EVP_MD *type,
710 unsigned char md[EVP_MAX_MD_SIZE];
713 if (!X509_digest(cert, type, md, &n))
716 for (i=0; i < n; i++)
717 sprintf(&buf[i*2], "%02X", md[i]);
722 int get_cert_md5_fingerprint(struct openconnect_info *vpninfo,
723 OPENCONNECT_X509 *cert, char *buf)
725 return get_cert_fingerprint(vpninfo, cert, EVP_md5(), buf);
728 int openconnect_get_cert_sha1(struct openconnect_info *vpninfo,
729 OPENCONNECT_X509 *cert, char *buf)
731 return get_cert_fingerprint(vpninfo, cert, EVP_sha1(), buf);
734 static int check_server_cert(struct openconnect_info *vpninfo, X509 *cert)
736 char fingerprint[EVP_MAX_MD_SIZE * 2 + 1];
739 ret = openconnect_get_cert_sha1(vpninfo, cert, fingerprint);
743 if (strcasecmp(vpninfo->servercert, fingerprint)) {
744 vpn_progress(vpninfo, PRG_ERR,
745 _("Server SSL certificate didn't match: %s\n"), fingerprint);
751 static int match_hostname_elem(const char *hostname, int helem_len,
752 const char *match, int melem_len)
754 if (!helem_len && !melem_len)
757 if (!helem_len || !melem_len)
761 if (match[0] == '*') {
764 for (i = 1 ; i <= helem_len; i++) {
765 if (!match_hostname_elem(hostname + i, helem_len - i,
766 match + 1, melem_len - 1))
772 /* From the NetBSD (5.1) man page for ctype(3):
773 Values of type char or signed char must first be cast to unsigned char,
774 to ensure that the values are within the correct range. The result
775 should then be cast to int to avoid warnings from some compilers.
776 We do indeed get warning "array subscript has type 'char'" without
778 if (toupper((int)(unsigned char)hostname[0]) ==
779 toupper((int)(unsigned char)match[0]))
780 return match_hostname_elem(hostname + 1, helem_len - 1,
781 match + 1, melem_len - 1);
786 static int match_hostname(const char *hostname, const char *match)
789 const char *h_dot, *m_dot;
790 int helem_len, melem_len;
792 h_dot = strchr(hostname, '.');
793 m_dot = strchr(match, '.');
795 if (h_dot && m_dot) {
796 helem_len = h_dot - hostname + 1;
797 melem_len = m_dot - match + 1;
798 } else if (!h_dot && !m_dot) {
799 helem_len = strlen(hostname);
800 melem_len = strlen(match);
805 if (match_hostname_elem(hostname, helem_len,
809 hostname += helem_len;
818 /* cf. RFC2818 and RFC2459 */
819 static int match_cert_hostname(struct openconnect_info *vpninfo, X509 *peer_cert)
821 STACK_OF(GENERAL_NAME) *altnames;
823 ASN1_STRING *subjasn1;
824 char *subjstr = NULL;
827 char addrbuf[sizeof(struct in6_addr)];
830 /* Allow GEN_IP in the certificate only if we actually connected
831 by IP address rather than by name. */
832 if (inet_pton(AF_INET, vpninfo->hostname, addrbuf) > 0)
834 else if (inet_pton(AF_INET6, vpninfo->hostname, addrbuf) > 0)
836 else if (vpninfo->hostname[0] == '[' &&
837 vpninfo->hostname[strlen(vpninfo->hostname)-1] == ']') {
838 char *p = &vpninfo->hostname[strlen(vpninfo->hostname)-1];
840 if (inet_pton(AF_INET6, vpninfo->hostname + 1, addrbuf) > 0)
845 altnames = X509_get_ext_d2i(peer_cert, NID_subject_alt_name,
847 for (i = 0; i < sk_GENERAL_NAME_num(altnames); i++) {
848 const GENERAL_NAME *this = sk_GENERAL_NAME_value(altnames, i);
850 if (this->type == GEN_DNS) {
853 int len = ASN1_STRING_to_UTF8((void *)&str, this->d.ia5);
859 /* We don't like names with embedded NUL */
860 if (strlen(str) != len)
863 if (!match_hostname(vpninfo->hostname, str)) {
864 vpn_progress(vpninfo, PRG_TRACE,
865 _("Matched DNS altname '%s'\n"),
867 GENERAL_NAMES_free(altnames);
871 vpn_progress(vpninfo, PRG_TRACE,
872 _("No match for altname '%s'\n"),
876 } else if (this->type == GEN_IPADD && addrlen) {
880 if (this->d.ip->length == 4) {
882 } else if (this->d.ip->length == 16) {
885 vpn_progress(vpninfo, PRG_ERR,
886 _("Certificate has GEN_IPADD altname with bogus length %d\n"),
891 /* We only do this for the debug messages */
892 inet_ntop(family, this->d.ip->data, host, sizeof(host));
894 if (this->d.ip->length == addrlen &&
895 !memcmp(addrbuf, this->d.ip->data, addrlen)) {
896 vpn_progress(vpninfo, PRG_TRACE,
897 _("Matched %s address '%s'\n"),
898 (family == AF_INET6)?"IPv6":"IPv4",
900 GENERAL_NAMES_free(altnames);
903 vpn_progress(vpninfo, PRG_TRACE,
904 _("No match for %s address '%s'\n"),
905 (family == AF_INET6)?"IPv6":"IPv4",
908 } else if (this->type == GEN_URI) {
910 char *url_proto, *url_host, *url_path, *url_host2;
912 int len = ASN1_STRING_to_UTF8((void *)&str, this->d.ia5);
917 /* We don't like names with embedded NUL */
918 if (strlen(str) != len)
921 if (internal_parse_url(str, &url_proto, &url_host, &url_port, &url_path, 0)) {
926 if (!url_proto || strcasecmp(url_proto, "https"))
929 if (url_port != vpninfo->port)
932 /* Leave url_host as it was so that it can be freed */
933 url_host2 = url_host;
934 if (addrlen == 16 && vpninfo->hostname[0] != '[' &&
935 url_host[0] == '[' && url_host[strlen(url_host)-1] == ']') {
936 /* Cope with https://[IPv6]/ when the hostname is bare IPv6 */
937 url_host[strlen(url_host)-1] = 0;
941 if (strcasecmp(vpninfo->hostname, url_host2))
945 vpn_progress(vpninfo, PRG_TRACE,
946 _("URI '%s' has non-empty path; ignoring\n"),
948 goto no_uri_match_silent;
950 vpn_progress(vpninfo, PRG_TRACE,
951 _("Matched URI '%s'\n"),
957 GENERAL_NAMES_free(altnames);
961 vpn_progress(vpninfo, PRG_TRACE,
962 _("No match for URI '%s'\n"),
971 GENERAL_NAMES_free(altnames);
973 /* According to RFC2818, we don't use the legacy subject name if
974 there was an altname with DNS type. */
976 vpn_progress(vpninfo, PRG_ERR,
977 _("No altname in peer cert matched '%s'\n"),
982 subjname = X509_get_subject_name(peer_cert);
984 vpn_progress(vpninfo, PRG_ERR,
985 _("No subject name in peer cert!\n"));
989 /* Find the _last_ (most specific) commonName */
992 int j = X509_NAME_get_index_by_NID(subjname, NID_commonName, i);
999 subjasn1 = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subjname, i));
1001 i = ASN1_STRING_to_UTF8((void *)&subjstr, subjasn1);
1003 if (!subjstr || strlen(subjstr) != i) {
1004 vpn_progress(vpninfo, PRG_ERR,
1005 _("Failed to parse subject name in peer cert\n"));
1010 if (match_hostname(vpninfo->hostname, subjstr)) {
1011 vpn_progress(vpninfo, PRG_ERR,
1012 _("Peer cert subject mismatch ('%s' != '%s')\n"),
1013 subjstr, vpninfo->hostname);
1016 vpn_progress(vpninfo, PRG_TRACE,
1017 _("Matched peer certificate subject name '%s'\n"),
1021 OPENSSL_free(subjstr);
1025 static int verify_peer(struct openconnect_info *vpninfo, SSL *https_ssl)
1030 peer_cert = SSL_get_peer_certificate(https_ssl);
1032 if (vpninfo->servercert) {
1033 /* If given a cert fingerprint on the command line, that's
1035 ret = check_server_cert(vpninfo, peer_cert);
1037 int vfy = SSL_get_verify_result(https_ssl);
1038 const char *err_string = NULL;
1040 if (vfy != X509_V_OK)
1041 err_string = X509_verify_cert_error_string(vfy);
1042 else if (match_cert_hostname(vpninfo, peer_cert))
1043 err_string = _("certificate does not match hostname");
1046 vpn_progress(vpninfo, PRG_INFO,
1047 _("Server certificate verify failed: %s\n"),
1050 if (vpninfo->validate_peer_cert)
1051 ret = vpninfo->validate_peer_cert(vpninfo->cbdata,
1060 X509_free(peer_cert);
1065 static void workaround_openssl_certchain_bug(struct openconnect_info *vpninfo,
1068 /* OpenSSL has problems with certificate chains -- if there are
1069 multiple certs with the same name, it doesn't necessarily
1070 choose the _right_ one. (RT#1942)
1071 Pick the right ones for ourselves and add them manually. */
1072 X509 *cert = SSL_get_certificate(ssl);
1074 X509_STORE *store = SSL_CTX_get_cert_store(vpninfo->https_ctx);
1077 if (!cert || !store)
1080 /* If we already have 'supporting' certs, don't add them again */
1081 if (vpninfo->https_ctx->extra_certs)
1084 if (!X509_STORE_CTX_init(&ctx, store, NULL, NULL))
1087 while (ctx.get_issuer(&cert2, &ctx, cert) == 1) {
1091 if (X509_check_issued(cert2, cert2) == X509_V_OK)
1094 X509_NAME_oneline(X509_get_subject_name(cert),
1096 vpn_progress(vpninfo, PRG_DEBUG,
1097 _("Extra cert from cafile: '%s'\n"), buf);
1098 SSL_CTX_add_extra_chain_cert(vpninfo->https_ctx, cert);
1100 X509_STORE_CTX_cleanup(&ctx);
1103 #if OPENSSL_VERSION_NUMBER >= 0x00908000
1104 static int ssl_app_verify_callback(X509_STORE_CTX *ctx, void *arg)
1106 /* We've seen certificates in the wild which don't have the
1107 purpose fields filled in correctly */
1108 X509_VERIFY_PARAM_set_purpose(ctx->param, X509_PURPOSE_ANY);
1109 return X509_verify_cert(ctx);
1113 static int check_certificate_expiry(struct openconnect_info *vpninfo)
1115 ASN1_TIME *notAfter;
1116 const char *reason = NULL;
1120 if (!vpninfo->cert_x509)
1124 notAfter = X509_get_notAfter(vpninfo->cert_x509);
1125 i = X509_cmp_time(notAfter, &t);
1127 vpn_progress(vpninfo, PRG_ERR,
1128 _("Error in client cert notAfter field\n"));
1131 reason = _("Client certificate has expired at");
1133 t += vpninfo->cert_expire_warning;
1134 i = X509_cmp_time(notAfter, &t);
1136 reason = _("Client certificate expires soon at");
1140 BIO *bp = BIO_new(BIO_s_mem());
1142 const char *expiry = _("<error>");
1146 ASN1_TIME_print(bp, notAfter);
1147 BIO_write(bp, &zero, 1);
1148 BIO_get_mem_ptr(bp, &bm);
1151 vpn_progress(vpninfo, PRG_ERR, "%s: %s\n", reason, expiry);
1157 int openconnect_open_https(struct openconnect_info *vpninfo)
1159 method_const SSL_METHOD *ssl3_method;
1165 if (vpninfo->https_ssl)
1168 if (vpninfo->peer_cert) {
1169 X509_free(vpninfo->peer_cert);
1170 vpninfo->peer_cert = NULL;
1173 ssl_sock = connect_https_socket(vpninfo);
1177 ssl3_method = TLSv1_client_method();
1178 if (!vpninfo->https_ctx) {
1179 vpninfo->https_ctx = SSL_CTX_new(ssl3_method);
1181 /* Some servers (or their firewalls) really don't like seeing
1183 #ifdef SSL_OP_NO_TICKET
1184 SSL_CTX_set_options (vpninfo->https_ctx, SSL_OP_NO_TICKET);
1187 if (vpninfo->cert) {
1188 err = load_certificate(vpninfo);
1190 vpn_progress(vpninfo, PRG_ERR,
1191 _("Loading certificate failed. Aborting.\n"));
1194 check_certificate_expiry(vpninfo);
1197 /* We just want to do:
1198 SSL_CTX_set_purpose(vpninfo->https_ctx, X509_PURPOSE_ANY);
1199 ... but it doesn't work with OpenSSL < 0.9.8k because of
1200 problems with inheritance (fixed in v1.1.4.6 of
1201 crypto/x509/x509_vpm.c) so we have to play silly buggers
1202 instead. This trick doesn't work _either_ in < 0.9.7 but
1203 I don't know of _any_ workaround which will, and can't
1204 be bothered to find out either. */
1205 #if OPENSSL_VERSION_NUMBER >= 0x00908000
1206 SSL_CTX_set_cert_verify_callback(vpninfo->https_ctx,
1207 ssl_app_verify_callback, NULL);
1209 SSL_CTX_set_default_verify_paths(vpninfo->https_ctx);
1211 if (vpninfo->cafile) {
1212 if (!SSL_CTX_load_verify_locations(vpninfo->https_ctx, vpninfo->cafile, NULL)) {
1213 vpn_progress(vpninfo, PRG_ERR,
1214 _("Failed to open CA file '%s'\n"),
1216 openconnect_report_ssl_errors(vpninfo);
1223 https_ssl = SSL_new(vpninfo->https_ctx);
1224 workaround_openssl_certchain_bug(vpninfo, https_ssl);
1226 https_bio = BIO_new_socket(ssl_sock, BIO_NOCLOSE);
1227 BIO_set_nbio(https_bio, 1);
1228 SSL_set_bio(https_ssl, https_bio, https_bio);
1230 vpn_progress(vpninfo, PRG_INFO, _("SSL negotiation with %s\n"),
1233 while ((err = SSL_connect(https_ssl)) <= 0) {
1234 fd_set wr_set, rd_set;
1235 int maxfd = ssl_sock;
1240 err = SSL_get_error(https_ssl, err);
1241 if (err == SSL_ERROR_WANT_READ)
1242 FD_SET(ssl_sock, &rd_set);
1243 else if (err == SSL_ERROR_WANT_WRITE)
1244 FD_SET(ssl_sock, &wr_set);
1246 vpn_progress(vpninfo, PRG_ERR, _("SSL connection failure\n"));
1247 openconnect_report_ssl_errors(vpninfo);
1248 SSL_free(https_ssl);
1253 if (vpninfo->cancel_fd != -1) {
1254 FD_SET(vpninfo->cancel_fd, &rd_set);
1255 if (vpninfo->cancel_fd > ssl_sock)
1256 maxfd = vpninfo->cancel_fd;
1258 select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
1259 if (vpninfo->cancel_fd != -1 &&
1260 FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
1261 vpn_progress(vpninfo, PRG_ERR, _("SSL connection cancelled\n"));
1262 SSL_free(https_ssl);
1268 if (verify_peer(vpninfo, https_ssl)) {
1269 SSL_free(https_ssl);
1274 vpninfo->ssl_fd = ssl_sock;
1275 vpninfo->https_ssl = https_ssl;
1277 /* Stash this now, because it might not be available later if the
1278 server has disconnected. */
1279 vpninfo->peer_cert = SSL_get_peer_certificate(vpninfo->https_ssl);
1281 vpn_progress(vpninfo, PRG_INFO, _("Connected to HTTPS on %s\n"),
1287 void openconnect_close_https(struct openconnect_info *vpninfo, int final)
1289 if (vpninfo->peer_cert) {
1290 X509_free(vpninfo->peer_cert);
1291 vpninfo->peer_cert = NULL;
1293 if (vpninfo->https_ssl) {
1294 SSL_free(vpninfo->https_ssl);
1295 vpninfo->https_ssl = NULL;
1297 if (vpninfo->ssl_fd != -1) {
1298 close(vpninfo->ssl_fd);
1299 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_rfds);
1300 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_wfds);
1301 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_efds);
1302 vpninfo->ssl_fd = -1;
1304 if (final && vpninfo->https_ctx) {
1305 SSL_CTX_free(vpninfo->https_ctx);
1306 vpninfo->https_ctx = NULL;
1310 void openconnect_init_ssl(void)
1312 SSL_library_init ();
1314 SSL_load_error_strings ();
1315 OpenSSL_add_all_algorithms ();
1318 char *openconnect_get_cert_details(struct openconnect_info *vpninfo,
1319 OPENCONNECT_X509 *cert)
1321 BIO *bp = BIO_new(BIO_s_mem());
1326 X509_print_ex(bp, cert, 0, 0);
1327 BIO_write(bp, &zero, 1);
1328 BIO_get_mem_ptr(bp, &certinfo);
1330 ret = strdup(certinfo->data);
1336 int openconnect_local_cert_md5(struct openconnect_info *vpninfo,
1341 if (!vpninfo->cert_x509)
1344 if (get_cert_md5_fingerprint(vpninfo, vpninfo->cert_x509, buf))