aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlbert Krewinkel2013-06-11 07:32:25 +0000
committerKatsumi Yamaoka2013-06-11 07:32:25 +0000
commit8e16fb987df9b80b8328e9dbf80351a5f9d85bbb (patch)
tree9940fe375e813eb79af7dac176d48888a763eec7
parent9102c47ad2fc39371b0931ed70940fa8511cc09d (diff)
downloademacs-8e16fb987df9b80b8328e9dbf80351a5f9d85bbb.tar.gz
emacs-8e16fb987df9b80b8328e9dbf80351a5f9d85bbb.zip
lisp/gnus/sievel-manage.el: fully support STARTTLS, fix bit rot
* Make sieve-manage-open work with STARTTLS: shorten stream managing functions by using open-protocol-stream to do most of the work. Has the nice benefit of enabling STARTTLS. * Remove unneeded functions and options: the following functions and options are neither in the API, nor called by any other function, so they are deleted: - sieve-manage-network-p - sieve-manage-network-open - sieve-manage-starttls-p - sieve-manage-starttls-open - sieve-manage-forward - sieve-manage-streams - sieve-manage-stream-alist The options could not be applied in a meaningful way anymore; they didn't happen to have much effect before. * Cosmetic changes and code clean-up * Enable Multibyte for SieveManage buffers: The parser won't properly handle umlauts and line endings unless multibyte is turned on in the process buffer. * Wait for capabilities after STARTTLS: following RFC5804, the server sends new capabilities after successfully establishing a TLS connection with the client. The client should update the cached list of capabilities, but we just ignore the answer for now.
-rw-r--r--lisp/gnus/ChangeLog18
-rw-r--r--lisp/gnus/sieve-manage.el248
2 files changed, 103 insertions, 163 deletions
diff --git a/lisp/gnus/ChangeLog b/lisp/gnus/ChangeLog
index 9809f5a7432..744e1871b65 100644
--- a/lisp/gnus/ChangeLog
+++ b/lisp/gnus/ChangeLog
@@ -1,3 +1,21 @@
12013-06-10 Albert Krewinkel <krewinkel@moltkeplatz.de>
2
3 * sieve-manage.el (sieve-manage-open): work with STARTTLS: shorten
4 stream managing functions by using open-protocol-stream to do most of
5 the work. Has the nice benefit of enabling STARTTLS.
6 Wait for capabilities after STARTTLS: following RFC5804, the server
7 sends new capabilities after successfully establishing a TLS connection
8 with the client. The client should update the cached list of
9 capabilities, but we just ignore the answer for now.
10 (sieve-manage-network-p, sieve-manage-network-open)
11 (sieve-manage-starttls-p, sieve-manage-starttls-open)
12 (sieve-manage-forward, sieve-manage-streams)
13 (sieve-manage-stream-alist): Remove unneeded functions neither in the
14 API, nor called by any other function.
15 Enable Multibyte for SieveManage buffers: The parser won't properly
16 handle umlauts and line endings unless multibyte is turned on in the
17 process buffer.
18
12013-06-11 Lars Magne Ingebrigtsen <larsi@gnus.org> 192013-06-11 Lars Magne Ingebrigtsen <larsi@gnus.org>
2 20
3 * eww.el (eww-tag-input): Support password fields. 21 * eww.el (eww-tag-input): Support password fields.
diff --git a/lisp/gnus/sieve-manage.el b/lisp/gnus/sieve-manage.el
index b96261764e5..23ab24152d9 100644
--- a/lisp/gnus/sieve-manage.el
+++ b/lisp/gnus/sieve-manage.el
@@ -3,6 +3,7 @@
3;; Copyright (C) 2001-2013 Free Software Foundation, Inc. 3;; Copyright (C) 2001-2013 Free Software Foundation, Inc.
4 4
5;; Author: Simon Josefsson <simon@josefsson.org> 5;; Author: Simon Josefsson <simon@josefsson.org>
6;; Albert Krewinkel <tarleb@moltkeplatz.de>
6 7
7;; This file is part of GNU Emacs. 8;; This file is part of GNU Emacs.
8 9
@@ -66,6 +67,7 @@
66;; 2001-10-31 Committed to Oort Gnus. 67;; 2001-10-31 Committed to Oort Gnus.
67;; 2002-07-27 Added DELETESCRIPT. Suggested by Ned Ludd. 68;; 2002-07-27 Added DELETESCRIPT. Suggested by Ned Ludd.
68;; 2002-08-03 Use SASL library. 69;; 2002-08-03 Use SASL library.
70;; 2013-06-05 Enabled STARTTLS support, fixed bit rot.
69 71
70;;; Code: 72;;; Code:
71 73
@@ -82,7 +84,6 @@
82 (require 'sasl) 84 (require 'sasl)
83 (require 'starttls)) 85 (require 'starttls))
84(autoload 'sasl-find-mechanism "sasl") 86(autoload 'sasl-find-mechanism "sasl")
85(autoload 'starttls-open-stream "starttls")
86(autoload 'auth-source-search "auth-source") 87(autoload 'auth-source-search "auth-source")
87 88
88;; User customizable variables: 89;; User customizable variables:
@@ -107,23 +108,6 @@
107 :type 'string 108 :type 'string
108 :group 'sieve-manage) 109 :group 'sieve-manage)
109 110
110(defcustom sieve-manage-streams '(network starttls shell)
111 "Priority of streams to consider when opening connection to server."
112 :group 'sieve-manage)
113
114(defcustom sieve-manage-stream-alist
115 '((network sieve-manage-network-p sieve-manage-network-open)
116 (shell sieve-manage-shell-p sieve-manage-shell-open)
117 (starttls sieve-manage-starttls-p sieve-manage-starttls-open))
118 "Definition of network streams.
119
120\(NAME CHECK OPEN)
121
122NAME names the stream, CHECK is a function returning non-nil if the
123server support the stream and OPEN is a function for opening the
124stream."
125 :group 'sieve-manage)
126
127(defcustom sieve-manage-authenticators '(digest-md5 111(defcustom sieve-manage-authenticators '(digest-md5
128 cram-md5 112 cram-md5
129 scram-md5 113 scram-md5
@@ -156,8 +140,7 @@ for doing the actual authentication."
156 :group 'sieve-manage) 140 :group 'sieve-manage)
157 141
158(defcustom sieve-manage-default-stream 'network 142(defcustom sieve-manage-default-stream 'network
159 "Default stream type to use for `sieve-manage'. 143 "Default stream type to use for `sieve-manage'."
160Must be a name of a stream in `sieve-manage-stream-alist'."
161 :version "24.1" 144 :version "24.1"
162 :type 'symbol 145 :type 'symbol
163 :group 'sieve-manage) 146 :group 'sieve-manage)
@@ -185,17 +168,21 @@ Valid states are `closed', `initial', `nonauth', and `auth'.")
185(defvar sieve-manage-capability nil) 168(defvar sieve-manage-capability nil)
186 169
187;; Internal utility functions 170;; Internal utility functions
188 171(defun sieve-manage-make-process-buffer ()
189(defmacro sieve-manage-disable-multibyte () 172 (with-current-buffer
190 "Enable multibyte in the current buffer." 173 (generate-new-buffer (format " *sieve %s:%s*"
191 (unless (featurep 'xemacs) 174 sieve-manage-server
192 '(set-buffer-multibyte nil))) 175 sieve-manage-port))
176 (mapc 'make-local-variable sieve-manage-local-variables)
177 (mm-enable-multibyte)
178 (buffer-disable-undo)
179 (current-buffer)))
193 180
194(defun sieve-manage-erase (&optional p buffer) 181(defun sieve-manage-erase (&optional p buffer)
195 (let ((buffer (or buffer (current-buffer)))) 182 (let ((buffer (or buffer (current-buffer))))
196 (and sieve-manage-log 183 (and sieve-manage-log
197 (with-current-buffer (get-buffer-create sieve-manage-log) 184 (with-current-buffer (get-buffer-create sieve-manage-log)
198 (sieve-manage-disable-multibyte) 185 (mm-enable-multibyte)
199 (buffer-disable-undo) 186 (buffer-disable-undo)
200 (goto-char (point-max)) 187 (goto-char (point-max))
201 (insert-buffer-substring buffer (with-current-buffer buffer 188 (insert-buffer-substring buffer (with-current-buffer buffer
@@ -204,71 +191,32 @@ Valid states are `closed', `initial', `nonauth', and `auth'.")
204 (point-max))))))) 191 (point-max)))))))
205 (delete-region (point-min) (or p (point-max)))) 192 (delete-region (point-min) (or p (point-max))))
206 193
207(defun sieve-manage-open-1 (buffer) 194(defun sieve-manage-open-server (server port &optional stream buffer)
195 "Open network connection to SERVER on PORT.
196Return the buffer associated with the connection."
208 (with-current-buffer buffer 197 (with-current-buffer buffer
209 (sieve-manage-erase) 198 (sieve-manage-erase)
210 (setq sieve-manage-state 'initial 199 (setq sieve-manage-state 'initial)
211 sieve-manage-process 200 (destructuring-bind (proc . props)
212 (condition-case () 201 (open-protocol-stream
213 (funcall (nth 2 (assq sieve-manage-stream 202 "SIEVE" buffer server port
214 sieve-manage-stream-alist)) 203 :type stream
215 "sieve" buffer sieve-manage-server sieve-manage-port) 204 :capability-command "CAPABILITY\r\n"
216 ((error quit) nil))) 205 :end-of-command "^\\(OK\\|NO\\).*\n"
217 (when sieve-manage-process 206 :success "^OK.*\n"
218 (while (and (eq sieve-manage-state 'initial) 207 :return-list t
219 (memq (process-status sieve-manage-process) '(open run))) 208 :starttls-function
220 (message "Waiting for response from %s..." sieve-manage-server) 209 '(lambda (capabilities)
221 (accept-process-output sieve-manage-process 1)) 210 (when (string-match "\\bSTARTTLS\\b" capabilities)
222 (message "Waiting for response from %s...done" sieve-manage-server) 211 "STARTTLS\r\n")))
223 (and (memq (process-status sieve-manage-process) '(open run)) 212 (setq sieve-manage-process proc)
224 sieve-manage-process)))) 213 (setq sieve-manage-capability
225 214 (sieve-manage-parse-capability (getf props :capabilities)))
226;; Streams 215 ;; Ignore new capabilities issues after successful STARTTLS
227 216 (when (and (memq stream '(nil network starttls))
228(defun sieve-manage-network-p (buffer) 217 (eq (getf props :type) 'tls))
229 t) 218 (sieve-manage-drop-next-answer))
230 219 (current-buffer))))
231(defun sieve-manage-network-open (name buffer server port)
232 (let* ((port (or port sieve-manage-default-port))
233 (coding-system-for-read sieve-manage-coding-system-for-read)
234 (coding-system-for-write sieve-manage-coding-system-for-write)
235 (process (open-network-stream name buffer server port)))
236 (when process
237 (while (and (memq (process-status process) '(open run))
238 (set-buffer buffer) ;; XXX "blue moon" nntp.el bug
239 (goto-char (point-min))
240 (not (sieve-manage-parse-greeting-1)))
241 (accept-process-output process 1)
242 (sit-for 1))
243 (sieve-manage-erase nil buffer)
244 (when (memq (process-status process) '(open run))
245 process))))
246
247(defun sieve-manage-starttls-p (buffer)
248 (condition-case ()
249 (progn
250 (require 'starttls)
251 (call-process "starttls"))
252 (error nil)))
253
254(defun sieve-manage-starttls-open (name buffer server port)
255 (let* ((port (or port sieve-manage-default-port))
256 (coding-system-for-read sieve-manage-coding-system-for-read)
257 (coding-system-for-write sieve-manage-coding-system-for-write)
258 (process (starttls-open-stream name buffer server port))
259 done)
260 (when process
261 (while (and (memq (process-status process) '(open run))
262 (set-buffer buffer) ;; XXX "blue moon" nntp.el bug
263 (goto-char (point-min))
264 (not (sieve-manage-parse-greeting-1)))
265 (accept-process-output process 1)
266 (sit-for 1))
267 (sieve-manage-erase nil buffer)
268 (sieve-manage-send "STARTTLS")
269 (starttls-negotiate process))
270 (when (memq (process-status process) '(open run))
271 process)))
272 220
273;; Authenticators 221;; Authenticators
274(defun sieve-sasl-auth (buffer mech) 222(defun sieve-sasl-auth (buffer mech)
@@ -396,63 +344,33 @@ Optional argument AUTH indicates authenticator to use, see
396If nil, chooses the best stream the server is capable of. 344If nil, chooses the best stream the server is capable of.
397Optional argument BUFFER is buffer (buffer, or string naming buffer) 345Optional argument BUFFER is buffer (buffer, or string naming buffer)
398to work in." 346to work in."
399 (or port (setq port sieve-manage-default-port)) 347 (setq sieve-manage-port (or port sieve-manage-default-port))
400 (setq buffer (or buffer (format " *sieve* %s:%s" server port))) 348 (with-current-buffer (or buffer (sieve-manage-make-process-buffer))
401 (with-current-buffer (get-buffer-create buffer) 349 (setq sieve-manage-server (or server
402 (mapc 'make-local-variable sieve-manage-local-variables) 350 sieve-manage-server)
403 (sieve-manage-disable-multibyte) 351 sieve-manage-stream (or stream
404 (buffer-disable-undo) 352 sieve-manage-stream
405 (setq sieve-manage-server (or server sieve-manage-server)) 353 sieve-manage-default-stream)
406 (setq sieve-manage-port port) 354 sieve-manage-auth (or auth
407 (setq sieve-manage-stream (or stream sieve-manage-stream)) 355 sieve-manage-auth))
408 (message "sieve: Connecting to %s..." sieve-manage-server) 356 (message "sieve: Connecting to %s..." sieve-manage-server)
409 (if (let ((sieve-manage-stream 357 (sieve-manage-open-server sieve-manage-server
410 (or sieve-manage-stream sieve-manage-default-stream))) 358 sieve-manage-port
411 (sieve-manage-open-1 buffer)) 359 sieve-manage-stream
412 ;; Choose stream. 360 (current-buffer))
413 (let (stream-changed) 361 (when (sieve-manage-opened (current-buffer))
414 (message "sieve: Connecting to %s...done" sieve-manage-server) 362 ;; Choose authenticator
415 (when (null sieve-manage-stream) 363 (when (and (null sieve-manage-auth)
416 (let ((streams sieve-manage-streams)) 364 (not (eq sieve-manage-state 'auth)))
417 (while (setq stream (pop streams)) 365 (dolist (auth sieve-manage-authenticators)
418 (if (funcall (nth 1 (assq stream 366 (when (funcall (nth 1 (assq auth sieve-manage-authenticator-alist))
419 sieve-manage-stream-alist)) buffer) 367 buffer)
420 (setq stream-changed 368 (setq sieve-manage-auth auth)
421 (not (eq (or sieve-manage-stream 369 (return)))
422 sieve-manage-default-stream) 370 (unless sieve-manage-auth
423 stream)) 371 (error "Couldn't figure out authenticator for server")))
424 sieve-manage-stream stream
425 streams nil)))
426 (unless sieve-manage-stream
427 (error "Couldn't figure out a stream for server"))))
428 (when stream-changed
429 (message "sieve: Reconnecting with stream `%s'..."
430 sieve-manage-stream)
431 (sieve-manage-close buffer)
432 (if (sieve-manage-open-1 buffer)
433 (message "sieve: Reconnecting with stream `%s'...done"
434 sieve-manage-stream)
435 (message "sieve: Reconnecting with stream `%s'...failed"
436 sieve-manage-stream))
437 (setq sieve-manage-capability nil))
438 (if (sieve-manage-opened buffer)
439 ;; Choose authenticator
440 (when (and (null sieve-manage-auth)
441 (not (eq sieve-manage-state 'auth)))
442 (let ((auths sieve-manage-authenticators))
443 (while (setq auth (pop auths))
444 (if (funcall (nth 1 (assq
445 auth
446 sieve-manage-authenticator-alist))
447 buffer)
448 (setq sieve-manage-auth auth
449 auths nil)))
450 (unless sieve-manage-auth
451 (error "Couldn't figure out authenticator for server"))))))
452 (message "sieve: Connecting to %s...failed" sieve-manage-server))
453 (when (sieve-manage-opened buffer)
454 (sieve-manage-erase) 372 (sieve-manage-erase)
455 buffer))) 373 (current-buffer))))
456 374
457(defun sieve-manage-authenticate (&optional buffer) 375(defun sieve-manage-authenticate (&optional buffer)
458 "Authenticate on server in BUFFER. 376 "Authenticate on server in BUFFER.
@@ -544,12 +462,22 @@ If NAME is nil, return the full server list of capabilities."
544 462
545;; Protocol parsing routines 463;; Protocol parsing routines
546 464
465(defun sieve-manage-wait-for-answer ()
466 (let ((pattern "^\\(OK\\|NO\\).*\n")
467 pos)
468 (while (not pos)
469 (setq pos (search-forward-regexp pattern nil t))
470 (goto-char (point-min))
471 (sleep-for 0 50))
472 pos))
473
474(defun sieve-manage-drop-next-answer ()
475 (sieve-manage-wait-for-answer)
476 (sieve-manage-erase))
477
547(defun sieve-manage-ok-p (rsp) 478(defun sieve-manage-ok-p (rsp)
548 (string= (downcase (or (car-safe rsp) "")) "ok")) 479 (string= (downcase (or (car-safe rsp) "")) "ok"))
549 480
550(defsubst sieve-manage-forward ()
551 (or (eobp) (forward-char)))
552
553(defun sieve-manage-is-okno () 481(defun sieve-manage-is-okno ()
554 (when (looking-at (concat 482 (when (looking-at (concat
555 "^\\(OK\\|NO\\)\\( (\\([^)]+\\))\\)?\\( \\(.*\\)\\)?" 483 "^\\(OK\\|NO\\)\\( (\\([^)]+\\))\\)?\\( \\(.*\\)\\)?"
@@ -571,21 +499,15 @@ If NAME is nil, return the full server list of capabilities."
571 (sieve-manage-erase) 499 (sieve-manage-erase)
572 rsp)) 500 rsp))
573 501
574(defun sieve-manage-parse-capability-1 () 502(defun sieve-manage-parse-capability (str)
575 "Accept a managesieve greeting." 503 "Parse managesieve capability string `STR'.
576 (let (str) 504Set variable `sieve-manage-capability' to "
577 (while (setq str (sieve-manage-is-string)) 505 (let ((capas (remove-if #'null
578 (if (eq (char-after) ? ) 506 (mapcar #'split-string-and-unquote
579 (progn 507 (split-string str "\n")))))
580 (sieve-manage-forward) 508 (when (string= "OK" (caar (last capas)))
581 (push (list str (sieve-manage-is-string)) 509 (setq sieve-manage-state 'nonauth))
582 sieve-manage-capability)) 510 capas))
583 (push (list str) sieve-manage-capability))
584 (forward-line)))
585 (when (re-search-forward (concat "^OK.*" sieve-manage-server-eol) nil t)
586 (setq sieve-manage-state 'nonauth)))
587
588(defalias 'sieve-manage-parse-greeting-1 'sieve-manage-parse-capability-1)
589 511
590(defun sieve-manage-is-string () 512(defun sieve-manage-is-string ()
591 (cond ((looking-at "\"\\([^\"]+\\)\"") 513 (cond ((looking-at "\"\\([^\"]+\\)\"")
@@ -639,7 +561,7 @@ If NAME is nil, return the full server list of capabilities."
639 (setq cmdstr (concat cmdstr sieve-manage-client-eol)) 561 (setq cmdstr (concat cmdstr sieve-manage-client-eol))
640 (and sieve-manage-log 562 (and sieve-manage-log
641 (with-current-buffer (get-buffer-create sieve-manage-log) 563 (with-current-buffer (get-buffer-create sieve-manage-log)
642 (sieve-manage-disable-multibyte) 564 (mm-enable-multibyte)
643 (buffer-disable-undo) 565 (buffer-disable-undo)
644 (goto-char (point-max)) 566 (goto-char (point-max))
645 (insert cmdstr))) 567 (insert cmdstr)))