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_add_user_data(ui, ui_data);
265 static int ui_write(UI *ui, UI_STRING *uis)
267 struct ui_data *ui_data = UI_get0_user_data(ui);
268 struct ui_form_opt *opt;
270 switch(UI_get_string_type(uis)) {
272 ui_data->form.error = (char *)UI_get0_output_string(uis);
275 ui_data->form.message = (char *)UI_get0_output_string(uis);
278 opt = malloc(sizeof(*opt));
281 memset(opt, 0, sizeof(*opt));
283 opt->opt.label = opt->opt.name = (char *)UI_get0_output_string(uis);
284 if (UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO)
285 opt->opt.type = OC_FORM_OPT_TEXT;
287 opt->opt.type = OC_FORM_OPT_PASSWORD;
288 *(ui_data->last_opt) = &opt->opt;
289 ui_data->last_opt = &opt->opt.next;
293 fprintf(stderr, "Unhandled SSL UI request type %d\n",
294 UI_get_string_type(uis));
300 static int ui_flush(UI *ui)
302 struct ui_data *ui_data = UI_get0_user_data(ui);
303 struct openconnect_info *vpninfo = ui_data->vpninfo;
304 struct ui_form_opt *opt;
307 ret = vpninfo->process_auth_form(vpninfo->cbdata, &ui_data->form);
311 for (opt = (struct ui_form_opt *)ui_data->form.opts; opt;
312 opt = (struct ui_form_opt *)opt->opt.next) {
313 if (opt->opt.value && opt->uis)
314 UI_set_result(ui, opt->uis, opt->opt.value);
319 static int ui_close(UI *ui)
321 struct ui_data *ui_data = UI_get0_user_data(ui);
322 struct ui_form_opt *opt, *next_opt;
324 opt = (struct ui_form_opt *)ui_data->form.opts;
326 next_opt = (struct ui_form_opt *)opt->opt.next;
328 free(opt->opt.value);
333 UI_add_user_data(ui, NULL);
338 static UI_METHOD *create_openssl_ui(struct openconnect_info *vpninfo)
340 UI_METHOD *ui_method = UI_create_method((char *)"AnyConnect VPN UI");
342 /* There is a race condition here because of the use of the
343 static ui_vpninfo pointer. This sucks, but it's OpenSSL's
344 fault and in practice it's *never* going to hurt us.
346 This UI is only used for loading certificates from a TPM; for
347 PKCS#12 and PEM files we hook the passphrase request differently.
348 The ui_vpninfo variable is set here, and is used from ui_open()
349 when the TPM ENGINE decides it needs to ask the user for a PIN.
351 The race condition exists because theoretically, there
352 could be more than one thread using libopenconnect and
353 trying to authenticate to a VPN server, within the *same*
354 process. And if *both* are using certificates from the TPM,
355 and *both* manage to be within that short window of time
356 between setting ui_vpninfo and invoking ui_open() to fetch
357 the PIN, then one connection's ->process_auth_form() could
358 get a PIN request for the *other* connection.
360 However, the only thing that ever does run libopenconnect more
361 than once from the same process is KDE's NetworkManager support,
362 and NetworkManager doesn't *support* having more than one VPN
363 connected anyway, so first that would have to be fixed and then
364 you'd have to connect to two VPNs simultaneously by clicking
365 'connect' on both at *exactly* the same time and then getting
368 Oh, and the KDE support won't be using OpenSSL anyway because of
369 licensing conflicts... so although this sucks, I'm not going to
372 ui_vpninfo = vpninfo;
374 /* Set up a UI method of our own for password/passphrase requests */
375 UI_method_set_opener(ui_method, ui_open);
376 UI_method_set_writer(ui_method, ui_write);
377 UI_method_set_flusher(ui_method, ui_flush);
378 UI_method_set_closer(ui_method, ui_close);
383 static int pem_pw_cb(char *buf, int len, int w, void *v)
385 struct openconnect_info *vpninfo = v;
389 if (vpninfo->cert_password) {
390 pass = vpninfo->cert_password;
391 vpninfo->cert_password = NULL;
392 } else if (request_passphrase(vpninfo, &pass,
393 _("Enter PEM pass phrase:")))
399 vpn_progress(vpninfo, PRG_ERR,
400 _("PEM password too long (%d >= %d)\n"),
406 memcpy(buf, pass, plen+1);
411 static int load_pkcs12_certificate(struct openconnect_info *vpninfo, PKCS12 *p12)
413 EVP_PKEY *pkey = NULL;
419 pass = vpninfo->cert_password;
420 vpninfo->cert_password = NULL;
422 /* We do this every time round the loop, to work around a bug in
423 OpenSSL < 1.0.0-beta2 -- where the stack at *ca will be freed
424 when PKCS12_parse() returns an error, but *ca is left pointing
425 to the freed memory. */
427 if (!pass && request_passphrase(vpninfo, &pass,
428 _("Enter PKCS#12 pass phrase:")) < 0) {
432 if (!PKCS12_parse(p12, pass, &pkey, &cert, &ca)) {
433 unsigned long err = ERR_peek_error();
435 openconnect_report_ssl_errors(vpninfo);
437 if (ERR_GET_LIB(err) == ERR_LIB_PKCS12 &&
438 ERR_GET_FUNC(err) == PKCS12_F_PKCS12_PARSE &&
439 ERR_GET_REASON(err) == PKCS12_R_MAC_VERIFY_FAILURE) {
440 vpn_progress(vpninfo, PRG_ERR,
441 _("Parse PKCS#12 failed (wrong passphrase?)\n"));
447 vpn_progress(vpninfo, PRG_ERR,
448 _("Parse PKCS#12 failed (see above errors)\n"));
456 vpninfo->cert_x509 = cert;
457 SSL_CTX_use_certificate(vpninfo->https_ctx, cert);
458 X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf));
459 vpn_progress(vpninfo, PRG_INFO,
460 _("Using client certificate '%s'\n"), buf);
462 vpn_progress(vpninfo, PRG_ERR,
463 _("PKCS#12 contained no certificate!"));
468 SSL_CTX_use_PrivateKey(vpninfo->https_ctx, pkey);
471 vpn_progress(vpninfo, PRG_ERR,
472 _("PKCS#12 contained no private key!"));
476 /* Only include supporting certificates which are actually necessary */
480 for (i = 0; i < sk_X509_num(ca); i++) {
481 X509 *cert2 = sk_X509_value(ca, i);
482 if (X509_check_issued(cert2, cert) == X509_V_OK) {
487 if (X509_check_issued(cert2, cert2) == X509_V_OK)
490 X509_NAME_oneline(X509_get_subject_name(cert2),
492 vpn_progress(vpninfo, PRG_DEBUG,
493 _("Extra cert from PKCS#12: '%s'\n"), buf);
494 CRYPTO_add(&cert2->references, 1, CRYPTO_LOCK_X509);
495 SSL_CTX_add_extra_chain_cert(vpninfo->https_ctx, cert2);
500 sk_X509_pop_free(ca, X509_free);
508 static int load_tpm_certificate(struct openconnect_info *vpninfo)
512 UI_METHOD *meth = NULL;
515 ENGINE_load_builtin_engines();
517 e = ENGINE_by_id("tpm");
519 vpn_progress(vpninfo, PRG_ERR, _("Can't load TPM engine.\n"));
520 openconnect_report_ssl_errors(vpninfo);
523 if (!ENGINE_init(e) || !ENGINE_set_default_RSA(e) ||
524 !ENGINE_set_default_RAND(e)) {
525 vpn_progress(vpninfo, PRG_ERR, _("Failed to init TPM engine\n"));
526 openconnect_report_ssl_errors(vpninfo);
531 if (vpninfo->cert_password) {
532 if (!ENGINE_ctrl_cmd(e, "PIN", strlen(vpninfo->cert_password),
533 vpninfo->cert_password, NULL, 0)) {
534 vpn_progress(vpninfo, PRG_ERR,
535 _("Failed to set TPM SRK password\n"));
536 openconnect_report_ssl_errors(vpninfo);
538 vpninfo->cert_password = NULL;
539 free(vpninfo->cert_password);
541 /* Provide our own UI method to handle the PIN callback. */
542 meth = create_openssl_ui(vpninfo);
544 key = ENGINE_load_private_key(e, vpninfo->sslkey, meth, NULL);
546 UI_destroy_method(meth);
548 vpn_progress(vpninfo, PRG_ERR,
549 _("Failed to load TPM private key\n"));
550 openconnect_report_ssl_errors(vpninfo);
554 if (!SSL_CTX_use_PrivateKey(vpninfo->https_ctx, key)) {
555 vpn_progress(vpninfo, PRG_ERR, _("Add key from TPM failed\n"));
556 openconnect_report_ssl_errors(vpninfo);
566 static int load_tpm_certificate(struct openconnect_info *vpninfo)
568 vpn_progress(vpninfo, PRG_ERR,
569 _("This version of OpenConnect was built without TPM support\n"));
574 static int reload_pem_cert(struct openconnect_info *vpninfo)
576 BIO *b = BIO_new(BIO_s_file_internal());
582 if (BIO_read_filename(b, vpninfo->cert) <= 0) {
585 vpn_progress(vpninfo, PRG_ERR,
586 _("Failed to reload X509 cert for expiry check\n"));
587 openconnect_report_ssl_errors(vpninfo);
590 vpninfo->cert_x509 = PEM_read_bio_X509_AUX(b, NULL, NULL, NULL);
592 if (!vpninfo->cert_x509)
595 X509_NAME_oneline(X509_get_subject_name(vpninfo->cert_x509), buf, sizeof(buf));
596 vpn_progress(vpninfo, PRG_INFO,
597 _("Using client certificate '%s'\n"), buf);
602 static int load_certificate(struct openconnect_info *vpninfo)
604 if (!strncmp(vpninfo->sslkey, "pkcs11:", 7) ||
605 !strncmp(vpninfo->cert, "pkcs11:", 7)) {
606 vpn_progress(vpninfo, PRG_ERR,
607 _("This binary built without PKCS#11 support\n"));
611 vpn_progress(vpninfo, PRG_TRACE,
612 _("Using certificate file %s\n"), vpninfo->cert);
614 if (vpninfo->cert_type == CERT_TYPE_PKCS12 ||
615 vpninfo->cert_type == CERT_TYPE_UNKNOWN) {
619 f = fopen(vpninfo->cert, "r");
621 vpn_progress(vpninfo, PRG_ERR,
622 _("Failed to open certificate file %s: %s\n"),
623 vpninfo->cert, strerror(errno));
626 p12 = d2i_PKCS12_fp(f, NULL);
629 return load_pkcs12_certificate(vpninfo, p12);
632 if (vpninfo->cert_type == CERT_TYPE_PKCS12) {
633 vpn_progress(vpninfo, PRG_ERR, _("Read PKCS#12 failed\n"));
634 openconnect_report_ssl_errors(vpninfo);
637 /* Clear error and fall through to see if it's a PEM file... */
641 /* It's PEM or TPM now, and either way we need to load the plain cert: */
642 if (!SSL_CTX_use_certificate_chain_file(vpninfo->https_ctx,
644 vpn_progress(vpninfo, PRG_ERR,
645 _("Loading certificate failed\n"));
646 openconnect_report_ssl_errors(vpninfo);
650 /* Ew, we can't get it back from the OpenSSL CTX in any sane fashion */
651 reload_pem_cert(vpninfo);
653 if (vpninfo->cert_type == CERT_TYPE_UNKNOWN) {
654 FILE *f = fopen(vpninfo->sslkey, "r");
658 vpn_progress(vpninfo, PRG_ERR,
659 _("Failed to open private key file %s: %s\n"),
660 vpninfo->cert, strerror(errno));
665 while (fgets(buf, 255, f)) {
666 if (!strcmp(buf, "-----BEGIN TSS KEY BLOB-----\n")) {
667 vpninfo->cert_type = CERT_TYPE_TPM;
669 } else if (!strcmp(buf, "-----BEGIN RSA PRIVATE KEY-----\n") ||
670 !strcmp(buf, "-----BEGIN DSA PRIVATE KEY-----\n") ||
671 !strcmp(buf, "-----BEGIN ENCRYPTED PRIVATE KEY-----\n")) {
672 vpninfo->cert_type = CERT_TYPE_PEM;
677 if (vpninfo->cert_type == CERT_TYPE_UNKNOWN) {
678 vpn_progress(vpninfo, PRG_ERR,
679 _("Failed to identify private key type in '%s'\n"),
685 if (vpninfo->cert_type == CERT_TYPE_TPM)
686 return load_tpm_certificate(vpninfo);
688 /* Standard PEM certificate */
689 SSL_CTX_set_default_passwd_cb(vpninfo->https_ctx, pem_pw_cb);
690 SSL_CTX_set_default_passwd_cb_userdata(vpninfo->https_ctx, vpninfo);
692 if (!SSL_CTX_use_RSAPrivateKey_file(vpninfo->https_ctx, vpninfo->sslkey,
694 unsigned long err = ERR_peek_error();
696 openconnect_report_ssl_errors(vpninfo);
698 #ifndef EVP_F_EVP_DECRYPTFINAL_EX
699 #define EVP_F_EVP_DECRYPTFINAL_EX EVP_F_EVP_DECRYPTFINAL
701 /* If the user fat-fingered the passphrase, try again */
702 if (ERR_GET_LIB(err) == ERR_LIB_EVP &&
703 ERR_GET_FUNC(err) == EVP_F_EVP_DECRYPTFINAL_EX &&
704 ERR_GET_REASON(err) == EVP_R_BAD_DECRYPT) {
705 vpn_progress(vpninfo, PRG_ERR,
706 _("Loading private key failed (wrong passphrase?)\n"));
710 vpn_progress(vpninfo, PRG_ERR,
711 _("Loading private key failed (see above errors)\n"));
717 static int get_cert_fingerprint(struct openconnect_info *vpninfo,
718 OPENCONNECT_X509 *cert, const EVP_MD *type,
721 unsigned char md[EVP_MAX_MD_SIZE];
724 if (!X509_digest(cert, type, md, &n))
727 for (i=0; i < n; i++)
728 sprintf(&buf[i*2], "%02X", md[i]);
733 int get_cert_md5_fingerprint(struct openconnect_info *vpninfo,
734 OPENCONNECT_X509 *cert, char *buf)
736 return get_cert_fingerprint(vpninfo, cert, EVP_md5(), buf);
739 int openconnect_get_cert_sha1(struct openconnect_info *vpninfo,
740 OPENCONNECT_X509 *cert, char *buf)
742 return get_cert_fingerprint(vpninfo, cert, EVP_sha1(), buf);
745 static int check_server_cert(struct openconnect_info *vpninfo, X509 *cert)
747 char fingerprint[EVP_MAX_MD_SIZE * 2 + 1];
750 ret = openconnect_get_cert_sha1(vpninfo, cert, fingerprint);
754 if (strcasecmp(vpninfo->servercert, fingerprint)) {
755 vpn_progress(vpninfo, PRG_ERR,
756 _("Server SSL certificate didn't match: %s\n"), fingerprint);
762 static int match_hostname_elem(const char *hostname, int helem_len,
763 const char *match, int melem_len)
765 if (!helem_len && !melem_len)
768 if (!helem_len || !melem_len)
772 if (match[0] == '*') {
775 for (i = 1 ; i <= helem_len; i++) {
776 if (!match_hostname_elem(hostname + i, helem_len - i,
777 match + 1, melem_len - 1))
783 /* From the NetBSD (5.1) man page for ctype(3):
784 Values of type char or signed char must first be cast to unsigned char,
785 to ensure that the values are within the correct range. The result
786 should then be cast to int to avoid warnings from some compilers.
787 We do indeed get warning "array subscript has type 'char'" without
789 if (toupper((int)(unsigned char)hostname[0]) ==
790 toupper((int)(unsigned char)match[0]))
791 return match_hostname_elem(hostname + 1, helem_len - 1,
792 match + 1, melem_len - 1);
797 static int match_hostname(const char *hostname, const char *match)
800 const char *h_dot, *m_dot;
801 int helem_len, melem_len;
803 h_dot = strchr(hostname, '.');
804 m_dot = strchr(match, '.');
806 if (h_dot && m_dot) {
807 helem_len = h_dot - hostname + 1;
808 melem_len = m_dot - match + 1;
809 } else if (!h_dot && !m_dot) {
810 helem_len = strlen(hostname);
811 melem_len = strlen(match);
816 if (match_hostname_elem(hostname, helem_len,
820 hostname += helem_len;
829 /* cf. RFC2818 and RFC2459 */
830 static int match_cert_hostname(struct openconnect_info *vpninfo, X509 *peer_cert)
832 STACK_OF(GENERAL_NAME) *altnames;
834 ASN1_STRING *subjasn1;
835 char *subjstr = NULL;
838 char addrbuf[sizeof(struct in6_addr)];
841 /* Allow GEN_IP in the certificate only if we actually connected
842 by IP address rather than by name. */
843 if (inet_pton(AF_INET, vpninfo->hostname, addrbuf) > 0)
845 else if (inet_pton(AF_INET6, vpninfo->hostname, addrbuf) > 0)
847 else if (vpninfo->hostname[0] == '[' &&
848 vpninfo->hostname[strlen(vpninfo->hostname)-1] == ']') {
849 char *p = &vpninfo->hostname[strlen(vpninfo->hostname)-1];
851 if (inet_pton(AF_INET6, vpninfo->hostname + 1, addrbuf) > 0)
856 altnames = X509_get_ext_d2i(peer_cert, NID_subject_alt_name,
858 for (i = 0; i < sk_GENERAL_NAME_num(altnames); i++) {
859 const GENERAL_NAME *this = sk_GENERAL_NAME_value(altnames, i);
861 if (this->type == GEN_DNS) {
864 int len = ASN1_STRING_to_UTF8((void *)&str, this->d.ia5);
870 /* We don't like names with embedded NUL */
871 if (strlen(str) != len)
874 if (!match_hostname(vpninfo->hostname, str)) {
875 vpn_progress(vpninfo, PRG_TRACE,
876 _("Matched DNS altname '%s'\n"),
878 GENERAL_NAMES_free(altnames);
882 vpn_progress(vpninfo, PRG_TRACE,
883 _("No match for altname '%s'\n"),
887 } else if (this->type == GEN_IPADD && addrlen) {
891 if (this->d.ip->length == 4) {
893 } else if (this->d.ip->length == 16) {
896 vpn_progress(vpninfo, PRG_ERR,
897 _("Certificate has GEN_IPADD altname with bogus length %d\n"),
902 /* We only do this for the debug messages */
903 inet_ntop(family, this->d.ip->data, host, sizeof(host));
905 if (this->d.ip->length == addrlen &&
906 !memcmp(addrbuf, this->d.ip->data, addrlen)) {
907 vpn_progress(vpninfo, PRG_TRACE,
908 _("Matched %s address '%s'\n"),
909 (family == AF_INET6)?"IPv6":"IPv4",
911 GENERAL_NAMES_free(altnames);
914 vpn_progress(vpninfo, PRG_TRACE,
915 _("No match for %s address '%s'\n"),
916 (family == AF_INET6)?"IPv6":"IPv4",
919 } else if (this->type == GEN_URI) {
921 char *url_proto, *url_host, *url_path, *url_host2;
923 int len = ASN1_STRING_to_UTF8((void *)&str, this->d.ia5);
928 /* We don't like names with embedded NUL */
929 if (strlen(str) != len)
932 if (internal_parse_url(str, &url_proto, &url_host, &url_port, &url_path, 0)) {
937 if (!url_proto || strcasecmp(url_proto, "https"))
940 if (url_port != vpninfo->port)
943 /* Leave url_host as it was so that it can be freed */
944 url_host2 = url_host;
945 if (addrlen == 16 && vpninfo->hostname[0] != '[' &&
946 url_host[0] == '[' && url_host[strlen(url_host)-1] == ']') {
947 /* Cope with https://[IPv6]/ when the hostname is bare IPv6 */
948 url_host[strlen(url_host)-1] = 0;
952 if (strcasecmp(vpninfo->hostname, url_host2))
956 vpn_progress(vpninfo, PRG_TRACE,
957 _("URI '%s' has non-empty path; ignoring\n"),
959 goto no_uri_match_silent;
961 vpn_progress(vpninfo, PRG_TRACE,
962 _("Matched URI '%s'\n"),
968 GENERAL_NAMES_free(altnames);
972 vpn_progress(vpninfo, PRG_TRACE,
973 _("No match for URI '%s'\n"),
982 GENERAL_NAMES_free(altnames);
984 /* According to RFC2818, we don't use the legacy subject name if
985 there was an altname with DNS type. */
987 vpn_progress(vpninfo, PRG_ERR,
988 _("No altname in peer cert matched '%s'\n"),
993 subjname = X509_get_subject_name(peer_cert);
995 vpn_progress(vpninfo, PRG_ERR,
996 _("No subject name in peer cert!\n"));
1000 /* Find the _last_ (most specific) commonName */
1003 int j = X509_NAME_get_index_by_NID(subjname, NID_commonName, i);
1010 subjasn1 = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subjname, i));
1012 i = ASN1_STRING_to_UTF8((void *)&subjstr, subjasn1);
1014 if (!subjstr || strlen(subjstr) != i) {
1015 vpn_progress(vpninfo, PRG_ERR,
1016 _("Failed to parse subject name in peer cert\n"));
1021 if (match_hostname(vpninfo->hostname, subjstr)) {
1022 vpn_progress(vpninfo, PRG_ERR,
1023 _("Peer cert subject mismatch ('%s' != '%s')\n"),
1024 subjstr, vpninfo->hostname);
1027 vpn_progress(vpninfo, PRG_TRACE,
1028 _("Matched peer certificate subject name '%s'\n"),
1032 OPENSSL_free(subjstr);
1036 static int verify_peer(struct openconnect_info *vpninfo, SSL *https_ssl)
1041 peer_cert = SSL_get_peer_certificate(https_ssl);
1043 if (vpninfo->servercert) {
1044 /* If given a cert fingerprint on the command line, that's
1046 ret = check_server_cert(vpninfo, peer_cert);
1048 int vfy = SSL_get_verify_result(https_ssl);
1049 const char *err_string = NULL;
1051 if (vfy != X509_V_OK)
1052 err_string = X509_verify_cert_error_string(vfy);
1053 else if (match_cert_hostname(vpninfo, peer_cert))
1054 err_string = _("certificate does not match hostname");
1057 vpn_progress(vpninfo, PRG_INFO,
1058 _("Server certificate verify failed: %s\n"),
1061 if (vpninfo->validate_peer_cert)
1062 ret = vpninfo->validate_peer_cert(vpninfo->cbdata,
1071 X509_free(peer_cert);
1076 static void workaround_openssl_certchain_bug(struct openconnect_info *vpninfo,
1079 /* OpenSSL has problems with certificate chains -- if there are
1080 multiple certs with the same name, it doesn't necessarily
1081 choose the _right_ one. (RT#1942)
1082 Pick the right ones for ourselves and add them manually. */
1083 X509 *cert = SSL_get_certificate(ssl);
1085 X509_STORE *store = SSL_CTX_get_cert_store(vpninfo->https_ctx);
1088 if (!cert || !store)
1091 /* If we already have 'supporting' certs, don't add them again */
1092 if (vpninfo->https_ctx->extra_certs)
1095 if (!X509_STORE_CTX_init(&ctx, store, NULL, NULL))
1098 while (ctx.get_issuer(&cert2, &ctx, cert) == 1) {
1102 if (X509_check_issued(cert2, cert2) == X509_V_OK)
1105 X509_NAME_oneline(X509_get_subject_name(cert),
1107 vpn_progress(vpninfo, PRG_DEBUG,
1108 _("Extra cert from cafile: '%s'\n"), buf);
1109 SSL_CTX_add_extra_chain_cert(vpninfo->https_ctx, cert);
1111 X509_STORE_CTX_cleanup(&ctx);
1114 #if OPENSSL_VERSION_NUMBER >= 0x00908000
1115 static int ssl_app_verify_callback(X509_STORE_CTX *ctx, void *arg)
1117 /* We've seen certificates in the wild which don't have the
1118 purpose fields filled in correctly */
1119 X509_VERIFY_PARAM_set_purpose(ctx->param, X509_PURPOSE_ANY);
1120 return X509_verify_cert(ctx);
1124 static int check_certificate_expiry(struct openconnect_info *vpninfo)
1126 ASN1_TIME *notAfter;
1127 const char *reason = NULL;
1131 if (!vpninfo->cert_x509)
1135 notAfter = X509_get_notAfter(vpninfo->cert_x509);
1136 i = X509_cmp_time(notAfter, &t);
1138 vpn_progress(vpninfo, PRG_ERR,
1139 _("Error in client cert notAfter field\n"));
1142 reason = _("Client certificate has expired at");
1144 t += vpninfo->cert_expire_warning;
1145 i = X509_cmp_time(notAfter, &t);
1147 reason = _("Client certificate expires soon at");
1151 BIO *bp = BIO_new(BIO_s_mem());
1153 const char *expiry = _("<error>");
1157 ASN1_TIME_print(bp, notAfter);
1158 BIO_write(bp, &zero, 1);
1159 BIO_get_mem_ptr(bp, &bm);
1162 vpn_progress(vpninfo, PRG_ERR, "%s: %s\n", reason, expiry);
1168 int openconnect_open_https(struct openconnect_info *vpninfo)
1170 method_const SSL_METHOD *ssl3_method;
1176 if (vpninfo->https_ssl)
1179 if (vpninfo->peer_cert) {
1180 X509_free(vpninfo->peer_cert);
1181 vpninfo->peer_cert = NULL;
1184 ssl_sock = connect_https_socket(vpninfo);
1188 ssl3_method = TLSv1_client_method();
1189 if (!vpninfo->https_ctx) {
1190 vpninfo->https_ctx = SSL_CTX_new(ssl3_method);
1192 /* Some servers (or their firewalls) really don't like seeing
1194 #ifdef SSL_OP_NO_TICKET
1195 SSL_CTX_set_options (vpninfo->https_ctx, SSL_OP_NO_TICKET);
1198 if (vpninfo->cert) {
1199 err = load_certificate(vpninfo);
1201 vpn_progress(vpninfo, PRG_ERR,
1202 _("Loading certificate failed. Aborting.\n"));
1205 check_certificate_expiry(vpninfo);
1208 /* We just want to do:
1209 SSL_CTX_set_purpose(vpninfo->https_ctx, X509_PURPOSE_ANY);
1210 ... but it doesn't work with OpenSSL < 0.9.8k because of
1211 problems with inheritance (fixed in v1.1.4.6 of
1212 crypto/x509/x509_vpm.c) so we have to play silly buggers
1213 instead. This trick doesn't work _either_ in < 0.9.7 but
1214 I don't know of _any_ workaround which will, and can't
1215 be bothered to find out either. */
1216 #if OPENSSL_VERSION_NUMBER >= 0x00908000
1217 SSL_CTX_set_cert_verify_callback(vpninfo->https_ctx,
1218 ssl_app_verify_callback, NULL);
1220 SSL_CTX_set_default_verify_paths(vpninfo->https_ctx);
1222 if (vpninfo->cafile) {
1223 if (!SSL_CTX_load_verify_locations(vpninfo->https_ctx, vpninfo->cafile, NULL)) {
1224 vpn_progress(vpninfo, PRG_ERR,
1225 _("Failed to open CA file '%s'\n"),
1227 openconnect_report_ssl_errors(vpninfo);
1234 https_ssl = SSL_new(vpninfo->https_ctx);
1235 workaround_openssl_certchain_bug(vpninfo, https_ssl);
1237 https_bio = BIO_new_socket(ssl_sock, BIO_NOCLOSE);
1238 BIO_set_nbio(https_bio, 1);
1239 SSL_set_bio(https_ssl, https_bio, https_bio);
1241 vpn_progress(vpninfo, PRG_INFO, _("SSL negotiation with %s\n"),
1244 while ((err = SSL_connect(https_ssl)) <= 0) {
1245 fd_set wr_set, rd_set;
1246 int maxfd = ssl_sock;
1251 err = SSL_get_error(https_ssl, err);
1252 if (err == SSL_ERROR_WANT_READ)
1253 FD_SET(ssl_sock, &rd_set);
1254 else if (err == SSL_ERROR_WANT_WRITE)
1255 FD_SET(ssl_sock, &wr_set);
1257 vpn_progress(vpninfo, PRG_ERR, _("SSL connection failure\n"));
1258 openconnect_report_ssl_errors(vpninfo);
1259 SSL_free(https_ssl);
1264 if (vpninfo->cancel_fd != -1) {
1265 FD_SET(vpninfo->cancel_fd, &rd_set);
1266 if (vpninfo->cancel_fd > ssl_sock)
1267 maxfd = vpninfo->cancel_fd;
1269 select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
1270 if (vpninfo->cancel_fd != -1 &&
1271 FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
1272 vpn_progress(vpninfo, PRG_ERR, _("SSL connection cancelled\n"));
1273 SSL_free(https_ssl);
1279 if (verify_peer(vpninfo, https_ssl)) {
1280 SSL_free(https_ssl);
1285 vpninfo->ssl_fd = ssl_sock;
1286 vpninfo->https_ssl = https_ssl;
1288 /* Stash this now, because it might not be available later if the
1289 server has disconnected. */
1290 vpninfo->peer_cert = SSL_get_peer_certificate(vpninfo->https_ssl);
1292 vpn_progress(vpninfo, PRG_INFO, _("Connected to HTTPS on %s\n"),
1298 void openconnect_close_https(struct openconnect_info *vpninfo, int final)
1300 if (vpninfo->peer_cert) {
1301 X509_free(vpninfo->peer_cert);
1302 vpninfo->peer_cert = NULL;
1304 if (vpninfo->https_ssl) {
1305 SSL_free(vpninfo->https_ssl);
1306 vpninfo->https_ssl = NULL;
1308 if (vpninfo->ssl_fd != -1) {
1309 close(vpninfo->ssl_fd);
1310 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_rfds);
1311 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_wfds);
1312 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_efds);
1313 vpninfo->ssl_fd = -1;
1316 if (vpninfo->https_ctx) {
1317 SSL_CTX_free(vpninfo->https_ctx);
1318 vpninfo->https_ctx = NULL;
1320 if (vpninfo->cert_x509) {
1321 X509_free(vpninfo->cert_x509);
1322 vpninfo->cert_x509 = NULL;
1327 void openconnect_init_ssl(void)
1329 SSL_library_init ();
1331 SSL_load_error_strings ();
1332 OpenSSL_add_all_algorithms ();
1335 char *openconnect_get_cert_details(struct openconnect_info *vpninfo,
1336 OPENCONNECT_X509 *cert)
1338 BIO *bp = BIO_new(BIO_s_mem());
1343 X509_print_ex(bp, cert, 0, 0);
1344 BIO_write(bp, &zero, 1);
1345 BIO_get_mem_ptr(bp, &certinfo);
1347 ret = strdup(certinfo->data);
1353 int openconnect_local_cert_md5(struct openconnect_info *vpninfo,
1358 if (!vpninfo->cert_x509)
1361 if (get_cert_md5_fingerprint(vpninfo, vpninfo->cert_x509, buf))