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"));
467 vpninfo->cert_x509 = cert;
468 SSL_CTX_use_certificate(vpninfo->https_ctx, cert);
469 X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf));
470 vpn_progress(vpninfo, PRG_INFO,
471 _("Using client certificate '%s'\n"), buf);
473 vpn_progress(vpninfo, PRG_ERR,
474 _("PKCS#12 contained no certificate!"));
479 SSL_CTX_use_PrivateKey(vpninfo->https_ctx, pkey);
482 vpn_progress(vpninfo, PRG_ERR,
483 _("PKCS#12 contained no private key!"));
487 /* Only include supporting certificates which are actually necessary */
491 for (i = 0; i < sk_X509_num(ca); i++) {
492 X509 *cert2 = sk_X509_value(ca, i);
493 if (X509_check_issued(cert2, cert) == X509_V_OK) {
498 if (X509_check_issued(cert2, cert2) == X509_V_OK)
501 X509_NAME_oneline(X509_get_subject_name(cert2),
503 vpn_progress(vpninfo, PRG_DEBUG,
504 _("Extra cert from PKCS#12: '%s'\n"), buf);
505 CRYPTO_add(&cert2->references, 1, CRYPTO_LOCK_X509);
506 SSL_CTX_add_extra_chain_cert(vpninfo->https_ctx, cert2);
511 sk_X509_pop_free(ca, X509_free);
519 static int load_tpm_certificate(struct openconnect_info *vpninfo)
523 UI_METHOD *meth = NULL;
524 ENGINE_load_builtin_engines();
526 e = ENGINE_by_id("tpm");
528 vpn_progress(vpninfo, PRG_ERR, _("Can't load TPM engine.\n"));
529 openconnect_report_ssl_errors(vpninfo);
532 if (!ENGINE_init(e) || !ENGINE_set_default_RSA(e) ||
533 !ENGINE_set_default_RAND(e)) {
534 vpn_progress(vpninfo, PRG_ERR, _("Failed to init TPM engine\n"));
535 openconnect_report_ssl_errors(vpninfo);
540 if (vpninfo->cert_password) {
541 if (!ENGINE_ctrl_cmd(e, "PIN", strlen(vpninfo->cert_password),
542 vpninfo->cert_password, NULL, 0)) {
543 vpn_progress(vpninfo, PRG_ERR,
544 _("Failed to set TPM SRK password\n"));
545 openconnect_report_ssl_errors(vpninfo);
548 /* Provide our own UI method to handle the PIN callback. */
549 meth = create_openssl_ui(vpninfo);
551 key = ENGINE_load_private_key(e, vpninfo->sslkey, meth, NULL);
553 UI_destroy_method(meth);
555 vpn_progress(vpninfo, PRG_ERR,
556 _("Failed to load TPM private key\n"));
557 openconnect_report_ssl_errors(vpninfo);
562 if (!SSL_CTX_use_PrivateKey(vpninfo->https_ctx, key)) {
563 vpn_progress(vpninfo, PRG_ERR, _("Add key from TPM failed\n"));
564 openconnect_report_ssl_errors(vpninfo);
572 static int load_tpm_certificate(struct openconnect_info *vpninfo)
574 vpn_progress(vpninfo, PRG_ERR,
575 _("This version of OpenConnect was built without TPM support\n"));
580 static int reload_pem_cert(struct openconnect_info *vpninfo)
582 BIO *b = BIO_new(BIO_s_file_internal());
588 if (BIO_read_filename(b, vpninfo->cert) <= 0) {
591 vpn_progress(vpninfo, PRG_ERR,
592 _("Failed to reload X509 cert for expiry check\n"));
593 openconnect_report_ssl_errors(vpninfo);
596 vpninfo->cert_x509 = PEM_read_bio_X509_AUX(b, NULL, NULL, NULL);
597 if (!vpninfo->cert_x509)
600 X509_NAME_oneline(X509_get_subject_name(vpninfo->cert_x509), buf, sizeof(buf));
601 vpn_progress(vpninfo, PRG_INFO,
602 _("Using client certificate '%s'\n"), buf);
607 static int load_certificate(struct openconnect_info *vpninfo)
609 vpn_progress(vpninfo, PRG_TRACE,
610 _("Using certificate file %s\n"), vpninfo->cert);
612 if (vpninfo->cert_type == CERT_TYPE_PKCS12 ||
613 vpninfo->cert_type == CERT_TYPE_UNKNOWN) {
617 f = fopen(vpninfo->cert, "r");
619 vpn_progress(vpninfo, PRG_ERR,
620 _("Failed to open certificate file %s: %s\n"),
621 vpninfo->cert, strerror(errno));
624 p12 = d2i_PKCS12_fp(f, NULL);
627 return load_pkcs12_certificate(vpninfo, p12);
630 if (vpninfo->cert_type == CERT_TYPE_PKCS12) {
631 vpn_progress(vpninfo, PRG_ERR, _("Read PKCS#12 failed\n"));
632 openconnect_report_ssl_errors(vpninfo);
635 /* Clear error and fall through to see if it's a PEM file... */
639 /* It's PEM or TPM now, and either way we need to load the plain cert: */
640 if (!SSL_CTX_use_certificate_chain_file(vpninfo->https_ctx,
642 vpn_progress(vpninfo, PRG_ERR,
643 _("Loading certificate failed\n"));
644 openconnect_report_ssl_errors(vpninfo);
648 /* Ew, we can't get it back from the OpenSSL CTX in any sane fashion */
649 reload_pem_cert(vpninfo);
651 if (vpninfo->cert_type == CERT_TYPE_UNKNOWN) {
652 FILE *f = fopen(vpninfo->sslkey, "r");
656 vpn_progress(vpninfo, PRG_ERR,
657 _("Failed to open private key file %s: %s\n"),
658 vpninfo->cert, strerror(errno));
663 while (fgets(buf, 255, f)) {
664 if (!strcmp(buf, "-----BEGIN TSS KEY BLOB-----\n")) {
665 vpninfo->cert_type = CERT_TYPE_TPM;
667 } else if (!strcmp(buf, "-----BEGIN RSA PRIVATE KEY-----\n") ||
668 !strcmp(buf, "-----BEGIN DSA PRIVATE KEY-----\n") ||
669 !strcmp(buf, "-----BEGIN ENCRYPTED PRIVATE KEY-----\n")) {
670 vpninfo->cert_type = CERT_TYPE_PEM;
675 if (vpninfo->cert_type == CERT_TYPE_UNKNOWN) {
676 vpn_progress(vpninfo, PRG_ERR,
677 _("Failed to identify private key type in '%s'\n"),
683 if (vpninfo->cert_type == CERT_TYPE_TPM)
684 return load_tpm_certificate(vpninfo);
686 /* Standard PEM certificate */
687 SSL_CTX_set_default_passwd_cb(vpninfo->https_ctx, pem_pw_cb);
688 SSL_CTX_set_default_passwd_cb_userdata(vpninfo->https_ctx, vpninfo);
690 if (!SSL_CTX_use_RSAPrivateKey_file(vpninfo->https_ctx, vpninfo->sslkey,
692 unsigned long err = ERR_peek_error();
694 openconnect_report_ssl_errors(vpninfo);
696 #ifndef EVP_F_EVP_DECRYPTFINAL_EX
697 #define EVP_F_EVP_DECRYPTFINAL_EX EVP_F_EVP_DECRYPTFINAL
699 /* If the user fat-fingered the passphrase, try again */
700 if (ERR_GET_LIB(err) == ERR_LIB_EVP &&
701 ERR_GET_FUNC(err) == EVP_F_EVP_DECRYPTFINAL_EX &&
702 ERR_GET_REASON(err) == EVP_R_BAD_DECRYPT) {
703 vpn_progress(vpninfo, PRG_ERR,
704 _("Loading private key failed (wrong passphrase?)\n"));
708 vpn_progress(vpninfo, PRG_ERR,
709 _("Loading private key failed (see above errors)\n"));
715 static int get_cert_fingerprint(struct openconnect_info *vpninfo,
716 OPENCONNECT_X509 *cert, const EVP_MD *type,
719 unsigned char md[EVP_MAX_MD_SIZE];
722 if (!X509_digest(cert, type, md, &n))
725 for (i=0; i < n; i++)
726 sprintf(&buf[i*2], "%02X", md[i]);
731 int get_cert_md5_fingerprint(struct openconnect_info *vpninfo,
732 OPENCONNECT_X509 *cert, char *buf)
734 return get_cert_fingerprint(vpninfo, cert, EVP_md5(), buf);
737 int openconnect_get_cert_sha1(struct openconnect_info *vpninfo,
738 OPENCONNECT_X509 *cert, char *buf)
740 return get_cert_fingerprint(vpninfo, cert, EVP_sha1(), buf);
743 static int check_server_cert(struct openconnect_info *vpninfo, X509 *cert)
745 char fingerprint[EVP_MAX_MD_SIZE * 2 + 1];
748 ret = openconnect_get_cert_sha1(vpninfo, cert, fingerprint);
752 if (strcasecmp(vpninfo->servercert, fingerprint)) {
753 vpn_progress(vpninfo, PRG_ERR,
754 _("Server SSL certificate didn't match: %s\n"), fingerprint);
760 static int match_hostname_elem(const char *hostname, int helem_len,
761 const char *match, int melem_len)
763 if (!helem_len && !melem_len)
766 if (!helem_len || !melem_len)
770 if (match[0] == '*') {
773 for (i = 1 ; i <= helem_len; i++) {
774 if (!match_hostname_elem(hostname + i, helem_len - i,
775 match + 1, melem_len - 1))
781 /* From the NetBSD (5.1) man page for ctype(3):
782 Values of type char or signed char must first be cast to unsigned char,
783 to ensure that the values are within the correct range. The result
784 should then be cast to int to avoid warnings from some compilers.
785 We do indeed get warning "array subscript has type 'char'" without
787 if (toupper((int)(unsigned char)hostname[0]) ==
788 toupper((int)(unsigned char)match[0]))
789 return match_hostname_elem(hostname + 1, helem_len - 1,
790 match + 1, melem_len - 1);
795 static int match_hostname(const char *hostname, const char *match)
798 const char *h_dot, *m_dot;
799 int helem_len, melem_len;
801 h_dot = strchr(hostname, '.');
802 m_dot = strchr(match, '.');
804 if (h_dot && m_dot) {
805 helem_len = h_dot - hostname + 1;
806 melem_len = m_dot - match + 1;
807 } else if (!h_dot && !m_dot) {
808 helem_len = strlen(hostname);
809 melem_len = strlen(match);
814 if (match_hostname_elem(hostname, helem_len,
818 hostname += helem_len;
827 /* cf. RFC2818 and RFC2459 */
828 static int match_cert_hostname(struct openconnect_info *vpninfo, X509 *peer_cert)
830 STACK_OF(GENERAL_NAME) *altnames;
832 ASN1_STRING *subjasn1;
833 char *subjstr = NULL;
836 char addrbuf[sizeof(struct in6_addr)];
839 /* Allow GEN_IP in the certificate only if we actually connected
840 by IP address rather than by name. */
841 if (inet_pton(AF_INET, vpninfo->hostname, addrbuf) > 0)
843 else if (inet_pton(AF_INET6, vpninfo->hostname, addrbuf) > 0)
845 else if (vpninfo->hostname[0] == '[' &&
846 vpninfo->hostname[strlen(vpninfo->hostname)-1] == ']') {
847 char *p = &vpninfo->hostname[strlen(vpninfo->hostname)-1];
849 if (inet_pton(AF_INET6, vpninfo->hostname + 1, addrbuf) > 0)
854 altnames = X509_get_ext_d2i(peer_cert, NID_subject_alt_name,
856 for (i = 0; i < sk_GENERAL_NAME_num(altnames); i++) {
857 const GENERAL_NAME *this = sk_GENERAL_NAME_value(altnames, i);
859 if (this->type == GEN_DNS) {
862 int len = ASN1_STRING_to_UTF8((void *)&str, this->d.ia5);
868 /* We don't like names with embedded NUL */
869 if (strlen(str) != len)
872 if (!match_hostname(vpninfo->hostname, str)) {
873 vpn_progress(vpninfo, PRG_TRACE,
874 _("Matched DNS altname '%s'\n"),
876 GENERAL_NAMES_free(altnames);
880 vpn_progress(vpninfo, PRG_TRACE,
881 _("No match for altname '%s'\n"),
885 } else if (this->type == GEN_IPADD && addrlen) {
889 if (this->d.ip->length == 4) {
891 } else if (this->d.ip->length == 16) {
894 vpn_progress(vpninfo, PRG_ERR,
895 _("Certificate has GEN_IPADD altname with bogus length %d\n"),
900 /* We only do this for the debug messages */
901 inet_ntop(family, this->d.ip->data, host, sizeof(host));
903 if (this->d.ip->length == addrlen &&
904 !memcmp(addrbuf, this->d.ip->data, addrlen)) {
905 vpn_progress(vpninfo, PRG_TRACE,
906 _("Matched %s address '%s'\n"),
907 (family == AF_INET6)?"IPv6":"IPv4",
909 GENERAL_NAMES_free(altnames);
912 vpn_progress(vpninfo, PRG_TRACE,
913 _("No match for %s address '%s'\n"),
914 (family == AF_INET6)?"IPv6":"IPv4",
917 } else if (this->type == GEN_URI) {
919 char *url_proto, *url_host, *url_path, *url_host2;
921 int len = ASN1_STRING_to_UTF8((void *)&str, this->d.ia5);
926 /* We don't like names with embedded NUL */
927 if (strlen(str) != len)
930 if (internal_parse_url(str, &url_proto, &url_host, &url_port, &url_path, 0)) {
935 if (!url_proto || strcasecmp(url_proto, "https"))
938 if (url_port != vpninfo->port)
941 /* Leave url_host as it was so that it can be freed */
942 url_host2 = url_host;
943 if (addrlen == 16 && vpninfo->hostname[0] != '[' &&
944 url_host[0] == '[' && url_host[strlen(url_host)-1] == ']') {
945 /* Cope with https://[IPv6]/ when the hostname is bare IPv6 */
946 url_host[strlen(url_host)-1] = 0;
950 if (strcasecmp(vpninfo->hostname, url_host2))
954 vpn_progress(vpninfo, PRG_TRACE,
955 _("URI '%s' has non-empty path; ignoring\n"),
957 goto no_uri_match_silent;
959 vpn_progress(vpninfo, PRG_TRACE,
960 _("Matched URI '%s'\n"),
966 GENERAL_NAMES_free(altnames);
970 vpn_progress(vpninfo, PRG_TRACE,
971 _("No match for URI '%s'\n"),
980 GENERAL_NAMES_free(altnames);
982 /* According to RFC2818, we don't use the legacy subject name if
983 there was an altname with DNS type. */
985 vpn_progress(vpninfo, PRG_ERR,
986 _("No altname in peer cert matched '%s'\n"),
991 subjname = X509_get_subject_name(peer_cert);
993 vpn_progress(vpninfo, PRG_ERR,
994 _("No subject name in peer cert!\n"));
998 /* Find the _last_ (most specific) commonName */
1001 int j = X509_NAME_get_index_by_NID(subjname, NID_commonName, i);
1008 subjasn1 = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subjname, i));
1010 i = ASN1_STRING_to_UTF8((void *)&subjstr, subjasn1);
1012 if (!subjstr || strlen(subjstr) != i) {
1013 vpn_progress(vpninfo, PRG_ERR,
1014 _("Failed to parse subject name in peer cert\n"));
1019 if (match_hostname(vpninfo->hostname, subjstr)) {
1020 vpn_progress(vpninfo, PRG_ERR,
1021 _("Peer cert subject mismatch ('%s' != '%s')\n"),
1022 subjstr, vpninfo->hostname);
1025 vpn_progress(vpninfo, PRG_TRACE,
1026 _("Matched peer certificate subject name '%s'\n"),
1030 OPENSSL_free(subjstr);
1034 static int verify_peer(struct openconnect_info *vpninfo, SSL *https_ssl)
1039 peer_cert = SSL_get_peer_certificate(https_ssl);
1041 if (vpninfo->servercert) {
1042 /* If given a cert fingerprint on the command line, that's
1044 ret = check_server_cert(vpninfo, peer_cert);
1046 int vfy = SSL_get_verify_result(https_ssl);
1047 const char *err_string = NULL;
1049 if (vfy != X509_V_OK)
1050 err_string = X509_verify_cert_error_string(vfy);
1051 else if (match_cert_hostname(vpninfo, peer_cert))
1052 err_string = _("certificate does not match hostname");
1055 vpn_progress(vpninfo, PRG_INFO,
1056 _("Server certificate verify failed: %s\n"),
1059 if (vpninfo->validate_peer_cert)
1060 ret = vpninfo->validate_peer_cert(vpninfo->cbdata,
1069 X509_free(peer_cert);
1074 static void workaround_openssl_certchain_bug(struct openconnect_info *vpninfo,
1077 /* OpenSSL has problems with certificate chains -- if there are
1078 multiple certs with the same name, it doesn't necessarily
1079 choose the _right_ one. (RT#1942)
1080 Pick the right ones for ourselves and add them manually. */
1081 X509 *cert = SSL_get_certificate(ssl);
1083 X509_STORE *store = SSL_CTX_get_cert_store(vpninfo->https_ctx);
1086 if (!cert || !store)
1089 /* If we already have 'supporting' certs, don't add them again */
1090 if (vpninfo->https_ctx->extra_certs)
1093 if (!X509_STORE_CTX_init(&ctx, store, NULL, NULL))
1096 while (ctx.get_issuer(&cert2, &ctx, cert) == 1) {
1100 if (X509_check_issued(cert2, cert2) == X509_V_OK)
1103 X509_NAME_oneline(X509_get_subject_name(cert),
1105 vpn_progress(vpninfo, PRG_DEBUG,
1106 _("Extra cert from cafile: '%s'\n"), buf);
1107 SSL_CTX_add_extra_chain_cert(vpninfo->https_ctx, cert);
1109 X509_STORE_CTX_cleanup(&ctx);
1112 #if OPENSSL_VERSION_NUMBER >= 0x00908000
1113 static int ssl_app_verify_callback(X509_STORE_CTX *ctx, void *arg)
1115 /* We've seen certificates in the wild which don't have the
1116 purpose fields filled in correctly */
1117 X509_VERIFY_PARAM_set_purpose(ctx->param, X509_PURPOSE_ANY);
1118 return X509_verify_cert(ctx);
1122 static int check_certificate_expiry(struct openconnect_info *vpninfo)
1124 ASN1_TIME *notAfter;
1125 const char *reason = NULL;
1129 if (!vpninfo->cert_x509)
1133 notAfter = X509_get_notAfter(vpninfo->cert_x509);
1134 i = X509_cmp_time(notAfter, &t);
1136 vpn_progress(vpninfo, PRG_ERR,
1137 _("Error in client cert notAfter field\n"));
1140 reason = _("Client certificate has expired at");
1142 t += vpninfo->cert_expire_warning;
1143 i = X509_cmp_time(notAfter, &t);
1145 reason = _("Client certificate expires soon at");
1149 BIO *bp = BIO_new(BIO_s_mem());
1151 const char *expiry = _("<error>");
1155 ASN1_TIME_print(bp, notAfter);
1156 BIO_write(bp, &zero, 1);
1157 BIO_get_mem_ptr(bp, &bm);
1160 vpn_progress(vpninfo, PRG_ERR, "%s: %s\n", reason, expiry);
1166 int openconnect_open_https(struct openconnect_info *vpninfo)
1168 method_const SSL_METHOD *ssl3_method;
1174 if (vpninfo->https_ssl)
1177 if (vpninfo->peer_cert) {
1178 X509_free(vpninfo->peer_cert);
1179 vpninfo->peer_cert = NULL;
1182 ssl_sock = connect_https_socket(vpninfo);
1186 ssl3_method = TLSv1_client_method();
1187 if (!vpninfo->https_ctx) {
1188 vpninfo->https_ctx = SSL_CTX_new(ssl3_method);
1190 /* Some servers (or their firewalls) really don't like seeing
1192 #ifdef SSL_OP_NO_TICKET
1193 SSL_CTX_set_options (vpninfo->https_ctx, SSL_OP_NO_TICKET);
1196 if (vpninfo->cert) {
1197 err = load_certificate(vpninfo);
1199 vpn_progress(vpninfo, PRG_ERR,
1200 _("Loading certificate failed. Aborting.\n"));
1203 check_certificate_expiry(vpninfo);
1206 /* We just want to do:
1207 SSL_CTX_set_purpose(vpninfo->https_ctx, X509_PURPOSE_ANY);
1208 ... but it doesn't work with OpenSSL < 0.9.8k because of
1209 problems with inheritance (fixed in v1.1.4.6 of
1210 crypto/x509/x509_vpm.c) so we have to play silly buggers
1211 instead. This trick doesn't work _either_ in < 0.9.7 but
1212 I don't know of _any_ workaround which will, and can't
1213 be bothered to find out either. */
1214 #if OPENSSL_VERSION_NUMBER >= 0x00908000
1215 SSL_CTX_set_cert_verify_callback(vpninfo->https_ctx,
1216 ssl_app_verify_callback, NULL);
1218 SSL_CTX_set_default_verify_paths(vpninfo->https_ctx);
1220 if (vpninfo->cafile) {
1221 if (!SSL_CTX_load_verify_locations(vpninfo->https_ctx, vpninfo->cafile, NULL)) {
1222 vpn_progress(vpninfo, PRG_ERR,
1223 _("Failed to open CA file '%s'\n"),
1225 openconnect_report_ssl_errors(vpninfo);
1232 https_ssl = SSL_new(vpninfo->https_ctx);
1233 workaround_openssl_certchain_bug(vpninfo, https_ssl);
1235 https_bio = BIO_new_socket(ssl_sock, BIO_NOCLOSE);
1236 BIO_set_nbio(https_bio, 1);
1237 SSL_set_bio(https_ssl, https_bio, https_bio);
1239 vpn_progress(vpninfo, PRG_INFO, _("SSL negotiation with %s\n"),
1242 while ((err = SSL_connect(https_ssl)) <= 0) {
1243 fd_set wr_set, rd_set;
1244 int maxfd = ssl_sock;
1249 err = SSL_get_error(https_ssl, err);
1250 if (err == SSL_ERROR_WANT_READ)
1251 FD_SET(ssl_sock, &rd_set);
1252 else if (err == SSL_ERROR_WANT_WRITE)
1253 FD_SET(ssl_sock, &wr_set);
1255 vpn_progress(vpninfo, PRG_ERR, _("SSL connection failure\n"));
1256 openconnect_report_ssl_errors(vpninfo);
1257 SSL_free(https_ssl);
1262 if (vpninfo->cancel_fd != -1) {
1263 FD_SET(vpninfo->cancel_fd, &rd_set);
1264 if (vpninfo->cancel_fd > ssl_sock)
1265 maxfd = vpninfo->cancel_fd;
1267 select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
1268 if (vpninfo->cancel_fd != -1 &&
1269 FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
1270 vpn_progress(vpninfo, PRG_ERR, _("SSL connection cancelled\n"));
1271 SSL_free(https_ssl);
1277 if (verify_peer(vpninfo, https_ssl)) {
1278 SSL_free(https_ssl);
1283 vpninfo->ssl_fd = ssl_sock;
1284 vpninfo->https_ssl = https_ssl;
1286 /* Stash this now, because it might not be available later if the
1287 server has disconnected. */
1288 vpninfo->peer_cert = SSL_get_peer_certificate(vpninfo->https_ssl);
1290 vpn_progress(vpninfo, PRG_INFO, _("Connected to HTTPS on %s\n"),
1296 void openconnect_close_https(struct openconnect_info *vpninfo, int final)
1298 if (vpninfo->peer_cert) {
1299 X509_free(vpninfo->peer_cert);
1300 vpninfo->peer_cert = NULL;
1302 if (vpninfo->https_ssl) {
1303 SSL_free(vpninfo->https_ssl);
1304 vpninfo->https_ssl = NULL;
1306 if (vpninfo->ssl_fd != -1) {
1307 close(vpninfo->ssl_fd);
1308 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_rfds);
1309 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_wfds);
1310 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_efds);
1311 vpninfo->ssl_fd = -1;
1313 if (final && vpninfo->https_ctx) {
1314 SSL_CTX_free(vpninfo->https_ctx);
1315 vpninfo->https_ctx = NULL;
1319 void openconnect_init_ssl(void)
1321 SSL_library_init ();
1323 SSL_load_error_strings ();
1324 OpenSSL_add_all_algorithms ();
1327 char *openconnect_get_cert_details(struct openconnect_info *vpninfo,
1328 OPENCONNECT_X509 *cert)
1330 BIO *bp = BIO_new(BIO_s_mem());
1335 X509_print_ex(bp, cert, 0, 0);
1336 BIO_write(bp, &zero, 1);
1337 BIO_get_mem_ptr(bp, &certinfo);
1339 ret = strdup(certinfo->data);
1345 int openconnect_local_cert_md5(struct openconnect_info *vpninfo,
1350 if (!vpninfo->cert_x509)
1353 if (get_cert_md5_fingerprint(vpninfo, vpninfo->cert_x509, buf))