From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Ted Zlatanov Newsgroups: gmane.emacs.devel Subject: client certs and CRL lists for GnuTLS (was: Opportunistic STARTTLS in smtpmail.el) Date: Tue, 03 May 2011 10:20:09 -0500 Organization: =?utf-8?B?0KLQtdC+0LTQvtGAINCX0LvQsNGC0LDQvdC+0LI=?= @ Cienfuegos Message-ID: <87y62nak0m.fsf_-_@lifelogs.com> References: <87d3kal0za.fsf@lifelogs.com> <874o5mky4o.fsf@lifelogs.com> <8762ptue8r.fsf@lifelogs.com> <87k4e8ucw3.fsf@lifelogs.com> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: dough.gmane.org 1304436039 11821 80.91.229.12 (3 May 2011 15:20:39 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Tue, 3 May 2011 15:20:39 +0000 (UTC) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Tue May 03 17:20:35 2011 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([140.186.70.17]) by lo.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1QHHOs-0002gf-AN for ged-emacs-devel@m.gmane.org; Tue, 03 May 2011 17:20:34 +0200 Original-Received: from localhost ([::1]:49399 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QHHOr-0007Gk-R0 for ged-emacs-devel@m.gmane.org; Tue, 03 May 2011 11:20:33 -0400 Original-Received: from eggs.gnu.org ([140.186.70.92]:46008) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QHHOn-0007Gc-Ad for emacs-devel@gnu.org; Tue, 03 May 2011 11:20:32 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QHHOi-0006tb-Do for emacs-devel@gnu.org; Tue, 03 May 2011 11:20:29 -0400 Original-Received: from lo.gmane.org ([80.91.229.12]:37253) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QHHOh-0006tQ-TW for emacs-devel@gnu.org; Tue, 03 May 2011 11:20:24 -0400 Original-Received: from list by lo.gmane.org with local (Exim 4.69) (envelope-from ) id 1QHHOg-0002ar-2M for emacs-devel@gnu.org; Tue, 03 May 2011 17:20:22 +0200 Original-Received: from 38.98.147.130 ([38.98.147.130]) by main.gmane.org with esmtp (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Tue, 03 May 2011 17:20:22 +0200 Original-Received: from tzz by 38.98.147.130 with local (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Tue, 03 May 2011 17:20:22 +0200 X-Injected-Via-Gmane: http://gmane.org/ Original-Lines: 205 Original-X-Complaints-To: usenet@dough.gmane.org X-Gmane-NNTP-Posting-Host: 38.98.147.130 X-Face: bd.DQ~'29fIs`T_%O%C\g%6jW)yi[zuz6; d4V0`@y-~$#3P_Ng{@m+e4o<4P'#(_GJQ%TT= D}[Ep*b!\e,fBZ'j_+#"Ps?s2!4H2-Y"sx" User-Agent: Gnus/5.110018 (No Gnus v0.18) Emacs/24.0.50 (gnu/linux) Cancel-Lock: sha1:/MqMq8j1UDJ8mjs0L/f+ofAyi5Y= X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3) X-Received-From: 80.91.229.12 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 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.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:139053 Archived-At: --=-=-= Content-Type: text/plain On Mon, 02 May 2011 14:21:32 -0500 Ted Zlatanov wrote: TZ> On Mon, 02 May 2011 20:59:18 +0200 Lars Magne Ingebrigtsen wrote: LMI> Ted Zlatanov writes: LMI> "--x509keyfile" "--x509certfile" >>> LMI> to gnutlc-cli. `open-network-stream' has no concept of these things, LMI> and I'm not sure gnutls.c has, either. Ted? >>> >>> Yes, definitely, with the :keyfiles and :trustfiles parameters to >>> `gnutls-boot'. LMI> Right. Would "--x509keyfile" correspond to :keyfiles and LMI> "--x509certfile" to :trustfiles? TZ> Oh wait, I think I'm wrong. The key+cert files (client-side SSL certs) TZ> are not the same as the trust files (which verify the server's SSL TZ> cert). Let me take a look, this may require another parameter or I'm TZ> missing something. OK, I found the problem. See the attached patch. Before I was processing client key files as CRL lists (I meant to do client key+cert pairs PLUS CRL lists and somehow merged the two mentally). The attached patch adds a :keylist parameter to `gnutls-boot' which is a list of (client key file, client cert file) pairs. It also renames the :keyfiles parameter to :crlfiles since it's for CRL lists. So now you can specify any number of client certs. If the key files require a passphrase, the decoding won't work because we don't set a callback. `gnutls-negotiate' also gets the parameter changes (should I just make it take a plist?) Please look it over and I'll commit if you agree it's correct. Thanks Ted --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=gnutls-crl-and-client-certs.patch === modified file 'lisp/net/gnutls.el' --- lisp/net/gnutls.el 2011-04-25 13:47:23 +0000 +++ lisp/net/gnutls.el 2011-05-03 15:14:03 +0000 @@ -86,7 +86,7 @@ (declare-function gnutls-errorp "gnutls.c" (error)) (defun gnutls-negotiate (proc type hostname &optional priority-string - trustfiles keyfiles verify-flags + trustfiles crlfiles keylist verify-flags verify-error verify-hostname-error) "Negotiate a SSL/TLS connection. Returns proc. Signals gnutls-error. TYPE is `gnutls-x509pki' (default) or `gnutls-anon'. Use nil for the default. @@ -94,7 +94,8 @@ HOSTNAME is the remote hostname. It must be a valid string. PRIORITY-STRING is as per the GnuTLS docs, default is \"NORMAL\". TRUSTFILES is a list of CA bundles. -KEYFILES is a list of client keys. +CRLFILES is a list of CRL files. +KEYLIST is an alist of (client key file, client cert file) pairs. When VERIFY-HOSTNAME-ERROR is not nil, an error will be raised when the hostname does not match the presented certificate's host @@ -141,7 +142,8 @@ :hostname ,hostname :loglevel ,gnutls-log-level :trustfiles ,trustfiles - :keyfiles ,keyfiles + :crlfiles ,crlfiles + :keylist ,keylist :verify-flags ,verify-flags :verify-error ,verify-error :verify-hostname-error ,verify-hostname-error === modified file 'src/gnutls.c' --- src/gnutls.c 2011-05-02 02:49:06 +0000 +++ src/gnutls.c 2011-05-03 15:11:35 +0000 @@ -44,7 +44,8 @@ /* The following are for the property list of `gnutls-boot'. */ static Lisp_Object Qgnutls_bootprop_priority; static Lisp_Object Qgnutls_bootprop_trustfiles; -static Lisp_Object Qgnutls_bootprop_keyfiles; +static Lisp_Object Qgnutls_bootprop_keylist; +static Lisp_Object Qgnutls_bootprop_crlfiles; static Lisp_Object Qgnutls_bootprop_callbacks; static Lisp_Object Qgnutls_bootprop_loglevel; static Lisp_Object Qgnutls_bootprop_hostname; @@ -412,7 +413,10 @@ :trustfiles is a list of PEM-encoded trust files for `gnutls-x509pki'. -:keyfiles is a list of PEM-encoded key files for `gnutls-x509pki'. +:crlfiles is a list of PEM-encoded CRL lists for `gnutls-x509pki'. + +:keylist is an alist of PEM-encoded key files and PEM-encoded +certificates for `gnutls-x509pki'. :callbacks is an alist of callback functions, see below. @@ -471,7 +475,8 @@ /* Placeholders for the property list elements. */ Lisp_Object priority_string; Lisp_Object trustfiles; - Lisp_Object keyfiles; + Lisp_Object crlfiles; + Lisp_Object keylist; /* Lisp_Object callbacks; */ Lisp_Object loglevel; Lisp_Object hostname; @@ -486,7 +491,8 @@ hostname = Fplist_get (proplist, Qgnutls_bootprop_hostname); priority_string = Fplist_get (proplist, Qgnutls_bootprop_priority); trustfiles = Fplist_get (proplist, Qgnutls_bootprop_trustfiles); - keyfiles = Fplist_get (proplist, Qgnutls_bootprop_keyfiles); + keylist = Fplist_get (proplist, Qgnutls_bootprop_keylist); + crlfiles = Fplist_get (proplist, Qgnutls_bootprop_crlfiles); /* callbacks = Fplist_get (proplist, Qgnutls_bootprop_callbacks); */ loglevel = Fplist_get (proplist, Qgnutls_bootprop_loglevel); verify_flags = Fplist_get (proplist, Qgnutls_bootprop_verify_flags); @@ -614,15 +620,41 @@ } } - for (tail = keyfiles; !NILP (tail); tail = Fcdr (tail)) - { - Lisp_Object keyfile = Fcar (tail); - if (STRINGP (keyfile)) - { - GNUTLS_LOG2 (1, max_log_level, "setting the keyfile: ", + for (tail = crlfiles; !NILP (tail); tail = Fcdr (tail)) + { + Lisp_Object crlfile = Fcar (tail); + if (STRINGP (crlfile)) + { + GNUTLS_LOG2 (1, max_log_level, "setting the CRL file: ", + SSDATA (crlfile)); + ret = gnutls_certificate_set_x509_crl_file + (x509_cred, + SSDATA (crlfile), + file_format); + + if (ret < GNUTLS_E_SUCCESS) + return gnutls_make_error (ret); + } + else + { + error ("Sorry, GnuTLS can't use non-string CRL file %s", + SDATA (crlfile)); + } + } + + for (tail = keylist; !NILP (tail); tail = Fcdr (tail)) + { + Lisp_Object keyfile = Fcar (Fcar (tail)); + Lisp_Object certfile = Fcar (Fcdr (tail)); + if (STRINGP (keyfile) && STRINGP (certfile)) + { + GNUTLS_LOG2 (1, max_log_level, "setting the client key file: ", SSDATA (keyfile)); - ret = gnutls_certificate_set_x509_crl_file + GNUTLS_LOG2 (1, max_log_level, "setting the client cert file: ", + SSDATA (certfile)); + ret = gnutls_certificate_set_x509_key_file (x509_cred, + SSDATA (certfile), SSDATA (keyfile), file_format); @@ -631,8 +663,12 @@ } else { - error ("Sorry, GnuTLS can't use non-string keyfile %s", - SDATA (keyfile)); + if (STRINGP (keyfile)) + error ("Sorry, GnuTLS can't use non-string client cert file %s", + SDATA (certfile)); + else + error ("Sorry, GnuTLS can't use non-string client key file %s", + SDATA (keyfile)); } } } @@ -868,8 +904,11 @@ Qgnutls_bootprop_trustfiles = intern_c_string (":trustfiles"); staticpro (&Qgnutls_bootprop_trustfiles); - Qgnutls_bootprop_keyfiles = intern_c_string (":keyfiles"); - staticpro (&Qgnutls_bootprop_keyfiles); + Qgnutls_bootprop_keylist = intern_c_string (":keylist"); + staticpro (&Qgnutls_bootprop_keylist); + + Qgnutls_bootprop_crlfiles = intern_c_string (":crlfiles"); + staticpro (&Qgnutls_bootprop_crlfiles); Qgnutls_bootprop_callbacks = intern_c_string (":callbacks"); staticpro (&Qgnutls_bootprop_callbacks); --=-=-=--