From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Robert Pluim Newsgroups: gmane.emacs.devel Subject: Re: ALPN support for GnuTLS connections Date: Thu, 10 Oct 2024 15:54:53 +0200 Message-ID: <877cagukpe.fsf@gmail.com> References: <7f11f60c-37da-4123-ae5b-98c79a132bb1@risk-engineering.org> <87zfnp1oqa.fsf@gmail.com> <3b0509fe-5a30-4e2a-a9fa-c196d79c81d4@risk-engineering.org> <87ttdx1dzy.fsf@gmail.com> <874j5o1fwe.fsf@gmail.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="10587"; mail-complaints-to="usenet@ciao.gmane.io" Cc: emacs-devel@gnu.org To: Eric Marsden Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Thu Oct 10 15:55:39 2024 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1sytdi-0002YR-Vl for ged-emacs-devel@m.gmane-mx.org; Thu, 10 Oct 2024 15:55:39 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sytd9-0001Cf-OM; Thu, 10 Oct 2024 09:55:03 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sytd7-0001Bs-Hh for emacs-devel@gnu.org; Thu, 10 Oct 2024 09:55:01 -0400 Original-Received: from mail-wm1-x32f.google.com ([2a00:1450:4864:20::32f]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sytd5-00042W-Fk for emacs-devel@gnu.org; Thu, 10 Oct 2024 09:55:01 -0400 Original-Received: by mail-wm1-x32f.google.com with SMTP id 5b1f17b1804b1-42cb806623eso8239345e9.2 for ; Thu, 10 Oct 2024 06:54:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1728568496; x=1729173296; darn=gnu.org; h=mime-version:message-id:date:references:in-reply-to:subject:cc:to :from:from:to:cc:subject:date:message-id:reply-to; bh=az/viIiWoCj0Vk+6FJ+5l4g2QAXFfXygJ6WbtinRxo8=; b=FGzmK1rjWASIKsw1IV0UCIQOvgLaqw459Qbvmiovl+IvlZ/u5SFTI1tu8XCIj2OBjE HEDGe30x0YSDaIQP+eIh4/iXkvTwRWuFZhhx1U+hGFeNevFcO/0WLTHjZF/+DRpNdcxO kA0/qN7eTN8RPgnL6bVa0roctHQaaV78FVS3tjoO55gvg6Ks0OvVqTnRDR9NlwMFGQPQ G+6YgxxYEMPsKoWZZsTJYi5Vojf32Juim3mD0RON2k4QFPWKc1nM7Vv5aDk5U/kGtpgq 803gUn/ihoCp8sNhqus81nDyXPGugNnjpswYmrqXnH5LzGjLhhIVnrpwmzvOkOjt9o6t h73w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1728568496; x=1729173296; h=mime-version:message-id:date:references:in-reply-to:subject:cc:to :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=az/viIiWoCj0Vk+6FJ+5l4g2QAXFfXygJ6WbtinRxo8=; b=VY6I4t/FTgH+ijtMWz5mHFVL9Oh+sx+fGz2HelvP3uE0pBwuXtWWYoy4zm5k+/VtKP vDtlLlk75qIj+Rx8rN7BEcF1rQpWKomMKBWrr+1HvNF07GOkgcTosc29OP8NWc+mpueA KZTC/R89L708VBJfogW0Nca77uq2HCRlFScagvgoKeGpwEmfRvGstHrPlKdBZ3h+gq1i WhfWJrmrPbe/iDLgP9S0eDepxT0wmRW9Zd/cGJbF9ZJoVu3ojhZrbG6P+nPjwkx++DO9 UYTEP+t9PyOueNYWI0Y8VtRukvQPBzsaHIm81TFuxOt5LmGNQuUDvAtkeaw/gBSlGk03 J0bQ== X-Gm-Message-State: AOJu0YxhAeX6cacBfxTxj5p7VCNNDx6b8kXTZgH21IUWMV9bdQ9Gh3QP EfrgY201/30z8fatQ5tzjTH/UjC4vmAmyngilszBr11nBXWDg6xoId5FSA== X-Google-Smtp-Source: AGHT+IGhwKlHzxu61MAY5Ligel+C9cnP2JJV+wq7tkm1HbwwYzlXFnTdkl8i1cm6wNLMt0eY1dJPhQ== X-Received: by 2002:a05:600c:1f07:b0:42c:b3e5:f68c with SMTP id 5b1f17b1804b1-430ccef6308mr50471155e9.4.1728568496264; Thu, 10 Oct 2024 06:54:56 -0700 (PDT) Original-Received: from rltb ([2a01:e0a:3f3:fb51:be4d:4433:9c35:492]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-431183062ddsm17452405e9.27.2024.10.10.06.54.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Oct 2024 06:54:54 -0700 (PDT) In-Reply-To: <874j5o1fwe.fsf@gmail.com> (Robert Pluim's message of "Mon, 07 Oct 2024 10:22:25 +0200") Received-SPF: pass client-ip=2a00:1450:4864:20::32f; envelope-from=rpluim@gmail.com; helo=mail-wm1-x32f.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.devel:324489 Archived-At: --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable >>>>> On Mon, 07 Oct 2024 10:22:25 +0200, Robert Pluim s= aid: >>>>> On Mon, 30 Sep 2024 19:26:54 +0200, Eric Marsden said: Eric> On 30/09/2024 15:13, Robert Pluim wrote: >>> The existing code in `gnutls-boot' already does very similar things >>> for other parameters. If I propose a patch, could you test it? I >>> should be able to have something by the end of the week. Eric> Sure, I would be glad to test a patch. Robert> The code is written but not tested fully, and since I=CA=BCve b= een sick the Robert> past few days I haven=CA=BCt been able to complete it. Hopefull= y I=CA=BCll get Robert> to it by the end of this week. Patch below. Works in my limited testing. --=-=-= Content-Type: text/x-diff Content-Disposition: attachment; filename=0001-Add-support-for-GnuTLS-ALPN-negotiation.patch >From 9ec71754d4c7b593772fa336101e189b6a0ff962 Mon Sep 17 00:00:00 2001 From: Robert Pluim Date: Thu, 10 Oct 2024 15:48:49 +0200 Subject: [PATCH] Add support for GnuTLS ALPN negotiation To: emacs-devel@gnu.org * lisp/net/gnutls.el (open-gnutls-stream): Pass unrecognized parameters down to gnutls-boot. (gnutls-negotiate): Add :alpn-protocols keyword. (gnutls-boot-parameters): Add :alpn-protocols keyword. * src/gnutls.c [GNUTLS_VERSION_NUMBER >= 0x030200] : Define HAVE_GNUTLS_ALPN_SET_PROTOCOLS. (Fgnutls_boot) [HAVE_GNUTLS_ALPN_SET_PROTOCOLS]: Add :alpn-protocols keyword. Pass any string values to gnutls_alpn_set_protocols. (syms_of_gnutls): Add QCalpn_protocols symbol. --- lisp/net/gnutls.el | 38 ++++++++++++++++++++++++++++---------- src/gnutls.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 10 deletions(-) diff --git a/lisp/net/gnutls.el b/lisp/net/gnutls.el index b5fb4d47d57..dc9870136d6 100644 --- a/lisp/net/gnutls.el +++ b/lisp/net/gnutls.el @@ -168,7 +168,9 @@ open-gnutls-stream Fifth arg PARAMETERS is an optional list of keyword/value pairs. Only :client-certificate, :nowait, and :coding keywords are recognized, and have the same meaning as for -`open-network-stream'. +`open-network-stream'. Any other keyword arguments are presumed to be +TLS-specific parameters, and are passed down to `gnutls-boot' +unmodified. For historical reasons PARAMETERS can also be a symbol, which is interpreted the same as passing a list containing :nowait and the value of that symbol. @@ -197,23 +199,32 @@ open-gnutls-stream (cert (network-stream-certificate host service parameters)) (keylist (and cert (list cert))) (nowait (plist-get parameters :nowait)) + (tls-parameters (apply #'append + (cl-remove-if + (lambda (elt) + (memq (car elt) + '(:client-certificate :nowait :coding))) + (seq-split parameters 2)))) (process (open-network-stream name buffer host service :nowait nowait :tls-parameters (and nowait (cons 'gnutls-x509pki - (gnutls-boot-parameters - :type 'gnutls-x509pki - :keylist keylist - :hostname (puny-encode-domain host)))) + (apply #'gnutls-boot-parameters + :type 'gnutls-x509pki + :keylist keylist + :hostname (puny-encode-domain host) + tls-parameters))) :coding (plist-get parameters :coding)))) (if nowait process - (gnutls-negotiate :process process - :type 'gnutls-x509pki - :keylist keylist - :hostname (puny-encode-domain host))))) + (apply #'gnutls-negotiate + :process process + :type 'gnutls-x509pki + :keylist keylist + :hostname (puny-encode-domain host) + tls-parameters)))) (define-error 'gnutls-error "GnuTLS error") @@ -226,6 +237,7 @@ gnutls-negotiate &key process type hostname priority-string trustfiles crlfiles keylist min-prime-bits verify-flags verify-error verify-hostname-error + alpn-protocols &allow-other-keys) "Negotiate a SSL/TLS connection. Return proc. Signal gnutls-error. @@ -241,6 +253,7 @@ gnutls-negotiate :type type :hostname hostname :priority-string priority-string + :alpn-protocols alpn-protocols :trustfiles trustfiles :crlfiles crlfiles :keylist keylist @@ -266,7 +279,7 @@ gnutls-boot-parameters &key type hostname priority-string trustfiles crlfiles keylist min-prime-bits verify-flags verify-error verify-hostname-error - pass flags + pass flags alpn-protocols &allow-other-keys) "Return a keyword list of parameters suitable for passing to `gnutls-boot'. @@ -290,6 +303,10 @@ gnutls-boot-parameters bitflag of the gnutls_pkcs_encrypt_flags_t enum of GnuTLS. The empty list corresponds to the bitflag with value 0. +ALPN-PROTOCOLS is a list of strings to be offered as protocols in ALPN +negotiation. Note that failure to negotiate a protocol is not treated +as a fatal error by Emacs. + When VERIFY-ERROR is t or a list containing `:trustfiles', an error will be raised when the peer certificate verification fails as per GnuTLS' gnutls_certificate_verify_peers2. Otherwise, only @@ -359,6 +376,7 @@ gnutls-boot-parameters (push :hostname verify-error)) `(:priority ,priority-string + :alpn-protocols ,alpn-protocols :hostname ,hostname :loglevel ,gnutls-log-level :min-prime-bits ,min-prime-bits diff --git a/src/gnutls.c b/src/gnutls.c index 334d1d47eb6..0360d9cb740 100644 --- a/src/gnutls.c +++ b/src/gnutls.c @@ -36,6 +36,7 @@ # if GNUTLS_VERSION_NUMBER >= 0x030200 # define HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2 # define HAVE_GNUTLS_CIPHER_GET_IV_SIZE +# define HAVE_GNUTLS_ALPN_SET_PROTOCOLS # endif # if GNUTLS_VERSION_NUMBER >= 0x030202 @@ -1900,6 +1901,10 @@ DEFUN ("gnutls-boot", Fgnutls_boot, Sgnutls_boot, 3, 3, 0, :priority is a GnuTLS priority string, defaults to "NORMAL". +:alpn-protocols is a list of strings to use for ALPN negotiation. +Failing to agree on an ALPN protocol is not treated as a fatal error by +Emacs. + :trustfiles is a list of PEM-encoded trust files for `gnutls-x509pki'. :crlfiles is a list of PEM-encoded CRL lists for `gnutls-x509pki'. @@ -1979,6 +1984,7 @@ DEFUN ("gnutls-boot", Fgnutls_boot, Sgnutls_boot, 3, 3, 0, /* Placeholders for the property list elements. */ Lisp_Object priority_string; + Lisp_Object alpn_protocols; Lisp_Object trustfiles; Lisp_Object crlfiles; Lisp_Object keylist; @@ -2011,6 +2017,7 @@ DEFUN ("gnutls-boot", Fgnutls_boot, Sgnutls_boot, 3, 3, 0, hostname = plist_get (proplist, QChostname); priority_string = plist_get (proplist, QCpriority); + alpn_protocols = plist_get (proplist, QCalpn_protocols); trustfiles = plist_get (proplist, QCtrustfiles); keylist = plist_get (proplist, QCkeylist); crlfiles = plist_get (proplist, QCcrlfiles); @@ -2251,6 +2258,41 @@ DEFUN ("gnutls-boot", Fgnutls_boot, Sgnutls_boot, 3, 3, 0, GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_PRIORITY; +#ifdef HAVE_GNUTLS_ALPN_SET_PROTOCOLS + if (!NILP (alpn_protocols)) + { + Lisp_Object length = Fproper_list_p (alpn_protocols); + if (!NILP (length)) + { + int count = XFIXNAT (length); + gnutls_datum_t *protocols = xzalloc (count * sizeof (gnutls_datum_t)); + count = 0; + GNUTLS_LOG (1, max_log_level, "setting ALPN protocols"); + for (Lisp_Object tail = alpn_protocols; CONSP (tail); tail = XCDR (tail)) + { + Lisp_Object proto = XCAR (tail); + if (STRINGP (proto)) + { + protocols[count].data = SDATA (proto); + protocols[count].size = strlen (SSDATA (proto)); + count++; + } + } + int ret = 0; + if (count) + ret = gnutls_alpn_set_protocols (state, protocols, count, 0); + + /* gnutls_alpn_set_protocols copies the protocol strings, so + we can free it here. */ + xfree (protocols); + if (ret < GNUTLS_E_SUCCESS) + return gnutls_make_error (ret); + + GNUTLS_LOG (1, max_log_level, "ALPN protocols set"); + } + } +#endif + if (FIXNUMP (prime_bits)) gnutls_dh_set_prime_bits (state, XUFIXNUM (prime_bits)); @@ -3020,6 +3062,7 @@ syms_of_gnutls (void) /* The following are for the property list of 'gnutls-boot'. */ DEFSYM (QChostname, ":hostname"); DEFSYM (QCpriority, ":priority"); + DEFSYM (QCalpn_protocols, ":alpn-protocols"); DEFSYM (QCtrustfiles, ":trustfiles"); DEFSYM (QCkeylist, ":keylist"); DEFSYM (QCcrlfiles, ":crlfiles"); -- 2.39.5 --=-=-=--