From mboxrd@z Thu Jan 1 00:00:00 1970 X-Msuck: nntp://news.gmane.io/gmane.emacs.gnus.general/86834 Path: news.gmane.org!not-for-mail From: Jochen Hein Newsgroups: gmane.emacs.gnus.general Subject: [PATCH] GSSAPI authentication for nnimap Date: Thu, 11 Feb 2016 20:51:15 +0100 Message-ID: <834mdfdo0c.fsf_-_@echidna.jochen.org> References: <87oaecan6t.fsf@mid.deneb.enyo.de> <87d1sanxyx.fsf@gnus.org> <83a8ncfnkc.fsf@echidna.jochen.org> <8737t3g4hk.fsf@gnus.org> <831t8mgbpi.fsf@echidna.jochen.org> <87io1ykh0h.fsf@linux-m68k.org> <83vb5yhjpo.fsf@echidna.jochen.org> <87wpqeix2s.fsf@linux-m68k.org> <83zivammhs.fsf@echidna.jochen.org> <83wpqd4pk6.fsf@echidna.jochen.org> <87egcl795w.fsf@gnus.org> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain X-Trace: ger.gmane.org 1455220608 18141 80.91.229.3 (11 Feb 2016 19:56:48 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Thu, 11 Feb 2016 19:56:48 +0000 (UTC) Cc: Andreas Schwab , ding@gnus.org, Florian Weimer To: Lars Ingebrigtsen Original-X-From: ding-owner+M35059@lists.math.uh.edu Thu Feb 11 20:56:36 2016 Return-path: Envelope-to: ding-account@gmane.org Original-Received: from lists1.math.uh.edu ([129.7.128.208]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1aTxLw-0003FY-36 for ding-account@gmane.org; Thu, 11 Feb 2016 20:56:36 +0100 Original-Received: from localhost ([127.0.0.1] helo=lists.math.uh.edu) by lists1.math.uh.edu with smtp (Exim 4.85) (envelope-from ) id 1aTxL8-0001FO-Pz; Thu, 11 Feb 2016 13:55:46 -0600 Original-Received: from mx2.math.uh.edu ([129.7.128.33]) by lists1.math.uh.edu with esmtps (TLSv1.2:AES128-GCM-SHA256:128) (Exim 4.85) (envelope-from ) id 1aTxL4-0001Ep-Ej for ding@lists.math.uh.edu; Thu, 11 Feb 2016 13:55:42 -0600 Original-Received: from quimby.gnus.org ([80.91.231.51]) by mx2.math.uh.edu with esmtps (TLSv1.2:DHE-RSA-AES128-SHA:128) (Exim 4.85) (envelope-from ) id 1aTxL2-0002yE-Bs for ding@lists.math.uh.edu; Thu, 11 Feb 2016 13:55:42 -0600 Original-Received: from smtp.dinoex.de ([188.40.204.4] ident=root) by quimby.gnus.org with esmtps (TLS1.2:DHE_RSA_AES_256_CBC_SHA256:256) (Exim 4.80) (envelope-from ) id 1aTxL0-0000Dn-D7; Thu, 11 Feb 2016 20:55:38 +0100 Original-Received: from smtp.dinoex.de (uucp@smtp.dinoex.de [188.40.204.4]) by smtp.dinoex.de (8.15.2/8.15.1) with ESMTPS id u1BJt83p040755 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 11 Feb 2016 20:55:09 +0100 (CET) (envelope-from jochen@jochen.org) Original-Received: (from uucp@localhost) by smtp.dinoex.de (8.15.2/8.15.1/Submit) with UUCP id u1BJt8nV040754; Thu, 11 Feb 2016 20:55:08 +0100 (CET) (envelope-from jochen@jochen.org) Original-Received: from echidna.jochen.org (echidna.jochen.org [IPv6:fd23:e163:19f7:1234:222:4dff:fe7c:d76a]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by jupiter.jochen.org (Postfix) with ESMTPSA id 05A59104; Thu, 11 Feb 2016 20:51:16 +0100 (CET) X-Message-Flag: This space is intentionally left blank In-Reply-To: <87egcl795w.fsf@gnus.org> (Lars Ingebrigtsen's message of "Wed, 10 Feb 2016 10:31:39 +1100") User-Agent: Gnus/5.130015 (Ma Gnus v0.15) Emacs/24.4 (gnu/linux) X-Milter: Spamilter (Reciever: smtp.dinoex.de; Sender-ip: 188.40.204.4; Sender-helo: smtp.dinoex.de;) X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.4.3 (smtp.dinoex.de [188.40.204.4]); Thu, 11 Feb 2016 20:55:10 +0100 (CET) X-Spam-Score: -1.9 (-) List-ID: Precedence: bulk Xref: news.gmane.org gmane.emacs.gnus.general:86834 Archived-At: The following patches add GSSAPI support to nnimap. I'll comment what I did and why above each patch. I'm currently cloning the emacs repository and I hope to forward port the patches and add/adapt the documentation accordingly. This post is to gather feedback concerning the design and the lisp code. Do we need ChangeLog patches as well to apply the patches to current emacs? Right now I've not worked on updates to the gnus manual. The first patch is against gssapi.el from Ma Gnus v0.15, the latest gnus release. I've removed the options "--authentication-id" from gsasl and "-u" from imtest invocations. If somebody needs these, we could add the user parameter back to open-gssapi-stream as an optional parameter. That way open-network-stream could still call open-gssapi-stream without changes, other users can pass a username. I'm not sure if the username is really neded - my usecase works fine without. If we don't want to add an optional parameter or need to pass the username from nnimap.el to network-stream.el and finally to gssapi.el, we could add a property like :gssapi-user to the call to open-network-stream and pass that to open-gssapi-stream. The second change is removing the call to erase buffer. That way the function open-network-stream-gssapi in network-stream.el can fetch the greeting and capabilities string from the buffer. I currently know of one difference between gsasl and imtest: connections with gsasl use TLS, imtest doesn't. If we want that, we can add '-t ""' to the imtest call according to the imtest manpage: -t keyfile Enable TLS. keyfile contains the TLS public and private keys. Specify "" to negotiate a TLS encryption layer but not use TLS authentication. Another option could be to handle STARTTLS in network-stream-open-gssapi. For my usecase I'll use gsasl, so I've not added code for that. Caveat: gsasl in Debian Jessie doesn't handle GSSAPI, so you need to compile it yourself and make sure gssapi/krb5 is enabled: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=768352 https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=776847 Both gsasl and imtest give no useful error message when the user doesn't have a ticket or it is expired. I've also not tried to handle that case in my patches. This may need further work. diff --git a/lisp/gssapi.el b/lisp/gssapi.el index 1f72805..08b2ec3 100644 --- a/lisp/gssapi.el +++ b/lisp/gssapi.el @@ -29,9 +29,8 @@ (defcustom gssapi-program (list (concat "gsasl %s %p " - "--mechanism GSSAPI " - "--authentication-id %l") - "imtest -m gssapi -u %l -p %p %s") + "--mechanism GSSAPI ") + "imtest -m gssapi -p %p %s") "List of strings containing commands for GSSAPI (krb5) authentication. %s is replaced with server hostname, %p with port to connect to, and %l with the user name. The program should accept commands on @@ -41,7 +40,7 @@ tried until a successful connection is made." :group 'network :type '(repeat string)) -(defun open-gssapi-stream (name buffer server port user) +(defun open-gssapi-stream (name buffer server port) (let ((cmds gssapi-program) cmd done) (with-current-buffer buffer @@ -57,8 +56,7 @@ tried until a successful connection is made." cmd (format-spec-make ?s server - ?p (number-to-string port) - ?l user)))) + ?p (number-to-string port))))) response) (when process (while (and (memq (process-status process) '(open run)) @@ -92,7 +90,6 @@ tried until a successful connection is made." (setq response (match-string 1))))) (accept-process-output process 1) (sit-for 1)) - (erase-buffer) (message "GSSAPI connection: %s" (or response "failed")) (if (and response (let ((case-fold-search nil)) (not (string-match "failed" response)))) The next patch is against network-stream.el from Emacs 24.4.1. The first part adds 'gssapi as a valid stream type and calls network-stream-open-gssapi. The second part simply defines that function, based on the other open-functions in network-stream.el. No special handling, no STARTTLS. I've not checked the value of capabilities that is returned, but further procession in nnimap.el worked fine. Most likely this patch needs forward porting to current emacs. --- network-stream.el.orig 2016-02-11 17:26:06.000000000 +0100 +++ network-stream.el 2016-02-11 18:31:02.000000000 +0100 @@ -44,6 +44,7 @@ (require 'tls) (require 'starttls) +(require 'gssapi) (require 'auth-source) (autoload 'gnutls-negotiate "gnutls") @@ -85,6 +86,7 @@ `tls' -- A TLS connection. `ssl' -- Equivalent to `tls'. `shell' -- A shell connection. + `gssapi' -- a GSSAPI connection. :return-list specifies this function's return value. If omitted or nil, return a process object. A non-nil means to @@ -156,6 +158,7 @@ 'network-stream-open-starttls) ((memq type '(tls ssl)) 'network-stream-open-tls) ((eq type 'shell) 'network-stream-open-shell) + ((eq type 'gssapi) 'network-stream-open-gssapi) (t (error "Invalid connection type %s" type)))) result) (unwind-protect @@ -172,6 +175,24 @@ :error (nth 4 result)) (car result)))))) +(defun network-stream-open-gssapi (name buffer host service parameters) + (let* ((start (with-current-buffer buffer (point))) + (capability-command (plist-get parameters :capability-command)) + (eoc (plist-get parameters :end-of-command)) + (eo-capa (or (plist-get parameters :end-of-capability) + eoc)) + (stream (open-gssapi-stream name buffer host service)) + (greeting (network-stream-get-response stream start eoc)) + (capabilities (when capability-command + (network-stream-command stream + capability-command + (or eo-capa eoc))))) + ;; Return (STREAM GREETING CAPABILITIES RESULTING-TYPE) + (list stream + greeting + capabilities + 'gssapi))) + (defun network-stream-certificate (host service parameters) (let ((spec (plist-get :client-certificate parameters))) (cond And finally we use the facilities in nnimap.el. The patch again is against Ma Gnus v0.15. We add 'gssapi as a valid stream type, provide a message when using GSSAPI similar to other stream types. All the heavy lifting is done in network-stream.el, so only one small change is needed: When using GSSAPI the connection is already authenticated, so we don't need to provide any credentials. diff --git a/lisp/nnimap.el b/lisp/nnimap.el index 05251ed..2eca2b4 100644 --- a/lisp/nnimap.el +++ b/lisp/nnimap.el @@ -65,7 +65,7 @@ it will default to `imap'.") (defvoo nnimap-stream 'undecided "How nnimap talks to the IMAP server. The value should be either `undecided', `ssl' or `tls', -`network', `starttls', `plain', or `shell'. +`network', `starttls', `plain', `gssapi', or `shell'. If the value is `undecided', nnimap tries `ssl' first, then falls back on `network'.") @@ -408,6 +408,10 @@ textual parts.") (nnheader-message 7 "Opening connection to %s via shell..." nnimap-address) '("imap")) + ((eq nnimap-stream 'gssapi) + (nnheader-message 7 "Opening connection to %s via GSSAPI..." + nnimap-address) + '(143)) ((memq nnimap-stream '(ssl tls)) (nnheader-message 7 "Opening connection to %s via tls..." nnimap-address) @@ -463,7 +467,9 @@ textual parts.") (setf (nnimap-capabilities nnimap-object) (mapcar #'upcase (split-string capabilities))) - (unless (gnus-string-match-p "[*.] PREAUTH" greeting) + (unless (or + (eq nnimap-stream 'gssapi) + (gnus-string-match-p "[*.] PREAUTH" greeting)) (if (not (setq credentials (if (eq nnimap-authenticator 'anonymous) (list "anonymous" Any comments? Jochen -- The only problem with troubleshooting is that the trouble shoots back.