From patchwork Mon Feb 10 06:59:32 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kristof Provost via Openvpn-devel X-Patchwork-Id: 987 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director12.mail.ord1d.rsapps.net ([172.30.191.6]) by backend30.mail.ord1d.rsapps.net with LMTP id UFgIE16aQV5sdgAAIUCqbw for ; Mon, 10 Feb 2020 13:01:02 -0500 Received: from proxy5.mail.ord1d.rsapps.net ([172.30.191.6]) by director12.mail.ord1d.rsapps.net with LMTP id OKG+El6aQV4BeAAAIasKDg ; Mon, 10 Feb 2020 13:01:02 -0500 Received: from smtp11.gate.ord1c ([172.30.191.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy5.mail.ord1d.rsapps.net with LMTP id ELS7EV6aQV7FXgAA8Zzt7w ; Mon, 10 Feb 2020 13:01:02 -0500 X-Spam-Threshold: 95 X-Spam-Score: 0 X-Spam-Flag: NO X-Virus-Scanned: OK X-Orig-To: openvpnslackdevel@openvpn.net X-Originating-Ip: [216.105.38.7] Authentication-Results: smtp11.gate.ord1c.rsapps.net; iprev=pass policy.iprev="216.105.38.7"; spf=pass smtp.mailfrom="openvpn-devel-bounces@lists.sourceforge.net" smtp.helo="lists.sourceforge.net"; dkim=pass header.d=lists.sourceforge.net; dkim=fail (signature verification failed) header.d=sourceforge.net; dkim=fail (signature verification failed) header.d=sf.net; dkim=fail (signature verification failed) header.d=protonmail.com; dmarc=pass (p=none; dis=none) header.from=lists.sourceforge.net X-Suspicious-Flag: NO X-Classification-ID: 4be78f9e-4c2f-11ea-b310-bc305beffa54-1-1 Received: from [216.105.38.7] ([216.105.38.7:32882] helo=lists.sourceforge.net) by smtp11.gate.ord1c.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id B4/65-32085-D5A914E5; Mon, 10 Feb 2020 13:01:01 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.sourceforge.net; s=beta; h=Content-Type:Reply-To:From:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:Subject: MIME-Version:Message-ID:To:Date:Sender:Cc:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Owner; bh=nyrXKuS0xIg28WLmgbmypK1eghBFOQ4kXrzgEti7fPs=; b=U9Dq73xankpstUwKp0kCETbNsb xXRF+C8jhxj2zt6BHmq4a8HvBmA8+Wb1jlgAvneNlgxoHHtg7Bc+ypEac/xRF/ZZ/yDZPuXxq+NCl DH/VzPAbwK/LnzyzvuiZPiVlYkg0BWVJe8+8KH4wILUwH8hTnU3r2qh0/ahzy+dSWmHc=; Received: from [127.0.0.1] (helo=sfs-ml-4.v29.lw.sourceforge.com) by sfs-ml-4.v29.lw.sourceforge.com with esmtp (Exim 4.90_1) (envelope-from ) id 1j1DLd-0004WS-91; Mon, 10 Feb 2020 17:59:53 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-4.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1j1DLa-0004WL-U5 for openvpn-devel@lists.sourceforge.net; Mon, 10 Feb 2020 17:59:50 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=Content-Type:MIME-Version:Message-ID:Subject: Reply-To:From:To:Date:Sender:Cc:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=5juNMkknIxvCAZCz7PamvDmKWax7JXoLr2z7AZCGDM0=; b=mHbLyXZxq51I6266uVP1SyYcZs d/cn5lV6RqOgO6AptX4pxlG8itKniSPZHITuUkuJonTyU72AoQKZ9T+jmgBuIbVcpVxvA0tQB83pA 18pIXla2EJli2gOeOtdh1Bp86+KKhLPh4JAquwqlnH1A8IsvGnqH4xPWfGuI/PHHMA4Y=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Type:MIME-Version:Message-ID:Subject:Reply-To:From:To:Date:Sender :Cc:Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To: References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post: List-Owner:List-Archive; bh=5juNMkknIxvCAZCz7PamvDmKWax7JXoLr2z7AZCGDM0=; b=B i4FCEaponf2cwCMRqK+f8YE1G2fidmBNrLwXWqQgqUuvo/2UhYHbgui5yYANTeIiu/6BLDQZDNhsC sq5Nncf1AZ9aUxIWH6lRVzuZ9A9glJdLM4e23Q2UPYSqWhuUS1gJQ3bjJnnZeEUZ/iFdi6ofpMGy7 7vTsghDC/mtX+Guw=; Received: from mail-40134.protonmail.ch ([185.70.40.134]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.92.2) id 1j1DLX-007lpG-9a for openvpn-devel@lists.sourceforge.net; Mon, 10 Feb 2020 17:59:50 +0000 Date: Mon, 10 Feb 2020 17:59:32 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com; s=default; t=1581357580; bh=5juNMkknIxvCAZCz7PamvDmKWax7JXoLr2z7AZCGDM0=; h=Date:To:From:Reply-To:Subject:Feedback-ID:From; b=iZEzCWb34XtZF/Fw3kOd+bzhV/dACb4wim9hiigVwUj8oJMwvO6SzHaegfuC5SC2a qLMJVTMIxgUgDLTlUvgsuImfqOPVT8clRSvjDDg2msflRZ67yFhsp86h5OSYGVcIk0 6RzI6ZImvkLtaqjMruHeyDbl+jYo983XV3zYkfwY= To: "openvpn-devel@lists.sourceforge.net" Message-ID: Feedback-ID: vaa0lkai1QK5ypT6Qvi4xRxdD3jcr4QzB3f0nwXJKCBJEu1adlHKPx1l9R_leF02tsc6boX4xVrapmUwjaXLhQ==:Ext:ProtonMail MIME-Version: 1.0 X-Spam-Status: No, score=-1.2 required=7.0 tests=ALL_TRUSTED,BAYES_05, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, HTML_MESSAGE shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on mail.protonmail.ch X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (poniekad[at]protonmail.com) -0.0 RCVD_IN_MSPIKE_H2 RBL: Average reputation (+2) [185.70.40.134 listed in wl.mailspike.net] -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.0 SPF_PASS SPF: sender matches SPF record 1.0 HTML_MESSAGE BODY: HTML included in message -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid X-Headers-End: 1j1DLX-007lpG-9a Subject: [Openvpn-devel] [PATCH] openssl: alternative names support for --verify-x509-name CN checks X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Mateusz Markowicz via Openvpn-devel From: Kristof Provost via Openvpn-devel Reply-To: Mateusz Markowicz Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox when using "--verify-x509-name [hostname] name" hostname will now be accepted also when matched against one of the X509v3 Subject Alternative Name IP or DNS entries (instead of just Subject's CN). see also: https://github.com/OpenVPN/openvpn/pull/136/ Signed-off-by: Mateusz Markowicz --- src/openvpn/options.c | 4 +++ src/openvpn/ssl_verify.c | 18 +++++++++++--- src/openvpn/ssl_verify.h | 1 + src/openvpn/ssl_verify_backend.h | 7 ++++++ src/openvpn/ssl_verify_mbedtls.c | 11 +++++++++ src/openvpn/ssl_verify_openssl.c | 42 ++++++++++++++++++++++++++++++++ 6 files changed, 80 insertions(+), 3 deletions(-) -- 2.20.1 diff --git a/src/openvpn/options.c b/src/openvpn/options.c index 173a1eea..438dfff0 100644 --- a/src/openvpn/options.c +++ b/src/openvpn/options.c @@ -8144,6 +8144,10 @@ add_option(struct options *options, { type = VERIFY_X509_SUBJECT_RDN_PREFIX; } + else if (streq(p[2], "subject-alt-name")) + { + type = VERIFY_X509_SAN; + } else { msg(msglevel, "unknown X.509 name type: %s", p[2]); diff --git a/src/openvpn/ssl_verify.c b/src/openvpn/ssl_verify.c index 65188d23..6480b5eb 100644 --- a/src/openvpn/ssl_verify.c +++ b/src/openvpn/ssl_verify.c @@ -390,15 +390,27 @@ verify_peer_cert(const struct tls_options *opt, openvpn_x509_cert_t *peer_cert, /* verify X509 name or username against --verify-x509-[user]name */ if (opt->verify_x509_type != VERIFY_X509_NONE) { - if ( (opt->verify_x509_type == VERIFY_X509_SUBJECT_DN + bool match; + if (opt->verify_x509_type == VERIFY_X509_SAN) + { + bool have_alt_names; + match = x509v3_is_host_in_alternative_names(peer_cert, opt->verify_x509_name, &have_alt_names) + || (!have_alt_names && strcmp(opt->verify_x509_name, common_name) == 0); + } + else + { + match = (opt->verify_x509_type == VERIFY_X509_SUBJECT_DN && strcmp(opt->verify_x509_name, subject) == 0) || (opt->verify_x509_type == VERIFY_X509_SUBJECT_RDN && strcmp(opt->verify_x509_name, common_name) == 0) || (opt->verify_x509_type == VERIFY_X509_SUBJECT_RDN_PREFIX && strncmp(opt->verify_x509_name, common_name, - strlen(opt->verify_x509_name)) == 0) ) + strlen(opt->verify_x509_name)) == 0); + } + + if (match) { - msg(D_HANDSHAKE, "VERIFY X509NAME OK: %s", subject); + msg(D_HANDSHAKE, "VERIFY X509NAME OK: %s", opt->verify_x509_name); } else { diff --git a/src/openvpn/ssl_verify.h b/src/openvpn/ssl_verify.h index c54b89a6..1295e76b 100644 --- a/src/openvpn/ssl_verify.h +++ b/src/openvpn/ssl_verify.h @@ -64,6 +64,7 @@ struct cert_hash_set { #define VERIFY_X509_SUBJECT_DN 1 #define VERIFY_X509_SUBJECT_RDN 2 #define VERIFY_X509_SUBJECT_RDN_PREFIX 3 +#define VERIFY_X509_SAN 4 #define TLS_AUTHENTICATION_SUCCEEDED 0 #define TLS_AUTHENTICATION_FAILED 1 diff --git a/src/openvpn/ssl_verify_backend.h b/src/openvpn/ssl_verify_backend.h index d6b31bfa..927a5a29 100644 --- a/src/openvpn/ssl_verify_backend.h +++ b/src/openvpn/ssl_verify_backend.h @@ -268,4 +268,11 @@ result_t x509_write_pem(FILE *peercert_file, openvpn_x509_cert_t *peercert); */ bool tls_verify_crl_missing(const struct tls_options *opt); +/** + * Return true iff {host} was found in {cert} Subject Alternative Names DNS or IP entries. + * If {has_alt_names} != NULL it'll return true iff Subject Alternative Names were defined + * for {cert}. + */ +bool x509v3_is_host_in_alternative_names(openvpn_x509_cert_t *cert, const char *host, bool *has_alt_names); + #endif /* SSL_VERIFY_BACKEND_H_ */ diff --git a/src/openvpn/ssl_verify_mbedtls.c b/src/openvpn/ssl_verify_mbedtls.c index fd31bbbd..2f2e04be 100644 --- a/src/openvpn/ssl_verify_mbedtls.c +++ b/src/openvpn/ssl_verify_mbedtls.c @@ -245,6 +245,17 @@ x509_get_subject(mbedtls_x509_crt *cert, struct gc_arena *gc) return subject; } +bool +x509v3_is_host_in_alternative_names(mbedtls_x509_crt *cert, const char *host, bool *has_alt_names) +{ + msg(M_WARN, "Missing support for subject alternative names in mbedtls."); + if (has_alt_names != NULL) + { + *has_alt_names = false; + } + return false; +} + static void do_setenv_x509(struct env_set *es, const char *name, char *value, int depth) { diff --git a/src/openvpn/ssl_verify_openssl.c b/src/openvpn/ssl_verify_openssl.c index ff14db23..bb639abc 100644 --- a/src/openvpn/ssl_verify_openssl.c +++ b/src/openvpn/ssl_verify_openssl.c @@ -364,6 +364,48 @@ err: return subject; } +bool +x509v3_is_host_in_alternative_names(X509 *cert, const char *host, bool *has_alt_names) +{ + GENERAL_NAMES* altnames = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); + if (has_alt_names != NULL) + { + *has_alt_names = altnames != NULL; + } + if (altnames == NULL) + { + return false; + } + + int n = sk_GENERAL_NAME_num(altnames); + for (int i = 0; i < n; i++) + { + GENERAL_NAME* altname = sk_GENERAL_NAME_value(altnames, i); + ASN1_STRING *altname_asn1 = NULL; + if (altname->type == GEN_DNS) + { + altname_asn1 = altname->d.dNSName; + } + else if (altname->type == GEN_IPADD) + { + altname_asn1 = altname->d.iPAddress; + } + + if (altname_asn1 != NULL) + { + char* altname_cstr = NULL; + if (ASN1_STRING_to_UTF8((unsigned char **)&altname_cstr, altname_asn1) >= 0) { + bool match = strcmp(host, altname_cstr) == 0; + OPENSSL_free(altname_cstr); + if (match) + { + return true; + } + } + } + } + return false; +} /* * x509-track implementation -- save X509 fields to environment,