From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: =?UTF-8?Q?Elias_M=C3=A5rtenson?= Newsgroups: gmane.emacs.devel Subject: Re: Request for advice on GNUS internals. GSSAPI progress report Date: Thu, 16 Feb 2017 18:17:51 +0800 Message-ID: References: NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: multipart/alternative; boundary=001a1143703a1e773e0548a31c77 X-Trace: blaine.gmane.org 1487240322 24636 195.159.176.226 (16 Feb 2017 10:18:42 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Thu, 16 Feb 2017 10:18:42 +0000 (UTC) To: emacs-devel Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Thu Feb 16 11:18:36 2017 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1ceJ91-0005sy-Uv for ged-emacs-devel@m.gmane.org; Thu, 16 Feb 2017 11:18:36 +0100 Original-Received: from localhost ([::1]:45605 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ceJ97-0000CL-NK for ged-emacs-devel@m.gmane.org; Thu, 16 Feb 2017 05:18:41 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:42449) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ceJ8O-00007w-JW for emacs-devel@gnu.org; Thu, 16 Feb 2017 05:17:59 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ceJ8L-0004eS-L0 for emacs-devel@gnu.org; Thu, 16 Feb 2017 05:17:56 -0500 Original-Received: from mail-vk0-x22d.google.com ([2607:f8b0:400c:c05::22d]:36232) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1ceJ8L-0004eE-Db for emacs-devel@gnu.org; Thu, 16 Feb 2017 05:17:53 -0500 Original-Received: by mail-vk0-x22d.google.com with SMTP id t8so7429555vke.3 for ; Thu, 16 Feb 2017 02:17:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:in-reply-to:references:from:date:message-id:subject:to; bh=iYhbCfEOh3x/cUOvQQloqYPtf0AuVbFZYU8CNS0rcgE=; b=PYEMrigmItgTjW4qtwUBXYLw3dVa9qMLREZYLmUDTe2Bf3KFHtYo6GxuhmnseoaxjR WNGsy7VvRYs1SmJmrjs779Vx3WgAGbBX5ai4zdleNuEuZVYTlBLgCRL+NssxQehFo8p6 qDVYi37yfwem2L1MZF8ExBF0C70+P275aQQD8jCWVObPl+PIE2b39BlTxa6n/FBXc1ty aDUN1jajsXehAnXlq/wHO8XNjJKHN42rLJYow/rscaw+IoQhMZCjCMzf3/+6jm/gzltK UgkxLOKuKh7WdvsInYXAj1E6SwNUTEPXzzx5vlSFCi8g8DuE26rtO0VU+/0JGrHGk3+z hd5Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to; bh=iYhbCfEOh3x/cUOvQQloqYPtf0AuVbFZYU8CNS0rcgE=; b=Y6cCvyr7eRNZrF2oO0+nZRsh9heL5iVRaLPIISmYP/7RonBgdhl3cRssYb8nJciwVo cMJUEp5NxWO5rm/tI6G4UufjqO7uJ0xHN1FwEfIKJRTs9RD6oyICN693HwsVuuZz44nR W4CAbJk4t+zBIValn4JIBwJKXFMLELWX+rap+dIvcvlPcTqf1bgCtQi2gSkQW6qYetya 2ceE3ECLFXmOmtpNuBc7aJ20z5dzrKau0MJYidlBKMVfVb2lREhIbtwFXldMn9EIAQ8K dbroqtC+pO9Zo0ihtcAOpSvgIEFjg9LwOiFKH8UWE4SGOxbEB2aH0gmF6mMgINNrR/Jn QITQ== X-Gm-Message-State: AMke39lYsCfOoB+fB+Eifk9bZXXOT/jTczexXE70JMRkpEknwGNes9JV2Qa6EmC5zDQU+GTqKge2Moklin5RFg== X-Received: by 10.31.142.68 with SMTP id q65mr671509vkd.83.1487240272172; Thu, 16 Feb 2017 02:17:52 -0800 (PST) Original-Received: by 10.103.131.215 with HTTP; Thu, 16 Feb 2017 02:17:51 -0800 (PST) In-Reply-To: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2607:f8b0:400c:c05::22d X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.21 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" Xref: news.gmane.org gmane.emacs.devel:212419 Archived-At: --001a1143703a1e773e0548a31c77 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable I am now able to read my email using a GSSAPI-authenticated connection. If anyone is willing to try it, build the native module here: https://github.com/lokedhs/emacs-gssapi Then apply the below patch to nnimap.el. To enable the use of GSSAPI for authentication, set =E2=80=98nnimap-authenticator=E2=80=99 to =E2=80=98gssa= pi=E2=80=99. Regards, Elias *** /home/emartenson/src/emacs/lisp/gnus/nnimap.el 2017-01-31 10:04:34.692388829 +0800 --- /usr/local/share/emacs/26.0.50/lisp/gnus/nnimap.el 2017-02-16 18:08:44.883875947 +0800 *************** *** 331,336 **** --- 331,337 ---- (set (make-local-variable 'nnimap-object) (make-nnimap :server (nnoo-current-server 'nnimap) :initial-resync 0)) + (set (make-local-variable 'nnimap-send-string-function) 'nnimap--unencoded-send-string-to-server) (push (list buffer (current-buffer)) nnimap-connection-alist) (push (current-buffer) nnimap-process-buffers) (current-buffer))) *************** *** 513,520 **** --- 514,652 ---- (autoload 'rfc2104-hash "rfc2104") + (defun nnimap--send-string-to-server (string) + (message "Sending string using %S: %S" nnimap-send-string-function string) + (funcall nnimap-send-string-function string)) + + (defun nnimap--unencoded-send-string-to-server (string) + (process-send-string (get-buffer-process (current-buffer)) string)) + + (defun nnimap--gss-send-string-to-server (string) + (cond ((eq nnimap-gss-protection-type :none) + (nnimap--unencoded-send-string-to-server string)) + (t + ;; TODO: We should check the maximum block size here. + (destructuring-bind (encoded conf) + (gss-wrap nnimap-gss-context string :conf (eq nnimap-gss-protection-type :priv)) + (let ((size (length encoded))) + (nnimap--unencoded-send-string-to-server (format "%c%c%c%c%s= " + (logand (ash size -24) #xff) + (logand (ash size -16) #xff) + (logand (ash size -8) #xff) + (logand size #xff) + encoded))))))) + + (defun nnimap--gss-read-filter (proc string) + (message "Read block using type %S: %S" nnimap-gss-protection-type string) + (cond ((eq nnimap-gss-protection-type :none) + (internal-default-process-filter proc string)) + (t + ;; TODO: This function is currently unimplemented. Although + ;; its implementation isn't particularly complicated, I've + ;; left it blank for now since I don't have access to a mail + ;; server which uses wrapped streams. + ;; + ;; Implementing this should be reasonably simple. =E2=80=98strin= g=E2=80=99 + ;; contains a sequence of bytes that has been received from + ;; the IMAP server. The first 4 bytes of the stream is the + ;; length of the packet in network byte-order. The bytes in + ;; the packet should be passed to =E2=80=98gss-unwrap=E2=80=99. = The =E2=80=98:conf=E2=80=99 + ;; parameter to this call should be nil if + ;; =E2=80=98nnimap-gss-protection-type=E2=80=99 is =E2=80=98:int= eg=E2=80=99 or t if it is + ;; =E2=80=98:priv=E2=80=99. The resulting string should then be = passed to + ;; =E2=80=98internal-default-process-filter=E2=80=99 in a simila= r way as what + ;; is done in the non-encrypted case. + (error "Wrapped streams are not implemented. Please see comments in the function =E2=80=98nnimap--gss-read-filter=E2=80=99")))) + + (defun nnimap--strip-cr (string) + (let ((length (length string))) + (if (and (plusp length) + (eql (aref string (1- length)) ?\r)) + (subseq string 0 (1- length)) + string))) + + (defun nnimap--decode-token (decrypted) + ;; The first octet is the bitmask + (let ((flags (aref decrypted 0)) + (max-message-size (logior (ash (aref decrypted 1) 16) + (ash (aref decrypted 2) 8) + (aref decrypted 3)))) + (list flags max-message-size))) + + ;;; GSSAPI authentication documented at: https://tools.ietf.org/html/rfc1731 + (defun nnimap-auth-gssapi (user) + (require 'gss) + (let ((sequence (nnimap-send-command "AUTHENTICATE GSSAPI"))) + (let ((resp (nnimap--strip-cr (nnimap-wait-for-line "^\\+\\(.*\\)\n")))) + (assert (equal resp "")) + (let ((context nil)) + (loop with authenticated-p =3D nil + with input-token =3D nil + with name =3D (gss-make-name (format "imap@%s" (downcase nnimap-address))) + while (not authenticated-p) + do (erase-buffer) + do (multiple-value-bind (continue-needed context-result token flags) + (gss-init-sec-context name :context context :input-token input-token :flags '(:replay :conf :integ :mutual)) + (setq context context-result) + (if token + (nnimap--send-string-to-server (concat (base64-encode-string token) "\r\n")) + ;; ELSE: The spec says that if there is no output token, there should be a response with no data + (nnimap--send-string-to-server "\r\n")) + (if continue-needed + (let ((server-message (nnimap-wait-for-line "^\\+\\(.*\\)\n"))) + (setq input-token (base64-decode-string server-message))) + ;; ELSE: We now have a valid context + (setq authenticated-p t)))) + ;; After initial GSS handshake, the server is expected to send a blank response. + (let ((token (nnimap-wait-for-line "^\\+\\(.*\\)\n"))) + (destructuring-bind (decrypted conf-p) + (gss-unwrap context (base64-decode-string token)) + (destructuring-bind (flags max-server-size) + (nnimap--decode-token decrypted) + ;; Select the strictest protection mechanism that the + ;; server supports. + (let ((protection-type (cond ((not (zerop (logand flags #x4))) + :priv) + ((not (zerop (logand flags #x2))) + :integ) + ((not (zerop (logand flags #x1))) + :none) + (t + (error "Unsupported privacy type: %d" flags))))) + ;; I don't know what the actual max message size should + ;; be, so for now let's just use whatever the server is + ;; using. + (let* ((max-client-size max-server-size)) + (erase-buffer) + (destructuring-bind (encoded conf) + (gss-wrap context (format "%c%c%c%c%s" + (ecase protection-type + (:priv #x4) + (:integ #x2) + (:none #x1)) + (logand (ash max-client-size -16) #xff) + (logand (ash max-client-size -8) #xff) + (logand max-client-size #xff) + user)) + (nnimap--send-string-to-server (concat (base64-encode-string encoded) "\r\n"))) + (nnimap-wait-for-response sequence "OK") + (cond ((equal (caar (nnimap-get-response sequence)) "OK") + (setq-local nnimap-gss-context context) + (setq-local nnimap-gss-expected-size nil) + (setq-local nnimap-gss-read-buf "") + (setq-local nnimap-gss-protection-type protection-type) + (setq-local nnimap-send-string-function #'nnimap--gss-send-string-to-server) + (set-process-filter (get-buffer-process (current-buffer)) #'nnimap--gss-read-filter) + (cons user nil)) + (t + (error "Authentication error")))))))))))) + (defun nnimap-login (user password) + (set-process-filter (get-buffer-process (current-buffer)) (lambda (proc string) (message "Input: %S" string) (insert string))) (cond + ((and (nnimap-capability "AUTH=3DGSSAPI") + (eq nnimap-authenticator 'gssapi)) + (nnimap-auth-gssapi user)) ;; Prefer plain LOGIN if it's enabled (since it requires fewer ;; round trips than CRAM-MD5, and it's less likely to be buggy), ;; and we're using an encrypted connection. *************** *** 529,536 **** (erase-buffer) (let ((sequence (nnimap-send-command "AUTHENTICATE CRAM-MD5")) (challenge (nnimap-wait-for-line "^\\+\\(.*\\)\n"))) ! (process-send-string ! (get-buffer-process (current-buffer)) (concat (base64-encode-string (concat user " " --- 661,667 ---- (erase-buffer) (let ((sequence (nnimap-send-command "AUTHENTICATE CRAM-MD5")) (challenge (nnimap-wait-for-line "^\\+\\(.*\\)\n"))) ! (nnimap--send-string-to-server (concat (base64-encode-string (concat user " " *************** *** 1192,1202 **** (length message))) (unless nnimap-streaming (nnimap-wait-for-connection "^[+]")) ! (process-send-string (get-buffer-process (current-buffer)) message) ! (process-send-string (get-buffer-process (current-buffer)) ! (if (nnimap-newlinep nnimap-object) ! "\n" ! "\r\n")) (let ((result (nnimap-get-response sequence))) (if (not (nnimap-ok-p result)) (progn --- 1323,1332 ---- (length message))) (unless nnimap-streaming (nnimap-wait-for-connection "^[+]")) ! (nnimap--send-string-to-server message) ! (nnimap--send-string-to-server (if (nnimap-newlinep nnimap-object) ! "\n" ! "\r\n")) (let ((result (nnimap-get-response sequence))) (if (not (nnimap-ok-p result)) (progn *************** *** 1864,1871 **** (defun nnimap-send-command (&rest args) (setf (nnimap-last-command-time nnimap-object) (current-time)) ! (process-send-string ! (get-buffer-process (current-buffer)) (nnimap-log-command (format "%d %s%s\n" (incf nnimap-sequence) --- 1994,2000 ---- (defun nnimap-send-command (&rest args) (setf (nnimap-last-command-time nnimap-object) (current-time)) ! (nnimap--send-string-to-server (nnimap-log-command (format "%d %s%s\n" (incf nnimap-sequence) On 15 February 2017 at 18:13, Elias M=C3=A5rtenson wrot= e: > On 15 February 2017 at 12:37, Elias M=C3=A5rtenson wr= ote: > > What approach should I take here? >> > > I have come up with a solution that uses a process filter to deal with > this. It probably works, but I can't really test it since my server doesn= 't > use GSS encryption, only the authentication part. > > Other than that, it seems to work now, and I'm working on cleaning up the > code. > > Regards, > Elias > --001a1143703a1e773e0548a31c77 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable
I am now able to read my email using a GSSAPI-authenticate= d connection.

If anyone is willing to try it, build the = native module here:=C2=A0https://github.com/lokedhs/emacs-gssapi

Then= apply the below patch to nnimap.el. To enable the use of GSSAPI for authen= tication, set =E2=80=98nnimap-authenticator=E2=80=99 to =E2=80=98gssapi=E2= =80=99.

Regards,
Elias

*** /home/emartenson/src/emacs/lisp/gnus/nnimap.el 2017-01-31 10:0= 4:34.692388829 +0800
--- /usr/local/share/emacs/26.0.50/lisp/gnus= /nnimap.el <= /span>2017-02-16 18:08:44.883875947 +0800
***************
*** 331,336 ****
--- 331,337 ----
=C2=A0 =C2=A0 =C2= =A0 (set (make-local-variable 'nnimap-object)
=C2=A0 (make-nnima= p :server (nnoo-current-server 'nnimap)
=C2=A0 =C2=A0 =C2=A0 = =C2=A0:initial-resync 0))
+ =C2=A0 =C2=A0 (set (make-local-variab= le 'nnimap-send-string-function) 'nnimap--unencoded-send-string-to-= server)
=C2=A0 =C2=A0 =C2=A0 (push (list buffer (current-buffer))= nnimap-connection-alist)
=C2=A0 =C2=A0 =C2=A0 (push (current-buf= fer) nnimap-process-buffers)
=C2=A0 =C2=A0 =C2=A0 (current-buffer= )))
***************
*** 513,520 ****
--- 514,= 652 ----
=C2=A0=C2=A0
=C2=A0 (autoload 'rfc2104-has= h "rfc2104")
=C2=A0=C2=A0
+ (defun nnimap--se= nd-string-to-server (string)
+ =C2=A0 (message "Sending stri= ng using %S: %S" nnimap-send-string-function string)
+ =C2= =A0 (funcall nnimap-send-string-function string))
+=C2=A0
+ (defun nnimap--unencoded-send-string-to-server (string)
+ = =C2=A0 (process-send-string (get-buffer-process (current-buffer)) string))<= /div>
+=C2=A0
+ (defun nnimap--gss-send-string-to-server (str= ing)
+ =C2=A0 (cond ((eq nnimap-gss-protection-type :none)
<= div>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(nnimap--unencoded-send-string-to-s= erver string))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 (t
+ =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;; TODO: We should check the maximum block s= ize here.
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(destructuring-bind= (encoded conf)
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0(gss-wrap nnimap-gss-context string :conf (eq nnimap-gss-protection-type= :priv))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(let ((size (= length encoded)))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0(nnimap--unencoded-send-string-to-server (format "%c%c%c%c%s"<= /div>
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 (logand (ash size -24) #xff)
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (logand (ash size -16) #xff)
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 (logand (ash size -8) #xff)
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (logand size #xff)
+ =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 encoded)= ))))))
+=C2=A0
+ (defun nnimap--gss-read-filter (proc s= tring)
+ =C2=A0 (message "Read block using type %S: %S"= nnimap-gss-protection-type string)
+ =C2=A0 (cond ((eq nnimap-gs= s-protection-type :none)
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(int= ernal-default-process-filter proc string))
+ =C2=A0 =C2=A0 =C2=A0= =C2=A0 (t
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;; TODO: This func= tion is currently unimplemented. Although
+ =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0;; its implementation isn't particularly complicated, I= 9;ve
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;; left it blank for now= since I don't have access to a mail
+ =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0;; server which uses wrapped streams.
+ =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0;;
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;;= Implementing this should be reasonably simple. =E2=80=98string=E2=80=99
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;; contains a sequence of bytes= that has been received from
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= ;; the IMAP server. The first 4 bytes of the stream is the
+ =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;; length of the packet in network byte-orde= r. The bytes in
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;; the packet= should be passed to =E2=80=98gss-unwrap=E2=80=99. The =E2=80=98:conf=E2=80= =99
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;; parameter to this call= should be nil if
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;; =E2=80= =98nnimap-gss-protection-type=E2=80=99 is =E2=80=98:integ=E2=80=99 or t if = it is
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;; =E2=80=98:priv=E2=80= =99. The resulting string should then be passed to
+ =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0;; =E2=80=98internal-default-process-filter=E2=80= =99 in a similar way as what
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= ;; is done in the non-encrypted case.
+ =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0(error "Wrapped streams are not implemented. Please see comm= ents in the function =E2=80=98nnimap--gss-read-filter=E2=80=99"))))
+=C2=A0
+ (defun nnimap--strip-cr (string)
+ = =C2=A0 (let ((length (length string)))
+ =C2=A0 =C2=A0 (if (and (= plusp length)
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(= eql (aref string (1- length)) ?\r))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0= (subseq string 0 (1- length))
+ =C2=A0 =C2=A0 =C2=A0 string)))
+=C2=A0
+ (defun nnimap--decode-token (decrypted)
<= div>+ =C2=A0 ;; The first octet is the bitmask
+ =C2=A0 (let ((fl= ags (aref decrypted 0))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 (max-messag= e-size (logior (ash (aref decrypted 1) 16)
+ =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 (ash (aref decrypted 2) 8)
+ =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (aref decrypted 3))))
+ =C2=A0= =C2=A0 (list flags max-message-size)))
+=C2=A0
+ ;;; G= SSAPI authentication documented at: https://tools.ietf.org/html/rfc1731
+ (defun nnimap-= auth-gssapi (user)
+ =C2=A0 (require 'gss)
+ =C2=A0= (let ((sequence (nnimap-send-command "AUTHENTICATE GSSAPI")))
+ =C2=A0 =C2=A0 (let ((resp (nnimap--strip-cr (nnimap-wait-for-line= "^\\+\\(.*\\)\n"))))
+ =C2=A0 =C2=A0 =C2=A0 (assert (e= qual resp ""))
+ =C2=A0 =C2=A0 =C2=A0 (let ((context ni= l))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 (loop with authenticated-p =3D = nil
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 with input= -token =3D nil
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= with name =3D (gss-make-name (format "imap@%s" (downcase nnimap-= address)))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 whi= le (not authenticated-p)
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 do (erase-buffer)
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 do (multiple-value-bind (continue-needed context-result toke= n flags)
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0(gss-init-sec-context name :context context :input-= token input-token :flags '(:replay :conf :integ :mutual))
+ = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(setq = context context-result)
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(if token
+ =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(nnimap--send= -string-to-server (concat (base64-encode-string token) "\r\n"))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0;; ELSE: The spec says that if there is no output token, there= should be a response with no data
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(nnimap--send-string-to-ser= ver "\r\n"))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(if continue-needed
+ =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(l= et ((server-message (nnimap-wait-for-line "^\\+\\(.*\\)\n")))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0(setq input-token (base64-decode-string server-mess= age)))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0;; ELSE: We now have a valid context
+ =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(setq= authenticated-p t))))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 ;; After ini= tial GSS handshake, the server is expected to send a blank response.
<= div>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 (let ((token (nnimap-wait-for-line "= ^\\+\\(.*\\)\n")))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (des= tructuring-bind (decrypted conf-p)
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 (gss-unwrap context (base64-decode-string token))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (destructuring-bind (flag= s max-server-size)
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 (nnimap--decode-token decrypted)
+ =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ;; Select the strictest protection mecha= nism that the
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = ;; server supports.
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 (let ((protection-type (cond ((not (zerop (logand flags #x4)))
=
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 :priv)
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0((not (zerop (logand flags #x2)))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 :integ)
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0((not (zerop (logand flags #x1)))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 :none)
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(t
+ =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (error "Un= supported privacy type: %d" flags)))))
+ =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ;; I don't know what the actual = max message size should
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 ;; be, so for now let's just use whatever the server = is
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ;; u= sing.
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (= let* ((max-client-size max-server-size))
+ =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (erase-buffer)
+ =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (destructuring-bin= d (encoded conf)
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (gss-wrap context (format "%c%c%c%c%s&= quot;
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (ecase protection-type
+ = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 (:priv #x4)
+ =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 (:integ #x2)
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (:none #x1))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (logand (ash max-client-size -16) #xff)
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 (logand (ash max-client-size -8) #xff)
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 (logand max-client-size #xff)
+ =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 user))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 (nnimap--send-string-to-server (concat (base64-= encode-string encoded) "\r\n")))
+ =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (nnimap-wait-for-response sequen= ce "OK")
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 (cond ((equal (caar (nnimap-get-response sequence)) &q= uot;OK")
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(setq-local nnimap-gss-context con= text)
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(setq-local nnimap-gss-expected-size nil)=
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0(setq-local nnimap-gss-read-buf "")
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0(setq-local nnimap-gss-protection-type protectio= n-type)
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(setq-local nnimap-send-string-function = #'nnimap--gss-send-string-to-server)
+ =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(set-p= rocess-filter (get-buffer-process (current-buffer)) #'nnimap--gss-read-= filter)
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(cons user nil))
+ =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (= t
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(error "Authentication error")))))= )))))))
+=C2=A0
=C2=A0 (defun nnimap-login (user passwo= rd)
+ =C2=A0 (set-process-filter (get-buffer-process (current-buf= fer)) (lambda (proc string) (message "Input: %S" string) (insert = string)))
=C2=A0 =C2=A0 (cond
+ =C2=A0 =C2=A0((and (nni= map-capability "AUTH=3DGSSAPI")
+ =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0(eq nnimap-authenticator 'gssapi))
+ =C2=A0 =C2= =A0 (nnimap-auth-gssapi user))
=C2=A0 =C2=A0 =C2=A0;; Prefer plai= n LOGIN if it's enabled (since it requires fewer
=C2=A0 =C2= =A0 =C2=A0;; round trips than CRAM-MD5, and it's less likely to be bugg= y),
=C2=A0 =C2=A0 =C2=A0;; and we're using an encrypted conne= ction.
***************
*** 529,536 ****
=C2= =A0 =C2=A0 =C2=A0 (erase-buffer)
=C2=A0 =C2=A0 =C2=A0 (let ((sequ= ence (nnimap-send-command "AUTHENTICATE CRAM-MD5"))
=C2= =A0 = =C2=A0(challenge (nnimap-wait-for-line "^\\+\\(.*\\)\n")))
=
! =C2=A0 =C2=A0 =C2=A0 (process-send-string
! =C2=A0 =C2=A0 = =C2=A0 =C2=A0(get-buffer-process (current-buffer))
=C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0(concat
=C2=A0 (base64-encode-string
= =C2=A0 (concat user " "
--- 661,667 ----
=C2=A0 = =C2=A0 =C2=A0 (erase-buffer)
=C2=A0 =C2=A0 =C2=A0 (let ((sequence= (nnimap-send-command "AUTHENTICATE CRAM-MD5"))
=C2=A0 = =C2= =A0(challenge (nnimap-wait-for-line "^\\+\\(.*\\)\n")))
! =C2=A0 =C2=A0 =C2=A0 (nnimap--send-string-to-server
=C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0(concat
=C2=A0 (base64-encode-string
=C2=A0 (concat user " "
***************
*** 11= 92,1202 ****
=C2=A0 =C2=A0(length message)))
=C2=A0 =C2=A0(= unless nnimap-streaming
=C2=A0 =C2=A0 =C2=A0(nnimap-wait-for-connect= ion "^[+]"))
! =C2=A0(process-send-string (get-buffer-proc= ess (current-buffer)) message)
! =C2=A0(process-send-string (get-buf= fer-process (current-buffer))
! =C2=A0 =C2=A0 =C2=A0 (if (nnimap-n= ewlinep nnimap-object)
! =C2=A0 "\n"
! "= \r\n"))
=C2=A0 =C2=A0(let ((result (nnimap-get-response sequenc= e)))
=C2=A0 =C2=A0 =C2=A0(if (not (nnimap-ok-p result))
= =C2=A0 (progn
--- 1323,1332 ----
=C2=A0 =C2=A0(length messa= ge)))
=C2=A0 =C2=A0(unless nnimap-streaming
=C2=A0 =C2=A0 =C2= =A0(nnimap-wait-for-connection "^[+]"))
! =C2=A0(nnimap-= -send-string-to-server message)
! =C2=A0(nnimap--send-string-to-serv= er (if (nnimap-newlinep nnimap-object)
! =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0"\n"= ;
! =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0"\r\n"))
=C2=A0 =C2=A0(let ((result (n= nimap-get-response sequence)))
=C2=A0 =C2=A0 =C2=A0(if (not (nnimap-= ok-p result))
=C2=A0 (progn
***************
**= * 1864,1871 ****
=C2=A0=C2=A0
=C2=A0 (defun nnimap-send= -command (&rest args)
=C2=A0 =C2=A0 (setf (nnimap-last-comman= d-time nnimap-object) (current-time))
! =C2=A0 (process-send-stri= ng
! =C2=A0 =C2=A0(get-buffer-process (current-buffer))
=C2=A0 =C2=A0 =C2=A0(nnimap-log-command
=C2=A0 =C2=A0 =C2=A0 (fo= rmat "%d %s%s\n"
=C2=A0 =C2=A0 =C2=A0(incf nnimap-sequence= )
--- 1994,2000 ----
=C2=A0=C2=A0
=C2=A0 (def= un nnimap-send-command (&rest args)
=C2=A0 =C2=A0 (setf (nnim= ap-last-command-time nnimap-object) (current-time))
! =C2=A0 (nni= map--send-string-to-server
=C2=A0 =C2=A0 =C2=A0(nnimap-log-comman= d
=C2=A0 =C2=A0 =C2=A0 (format "%d %s%s\n"
= =C2=A0 =C2=A0 =C2=A0(incf nnimap-sequence)


On 15 February 2017 = at 18:13, Elias M=C3=A5rtenson <lokedhs@gmail.com> wrote:
On 15 February 2017 at 12:37, = Elias M=C3=A5rtenson <lokedhs@gmail.com> wrote:
=

What approach should I take here?

I have come up with a solution that use= s a process filter to deal with this. It probably works, but I can't re= ally test it since my server doesn't use GSS encryption, only the authe= ntication part.

Other than that, it seems to work = now, and I'm working on cleaning up the code.

= Regards,
Elias=C2=A0

--001a1143703a1e773e0548a31c77--