Gnus development mailing list
 help / color / mirror / Atom feed
* gssapi authentication for nnimap
@ 2015-11-29 14:35 Florian Weimer
  2016-02-06  6:40 ` Lars Ingebrigtsen
  0 siblings, 1 reply; 22+ messages in thread
From: Florian Weimer @ 2015-11-29 14:35 UTC (permalink / raw)
  To: ding

In the past, it was possible to authenticate to an IMAP server using
GSSAPI (over a TLS connection).  This enabled me to use an active
Kerberos ticket to authenticate to a Zimbra email server.  The old way
of configuring this no longer works.  Is there a replacement?

Florian



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: gssapi authentication for nnimap
  2015-11-29 14:35 gssapi authentication for nnimap Florian Weimer
@ 2016-02-06  6:40 ` Lars Ingebrigtsen
  2016-02-07 17:16   ` Jochen Hein
  0 siblings, 1 reply; 22+ messages in thread
From: Lars Ingebrigtsen @ 2016-02-06  6:40 UTC (permalink / raw)
  To: Florian Weimer; +Cc: ding

Florian Weimer <fw@deneb.enyo.de> writes:

> In the past, it was possible to authenticate to an IMAP server using
> GSSAPI (over a TLS connection).  This enabled me to use an active
> Kerberos ticket to authenticate to a Zimbra email server.  The old way
> of configuring this no longer works.  Is there a replacement?

I think somebody was working on this?  But I don't recall what the
outcome was.  Anybody remember?

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: gssapi authentication for nnimap
  2016-02-06  6:40 ` Lars Ingebrigtsen
@ 2016-02-07 17:16   ` Jochen Hein
  2016-02-08  5:23     ` Lars Ingebrigtsen
  0 siblings, 1 reply; 22+ messages in thread
From: Jochen Hein @ 2016-02-07 17:16 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: Florian Weimer, ding

Lars Ingebrigtsen <larsi@gnus.org> writes:

> Florian Weimer <fw@deneb.enyo.de> writes:
>
>> In the past, it was possible to authenticate to an IMAP server using
>> GSSAPI (over a TLS connection).  This enabled me to use an active
>> Kerberos ticket to authenticate to a Zimbra email server.  The old way
>> of configuring this no longer works.  Is there a replacement?
>
> I think somebody was working on this?  But I don't recall what the
> outcome was.  Anybody remember?

I've recently tried it.  The following worked for me:

(setq gnus-secondary-select-methods
      '((nnml "private")
              (nnimap "jochen@jochen.org"
                (nnimap-expunge t)
                (nnimap-stream shell)
                (nnimap-shell-program "echo -e '* PREAUTH\r\n'; imtest %s %p -m GSSAPI")
                (nnimap-address "imap.jochen.org"))
...

We should remove references in the gnus manual to gssapi or reference
nnimap-shell-program.  I'm not sure that the following gssapi options
would be still useful:

    `:stream'
              What stream to use for connecting to the server, this is one
              of the symbols in `imap-stream-alist'.  Right now, this means
              `gssapi', `kerberos4', `starttls', `tls', `ssl', `shell' or
              the default `network'.

    `:authentication'
              Which authenticator to use for authenticating to the server,
              this is one of the symbols in `imap-authenticator-alist'.
              Right now, this means `gssapi', `kerberos4', `digest-md5',
              `cram-md5', `anonymous' or the default `login'.

Jochen

-- 
The only problem with troubleshooting is that the trouble shoots back.



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: gssapi authentication for nnimap
  2016-02-07 17:16   ` Jochen Hein
@ 2016-02-08  5:23     ` Lars Ingebrigtsen
  2016-02-08  9:51       ` Jochen Hein
  2016-02-08 20:59       ` Jochen Hein
  0 siblings, 2 replies; 22+ messages in thread
From: Lars Ingebrigtsen @ 2016-02-08  5:23 UTC (permalink / raw)
  To: Jochen Hein; +Cc: Florian Weimer, ding

Jochen Hein <jochen@jochen.org> writes:

> I've recently tried it.  The following worked for me:
>
> (setq gnus-secondary-select-methods
>       '((nnml "private")
>               (nnimap "jochen@jochen.org"
>                 (nnimap-expunge t)
>                 (nnimap-stream shell)
>                 (nnimap-shell-program "echo -e '* PREAUTH\r\n'; imtest %s %p -m GSSAPI")
>                 (nnimap-address "imap.jochen.org"))
> ...

Nice.

> We should remove references in the gnus manual to gssapi or reference
> nnimap-shell-program.  I'm not sure that the following gssapi options
> would be still useful:
>
>     `:stream'
>               What stream to use for connecting to the server, this is one
>               of the symbols in `imap-stream-alist'.  Right now, this means
>               `gssapi', `kerberos4', `starttls', `tls', `ssl', `shell' or
>               the default `network'.
>
>     `:authentication'
>               Which authenticator to use for authenticating to the server,
>               this is one of the symbols in `imap-authenticator-alist'.
>               Right now, this means `gssapi', `kerberos4', `digest-md5',
>               `cram-md5', `anonymous' or the default `login'.

We do still have the gssapi.el file, so we could presumably get this
stuff working again, if somebody with access to a server that uses
gssapi could hack away at it a bit...

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: gssapi authentication for nnimap
  2016-02-08  5:23     ` Lars Ingebrigtsen
@ 2016-02-08  9:51       ` Jochen Hein
  2016-02-08 20:59       ` Jochen Hein
  1 sibling, 0 replies; 22+ messages in thread
From: Jochen Hein @ 2016-02-08  9:51 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: Florian Weimer, ding

Lars Ingebrigtsen <larsi@gnus.org> writes:

>> We should remove references in the gnus manual to gssapi or reference
>> nnimap-shell-program.  I'm not sure that the following gssapi options
>> would be still useful:
>>
>>     `:stream'
>>               What stream to use for connecting to the server, this is one
>>               of the symbols in `imap-stream-alist'.  Right now, this means
>>               `gssapi', `kerberos4', `starttls', `tls', `ssl', `shell' or
>>               the default `network'.
>>
>>     `:authentication'
>>               Which authenticator to use for authenticating to the server,
>>               this is one of the symbols in `imap-authenticator-alist'.
>>               Right now, this means `gssapi', `kerberos4', `digest-md5',
>>               `cram-md5', `anonymous' or the default `login'.
>
> We do still have the gssapi.el file, so we could presumably get this
> stuff working again, if somebody with access to a server that uses
> gssapi could hack away at it a bit...

I had a look at gssapi.el - I think that file only handles the :stream
part of gssapi. Right?  Doesn't look to hard to hack on that file,
except that Debians gsasl in Jessie doesn't handle gssapi due to bug
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=776847
I'll have a look at backporting the newer gsasl package.

Jochen

-- 
The only problem with troubleshooting is that the trouble shoots back.



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: gssapi authentication for nnimap
  2016-02-08  5:23     ` Lars Ingebrigtsen
  2016-02-08  9:51       ` Jochen Hein
@ 2016-02-08 20:59       ` Jochen Hein
  2016-02-08 21:51         ` Andreas Schwab
  1 sibling, 1 reply; 22+ messages in thread
From: Jochen Hein @ 2016-02-08 20:59 UTC (permalink / raw)
  To: ding; +Cc: Lars Ingebrigtsen, Florian Weimer

Lars Ingebrigtsen <larsi@gnus.org> writes:

> We do still have the gssapi.el file, so we could presumably get this
> stuff working again, if somebody with access to a server that uses
> gssapi could hack away at it a bit...

I've tried to follow thru the twisted maze of functions, but was not
successful.  First, let's start with a log using gsasl to connect to my
imap server with telnet:

$ telnet imap.jochen.org imap
Trying fd23:e163:19f7:1234:216:3eff:feef:b5d4...
Connected to jupiter.jochen.org.
Escape character is '^]'.
* OK [CAPABILITY IMAP4rev1 LITERAL+ ID ENABLE STARTTLS LOGINDISABLED AUTH=GSSAPI SASL-IR] jupiter.jochen.org Cyrus IMAP git2.5+0-Debian-2.5~dev2015021301-0~kolab2 server ready

My server advertises both STARTTLS and AUTH=GSSAPI - I can use STARTTLS
and password authentication or GSSAPI.  Let's try with gsasl (with
LANG=C, so the last two lines are not translated):

$ LANG=C gsasl imap.jochen.org imap --mechanism=GSSAPI --authentication-id=jochen@JOCHEN.ORG
Trying 'jupiter.jochen.org'...
* OK [CAPABILITY IMAP4rev1 LITERAL+ ID ENABLE STARTTLS LOGINDISABLED AUTH=GSSAPI SASL-IR] jupiter.jochen.org Cyrus IMAP git2.5+0-Debian-2.5~dev2015021301-0~kolab2 server ready
. CAPABILITY
* 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 STARTTLS LOGINDISABLED AUTH=GSSAPI SASL-IR COMPRESS=DEFLATE X-QUOTA=STORAGE X-QUOTA=MESSAGE X-QUOTA=X-ANNOTATION-STORAGE X-QUOTA=X-NUM-FOLDERS IDLE
. OK Completed
. STARTTLS
. OK Begin TLS negotiation now
. CAPABILITY
* 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 AUTH=PLAIN AUTH=LOGIN AUTH=GSSAPI SASL-IR COMPRESS=DEFLATE X-QUOTA=STORAGE X-QUOTA=MESSAGE X-QUOTA=X-ANNOTATION-STORAGE X-QUOTA=X-NUM-FOLDERS IDLE
. OK Completed
. AUTHENTICATE GSSAPI
+
YII...[lotsmorebas64]...EOsDQ==
+ YIG...[againbase64]...k+V86o=

+ BQQF/wAMAAAAAAAA...HRui4A=
BQQE/wAMAAAAAAAA.....YYR+jKQ3/PncQ==
. 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=<jupiter.jochen.org-20677-1454962976-1-9320604477375554810>
Client authentication finished (server trusted)...
Enter application data (EOF to finish):

So my guess is that we only need to start gsasl and get a session with
STARTTLS and authenticated with GSSAPI.  Nice.

Using imtest with the options defined in gssapi.el gives me a non-TLS
session - at least I don't see any STARTTLS.

So the basic commands from gssapi.el seem to work nicely.  The only
function in that file is open-gssapi-stream, so, how get I gnus to call
that function?

In
https://lists.gnu.org/archive/html/info-gnus-english/2012-06/msg00009.html
there's a diff, that uses nnimap-authenticator.  Is that the right
option to use, or would be nnimap-stream better?

Anyway, I've modified that diff like that:

diff --git a/lisp/nnimap.el b/lisp/nnimap.el
index 05251ed..aba48f3 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 "jk:Opening connection to %s via GSSAPI..."
+				nnimap-address)
+	      '("imap"))
 	     ((memq nnimap-stream '(ssl tls))
 	      (nnheader-message 7 "Opening connection to %s via tls..."
 				nnimap-address)
@@ -417,22 +421,26 @@ textual parts.")
            login-result credentials)
       (when nnimap-server-port
 	(push nnimap-server-port ports))
-      (let* ((stream-list
-	      (open-protocol-stream
-	       "*nnimap*" (current-buffer) nnimap-address
-	       (nnimap-map-port (car ports))
-	       :type nnimap-stream
-	       :warn-unless-encrypted t
-	       :return-list t
-	       :shell-command nnimap-shell-program
-	       :capability-command "1 CAPABILITY\r\n"
-               :always-query-capabilities t
-	       :end-of-command "\r\n"
-	       :success " OK "
-	       :starttls-function
-	       (lambda (capabilities)
-		 (when (gnus-string-match-p "STARTTLS" capabilities)
-		   "1 STARTTLS\r\n"))))
+	(let* ((stream-list
+		(if (eq nnimap-stream 'gssapi)
+		    (open-protocol-stream
+		     "*nnimap*" (current-buffer) nnimap-address
+		     (nnimap-map-port (car ports)) nnimap-user)
+		  (open-protocol-stream
+		   "*nnimap*" (current-buffer) nnimap-address
+		   (nnimap-map-port (car ports))
+		   :type nnimap-stream
+		   :warn-unless-encrypted t
+		   :return-list t
+		   :shell-command nnimap-shell-program
+		   :capability-command "1 CAPABILITY\r\n"
+		   :always-query-capabilities t
+		   :end-of-command "\r\n"
+		   :success " OK "
+		   :starttls-function
+		   (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))

Now I get:

Warning: Opening nnimap server on jochen@jochen.org...failed: ; Unable
to open server nnimap+jochen@jochen.org due to: Wrong type argument:
listp, #<process *nnimap*>

Any idea how to wire that all together?  My limited lisp knowledge isn't
really useful...

Jochen

-- 
The only problem with troubleshooting is that the trouble shoots back.



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: gssapi authentication for nnimap
  2016-02-08 20:59       ` Jochen Hein
@ 2016-02-08 21:51         ` Andreas Schwab
  2016-02-08 23:21           ` Jochen Hein
  0 siblings, 1 reply; 22+ messages in thread
From: Andreas Schwab @ 2016-02-08 21:51 UTC (permalink / raw)
  To: Jochen Hein; +Cc: ding, Lars Ingebrigtsen, Florian Weimer

Jochen Hein <jochen@jochen.org> writes:

> +	(let* ((stream-list
> +		(if (eq nnimap-stream 'gssapi)
> +		    (open-protocol-stream
> +		     "*nnimap*" (current-buffer) nnimap-address
> +		     (nnimap-map-port (car ports)) nnimap-user)
> +		  (open-protocol-stream
> +		   "*nnimap*" (current-buffer) nnimap-address
> +		   (nnimap-map-port (car ports))
> +		   :type nnimap-stream
> +		   :warn-unless-encrypted t
> +		   :return-list t
                   ^^^^^^^^^^^^^^
> +		   :shell-command nnimap-shell-program
> +		   :capability-command "1 CAPABILITY\r\n"
> +		   :always-query-capabilities t
> +		   :end-of-command "\r\n"
> +		   :success " OK "
> +		   :starttls-function
> +		   (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))
>
> Now I get:
>
> Warning: Opening nnimap server on jochen@jochen.org...failed: ; Unable
> to open server nnimap+jochen@jochen.org due to: Wrong type argument:
> listp, #<process *nnimap*>

You didn't tell open-protocol-stream to return a list.

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: gssapi authentication for nnimap
  2016-02-08 21:51         ` Andreas Schwab
@ 2016-02-08 23:21           ` Jochen Hein
  2016-02-08 23:47             ` Andreas Schwab
  0 siblings, 1 reply; 22+ messages in thread
From: Jochen Hein @ 2016-02-08 23:21 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: ding, Lars Ingebrigtsen, Florian Weimer

Andreas Schwab <schwab@linux-m68k.org> writes:

> Jochen Hein <jochen@jochen.org> writes:
>
>> +		   :return-list t
>                    ^^^^^^^^^^^^^^
>> +		   :shell-command nnimap-shell-program

>> Warning: Opening nnimap server on jochen@jochen.org...failed: ; Unable
>> to open server nnimap+jochen@jochen.org due to: Wrong type argument:
>> listp, #<process *nnimap*>
>
> You didn't tell open-protocol-stream to return a list.

I tried that - but no success.  I also tried to get a grip on the
program flow, but I'm at a loss here.

Jochen

-- 
The only problem with troubleshooting is that the trouble shoots back.



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: gssapi authentication for nnimap
  2016-02-08 23:21           ` Jochen Hein
@ 2016-02-08 23:47             ` Andreas Schwab
  2016-02-09  6:22               ` Jochen Hein
  0 siblings, 1 reply; 22+ messages in thread
From: Andreas Schwab @ 2016-02-08 23:47 UTC (permalink / raw)
  To: Jochen Hein; +Cc: ding, Lars Ingebrigtsen, Florian Weimer

Jochen Hein <jochen@jochen.org> writes:

> Andreas Schwab <schwab@linux-m68k.org> writes:
>
>> Jochen Hein <jochen@jochen.org> writes:
>>
>>> +		   :return-list t
>>                    ^^^^^^^^^^^^^^
>>> +		   :shell-command nnimap-shell-program
>
>>> Warning: Opening nnimap server on jochen@jochen.org...failed: ; Unable
>>> to open server nnimap+jochen@jochen.org due to: Wrong type argument:
>>> listp, #<process *nnimap*>
>>
>> You didn't tell open-protocol-stream to return a list.
>
> I tried that - but no success.

What did you try?

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: gssapi authentication for nnimap
  2016-02-08 23:47             ` Andreas Schwab
@ 2016-02-09  6:22               ` Jochen Hein
  2016-02-09 20:05                 ` Jochen Hein
  0 siblings, 1 reply; 22+ messages in thread
From: Jochen Hein @ 2016-02-09  6:22 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: ding, Lars Ingebrigtsen, Florian Weimer

Andreas Schwab <schwab@linux-m68k.org> writes:

> What did you try?

Right now I have the following diff to nnimap.el:

diff --git a/lisp/nnimap.el b/lisp/nnimap.el
index 05251ed..02c651e 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 "jk:Opening connection to %s via GSSAPI..."
+				nnimap-address)
+	      '("imap"))
 	     ((memq nnimap-stream '(ssl tls))
 	      (nnheader-message 7 "Opening connection to %s via tls..."
 				nnimap-address)
@@ -417,28 +421,35 @@ textual parts.")
            login-result credentials)
       (when nnimap-server-port
 	(push nnimap-server-port ports))
-      (let* ((stream-list
-	      (open-protocol-stream
-	       "*nnimap*" (current-buffer) nnimap-address
-	       (nnimap-map-port (car ports))
-	       :type nnimap-stream
-	       :warn-unless-encrypted t
-	       :return-list t
-	       :shell-command nnimap-shell-program
-	       :capability-command "1 CAPABILITY\r\n"
-               :always-query-capabilities t
-	       :end-of-command "\r\n"
-	       :success " OK "
-	       :starttls-function
-	       (lambda (capabilities)
-		 (when (gnus-string-match-p "STARTTLS" capabilities)
-		   "1 STARTTLS\r\n"))))
+	(let* ((stream-list
+		(if (eq nnimap-stream 'gssapi)
+		    (open-protocol-stream
+		     "*nnimap*" (current-buffer) nnimap-address
+		     (nnimap-map-port (car ports)) nnimap-user
+			:return-list t)
+		  (open-protocol-stream
+		   "*nnimap*" (current-buffer) nnimap-address
+		   (nnimap-map-port (car ports))
+		   :type nnimap-stream
+		   :warn-unless-encrypted t
+		   :return-list t
+		   :shell-command nnimap-shell-program
+		   :capability-command "1 CAPABILITY\r\n"
+		   :always-query-capabilities t
+		   :end-of-command "\r\n"
+		   :success " OK "
+		   :starttls-function
+		   (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))
 	     (capabilities (plist-get props :capabilities))
 	     (stream-type (plist-get props :type)))
 	(when (and stream (not (memq (process-status stream) '(open run))))
+	      (nnheader-message 7 "XXX ...")
 	  (setq stream nil))
 
         (when (and (fboundp 'set-network-process-option) ;; Not in XEmacs.
@@ -450,12 +461,14 @@ textual parts.")
 
 	(setf (nnimap-process nnimap-object) stream)
 	(setf (nnimap-stream-type nnimap-object) stream-type)
+	(nnheader-message 7 "YYY ...")
 	(if (not stream)
 	    (progn
 	      (nnheader-report 'nnimap "Unable to contact %s:%s via %s"
 			       nnimap-address (car ports) nnimap-stream)
 	      'no-connect)
 	  (gnus-set-process-query-on-exit-flag stream nil)
+	  (nnheader-message 7 "ZZZ ...")
 	  (if (not (gnus-string-match-p "[*.] \\(OK\\|PREAUTH\\)" greeting))
 	      (nnheader-report 'nnimap "%s" greeting)
 	    ;; Store the greeting (for debugging purposes).

I've sprinled some messages into the function, which trigger when
connecting as a non-GSSAPI user:

Opening nnimap server on jochen@jochen.org...
jk:Opening connection to imap.jochen.org via GSSAPI...
Unable to open server nnimap+jochen@jochen.org due to: Wrong type
argument: listp, #<process *nnimap*>
Opening nnimap server on jochen@jochen.org...failed:
Opening nnimap server on nongssapi-user@jochen.org...
Opening connection to imap.jochen.org via tls...
YYY ...
ZZZ ...
Opening connection to imap.jochen.org...done
Opening nnimap server on nongssapi-user@jochen.org...done

I was not successful getting a backtrace at the "Wrong type" message -
so I'm not sure what call is failing.

My gnus config for gnus-secondary select methods is:

(require 'gssapi)
(setq debug-on-error t)
; Mail mittels nnml und imap lesen
(setq gnus-secondary-select-methods
      '((nnml "private")
	(nnimap "jochen@jochen.org"
		(nnimap-expunge t)
		(nnimap-stream        gssapi)
		(nnimap-address "imap.jochen.org"))
[...]

When I quit gnus after connecting with that config I get asked:
Buffer " *nnimap imap.jochen.org nil  *nntpd**" has a running process;
kill it? (yes or no)
If I look at the buffer I see:
* OK [CAPABILITY IMAP4rev1 LITERAL+ ID ENABLE STARTTLS LOGINDISABLED AUTH=GSSAPI SASL-IR] jupiter.jochen.org Cyrus IMAP git2.5+0-Debian-2.5~dev2015021301-0~kolab2 server ready^M
But no running process...

I've not arrived at gssapi.el, because that message is missing:

(defun open-gssapi-stream (name buffer server port user)
  (let ((cmds gssapi-program)
          cmd done)
    (with-current-buffer buffer
      (while (and (not done)
                  (setq cmd (pop cmds)))
        (message "Opening GSSAPI connection with `%s'..." cmd)

Any idea how to get further?

Jochen

-- 
The only problem with troubleshooting is that the trouble shoots back.



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: gssapi authentication for nnimap
  2016-02-09  6:22               ` Jochen Hein
@ 2016-02-09 20:05                 ` Jochen Hein
  2016-02-09 23:31                   ` Lars Ingebrigtsen
  0 siblings, 1 reply; 22+ messages in thread
From: Jochen Hein @ 2016-02-09 20:05 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: ding, Lars Ingebrigtsen, Florian Weimer

Jochen Hein <jochen@jochen.org> writes:


I've got a few steps further - I seem to be able to authenticate with
GSSAPI. Here's what I've done right now:

First the log from *Messages*:

Opening nnimap server on jochen@jochen.org...
jk:Opening connection to imap.jochen.org via GSSAPI...
Opening GSSAPI connection with `gsasl %s %p --mechanism GSSAPI --authentication-id %l'...
GSSAPI connection: Client authentication finished (server trusted)...
YYY ...
ZZZ ...
Unable to open server nnimap+jochen@jochen.org due to: Wrong type argument: stringp, nil
Opening nnimap server on jochen@jochen.org...failed:

Right now I have the following diff to nnimap.el.  The second hunk
hardcodes the imap port number - I didn't get that to work otherwise.
In the third hunk I call open-gssapi-stream directly -
open-protocol-stream doesn't handle the nnimap-user.  Should that be
added to open-protocol-stream?

diff --git a/lisp/nnimap.el b/lisp/nnimap.el
index 05251ed..d11f4d0 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 "jk: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,28 +421,33 @@ textual parts.")
            login-result credentials)
       (when nnimap-server-port
 	(push nnimap-server-port ports))
-      (let* ((stream-list
-	      (open-protocol-stream
-	       "*nnimap*" (current-buffer) nnimap-address
-	       (nnimap-map-port (car ports))
-	       :type nnimap-stream
-	       :warn-unless-encrypted t
-	       :return-list t
-	       :shell-command nnimap-shell-program
-	       :capability-command "1 CAPABILITY\r\n"
-               :always-query-capabilities t
-	       :end-of-command "\r\n"
-	       :success " OK "
-	       :starttls-function
-	       (lambda (capabilities)
-		 (when (gnus-string-match-p "STARTTLS" capabilities)
-		   "1 STARTTLS\r\n"))))
+	(let* ((stream-list
+		(if (eq nnimap-stream 'gssapi)
+		     (list (open-gssapi-stream
+		      "*nnimap*" (current-buffer) nnimap-address
+		      (nnimap-map-port (car ports)) nnimap-user))
+		  (open-protocol-stream
+		   "*nnimap*" (current-buffer) nnimap-address
+		   (nnimap-map-port (car ports))
+		   :type nnimap-stream
+		   :warn-unless-encrypted t
+		   :return-list t
+		   :shell-command nnimap-shell-program
+		   :capability-command "1 CAPABILITY\r\n"
+		   :always-query-capabilities t
+		   :end-of-command "\r\n"
+		   :success " OK "
+		   :starttls-function
+		   (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))
 	     (capabilities (plist-get props :capabilities))
 	     (stream-type (plist-get props :type)))
 	(when (and stream (not (memq (process-status stream) '(open run))))
+	      (nnheader-message 7 "XXX ...")
 	  (setq stream nil))
 
         (when (and (fboundp 'set-network-process-option) ;; Not in XEmacs.
@@ -450,12 +459,14 @@ textual parts.")
 
 	(setf (nnimap-process nnimap-object) stream)
 	(setf (nnimap-stream-type nnimap-object) stream-type)
+	(nnheader-message 7 "YYY ...")
 	(if (not stream)
 	    (progn
 	      (nnheader-report 'nnimap "Unable to contact %s:%s via %s"
 			       nnimap-address (car ports) nnimap-stream)
 	      'no-connect)
 	  (gnus-set-process-query-on-exit-flag stream nil)
+	  (nnheader-message 7 "ZZZ ...")
 	  (if (not (gnus-string-match-p "[*.] \\(OK\\|PREAUTH\\)" greeting))
 	      (nnheader-report 'nnimap "%s" greeting)
 	    ;; Store the greeting (for debugging purposes).

I've sprinkled some messages into the function, which trigger when
connecting as a non-GSSAPI user:

My gnus config for gnus-secondary select methods is:

(require 'gssapi)  		  	 ; move into which gnus files?
; Mail mittels nnml und imap lesen
(setq gnus-secondary-select-methods
      '((nnml "private")
	(nnimap "jochen@jochen.org"
		(nnimap-expunge t)
		(nnimap-stream        gssapi)
		(nnimap-user        "jochen@jochen.org")
		(nnimap-address "imap.jochen.org"))
[...]

My current guess is that my gssapi-session is already authenticated,
but nnimap-open-connection-1 after "ZZZ" is getting confused somehow.

Some more debugging shows, that the next statement fails:

          (if (not (gnus-string-match-p "[*.] \\(OK\\|PREAUTH\\)" greeting))
	                (nnheader-report 'nnimap "%s" greeting)

That is somewhat expected, since my call to open-gssapi-stream doesn't
set greeting (and I'm almost sure that later capability will also fail).

Is my current approach ok, or should I massage open-protocol-stream to
handle nnimap-user?  Any hints how to proceed?

Jochen

-- 
The only problem with troubleshooting is that the trouble shoots back.



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: gssapi authentication for nnimap
  2016-02-09 20:05                 ` Jochen Hein
@ 2016-02-09 23:31                   ` Lars Ingebrigtsen
  2016-02-10  4:16                     ` Jochen Hein
                                       ` (2 more replies)
  0 siblings, 3 replies; 22+ messages in thread
From: Lars Ingebrigtsen @ 2016-02-09 23:31 UTC (permalink / raw)
  To: Jochen Hein; +Cc: Andreas Schwab, ding, Florian Weimer

Jochen Hein <jochen@jochen.org> writes:

> Right now I have the following diff to nnimap.el.  The second hunk
> hardcodes the imap port number - I didn't get that to work otherwise.
> In the third hunk I call open-gssapi-stream directly -
> open-protocol-stream doesn't handle the nnimap-user.  Should that be
> added to open-protocol-stream?

No, open-protocol-stream shouldn't know anything about nnimap.

> +	(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...

> My current guess is that my gssapi-session is already authenticated,
> but nnimap-open-connection-1 after "ZZZ" is getting confused somehow.
>
> Some more debugging shows, that the next statement fails:
>
>           (if (not (gnus-string-match-p "[*.] \\(OK\\|PREAUTH\\)" greeting))
> 	                (nnheader-report 'nnimap "%s" greeting)
>
> That is somewhat expected, since my call to open-gssapi-stream doesn't
> set greeting (and I'm almost sure that later capability will also fail).

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?

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: gssapi authentication for nnimap
  2016-02-09 23:31                   ` Lars Ingebrigtsen
@ 2016-02-10  4:16                     ` Jochen Hein
  2016-02-10  4:23                       ` Lars Ingebrigtsen
  2016-02-10  4:30                       ` Lars Ingebrigtsen
  2016-02-10 21:37                     ` Jochen Hein
  2016-02-11 19:51                     ` [PATCH] GSSAPI " Jochen Hein
  2 siblings, 2 replies; 22+ messages in thread
From: Jochen Hein @ 2016-02-10  4:16 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: Andreas Schwab, ding, Florian Weimer

Lars Ingebrigtsen <larsi@gnus.org> writes:

>> My current guess is that my gssapi-session is already authenticated,
>> but nnimap-open-connection-1 after "ZZZ" is getting confused somehow.
>>
>> Some more debugging shows, that the next statement fails:
>>
>>           (if (not (gnus-string-match-p "[*.] \\(OK\\|PREAUTH\\)" greeting))
>> 	                (nnheader-report 'nnimap "%s" greeting)
>>
>> That is somewhat expected, since my call to open-gssapi-stream doesn't
>> set greeting (and I'm almost sure that later capability will also fail).
>
> 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?

That seems to be the way forward, yes.  I guess that the wrapper willl
look a lot like open-protocol-stream...  I'll have a try in the next few
days.

Jochen

-- 
The only problem with troubleshooting is that the trouble shoots back.



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: gssapi authentication for nnimap
  2016-02-10  4:16                     ` Jochen Hein
@ 2016-02-10  4:23                       ` Lars Ingebrigtsen
  2016-02-10  4:30                       ` Lars Ingebrigtsen
  1 sibling, 0 replies; 22+ messages in thread
From: Lars Ingebrigtsen @ 2016-02-10  4:23 UTC (permalink / raw)
  To: Jochen Hein; +Cc: Andreas Schwab, ding, Florian Weimer

Jochen Hein <jochen@jochen.org> writes:

> That seems to be the way forward, yes.  I guess that the wrapper willl
> look a lot like open-protocol-stream...  I'll have a try in the next few
> days.

Great!

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: gssapi authentication for nnimap
  2016-02-10  4:16                     ` Jochen Hein
  2016-02-10  4:23                       ` Lars Ingebrigtsen
@ 2016-02-10  4:30                       ` Lars Ingebrigtsen
  2016-02-10  4:42                         ` Jochen Hein
  1 sibling, 1 reply; 22+ messages in thread
From: Lars Ingebrigtsen @ 2016-02-10  4:30 UTC (permalink / raw)
  To: Jochen Hein; +Cc: Andreas Schwab, ding, Florian Weimer

Jochen Hein <jochen@jochen.org> writes:

> That seems to be the way forward, yes.  I guess that the wrapper willl
> look a lot like open-protocol-stream...  I'll have a try in the next few
> days.

An idea just occurred to me...  This is the definition of
open-network-stream is this:

(open-network-stream NAME BUFFER HOST SERVICE &rest PARAMETERS)

[...]

:type specifies the connection type, one of the following:
  nil or ‘network’
             -- Begin with an ordinary network connection, and if
                the parameters :success and :capability-command
                are also supplied, try to upgrade to an encrypted
                connection via STARTTLS.  Even if that
                fails (e.g. if HOST does not support TLS), retain
                an unencrypted connection.
  ‘plain’    -- An ordinary, unencrypted network connection.
  ‘starttls’ -- Begin with an ordinary connection, and try
                upgrading via STARTTLS.  If that fails for any
                reason, drop the connection; in that case the
                returned object is a killed process.
  ‘tls’      -- A TLS connection.
  ‘ssl’      -- Equivalent to ‘tls’.
  ‘shell’    -- A shell connection.

We could extend this to `function', and that function would then deliver
the socket top `open-network-stream'.  It'd be exactly like `shell', but
instead of calling the shell, we'd call the function.

The function in this case would be a slight variation over
open-gssapi-stream.

Or rather, it would kinda look like this:

(open-network-stream NAME BUFFER HOST SERVICE
  ... :type 'function
  :connection-function (lambda (name buffer host service parameters)
                         (open-gssapi-stream name buffer server port nnimap-user)))

Wouldn't that do the trick with the minimal amount of hacking?  If so, I
can add the :type 'function to open-network-stream on the Emacs trunk...

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: gssapi authentication for nnimap
  2016-02-10  4:30                       ` Lars Ingebrigtsen
@ 2016-02-10  4:42                         ` Jochen Hein
  2016-02-10  4:50                           ` Lars Ingebrigtsen
  0 siblings, 1 reply; 22+ messages in thread
From: Jochen Hein @ 2016-02-10  4:42 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: Andreas Schwab, ding, Florian Weimer

Lars Ingebrigtsen <larsi@gnus.org> writes:

> Jochen Hein <jochen@jochen.org> writes:
>
>> That seems to be the way forward, yes.  I guess that the wrapper willl
>> look a lot like open-protocol-stream...  I'll have a try in the next few
>> days.
>
> An idea just occurred to me...
...
> We could extend this to `function', and that function would then deliver
> the socket top `open-network-stream'.  It'd be exactly like `shell', but
> instead of calling the shell, we'd call the function.
>
> The function in this case would be a slight variation over
> open-gssapi-stream.
>
> Or rather, it would kinda look like this:
>
> (open-network-stream NAME BUFFER HOST SERVICE
>   ... :type 'function
>   :connection-function (lambda (name buffer host service parameters)
>                          (open-gssapi-stream name buffer server port nnimap-user)))
>
> Wouldn't that do the trick with the minimal amount of hacking?  If so, I
> can add the :type 'function to open-network-stream on the Emacs trunk...

I'm not sure.  Right now open-gssapi-stream kills the greeting with
erase-buffer.  We need to scrapt greeting first, if needed.  Or
something like that.  I think I'll have to explore some different paths
to see what might be the best way forward.

Jochen

-- 
The only problem with troubleshooting is that the trouble shoots back.



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: gssapi authentication for nnimap
  2016-02-10  4:42                         ` Jochen Hein
@ 2016-02-10  4:50                           ` Lars Ingebrigtsen
  0 siblings, 0 replies; 22+ messages in thread
From: Lars Ingebrigtsen @ 2016-02-10  4:50 UTC (permalink / raw)
  To: Jochen Hein; +Cc: Andreas Schwab, ding, Florian Weimer

Jochen Hein <jochen@jochen.org> writes:

> I'm not sure.  Right now open-gssapi-stream kills the greeting with
> erase-buffer.  We need to scrapt greeting first, if needed.  Or
> something like that.

Oh, OK.  But...  it doesn't have to do that.  :-)

> I think I'll have to explore some different paths
> to see what might be the best way forward.

Okidoke.

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: gssapi authentication for nnimap
  2016-02-09 23:31                   ` Lars Ingebrigtsen
  2016-02-10  4:16                     ` Jochen Hein
@ 2016-02-10 21:37                     ` Jochen Hein
  2016-02-11 19:51                     ` [PATCH] GSSAPI " Jochen Hein
  2 siblings, 0 replies; 22+ messages in thread
From: Jochen Hein @ 2016-02-10 21:37 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: Andreas Schwab, ding, Florian Weimer

Lars Ingebrigtsen <larsi@gnus.org> 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=<jupiter.jochen.org-13079-1455130571-1-11713551379411196108>")
 	      (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.



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH] GSSAPI authentication for nnimap
  2016-02-09 23:31                   ` Lars Ingebrigtsen
  2016-02-10  4:16                     ` Jochen Hein
  2016-02-10 21:37                     ` Jochen Hein
@ 2016-02-11 19:51                     ` Jochen Hein
  2016-02-13  6:50                       ` Lars Ingebrigtsen
  2 siblings, 1 reply; 22+ messages in thread
From: Jochen Hein @ 2016-02-11 19:51 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: Andreas Schwab, ding, Florian Weimer


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.



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] GSSAPI authentication for nnimap
  2016-02-11 19:51                     ` [PATCH] GSSAPI " Jochen Hein
@ 2016-02-13  6:50                       ` Lars Ingebrigtsen
  2016-02-13 10:30                         ` Jochen Hein
  0 siblings, 1 reply; 22+ messages in thread
From: Lars Ingebrigtsen @ 2016-02-13  6:50 UTC (permalink / raw)
  To: Jochen Hein; +Cc: Andreas Schwab, ding, Florian Weimer

Jochen Hein <jochen@jochen.org> writes:

> 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.

Great!

> 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.

We don't need ChangeLog patches any more, but we generate
"ChangeLog-style" git commits instead.  Basically, just use `C-x 4 a',
and type in the change as usual, and then when checking in, vc-mode will
snarf those entries into the commit buffer.

> 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.

There's no user name in the default gssapi-program, at least...

> 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.

It would be nice if we didn't, but that's a possibility.

> 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.

Hm...  it would have been nice if this all went through our normal TLS
functions, so that the user could be given the opportunity to use the
network security manager in Emacs, which handles certificate errors and
the like.  So I think it would be very nice if
network-stream-open-gssapi handled TLS itself.

> Any comments?

I think everything looked very nice.  :-)

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] GSSAPI authentication for nnimap
  2016-02-13  6:50                       ` Lars Ingebrigtsen
@ 2016-02-13 10:30                         ` Jochen Hein
  2016-02-14  2:25                           ` Lars Ingebrigtsen
  0 siblings, 1 reply; 22+ messages in thread
From: Jochen Hein @ 2016-02-13 10:30 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: Andreas Schwab, ding, Florian Weimer

Lars Ingebrigtsen <larsi@gnus.org> writes:

> Jochen Hein <jochen@jochen.org> writes:
>
>> 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.
>
> Great!

Except that nnimap didn't work for me at all - I'll have a look, but
might want to wait after the cleanup frenzy is over :-)  I've also seem
some fixes already...

While you're at it - it might be a good idea to move starttls.el and
gssapi.el from lisp/gnus to lisp/net.  Both are used by
network-stream.el.  tls.el is already there.

There's also net/imap.el - which also claims to handle GSSAPI.  I have
no idea if that's in use anywhere.

>> 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.
>
> Hm...  it would have been nice if this all went through our normal TLS
> functions, so that the user could be given the opportunity to use the
> network security manager in Emacs, which handles certificate errors and
> the like.  So I think it would be very nice if
> network-stream-open-gssapi handled TLS itself.

That might not work with the current approach:

$ imtest -m gssapi -p imap imap
...
. STARTTLS
. BAD Can't Starttls after authentication

On the other hand I expect that someone doing Single-Sign-On with his
mail server will also have the right SSL-certificates in place.  For
example, both my server and client have been added to a FreeIPA domain.
So I currently contemplate to add '-t ""' to the imtest command in
gssapi.el, because it matches my use case and we'd use STARTTLS in both
commands.  I think we've reached a time where TLS should be enabled by
default.

In list/net I've found sasl*.el - that doesn't do GSSAPI at all, but it
could possibly be implemented there.  But I expect that this is beyond
my minimal elisp skill, so that's something to explore much later.

Jochen

-- 
The only problem with troubleshooting is that the trouble shoots back.



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] GSSAPI authentication for nnimap
  2016-02-13 10:30                         ` Jochen Hein
@ 2016-02-14  2:25                           ` Lars Ingebrigtsen
  0 siblings, 0 replies; 22+ messages in thread
From: Lars Ingebrigtsen @ 2016-02-14  2:25 UTC (permalink / raw)
  To: Jochen Hein; +Cc: ding

Jochen Hein <jochen@jochen.org> writes:

> Except that nnimap didn't work for me at all - I'll have a look, but
> might want to wait after the cleanup frenzy is over :-)  I've also seem
> some fixes already...

The patch that made nnimap not work at all has been reverted, so things
should be back to normal..

> While you're at it - it might be a good idea to move starttls.el and
> gssapi.el from lisp/gnus to lisp/net.  Both are used by
> network-stream.el.  tls.el is already there.

Sure.

> On the other hand I expect that someone doing Single-Sign-On with his
> mail server will also have the right SSL-certificates in place.  For
> example, both my server and client have been added to a FreeIPA domain.
> So I currently contemplate to add '-t ""' to the imtest command in
> gssapi.el, because it matches my use case and we'd use STARTTLS in both
> commands.

Yeah, that makes sense.

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no



^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2016-02-14  2:25 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-29 14:35 gssapi authentication for nnimap Florian Weimer
2016-02-06  6:40 ` Lars Ingebrigtsen
2016-02-07 17:16   ` Jochen Hein
2016-02-08  5:23     ` Lars Ingebrigtsen
2016-02-08  9:51       ` Jochen Hein
2016-02-08 20:59       ` Jochen Hein
2016-02-08 21:51         ` Andreas Schwab
2016-02-08 23:21           ` Jochen Hein
2016-02-08 23:47             ` Andreas Schwab
2016-02-09  6:22               ` Jochen Hein
2016-02-09 20:05                 ` Jochen Hein
2016-02-09 23:31                   ` Lars Ingebrigtsen
2016-02-10  4:16                     ` Jochen Hein
2016-02-10  4:23                       ` Lars Ingebrigtsen
2016-02-10  4:30                       ` Lars Ingebrigtsen
2016-02-10  4:42                         ` Jochen Hein
2016-02-10  4:50                           ` Lars Ingebrigtsen
2016-02-10 21:37                     ` Jochen Hein
2016-02-11 19:51                     ` [PATCH] GSSAPI " Jochen Hein
2016-02-13  6:50                       ` Lars Ingebrigtsen
2016-02-13 10:30                         ` Jochen Hein
2016-02-14  2:25                           ` Lars Ingebrigtsen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).