From patchwork Thu Jun 6 10:34:41 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gert Doering X-Patchwork-Id: 3723 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:4507:b0:57d:b2cb:6cf with SMTP id d7csp253838mae; Thu, 6 Jun 2024 03:35:35 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCWkkzCli5dGJtvD5YCV+x7tFFhRwSus/l7nxtcimQe1IiDCGrJZT4O/IV60nr3Th4xeQKx7mqT32L3VxuqyH+0092knKk0= X-Google-Smtp-Source: AGHT+IHCVVtt7Viqa+N8lfmlXCFlT43vz2E4/FRKpC1SdKKxrx5L1k8Ay6Vkta3TLkTjJ4jctMdK X-Received: by 2002:a92:c262:0:b0:374:9cfb:ee13 with SMTP id e9e14a558f8ab-374b1e13259mr55532625ab.0.1717670135198; Thu, 06 Jun 2024 03:35:35 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1717670135; cv=none; d=google.com; s=arc-20160816; b=GW1sZR5i7ApKhmbw5qR4m4k6g6bYHCj4iZ9escHnf5foOpjDV+8AhFnb7rj16ayy3r tjzEp73elWsF8Bf1fwpy21jh8qDSOI4hj2R2480zBP4Zq4J8CAK3fAHRt/lrEXgQfkAc dyuGGY3L7hK4ZhqfkErF7uh9CoatJwPXJv6Y3aLKW76geWQTOfqbFXxnBtR/vAinK5ci SqUToRpGB4cdugXV0y2DYzRgNlhQnfo3T4VwTI0PupB/Ki4K2Heu7sUhYBM7Q5H6v8a4 dwwe89joTlqNFc3f70ROzdSHicKq7r3nzAr4pPav5qeXco9EfXmXqhYxrmHvipq7tHqe 50IA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:content-transfer-encoding:list-subscribe:list-help :list-post:list-archive:list-unsubscribe:list-id:precedence:subject :mime-version:references:in-reply-to:message-id:date:to:from :dkim-signature:dkim-signature; bh=YYC9agjnIbMUrEjvS/U84KoxLIbfCAgVUd6ulbxWz1o=; fh=4NbAC/LsuMLI0S0hprUlLSLCiHwg6SCAifhH718Jh0Q=; b=i53qJ+aRPnzaQo1YYacTFhM8TZnv9ZaYMqg2/KhLKa7B/eyCoiW7+FPS7Ee4ldTnFx t7O7cqigxRi6umvXuuqNqg1WacPY6nLnOM+VW6sTXuzC5IoR7gckOHu0+P3RByEHCV2f XyXWJkzemIJO4wRBLdvsMO92g9Ha/IeiVV/o8Mx4os/60CRifyJV6o6LmkWtvOahfp19 GuL2KkHIFVKlfJ0Sy5qdLy5BR0XlZxtiVXwG2fw4X/nHK2DxukreUSsMAVBsBJ/6MT8W hdm55UzaUDciHNZ5MYsiMTN1s5hi0MTqsOIgOZC/Oo98LC0TZei+D1Q2czKX1KP4M61h fOCg==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=fgVyAn1w; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=gQOoGiOC; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=muc.de Received: from lists.sourceforge.net (lists.sourceforge.net. [216.105.38.7]) by mx.google.com with ESMTPS id 41be03b00d2f7-6de275fabacsi904662a12.437.2024.06.06.03.35.35 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 06 Jun 2024 03:35:35 -0700 (PDT) Received-SPF: pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) client-ip=216.105.38.7; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=fgVyAn1w; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=gQOoGiOC; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=muc.de 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.95) (envelope-from ) id 1sFASS-0001XZ-5f; Thu, 06 Jun 2024 10:35:00 +0000 Received: from [172.30.29.66] (helo=mx.sourceforge.net) by sfs-ml-4.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1sFASO-0001XO-Ah for openvpn-devel@lists.sourceforge.net; Thu, 06 Jun 2024 10:34:56 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=Content-Transfer-Encoding:MIME-Version:References: In-Reply-To:Message-ID:Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=qt/EPkmLhrSzeHLYtv6Zgg65SzBrAyGaE/bI5HRCoxY=; b=fgVyAn1wJiJ0jV3s5lCmcub0bt we+NWLPrykLGOtqvSipow1rqw8jD/10fxZCS9ZdoSKB8eAuSsRNCZuV0m+OsPWsy594ccRPuXZZR0 ctXnsUeQ73zpjnwPY+wxb1NqjxNzJO/9n9MWtcGteJeEm38fGUCnRGuC8GFENMpSQoLU=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID: Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=qt/EPkmLhrSzeHLYtv6Zgg65SzBrAyGaE/bI5HRCoxY=; b=gQOoGiOCHVBgHFy5SF25/ubbjp x7bgDAsdeIH3Rap1LaQ2H58MFKJ4iPT3goGget5w2GAbYDILbjNIpA6VDYGku6yy3Uij/jHp3I7ow pyj5EzKadHv9H1EDT6LaqhOWzNAng8U2uyRVn72Aff4hgnv8jyy4N3JX1+bCYUAXDF30=; Received: from dhcp-174.greenie.muc.de ([193.149.48.174] helo=blue.greenie.muc.de) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1sFASN-0007tj-AZ for openvpn-devel@lists.sourceforge.net; Thu, 06 Jun 2024 10:34:56 +0000 Received: from blue.greenie.muc.de (localhost [127.0.0.1]) by blue.greenie.muc.de (8.17.1.9/8.17.1.9) with ESMTP id 456AYg7l026610 for ; Thu, 6 Jun 2024 12:34:42 +0200 Received: (from gert@localhost) by blue.greenie.muc.de (8.17.1.9/8.17.1.9/Submit) id 456AYg1e026609 for openvpn-devel@lists.sourceforge.net; Thu, 6 Jun 2024 12:34:42 +0200 From: Gert Doering To: openvpn-devel@lists.sourceforge.net Date: Thu, 6 Jun 2024 12:34:41 +0200 Message-ID: <20240606103441.26598-1-gert@greenie.muc.de> X-Mailer: git-send-email 2.44.1 In-Reply-To: References: MIME-Version: 1.0 X-Spam-Score: -0.0 (/) X-Spam-Report: Spam detection software, running on the system "util-spamd-1.v13.lw.sourceforge.com", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: From: Heiko Wundram The certificate selection process for the Crypto API certificates is currently fixed to match on subject or identifier. Especially if certificates that are used for OpenVPN are managed by a Windows CA [...] Content analysis details: (-0.0 points, 6.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 URIBL_BLOCKED ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [URIs: openvpn.net] 0.0 RCVD_IN_VALIDITY_CERTIFIED_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [193.149.48.174 listed in sa-trusted.bondedsender.org] 0.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [193.149.48.174 listed in bl.score.senderscore.com] -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.0 SPF_PASS SPF: sender matches SPF record -0.0 T_SCC_BODY_TEXT_LINE No description available. X-Headers-End: 1sFASN-0007tj-AZ Subject: [Openvpn-devel] [PATCH v2] Implement Windows CA template match for Crypto-API selector 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: , Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox X-GMAIL-THRID: =?utf-8?q?1801107679767249439?= X-GMAIL-MSGID: =?utf-8?q?1801107679767249439?= From: Heiko Wundram The certificate selection process for the Crypto API certificates is currently fixed to match on subject or identifier. Especially if certificates that are used for OpenVPN are managed by a Windows CA, it is appropriate to select the certificate to use by the template that it is generated from, especially on domain-joined clients which automatically acquire/renew the corresponding certificate. The attached match implements the match on TMPL: with either a template name (which is looked up through CryptFindOIDInfo) or by specifying the OID of the template directly, which then is matched against the corresponding X509 extensions specifying the template that the certificate was generated from. The logic requires to walk all certificates in the underlying store and to match the certificate extensions directly. The hook which is implemented in the certificate selection logic is generic to allow other Crypto-API certificate matches to also be implemented at some point in the future. The logic to match the certificate template is taken from the implementation in the .NET core runtime, see Pal.Windows/FindPal.cs in in the implementation of System.Security.Cryptography.X509Certificates. Change-Id: Ia2c3e4c5c83ecccce1618c43b489dbe811de5351 Signed-off-by: Heiko Wundram Signed-off-by: Hannes Domani --- This change was reviewed on Gerrit and approved by at least one developer. I request to merge it to master. Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/621 This mail reflects revision 2 of this Change. Acked-by according to Gerrit (reflected above): diff --git a/doc/man-sections/windows-options.rst b/doc/man-sections/windows-options.rst index e87291f..1955869 100644 --- a/doc/man-sections/windows-options.rst +++ b/doc/man-sections/windows-options.rst @@ -55,6 +55,13 @@ cryptoapicert "ISSUER:Sample CA" + To select a certificate based on a certificate's template name or + OID of the template: + :: + + cryptoapicert "TMPL:Name of Template" + cryptoapicert "TMPL:1.3.6.1.4..." + The first non-expired certificate found in the user's store or the machine store that matches the select-string is used. diff --git a/src/openvpn/cryptoapi.c b/src/openvpn/cryptoapi.c index f7e5b67..0cf8e2b 100644 --- a/src/openvpn/cryptoapi.c +++ b/src/openvpn/cryptoapi.c @@ -178,6 +178,87 @@ return i; } +static void * +decode_object(struct gc_arena *gc, LPCSTR struct_type, + const CRYPT_OBJID_BLOB *val, DWORD flags, DWORD *cb) +{ + /* get byte count for decoding */ + BYTE *buf; + if (!CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, struct_type, + val->pbData, val->cbData, flags, NULL, cb)) + { + return NULL; + } + + /* do the actual decode */ + buf = gc_malloc(*cb, false, gc); + if (!CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, struct_type, + val->pbData, val->cbData, flags, buf, cb)) + { + return NULL; + } + + return buf; +} + +static const CRYPT_OID_INFO * +find_oid(DWORD keytype, const void *key, DWORD groupid) +{ + const CRYPT_OID_INFO *info = NULL; + + /* try proper resolve, also including AD */ + info = CryptFindOIDInfo(keytype, (void*)key, groupid); + + /* fall back to all groups if not found yet and fallback requested */ + if (!info && groupid) + { + info = CryptFindOIDInfo(keytype, (void*)key, 0); + } + + return info; +} + +static bool +test_certificate_template(const char *cert_prop, const CERT_CONTEXT *cert_ctx) +{ + const CERT_INFO *info = cert_ctx->pCertInfo; + const CERT_EXTENSION *ext; + DWORD cbext; + void *pvext; + struct gc_arena gc = gc_new(); + const WCHAR *tmpl_name = wide_string(cert_prop, &gc); + + /* check for V2 extension (Windows 2003+) */ + ext = CertFindExtension(szOID_CERTIFICATE_TEMPLATE, info->cExtension, info->rgExtension); + if (ext) + { + pvext = decode_object(&gc, X509_CERTIFICATE_TEMPLATE, &ext->Value, 0, &cbext); + if (pvext && cbext >= sizeof(CERT_TEMPLATE_EXT)) + { + const CERT_TEMPLATE_EXT *cte = (const CERT_TEMPLATE_EXT*)pvext; + if (!stricmp(cert_prop, cte->pszObjId)) + { + /* found direct OID match with certificate property specified */ + gc_free(&gc); + return true; + } + + const CRYPT_OID_INFO *tmpl_oid = find_oid(CRYPT_OID_INFO_NAME_KEY, tmpl_name, + CRYPT_TEMPLATE_OID_GROUP_ID); + if (tmpl_oid && !stricmp(tmpl_oid->pszOID, cte->pszObjId)) + { + /* found OID match in extension against resolved key */ + gc_free(&gc); + return true; + } + } + } + + /* no extension found, exit */ + gc_free(&gc); + return false; +} + static const CERT_CONTEXT * find_certificate_in_store(const char *cert_prop, HCERTSTORE cert_store) { @@ -186,6 +267,7 @@ * SUBJ: * THUMB:, e.g. * THUMB:f6 49 24 41 01 b4 fb 44 0c ce f4 36 ae d0 c4 c9 df 7a b6 28 + * TMPL: