From mboxrd@z Thu Jan 1 00:00:00 1970 X-Msuck: nntp://news.gmane.io/gmane.emacs.gnus.general/86831 Path: news.gmane.org!not-for-mail From: Jochen Hein Newsgroups: gmane.emacs.gnus.general Subject: Re: gssapi authentication for nnimap Date: Wed, 10 Feb 2016 22:37:08 +0100 Message-ID: <83twlgi6wr.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 1455140473 12016 80.91.229.3 (10 Feb 2016 21:41:13 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Wed, 10 Feb 2016 21:41:13 +0000 (UTC) Cc: Andreas Schwab , ding@gnus.org, Florian Weimer To: Lars Ingebrigtsen Original-X-From: ding-owner+M35056@lists.math.uh.edu Wed Feb 10 22:40:59 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 1aTcVM-0002gc-3a for ding-account@gmane.org; Wed, 10 Feb 2016 22:40:56 +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 1aTcUv-0000cz-9L; Wed, 10 Feb 2016 15:40:29 -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 1aTcUr-0000cM-MS for ding@lists.math.uh.edu; Wed, 10 Feb 2016 15:40:25 -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 1aTcUn-0007kR-8G for ding@lists.math.uh.edu; Wed, 10 Feb 2016 15:40:25 -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 1aTcUl-0003VC-G0; Wed, 10 Feb 2016 22:40:19 +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 u1ALe5ur095250 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Wed, 10 Feb 2016 22:40:06 +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 u1ALe5tc095249; Wed, 10 Feb 2016 22:40:05 +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 85BD21BD; Wed, 10 Feb 2016 22:37:08 +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]); Wed, 10 Feb 2016 22:40:07 +0100 (CET) X-Spam-Score: -1.9 (-) List-ID: Precedence: bulk Xref: news.gmane.org gmane.emacs.gnus.general:86831 Archived-At: Lars Ingebrigtsen writes: > No, open-protocol-stream shouldn't know anything about nnimap. Maybe, I'm not sure. First, I've been confused, because my changes to lisp/proto-stream.el didn't have an effect - I still got the message "Invalid connection type". Gnus uses the function as defined in network-stream.el from Emacs24. The file proto-stream.el should be deleted while removing compat stuff :-) Iff we want to add connection type 'gssapi to open-network-stream we need to handle the username somehow. gssapi.el execpts to get the username, but gsasl and imtest work without the name: $ imtest -m gssapi -p imap imap.jochen.org ... Authenticated. ... Feb 10 22:08:06 jupiter imap[6255]: login: [...] jochen@jochen.org GSSAPI User logged in For my usage that would work - I have no idea if we really need to handle different usernames on the Gnus host and the IMAP host when using GSSAPI. We may want to decide that this case will be handled when a user requests it :-) So one way forward might be to change the commands in gssapi.el (untested, I didn't make any changes to open-network-stream yet): --- gssapi.el.orig 2016-02-10 22:11:24.000000000 +0100 +++ gssapi.el 2016-02-10 22:13:28.000000000 +0100 @@ -29,19 +29,18 @@ (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 +%s is replaced with server hostname and %p with port to connect to. +The program should accept commands on stdin and return responses to stdout. Each entry in the list is tried until a successful connection is made." :version "24.1" :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 @@ 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)) The other option I see is to add an additional parameter to open-network-stream for usage with type 'gssapi, something like the following (patch will not work - must patch network-stream.el from emacs): diff --git a/lisp/proto-stream.el b/lisp/proto-stream.el index 11ffd0c..a059b0b 100644 --- a/lisp/proto-stream.el +++ b/lisp/proto-stream.el @@ -50,6 +50,7 @@ (require 'tls) (require 'starttls) +(require 'gssapi) (autoload 'gnutls-negotiate "gnutls") (autoload 'open-gnutls-stream "gnutls") @@ -80,6 +81,9 @@ PARAMETERS should be a sequence of keywords and values: `tls' -- A TLS connection. `ssl' -- Equivalent to `tls'. `shell' -- A shell connection. + `gssapi' -- a GSSAPI connection. + +:gssapi-user specifies the username for GSSAPI authentication. :return-list specifies this function's return value. If omitted or nil, return a process object. A non-nil means to @@ -129,9 +137,12 @@ PARAMETERS should be a sequence of keywords and values: 'proto-stream-open-starttls) ((memq type '(tls ssl)) 'proto-stream-open-tls) ((eq type 'shell) 'proto-stream-open-shell) - (t (error "Invalid connection type %s" type)))) + ((eq type "gssapi") 'proto-stream-open-gssapi) + (t (error "Invalid x connection type %s" type)))) (result (funcall connection-function name buffer host service parameters))) (if return-list (list (car result) :greeting (nth 1 result) @@ -148,6 +159,26 @@ PARAMETERS should be a sequence of keywords and values: nil 'plain))) +(defun proto-stream-open-gssapi (name buffer host service parameters) + (let* ((start (with-current-buffer buffer (point))) + (gssapi-user (plist-get parameters :gssapi-user)) + (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 gssapi-user))) + (greeting (proto-stream-get-response stream start eoc)) + (capabilities (when capability-command + (proto-stream-command stream + capability-command + (or eo-capa eoc)))) + (list stream + (proto-stream-get-response stream start + (plist-get parameters :end-of-command)) + greeting + capabitilies + 'gssapi))) + (defun proto-stream-open-starttls (name buffer host service parameters) (let* ((start (with-current-buffer buffer (point))) (require-tls (eq (plist-get parameters :type) 'starttls)) > >> + (let* ((stream-list >> + (if (eq nnimap-stream 'gssapi) >> + (list (open-gssapi-stream >> + "*nnimap*" (current-buffer) nnimap-address >> + (nnimap-map-port (car ports)) nnimap-user)) > > That looks OK... Here's my minimal and working diff (with fake greeting/capabilities), the commented hunk was a try to fake gssapi with connection-type 'shell. The fake was successful for a GSSAPI user, but I failed to run the same code for a normal mailbox - I guess my lisp skill needs some help...: diff --git a/lisp/gssapi.el b/lisp/gssapi.el index 1f72805..ae4fefa 100644 --- a/lisp/gssapi.el +++ b/lisp/gssapi.el @@ -92,7 +92,7 @@ tried until a successful connection is made." (setq response (match-string 1))))) (accept-process-output process 1) (sit-for 1)) - (erase-buffer) + ;(erase-buffer) (message "GSSAPI connection: %s" (or response "failed")) (if (and response (let ((case-fold-search nil)) (not (string-match "failed" response)))) diff --git a/lisp/nnimap.el b/lisp/nnimap.el index 05251ed..facb36c 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) @@ -417,7 +421,19 @@ textual parts.") login-result credentials) (when nnimap-server-port (push nnimap-server-port ports)) + +; (setq nnimap-auth (eq nnimap-stream 'gssapi)) +; (if (eq nnimap-stream 'gssapi) +; (let ((nnimap-stream 'shell) +; (nnimap-auth 'gssapi) +; (nnimap-shell-command "gsasl %s %p --mechanism=GSSAPI --authentication-id=%l")))) + (let* ((stream-list + (if (eq nnimap-stream 'gssapi) + (list (open-gssapi-stream "*nnimap*" (current-buffer) nnimap-address + (nnimap-map-port (car ports)) nnimap-user) + :greeting "* OK [CAPABILITY IMAP4rev1 LITERAL+ ID ENABLE STARTTLS LOGINDISABLED AUTH=GSSAPI SASL-IR] jupiter.jochen.org Cyrus IMAP git2.5+0-ebian-2.5~dev2015021301-0~kolab2 server ready" + :capabilities ". OK [CAPABILITY IMAP4rev1 LITERAL+ ID ENABLE ACL RIGHTS=kxten QUOTA MAILBOX-REFERRALS NAMESPACE UIDPLUS NO_ATOMIC_RENAME UNSELECT CHILDREN MULTIAPPEND BINARY CATENATE CONDSTORE ESEARCH SORT SORT=MODSEQ SORT=DISPLAY SORT=UID THREAD=ORDEREDSUBJECT THREAD=REFERENCES ANNOTATEMORE ANNOTATE-EXPERIMENT-1 METADATA LIST-EXTENDED LIST-STATUS LIST-MYRIGHTS WITHIN QRESYNC SCAN XLIST XMOVE MOVE SPECIAL-USE CREATE-SPECIAL-USE URLAUTH URLAUTH=BINARY LOGINDISABLED COMPRESS=DEFLATE X-QUOTA=STORAGE X-QUOTA=MESSAGE X-QUOTA=X-ANNOTATION-STORAGE X-QUOTA=X-NUM-FOLDERS IDLE] Success (tls protection) SESSIONID=") (open-protocol-stream "*nnimap*" (current-buffer) nnimap-address (nnimap-map-port (car ports)) @@ -433,6 +449,7 @@ textual parts.") (lambda (capabilities) (when (gnus-string-match-p "STARTTLS" capabilities) "1 STARTTLS\r\n")))) + ) (stream (car stream-list)) (props (cdr stream-list)) (greeting (plist-get props :greeting)) @@ -463,7 +480,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" > open-protocol-stream returns the greetings and the capabilities, but > open-gssapi-stream doesn't do that. So perhaps there should be a > wrapper around the latter function that will save the greeting and issue > the capability command? Something like that. First open-gssapi-stream must not call erase-buffer, see the patch above. Now I'm confused how I can transfer to code from open-network-stream in my code. Still unsure how to proceed, but quite happy with my success :-) Hopefully nobody gets confused by my trial and error hacking... Jochen -- The only problem with troubleshooting is that the trouble shoots back.