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 int openconnect_SSL_gets(struct openconnect_info *vpninfo, char *buf, size_t len)
175 ret = SSL_read(vpninfo->https_ssl, buf + i, 1);
177 if (buf[i] == '\n') {
179 if (i && buf[i-1] == '\r') {
192 fd_set rd_set, wr_set;
193 int maxfd = vpninfo->ssl_fd;
198 ret = SSL_get_error(vpninfo->https_ssl, ret);
199 if (ret == SSL_ERROR_WANT_READ)
200 FD_SET(vpninfo->ssl_fd, &rd_set);
201 else if (ret == SSL_ERROR_WANT_WRITE)
202 FD_SET(vpninfo->ssl_fd, &wr_set);
204 vpn_progress(vpninfo, PRG_ERR, _("Failed to read from SSL socket\n"));
205 openconnect_report_ssl_errors(vpninfo);
209 if (vpninfo->cancel_fd != -1) {
210 FD_SET(vpninfo->cancel_fd, &rd_set);
211 if (vpninfo->cancel_fd > vpninfo->ssl_fd)
212 maxfd = vpninfo->cancel_fd;
214 select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
215 if (vpninfo->cancel_fd != -1 &&
216 FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
217 vpn_progress(vpninfo, PRG_ERR, _("SSL read cancelled\n"));
228 /* UI handling. All this just to handle the PIN callback from the TPM ENGINE,
229 and turn it into a call to our ->process_auth_form function */
232 struct openconnect_info *vpninfo;
233 struct oc_form_opt **last_opt;
234 struct oc_auth_form form;
238 struct oc_form_opt opt;
242 /* Ick. But there is no way to pass this sanely through OpenSSL */
243 static struct openconnect_info *ui_vpninfo;
245 static int ui_open(UI *ui)
247 struct openconnect_info *vpninfo = ui_vpninfo; /* Ick */
248 struct ui_data *ui_data;
250 if (!vpninfo || !vpninfo->process_auth_form)
253 ui_data = malloc(sizeof(*ui_data));
257 memset(ui_data, 0, sizeof(*ui_data));
258 ui_data->last_opt = &ui_data->form.opts;
259 ui_data->vpninfo = vpninfo;
260 ui_data->form.auth_id = (char *)"openssl_ui";
261 UI_add_user_data(ui, ui_data);
266 static int ui_write(UI *ui, UI_STRING *uis)
268 struct ui_data *ui_data = UI_get0_user_data(ui);
269 struct ui_form_opt *opt;
271 switch(UI_get_string_type(uis)) {
273 ui_data->form.error = (char *)UI_get0_output_string(uis);
276 ui_data->form.message = (char *)UI_get0_output_string(uis);
279 opt = malloc(sizeof(*opt));
282 memset(opt, 0, sizeof(*opt));
284 opt->opt.label = opt->opt.name = (char *)UI_get0_output_string(uis);
285 if (UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO)
286 opt->opt.type = OC_FORM_OPT_TEXT;
288 opt->opt.type = OC_FORM_OPT_PASSWORD;
289 *(ui_data->last_opt) = &opt->opt;
290 ui_data->last_opt = &opt->opt.next;
294 fprintf(stderr, "Unhandled SSL UI request type %d\n",
295 UI_get_string_type(uis));
301 static int ui_flush(UI *ui)
303 struct ui_data *ui_data = UI_get0_user_data(ui);
304 struct openconnect_info *vpninfo = ui_data->vpninfo;
305 struct ui_form_opt *opt;
308 ret = vpninfo->process_auth_form(vpninfo->cbdata, &ui_data->form);
312 for (opt = (struct ui_form_opt *)ui_data->form.opts; opt;
313 opt = (struct ui_form_opt *)opt->opt.next) {
314 if (opt->opt.value && opt->uis)
315 UI_set_result(ui, opt->uis, opt->opt.value);
320 static int ui_close(UI *ui)
322 struct ui_data *ui_data = UI_get0_user_data(ui);
323 struct ui_form_opt *opt, *next_opt;
325 opt = (struct ui_form_opt *)ui_data->form.opts;
327 next_opt = (struct ui_form_opt *)opt->opt.next;
329 free(opt->opt.value);
334 UI_add_user_data(ui, NULL);
339 static UI_METHOD *create_openssl_ui(struct openconnect_info *vpninfo)
341 UI_METHOD *ui_method = UI_create_method((char *)"AnyConnect VPN UI");
343 /* There is a race condition here because of the use of the
344 static ui_vpninfo pointer. This sucks, but it's OpenSSL's
345 fault and in practice it's *never* going to hurt us.
347 This UI is only used for loading certificates from a TPM; for
348 PKCS#12 and PEM files we hook the passphrase request differently.
349 The ui_vpninfo variable is set here, and is used from ui_open()
350 when the TPM ENGINE decides it needs to ask the user for a PIN.
352 The race condition exists because theoretically, there
353 could be more than one thread using libopenconnect and
354 trying to authenticate to a VPN server, within the *same*
355 process. And if *both* are using certificates from the TPM,
356 and *both* manage to be within that short window of time
357 between setting ui_vpninfo and invoking ui_open() to fetch
358 the PIN, then one connection's ->process_auth_form() could
359 get a PIN request for the *other* connection.
361 However, the only thing that ever does run libopenconnect more
362 than once from the same process is KDE's NetworkManager support,
363 and NetworkManager doesn't *support* having more than one VPN
364 connected anyway, so first that would have to be fixed and then
365 you'd have to connect to two VPNs simultaneously by clicking
366 'connect' on both at *exactly* the same time and then getting
369 Oh, and the KDE support won't be using OpenSSL anyway because of
370 licensing conflicts... so although this sucks, I'm not going to
373 ui_vpninfo = vpninfo;
375 /* Set up a UI method of our own for password/passphrase requests */
376 UI_method_set_opener(ui_method, ui_open);
377 UI_method_set_writer(ui_method, ui_write);
378 UI_method_set_flusher(ui_method, ui_flush);
379 UI_method_set_closer(ui_method, ui_close);
384 static int pem_pw_cb(char *buf, int len, int w, void *v)
386 struct openconnect_info *vpninfo = v;
390 if (vpninfo->cert_password) {
391 pass = vpninfo->cert_password;
392 vpninfo->cert_password = NULL;
393 } else if (request_passphrase(vpninfo, "openconnect_pem",
394 &pass, _("Enter PEM pass phrase:")))
400 vpn_progress(vpninfo, PRG_ERR,
401 _("PEM password too long (%d >= %d)\n"),
407 memcpy(buf, pass, plen+1);
412 static int load_pkcs12_certificate(struct openconnect_info *vpninfo, PKCS12 *p12)
414 EVP_PKEY *pkey = NULL;
420 pass = vpninfo->cert_password;
421 vpninfo->cert_password = NULL;
423 /* We do this every time round the loop, to work around a bug in
424 OpenSSL < 1.0.0-beta2 -- where the stack at *ca will be freed
425 when PKCS12_parse() returns an error, but *ca is left pointing
426 to the freed memory. */
428 if (!pass && request_passphrase(vpninfo, "openconnect_pkcs12", &pass,
429 _("Enter PKCS#12 pass phrase:")) < 0) {
433 if (!PKCS12_parse(p12, pass, &pkey, &cert, &ca)) {
434 unsigned long err = ERR_peek_error();
436 openconnect_report_ssl_errors(vpninfo);
438 if (ERR_GET_LIB(err) == ERR_LIB_PKCS12 &&
439 ERR_GET_FUNC(err) == PKCS12_F_PKCS12_PARSE &&
440 ERR_GET_REASON(err) == PKCS12_R_MAC_VERIFY_FAILURE) {
441 vpn_progress(vpninfo, PRG_ERR,
442 _("Parse PKCS#12 failed (wrong passphrase?)\n"));
448 vpn_progress(vpninfo, PRG_ERR,
449 _("Parse PKCS#12 failed (see above errors)\n"));
457 vpninfo->cert_x509 = cert;
458 SSL_CTX_use_certificate(vpninfo->https_ctx, cert);
459 X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf));
460 vpn_progress(vpninfo, PRG_INFO,
461 _("Using client certificate '%s'\n"), buf);
463 vpn_progress(vpninfo, PRG_ERR,
464 _("PKCS#12 contained no certificate!"));
469 SSL_CTX_use_PrivateKey(vpninfo->https_ctx, pkey);
472 vpn_progress(vpninfo, PRG_ERR,
473 _("PKCS#12 contained no private key!"));
477 /* Only include supporting certificates which are actually necessary */
481 for (i = 0; i < sk_X509_num(ca); i++) {
482 X509 *cert2 = sk_X509_value(ca, i);
483 if (X509_check_issued(cert2, cert) == X509_V_OK) {
488 if (X509_check_issued(cert2, cert2) == X509_V_OK)
491 X509_NAME_oneline(X509_get_subject_name(cert2),
493 vpn_progress(vpninfo, PRG_DEBUG,
494 _("Extra cert from PKCS#12: '%s'\n"), buf);
495 CRYPTO_add(&cert2->references, 1, CRYPTO_LOCK_X509);
496 SSL_CTX_add_extra_chain_cert(vpninfo->https_ctx, cert2);
501 sk_X509_pop_free(ca, X509_free);
509 static int load_tpm_certificate(struct openconnect_info *vpninfo)
513 UI_METHOD *meth = NULL;
516 ENGINE_load_builtin_engines();
518 e = ENGINE_by_id("tpm");
520 vpn_progress(vpninfo, PRG_ERR, _("Can't load TPM engine.\n"));
521 openconnect_report_ssl_errors(vpninfo);
524 if (!ENGINE_init(e) || !ENGINE_set_default_RSA(e) ||
525 !ENGINE_set_default_RAND(e)) {
526 vpn_progress(vpninfo, PRG_ERR, _("Failed to init TPM engine\n"));
527 openconnect_report_ssl_errors(vpninfo);
532 if (vpninfo->cert_password) {
533 if (!ENGINE_ctrl_cmd(e, "PIN", strlen(vpninfo->cert_password),
534 vpninfo->cert_password, NULL, 0)) {
535 vpn_progress(vpninfo, PRG_ERR,
536 _("Failed to set TPM SRK password\n"));
537 openconnect_report_ssl_errors(vpninfo);
539 vpninfo->cert_password = NULL;
540 free(vpninfo->cert_password);
542 /* Provide our own UI method to handle the PIN callback. */
543 meth = create_openssl_ui(vpninfo);
545 key = ENGINE_load_private_key(e, vpninfo->sslkey, meth, NULL);
547 UI_destroy_method(meth);
549 vpn_progress(vpninfo, PRG_ERR,
550 _("Failed to load TPM private key\n"));
551 openconnect_report_ssl_errors(vpninfo);
555 if (!SSL_CTX_use_PrivateKey(vpninfo->https_ctx, key)) {
556 vpn_progress(vpninfo, PRG_ERR, _("Add key from TPM failed\n"));
557 openconnect_report_ssl_errors(vpninfo);
567 static int load_tpm_certificate(struct openconnect_info *vpninfo)
569 vpn_progress(vpninfo, PRG_ERR,
570 _("This version of OpenConnect was built without TPM support\n"));
575 static int reload_pem_cert(struct openconnect_info *vpninfo)
577 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);
593 if (!vpninfo->cert_x509)
596 X509_NAME_oneline(X509_get_subject_name(vpninfo->cert_x509), buf, sizeof(buf));
597 vpn_progress(vpninfo, PRG_INFO,
598 _("Using client certificate '%s'\n"), buf);
603 #ifdef ANDROID_KEYSTORE
604 static BIO *BIO_from_keystore(struct openconnect_info *vpninfo, const char *item)
606 char content[KEYSTORE_MESSAGE_SIZE];
609 const char *p = item + 9;
611 /* Skip first two slashes if the user has given it as
612 keystore://foo ... */
617 /* Old versions of keystore_get.h will return the input length
618 instead of an error, in some circumstances. So check the
619 content actually changes, too. */
621 len = keystore_get(p, strlen(p), content);
622 if (len < 0 || content[0] == 0) {
623 vpn_progress(vpninfo, PRG_ERR,
624 _("Failed to lead item '%s' from keystore\n"),
628 if (!(b = BIO_new(BIO_s_mem())) || BIO_write(b, content, len) != len) {
629 vpn_progress(vpninfo, PRG_ERR,
630 _("Failed to create BIO for keystore item '%s'\n"),
639 static int is_pem_password_error(struct openconnect_info *vpninfo)
641 unsigned long err = ERR_peek_error();
643 openconnect_report_ssl_errors(vpninfo);
645 #ifndef EVP_F_EVP_DECRYPTFINAL_EX
646 #define EVP_F_EVP_DECRYPTFINAL_EX EVP_F_EVP_DECRYPTFINAL
648 /* If the user fat-fingered the passphrase, try again */
649 if (ERR_GET_LIB(err) == ERR_LIB_EVP &&
650 ERR_GET_FUNC(err) == EVP_F_EVP_DECRYPTFINAL_EX &&
651 ERR_GET_REASON(err) == EVP_R_BAD_DECRYPT) {
652 vpn_progress(vpninfo, PRG_ERR,
653 _("Loading private key failed (wrong passphrase?)\n"));
658 vpn_progress(vpninfo, PRG_ERR,
659 _("Loading private key failed (see above errors)\n"));
663 static int load_certificate(struct openconnect_info *vpninfo)
665 if (!strncmp(vpninfo->sslkey, "pkcs11:", 7) ||
666 !strncmp(vpninfo->cert, "pkcs11:", 7)) {
667 vpn_progress(vpninfo, PRG_ERR,
668 _("This binary built without PKCS#11 support\n"));
672 vpn_progress(vpninfo, PRG_TRACE,
673 _("Using certificate file %s\n"), vpninfo->cert);
675 if (strncmp(vpninfo->cert, "keystore:", 9) &&
676 (vpninfo->cert_type == CERT_TYPE_PKCS12 ||
677 vpninfo->cert_type == CERT_TYPE_UNKNOWN)) {
681 f = fopen(vpninfo->cert, "r");
683 vpn_progress(vpninfo, PRG_ERR,
684 _("Failed to open certificate file %s: %s\n"),
685 vpninfo->cert, strerror(errno));
688 p12 = d2i_PKCS12_fp(f, NULL);
691 return load_pkcs12_certificate(vpninfo, p12);
694 if (vpninfo->cert_type == CERT_TYPE_PKCS12) {
695 vpn_progress(vpninfo, PRG_ERR, _("Read PKCS#12 failed\n"));
696 openconnect_report_ssl_errors(vpninfo);
699 /* Clear error and fall through to see if it's a PEM file... */
703 /* It's PEM or TPM now, and either way we need to load the plain cert: */
704 #ifdef ANDROID_KEYSTORE
705 if (!strncmp(vpninfo->cert, "keystore:", 9)) {
706 BIO *b = BIO_from_keystore(vpninfo, vpninfo->cert);
709 vpninfo->cert_x509 = PEM_read_bio_X509_AUX(b, NULL, pem_pw_cb, vpninfo);
711 if (!vpninfo->cert_x509) {
712 vpn_progress(vpninfo, PRG_ERR,
713 _("Failed to load X509 certificate from keystore\n"));
714 openconnect_report_ssl_errors(vpninfo);
718 if (!SSL_CTX_use_certificate(vpninfo->https_ctx, vpninfo->cert_x509)) {
719 vpn_progress(vpninfo, PRG_ERR,
720 _("Failed to use X509 certificate from keystore\n"));
721 openconnect_report_ssl_errors(vpninfo);
722 X509_free(vpninfo->cert_x509);
723 vpninfo->cert_x509 = NULL;
727 #endif /* ANDROID_KEYSTORE */
729 if (!SSL_CTX_use_certificate_chain_file(vpninfo->https_ctx,
731 vpn_progress(vpninfo, PRG_ERR,
732 _("Loading certificate failed\n"));
733 openconnect_report_ssl_errors(vpninfo);
737 /* Ew, we can't get it back from the OpenSSL CTX in any sane fashion */
738 reload_pem_cert(vpninfo);
741 #ifdef ANDROID_KEYSTORE
742 if (!strncmp(vpninfo->sslkey, "keystore:", 9)) {
747 b = BIO_from_keystore(vpninfo, vpninfo->sslkey);
750 key = PEM_read_bio_PrivateKey(b, NULL, pem_pw_cb, vpninfo);
753 if (is_pem_password_error(vpninfo))
757 if (!SSL_CTX_use_PrivateKey(vpninfo->https_ctx, key)) {
758 vpn_progress(vpninfo, PRG_ERR,
759 _("Failed to use private key from keystore\n"));
761 X509_free(vpninfo->cert_x509);
762 vpninfo->cert_x509 = NULL;
769 if (vpninfo->cert_type == CERT_TYPE_UNKNOWN) {
770 FILE *f = fopen(vpninfo->sslkey, "r");
774 vpn_progress(vpninfo, PRG_ERR,
775 _("Failed to open private key file %s: %s\n"),
776 vpninfo->cert, strerror(errno));
781 while (fgets(buf, 255, f)) {
782 if (!strcmp(buf, "-----BEGIN TSS KEY BLOB-----\n")) {
783 vpninfo->cert_type = CERT_TYPE_TPM;
785 } else if (!strcmp(buf, "-----BEGIN RSA PRIVATE KEY-----\n") ||
786 !strcmp(buf, "-----BEGIN DSA PRIVATE KEY-----\n") ||
787 !strcmp(buf, "-----BEGIN ENCRYPTED PRIVATE KEY-----\n")) {
788 vpninfo->cert_type = CERT_TYPE_PEM;
793 if (vpninfo->cert_type == CERT_TYPE_UNKNOWN) {
794 vpn_progress(vpninfo, PRG_ERR,
795 _("Failed to identify private key type in '%s'\n"),
801 if (vpninfo->cert_type == CERT_TYPE_TPM)
802 return load_tpm_certificate(vpninfo);
804 /* Standard PEM certificate */
805 SSL_CTX_set_default_passwd_cb(vpninfo->https_ctx, pem_pw_cb);
806 SSL_CTX_set_default_passwd_cb_userdata(vpninfo->https_ctx, vpninfo);
808 if (!SSL_CTX_use_RSAPrivateKey_file(vpninfo->https_ctx, vpninfo->sslkey,
810 if (is_pem_password_error(vpninfo))
817 static int get_cert_fingerprint(struct openconnect_info *vpninfo,
818 OPENCONNECT_X509 *cert, const EVP_MD *type,
821 unsigned char md[EVP_MAX_MD_SIZE];
824 if (!X509_digest(cert, type, md, &n))
827 for (i=0; i < n; i++)
828 sprintf(&buf[i*2], "%02X", md[i]);
833 int get_cert_md5_fingerprint(struct openconnect_info *vpninfo,
834 OPENCONNECT_X509 *cert, char *buf)
836 return get_cert_fingerprint(vpninfo, cert, EVP_md5(), buf);
839 int openconnect_get_cert_sha1(struct openconnect_info *vpninfo,
840 OPENCONNECT_X509 *cert, char *buf)
842 return get_cert_fingerprint(vpninfo, cert, EVP_sha1(), buf);
845 static int check_server_cert(struct openconnect_info *vpninfo, X509 *cert)
847 char fingerprint[EVP_MAX_MD_SIZE * 2 + 1];
850 ret = openconnect_get_cert_sha1(vpninfo, cert, fingerprint);
854 if (strcasecmp(vpninfo->servercert, fingerprint)) {
855 vpn_progress(vpninfo, PRG_ERR,
856 _("Server SSL certificate didn't match: %s\n"), fingerprint);
862 static int match_hostname_elem(const char *hostname, int helem_len,
863 const char *match, int melem_len)
865 if (!helem_len && !melem_len)
868 if (!helem_len || !melem_len)
872 if (match[0] == '*') {
875 for (i = 1 ; i <= helem_len; i++) {
876 if (!match_hostname_elem(hostname + i, helem_len - i,
877 match + 1, melem_len - 1))
883 /* From the NetBSD (5.1) man page for ctype(3):
884 Values of type char or signed char must first be cast to unsigned char,
885 to ensure that the values are within the correct range. The result
886 should then be cast to int to avoid warnings from some compilers.
887 We do indeed get warning "array subscript has type 'char'" without
889 if (toupper((int)(unsigned char)hostname[0]) ==
890 toupper((int)(unsigned char)match[0]))
891 return match_hostname_elem(hostname + 1, helem_len - 1,
892 match + 1, melem_len - 1);
897 static int match_hostname(const char *hostname, const char *match)
900 const char *h_dot, *m_dot;
901 int helem_len, melem_len;
903 h_dot = strchr(hostname, '.');
904 m_dot = strchr(match, '.');
906 if (h_dot && m_dot) {
907 helem_len = h_dot - hostname + 1;
908 melem_len = m_dot - match + 1;
909 } else if (!h_dot && !m_dot) {
910 helem_len = strlen(hostname);
911 melem_len = strlen(match);
916 if (match_hostname_elem(hostname, helem_len,
920 hostname += helem_len;
929 /* cf. RFC2818 and RFC2459 */
930 static int match_cert_hostname(struct openconnect_info *vpninfo, X509 *peer_cert)
932 STACK_OF(GENERAL_NAME) *altnames;
934 ASN1_STRING *subjasn1;
935 char *subjstr = NULL;
938 char addrbuf[sizeof(struct in6_addr)];
941 /* Allow GEN_IP in the certificate only if we actually connected
942 by IP address rather than by name. */
943 if (inet_pton(AF_INET, vpninfo->hostname, addrbuf) > 0)
945 else if (inet_pton(AF_INET6, vpninfo->hostname, addrbuf) > 0)
947 else if (vpninfo->hostname[0] == '[' &&
948 vpninfo->hostname[strlen(vpninfo->hostname)-1] == ']') {
949 char *p = &vpninfo->hostname[strlen(vpninfo->hostname)-1];
951 if (inet_pton(AF_INET6, vpninfo->hostname + 1, addrbuf) > 0)
956 altnames = X509_get_ext_d2i(peer_cert, NID_subject_alt_name,
958 for (i = 0; i < sk_GENERAL_NAME_num(altnames); i++) {
959 const GENERAL_NAME *this = sk_GENERAL_NAME_value(altnames, i);
961 if (this->type == GEN_DNS) {
964 int len = ASN1_STRING_to_UTF8((void *)&str, this->d.ia5);
970 /* We don't like names with embedded NUL */
971 if (strlen(str) != len)
974 if (!match_hostname(vpninfo->hostname, str)) {
975 vpn_progress(vpninfo, PRG_TRACE,
976 _("Matched DNS altname '%s'\n"),
978 GENERAL_NAMES_free(altnames);
982 vpn_progress(vpninfo, PRG_TRACE,
983 _("No match for altname '%s'\n"),
987 } else if (this->type == GEN_IPADD && addrlen) {
991 if (this->d.ip->length == 4) {
993 } else if (this->d.ip->length == 16) {
996 vpn_progress(vpninfo, PRG_ERR,
997 _("Certificate has GEN_IPADD altname with bogus length %d\n"),
1002 /* We only do this for the debug messages */
1003 inet_ntop(family, this->d.ip->data, host, sizeof(host));
1005 if (this->d.ip->length == addrlen &&
1006 !memcmp(addrbuf, this->d.ip->data, addrlen)) {
1007 vpn_progress(vpninfo, PRG_TRACE,
1008 _("Matched %s address '%s'\n"),
1009 (family == AF_INET6)?"IPv6":"IPv4",
1011 GENERAL_NAMES_free(altnames);
1014 vpn_progress(vpninfo, PRG_TRACE,
1015 _("No match for %s address '%s'\n"),
1016 (family == AF_INET6)?"IPv6":"IPv4",
1019 } else if (this->type == GEN_URI) {
1021 char *url_proto, *url_host, *url_path, *url_host2;
1023 int len = ASN1_STRING_to_UTF8((void *)&str, this->d.ia5);
1028 /* We don't like names with embedded NUL */
1029 if (strlen(str) != len)
1032 if (internal_parse_url(str, &url_proto, &url_host, &url_port, &url_path, 0)) {
1037 if (!url_proto || strcasecmp(url_proto, "https"))
1040 if (url_port != vpninfo->port)
1043 /* Leave url_host as it was so that it can be freed */
1044 url_host2 = url_host;
1045 if (addrlen == 16 && vpninfo->hostname[0] != '[' &&
1046 url_host[0] == '[' && url_host[strlen(url_host)-1] == ']') {
1047 /* Cope with https://[IPv6]/ when the hostname is bare IPv6 */
1048 url_host[strlen(url_host)-1] = 0;
1052 if (strcasecmp(vpninfo->hostname, url_host2))
1056 vpn_progress(vpninfo, PRG_TRACE,
1057 _("URI '%s' has non-empty path; ignoring\n"),
1059 goto no_uri_match_silent;
1061 vpn_progress(vpninfo, PRG_TRACE,
1062 _("Matched URI '%s'\n"),
1068 GENERAL_NAMES_free(altnames);
1072 vpn_progress(vpninfo, PRG_TRACE,
1073 _("No match for URI '%s'\n"),
1075 no_uri_match_silent:
1082 GENERAL_NAMES_free(altnames);
1084 /* According to RFC2818, we don't use the legacy subject name if
1085 there was an altname with DNS type. */
1087 vpn_progress(vpninfo, PRG_ERR,
1088 _("No altname in peer cert matched '%s'\n"),
1093 subjname = X509_get_subject_name(peer_cert);
1095 vpn_progress(vpninfo, PRG_ERR,
1096 _("No subject name in peer cert!\n"));
1100 /* Find the _last_ (most specific) commonName */
1103 int j = X509_NAME_get_index_by_NID(subjname, NID_commonName, i);
1110 subjasn1 = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subjname, i));
1112 i = ASN1_STRING_to_UTF8((void *)&subjstr, subjasn1);
1114 if (!subjstr || strlen(subjstr) != i) {
1115 vpn_progress(vpninfo, PRG_ERR,
1116 _("Failed to parse subject name in peer cert\n"));
1121 if (match_hostname(vpninfo->hostname, subjstr)) {
1122 vpn_progress(vpninfo, PRG_ERR,
1123 _("Peer cert subject mismatch ('%s' != '%s')\n"),
1124 subjstr, vpninfo->hostname);
1127 vpn_progress(vpninfo, PRG_TRACE,
1128 _("Matched peer certificate subject name '%s'\n"),
1132 OPENSSL_free(subjstr);
1136 static int verify_peer(struct openconnect_info *vpninfo, SSL *https_ssl)
1141 peer_cert = SSL_get_peer_certificate(https_ssl);
1143 if (vpninfo->servercert) {
1144 /* If given a cert fingerprint on the command line, that's
1146 ret = check_server_cert(vpninfo, peer_cert);
1148 int vfy = SSL_get_verify_result(https_ssl);
1149 const char *err_string = NULL;
1151 if (vfy != X509_V_OK)
1152 err_string = X509_verify_cert_error_string(vfy);
1153 else if (match_cert_hostname(vpninfo, peer_cert))
1154 err_string = _("certificate does not match hostname");
1157 vpn_progress(vpninfo, PRG_INFO,
1158 _("Server certificate verify failed: %s\n"),
1161 if (vpninfo->validate_peer_cert)
1162 ret = vpninfo->validate_peer_cert(vpninfo->cbdata,
1171 X509_free(peer_cert);
1176 static void workaround_openssl_certchain_bug(struct openconnect_info *vpninfo,
1179 /* OpenSSL has problems with certificate chains -- if there are
1180 multiple certs with the same name, it doesn't necessarily
1181 choose the _right_ one. (RT#1942)
1182 Pick the right ones for ourselves and add them manually. */
1183 X509 *cert = SSL_get_certificate(ssl);
1185 X509_STORE *store = SSL_CTX_get_cert_store(vpninfo->https_ctx);
1188 if (!cert || !store)
1191 /* If we already have 'supporting' certs, don't add them again */
1192 if (vpninfo->https_ctx->extra_certs)
1195 if (!X509_STORE_CTX_init(&ctx, store, NULL, NULL))
1198 while (ctx.get_issuer(&cert2, &ctx, cert) == 1) {
1202 if (X509_check_issued(cert2, cert2) == X509_V_OK)
1205 X509_NAME_oneline(X509_get_subject_name(cert),
1207 vpn_progress(vpninfo, PRG_DEBUG,
1208 _("Extra cert from cafile: '%s'\n"), buf);
1209 SSL_CTX_add_extra_chain_cert(vpninfo->https_ctx, cert);
1211 X509_STORE_CTX_cleanup(&ctx);
1214 #if OPENSSL_VERSION_NUMBER >= 0x00908000
1215 static int ssl_app_verify_callback(X509_STORE_CTX *ctx, void *arg)
1217 /* We've seen certificates in the wild which don't have the
1218 purpose fields filled in correctly */
1219 X509_VERIFY_PARAM_set_purpose(ctx->param, X509_PURPOSE_ANY);
1220 return X509_verify_cert(ctx);
1224 static int check_certificate_expiry(struct openconnect_info *vpninfo)
1226 ASN1_TIME *notAfter;
1227 const char *reason = NULL;
1231 if (!vpninfo->cert_x509)
1235 notAfter = X509_get_notAfter(vpninfo->cert_x509);
1236 i = X509_cmp_time(notAfter, &t);
1238 vpn_progress(vpninfo, PRG_ERR,
1239 _("Error in client cert notAfter field\n"));
1242 reason = _("Client certificate has expired at");
1244 t += vpninfo->cert_expire_warning;
1245 i = X509_cmp_time(notAfter, &t);
1247 reason = _("Client certificate expires soon at");
1251 BIO *bp = BIO_new(BIO_s_mem());
1253 const char *expiry = _("<error>");
1257 ASN1_TIME_print(bp, notAfter);
1258 BIO_write(bp, &zero, 1);
1259 BIO_get_mem_ptr(bp, &bm);
1262 vpn_progress(vpninfo, PRG_ERR, "%s: %s\n", reason, expiry);
1268 int openconnect_open_https(struct openconnect_info *vpninfo)
1270 method_const SSL_METHOD *ssl3_method;
1276 if (vpninfo->https_ssl)
1279 if (vpninfo->peer_cert) {
1280 X509_free(vpninfo->peer_cert);
1281 vpninfo->peer_cert = NULL;
1284 ssl_sock = connect_https_socket(vpninfo);
1288 ssl3_method = TLSv1_client_method();
1289 if (!vpninfo->https_ctx) {
1290 vpninfo->https_ctx = SSL_CTX_new(ssl3_method);
1292 /* Some servers (or their firewalls) really don't like seeing
1294 #ifdef SSL_OP_NO_TICKET
1295 SSL_CTX_set_options (vpninfo->https_ctx, SSL_OP_NO_TICKET);
1298 if (vpninfo->cert) {
1299 err = load_certificate(vpninfo);
1301 vpn_progress(vpninfo, PRG_ERR,
1302 _("Loading certificate failed. Aborting.\n"));
1305 check_certificate_expiry(vpninfo);
1308 /* We just want to do:
1309 SSL_CTX_set_purpose(vpninfo->https_ctx, X509_PURPOSE_ANY);
1310 ... but it doesn't work with OpenSSL < 0.9.8k because of
1311 problems with inheritance (fixed in v1.1.4.6 of
1312 crypto/x509/x509_vpm.c) so we have to play silly buggers
1313 instead. This trick doesn't work _either_ in < 0.9.7 but
1314 I don't know of _any_ workaround which will, and can't
1315 be bothered to find out either. */
1316 #if OPENSSL_VERSION_NUMBER >= 0x00908000
1317 SSL_CTX_set_cert_verify_callback(vpninfo->https_ctx,
1318 ssl_app_verify_callback, NULL);
1320 SSL_CTX_set_default_verify_paths(vpninfo->https_ctx);
1322 if (vpninfo->cafile) {
1323 if (!SSL_CTX_load_verify_locations(vpninfo->https_ctx, vpninfo->cafile, NULL)) {
1324 vpn_progress(vpninfo, PRG_ERR,
1325 _("Failed to open CA file '%s'\n"),
1327 openconnect_report_ssl_errors(vpninfo);
1334 https_ssl = SSL_new(vpninfo->https_ctx);
1335 workaround_openssl_certchain_bug(vpninfo, https_ssl);
1337 https_bio = BIO_new_socket(ssl_sock, BIO_NOCLOSE);
1338 BIO_set_nbio(https_bio, 1);
1339 SSL_set_bio(https_ssl, https_bio, https_bio);
1341 vpn_progress(vpninfo, PRG_INFO, _("SSL negotiation with %s\n"),
1344 while ((err = SSL_connect(https_ssl)) <= 0) {
1345 fd_set wr_set, rd_set;
1346 int maxfd = ssl_sock;
1351 err = SSL_get_error(https_ssl, err);
1352 if (err == SSL_ERROR_WANT_READ)
1353 FD_SET(ssl_sock, &rd_set);
1354 else if (err == SSL_ERROR_WANT_WRITE)
1355 FD_SET(ssl_sock, &wr_set);
1357 vpn_progress(vpninfo, PRG_ERR, _("SSL connection failure\n"));
1358 openconnect_report_ssl_errors(vpninfo);
1359 SSL_free(https_ssl);
1364 if (vpninfo->cancel_fd != -1) {
1365 FD_SET(vpninfo->cancel_fd, &rd_set);
1366 if (vpninfo->cancel_fd > ssl_sock)
1367 maxfd = vpninfo->cancel_fd;
1369 select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
1370 if (vpninfo->cancel_fd != -1 &&
1371 FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
1372 vpn_progress(vpninfo, PRG_ERR, _("SSL connection cancelled\n"));
1373 SSL_free(https_ssl);
1379 if (verify_peer(vpninfo, https_ssl)) {
1380 SSL_free(https_ssl);
1385 vpninfo->ssl_fd = ssl_sock;
1386 vpninfo->https_ssl = https_ssl;
1388 /* Stash this now, because it might not be available later if the
1389 server has disconnected. */
1390 vpninfo->peer_cert = SSL_get_peer_certificate(vpninfo->https_ssl);
1392 vpn_progress(vpninfo, PRG_INFO, _("Connected to HTTPS on %s\n"),
1398 void openconnect_close_https(struct openconnect_info *vpninfo, int final)
1400 if (vpninfo->peer_cert) {
1401 X509_free(vpninfo->peer_cert);
1402 vpninfo->peer_cert = NULL;
1404 if (vpninfo->https_ssl) {
1405 SSL_free(vpninfo->https_ssl);
1406 vpninfo->https_ssl = NULL;
1408 if (vpninfo->ssl_fd != -1) {
1409 close(vpninfo->ssl_fd);
1410 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_rfds);
1411 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_wfds);
1412 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_efds);
1413 vpninfo->ssl_fd = -1;
1416 if (vpninfo->https_ctx) {
1417 SSL_CTX_free(vpninfo->https_ctx);
1418 vpninfo->https_ctx = NULL;
1420 if (vpninfo->cert_x509) {
1421 X509_free(vpninfo->cert_x509);
1422 vpninfo->cert_x509 = NULL;
1427 void openconnect_init_ssl(void)
1429 SSL_library_init ();
1431 SSL_load_error_strings ();
1432 OpenSSL_add_all_algorithms ();
1435 char *openconnect_get_cert_details(struct openconnect_info *vpninfo,
1436 OPENCONNECT_X509 *cert)
1438 BIO *bp = BIO_new(BIO_s_mem());
1443 X509_print_ex(bp, cert, 0, 0);
1444 BIO_write(bp, &zero, 1);
1445 BIO_get_mem_ptr(bp, &certinfo);
1447 ret = strdup(certinfo->data);
1453 int openconnect_local_cert_md5(struct openconnect_info *vpninfo,
1458 if (!vpninfo->cert_x509)
1461 if (get_cert_md5_fingerprint(vpninfo, vpninfo->cert_x509, buf))