aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGlenn Morris2007-12-02 21:52:46 +0000
committerGlenn Morris2007-12-02 21:52:46 +0000
commit369fc5a6265998ababe34519f48732ad7fb335fc (patch)
tree1389515bdc4181f45b7727a387a09fe01246a199
parent323fc9ec1af6e911a86db428cc38cdcdc5c31c75 (diff)
downloademacs-369fc5a6265998ababe34519f48732ad7fb335fc.tar.gz
emacs-369fc5a6265998ababe34519f48732ad7fb335fc.zip
Move here from ../gnus.
-rw-r--r--lisp/ChangeLog6
-rw-r--r--lisp/net/sasl-cram.el52
-rw-r--r--lisp/net/sasl-digest.el159
-rw-r--r--lisp/net/sasl-ntlm.el68
-rw-r--r--lisp/net/sasl.el273
5 files changed, 558 insertions, 0 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 9038d2b98dc..bec72ccb1f2 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -13,6 +13,9 @@
13 13
142007-12-02 Glenn Morris <rgm@gnu.org> 142007-12-02 Glenn Morris <rgm@gnu.org>
15 15
16 * emacs-lisp/bytecomp.el (byte-compile-declare-function): Reverse
17 branches of if statement.
18
16 * emulation/viper-cmd.el (top-level): Don't require advice. 19 * emulation/viper-cmd.el (top-level): Don't require advice.
17 Don't load viper-util, viper-keym, viper-mous, viper-macs, 20 Don't load viper-util, viper-keym, viper-mous, viper-macs,
18 viper-ex when compiling. 21 viper-ex when compiling.
@@ -37,6 +40,9 @@
37 * emulation/viper.el (top-level): Don't require ring. 40 * emulation/viper.el (top-level): Don't require ring.
38 Don't load viper-init, viper-cmd when compiling. 41 Don't load viper-init, viper-cmd when compiling.
39 42
43 * net/sasl-cram.el, net/sasl-digest.el, net/sasl-ntlm.el, net/sasl.el:
44 Move here from gnus/.
45
402007-12-02 Karl Fogel <kfogel@red-bean.com> 462007-12-02 Karl Fogel <kfogel@red-bean.com>
41 47
42 Offer option for saveplace to be quiet about loading and saving. 48 Offer option for saveplace to be quiet about loading and saving.
diff --git a/lisp/net/sasl-cram.el b/lisp/net/sasl-cram.el
new file mode 100644
index 00000000000..32f1e69f81f
--- /dev/null
+++ b/lisp/net/sasl-cram.el
@@ -0,0 +1,52 @@
1;;; sasl-cram.el --- CRAM-MD5 module for the SASL client framework
2
3;; Copyright (C) 2000, 2007 Free Software Foundation, Inc.
4
5;; Author: Daiki Ueno <ueno@unixuser.org>
6;; Kenichi OKADA <okada@opaopa.org>
7;; Keywords: SASL, CRAM-MD5
8
9;; This file is part of GNU Emacs.
10
11;; GNU Emacs is free software; you can redistribute it and/or modify
12;; it under the terms of the GNU General Public License as published by
13;; the Free Software Foundation; either version 3, or (at your option)
14;; any later version.
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
22;; along with GNU Emacs; see the file COPYING. If not, write to the
23;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24;; Boston, MA 02110-1301, USA.
25
26;;; Commentary:
27
28(require 'sasl)
29(require 'hmac-md5)
30
31(defconst sasl-cram-md5-steps
32 '(ignore ;no initial response
33 sasl-cram-md5-response))
34
35(defun sasl-cram-md5-response (client step)
36 (let ((passphrase
37 (sasl-read-passphrase
38 (format "CRAM-MD5 passphrase for %s: "
39 (sasl-client-name client)))))
40 (unwind-protect
41 (concat (sasl-client-name client) " "
42 (encode-hex-string
43 (hmac-md5 (sasl-step-data step) passphrase)))
44 (fillarray passphrase 0))))
45
46(put 'sasl-cram 'sasl-mechanism
47 (sasl-make-mechanism "CRAM-MD5" sasl-cram-md5-steps))
48
49(provide 'sasl-cram)
50
51;;; arch-tag: 46cb281b-975a-4fe0-a39f-3018691b1b05
52;;; sasl-cram.el ends here
diff --git a/lisp/net/sasl-digest.el b/lisp/net/sasl-digest.el
new file mode 100644
index 00000000000..6c544518e7f
--- /dev/null
+++ b/lisp/net/sasl-digest.el
@@ -0,0 +1,159 @@
1;;; sasl-digest.el --- DIGEST-MD5 module for the SASL client framework
2
3;; Copyright (C) 2000, 2007 Free Software Foundation, Inc.
4
5;; Author: Daiki Ueno <ueno@unixuser.org>
6;; Kenichi OKADA <okada@opaopa.org>
7;; Keywords: SASL, DIGEST-MD5
8
9;; This file is part of GNU Emacs.
10
11;; GNU Emacs is free software; you can redistribute it and/or modify
12;; it under the terms of the GNU General Public License as published by
13;; the Free Software Foundation; either version 3, or (at your option)
14;; any later version.
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
22;; along with GNU Emacs; see the file COPYING. If not, write to the
23;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24;; Boston, MA 02110-1301, USA.
25
26;;; Commentary:
27
28;; This program is implemented from draft-leach-digest-sasl-05.txt.
29;;
30;; It is caller's responsibility to base64-decode challenges and
31;; base64-encode responses in IMAP4 AUTHENTICATE command.
32;;
33;; Passphrase should be longer than 16 bytes. (See RFC 2195)
34
35;;; Commentary:
36
37(require 'sasl)
38(require 'hmac-md5)
39
40(defvar sasl-digest-md5-nonce-count 1)
41(defvar sasl-digest-md5-unique-id-function
42 sasl-unique-id-function)
43
44(defvar sasl-digest-md5-syntax-table
45 (let ((table (make-syntax-table)))
46 (modify-syntax-entry ?= "." table)
47 (modify-syntax-entry ?, "." table)
48 table)
49 "A syntax table for parsing digest-challenge attributes.")
50
51(defconst sasl-digest-md5-steps
52 '(ignore ;no initial response
53 sasl-digest-md5-response
54 ignore)) ;""
55
56(defun sasl-digest-md5-parse-string (string)
57 "Parse STRING and return a property list.
58The value is a cons cell of the form \(realm nonce qop-options stale maxbuf
59charset algorithm cipher-opts auth-param)."
60 (with-temp-buffer
61 (set-syntax-table sasl-digest-md5-syntax-table)
62 (save-excursion
63 (insert string)
64 (goto-char (point-min))
65 (insert "(")
66 (while (progn (forward-sexp) (not (eobp)))
67 (delete-char 1)
68 (insert " "))
69 (insert ")")
70 (read (point-min-marker)))))
71
72(defun sasl-digest-md5-digest-uri (serv-type host &optional serv-name)
73 (concat serv-type "/" host
74 (if (and serv-name
75 (not (string= host serv-name)))
76 (concat "/" serv-name))))
77
78(defun sasl-digest-md5-cnonce ()
79 (let ((sasl-unique-id-function sasl-digest-md5-unique-id-function))
80 (sasl-unique-id)))
81
82(defun sasl-digest-md5-response-value (username
83 realm
84 nonce
85 cnonce
86 nonce-count
87 qop
88 digest-uri
89 authzid)
90 (let ((passphrase
91 (sasl-read-passphrase
92 (format "DIGEST-MD5 passphrase for %s: "
93 username))))
94 (unwind-protect
95 (encode-hex-string
96 (md5-binary
97 (concat
98 (encode-hex-string
99 (md5-binary (concat (md5-binary
100 (concat username ":" realm ":" passphrase))
101 ":" nonce ":" cnonce
102 (if authzid
103 (concat ":" authzid)))))
104 ":" nonce
105 ":" (format "%08x" nonce-count) ":" cnonce ":" qop ":"
106 (encode-hex-string
107 (md5-binary
108 (concat "AUTHENTICATE:" digest-uri
109 (if (member qop '("auth-int" "auth-conf"))
110 ":00000000000000000000000000000000")))))))
111 (fillarray passphrase 0))))
112
113(defun sasl-digest-md5-response (client step)
114 (let* ((plist
115 (sasl-digest-md5-parse-string (sasl-step-data step)))
116 (realm
117 (or (sasl-client-property client 'realm)
118 (plist-get plist 'realm))) ;need to check
119 (nonce-count
120 (or (sasl-client-property client 'nonce-count)
121 sasl-digest-md5-nonce-count))
122 (qop
123 (or (sasl-client-property client 'qop)
124 "auth"))
125 (digest-uri
126 (sasl-digest-md5-digest-uri
127 (sasl-client-service client)(sasl-client-server client)))
128 (cnonce
129 (or (sasl-client-property client 'cnonce)
130 (sasl-digest-md5-cnonce))))
131 (sasl-client-set-property client 'nonce-count (1+ nonce-count))
132 (unless (string= qop "auth")
133 (sasl-error (format "Unsupported \"qop-value\": %s" qop)))
134 (concat
135 "username=\"" (sasl-client-name client) "\","
136 "realm=\"" realm "\","
137 "nonce=\"" (plist-get plist 'nonce) "\","
138 "cnonce=\"" cnonce "\","
139 (format "nc=%08x," nonce-count)
140 "digest-uri=\"" digest-uri "\","
141 "qop=" qop ","
142 "response="
143 (sasl-digest-md5-response-value
144 (sasl-client-name client)
145 realm
146 (plist-get plist 'nonce)
147 cnonce
148 nonce-count
149 qop
150 digest-uri
151 (plist-get plist 'authzid)))))
152
153(put 'sasl-digest 'sasl-mechanism
154 (sasl-make-mechanism "DIGEST-MD5" sasl-digest-md5-steps))
155
156(provide 'sasl-digest)
157
158;;; arch-tag: 786e02ed-1bc4-4b3c-bf34-96c27e31084d
159;;; sasl-digest.el ends here
diff --git a/lisp/net/sasl-ntlm.el b/lisp/net/sasl-ntlm.el
new file mode 100644
index 00000000000..cd8304db70a
--- /dev/null
+++ b/lisp/net/sasl-ntlm.el
@@ -0,0 +1,68 @@
1;;; sasl-ntlm.el --- NTLM (NT Lan Manager) module for the SASL client framework
2
3;; Copyright (C) 2000, 2007 Free Software Foundation, Inc.
4
5;; Author: Taro Kawagishi <tarok@transpulse.org>
6;; Keywords: SASL, NTLM
7;; Version: 1.00
8;; Created: February 2001
9
10;; This file is part of GNU Emacs.
11
12;; GNU Emacs is free software; you can redistribute it and/or modify
13;; it under the terms of the GNU General Public License as published by
14;; the Free Software Foundation; either version 3, or (at your option)
15;; any later version.
16
17;; GNU Emacs is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
23;; along with GNU Emacs; see the file COPYING. If not, write to the
24;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25;; Boston, MA 02110-1301, USA.
26
27;;; Commentary:
28
29;; This is a SASL interface layer for NTLM authentication message
30;; generation by ntlm.el
31
32;;; Code:
33
34(require 'sasl)
35(require 'ntlm)
36
37(defconst sasl-ntlm-steps
38 '(ignore ;nothing to do before making
39 sasl-ntlm-request ;authentication request
40 sasl-ntlm-response) ;response to challenge
41 "A list of functions to be called in sequnece for the NTLM
42authentication steps. Ther are called by 'sasl-next-step.")
43
44(defun sasl-ntlm-request (client step)
45 "SASL step function to generate a NTLM authentication request to the server.
46Called from 'sasl-next-step.
47CLIENT is a vector [mechanism user service server sasl-client-properties]
48STEP is a vector [<previous step function> <result of previous step function>]"
49 (let ((user (sasl-client-name client)))
50 (ntlm-build-auth-request user)))
51
52(defun sasl-ntlm-response (client step)
53 "SASL step function to generate a NTLM response against the server
54challenge stored in the 2nd element of STEP. Called from 'sasl-next-step."
55 (let* ((user (sasl-client-name client))
56 (passphrase
57 (sasl-read-passphrase (format "NTLM passphrase for %s: " user)))
58 (challenge (sasl-step-data step)))
59 (ntlm-build-auth-response challenge user
60 (ntlm-get-password-hashes passphrase))))
61
62(put 'sasl-ntlm 'sasl-mechanism
63 (sasl-make-mechanism "NTLM" sasl-ntlm-steps))
64
65(provide 'sasl-ntlm)
66
67;;; arch-tag: 1d9164c1-1df0-418f-b7ab-360157fd05dc
68;;; sasl-ntlm.el ends here
diff --git a/lisp/net/sasl.el b/lisp/net/sasl.el
new file mode 100644
index 00000000000..9118d288da4
--- /dev/null
+++ b/lisp/net/sasl.el
@@ -0,0 +1,273 @@
1;;; sasl.el --- SASL client framework
2
3;; Copyright (C) 2000, 2007 Free Software Foundation, Inc.
4
5;; Author: Daiki Ueno <ueno@unixuser.org>
6;; Keywords: SASL
7
8;; This file is part of GNU Emacs.
9
10;; GNU Emacs is free software; you can redistribute it and/or modify
11;; it under the terms of the GNU General Public License as published by
12;; the Free Software Foundation; either version 3, or (at your option)
13;; any later version.
14
15;; GNU Emacs is distributed in the hope that it will be useful,
16;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18;; GNU General Public License for more details.
19
20;; You should have received a copy of the GNU General Public License
21;; along with GNU Emacs; see the file COPYING. If not, write to the
22;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23;; Boston, MA 02110-1301, USA.
24
25;;; Commentary:
26
27;; This module provides common interface functions to share several
28;; SASL mechanism drivers. The toplevel is designed to be mostly
29;; compatible with [Java-SASL].
30;;
31;; [SASL] J. Myers, "Simple Authentication and Security Layer (SASL)",
32;; RFC 2222, October 1997.
33;;
34;; [Java-SASL] R. Weltman & R. Lee, "The Java SASL Application Program
35;; Interface", draft-weltman-java-sasl-03.txt, March 2000.
36
37;;; Code:
38
39(defvar sasl-mechanisms
40 '("CRAM-MD5" "DIGEST-MD5" "PLAIN" "LOGIN" "ANONYMOUS"
41 "NTLM" "SCRAM-MD5"))
42
43(defvar sasl-mechanism-alist
44 '(("CRAM-MD5" sasl-cram)
45 ("DIGEST-MD5" sasl-digest)
46 ("PLAIN" sasl-plain)
47 ("LOGIN" sasl-login)
48 ("ANONYMOUS" sasl-anonymous)
49 ("NTLM" sasl-ntlm)
50 ("SCRAM-MD5" sasl-scram)))
51
52(defvar sasl-unique-id-function #'sasl-unique-id-function)
53
54(put 'sasl-error 'error-message "SASL error")
55(put 'sasl-error 'error-conditions '(sasl-error error))
56
57(defun sasl-error (datum)
58 (signal 'sasl-error (list datum)))
59
60;;; @ SASL client
61;;;
62
63(defun sasl-make-client (mechanism name service server)
64 "Return a newly allocated SASL client.
65NAME is name of the authorization. SERVICE is name of the service desired.
66SERVER is the fully qualified host name of the server to authenticate to."
67 (vector mechanism name service server (make-symbol "sasl-client-properties")))
68
69(defun sasl-client-mechanism (client)
70 "Return the authentication mechanism driver of CLIENT."
71 (aref client 0))
72
73(defun sasl-client-name (client)
74 "Return the authorization name of CLIENT, a string."
75 (aref client 1))
76
77(defun sasl-client-service (client)
78 "Return the service name of CLIENT, a string."
79 (aref client 2))
80
81(defun sasl-client-server (client)
82 "Return the server name of CLIENT, a string."
83 (aref client 3))
84
85(defun sasl-client-set-properties (client plist)
86 "Destructively set the properties of CLIENT.
87The second argument PLIST is the new property list."
88 (setplist (aref client 4) plist))
89
90(defun sasl-client-set-property (client property value)
91 "Add the given property/value to CLIENT."
92 (put (aref client 4) property value))
93
94(defun sasl-client-property (client property)
95 "Return the value of the PROPERTY of CLIENT."
96 (get (aref client 4) property))
97
98(defun sasl-client-properties (client)
99 "Return the properties of CLIENT."
100 (symbol-plist (aref client 4)))
101
102;;; @ SASL mechanism
103;;;
104
105(defun sasl-make-mechanism (name steps)
106 "Make an authentication mechanism.
107NAME is a IANA registered SASL mechanism name.
108STEPS is list of continuation function."
109 (vector name
110 (mapcar
111 (lambda (step)
112 (let ((symbol (make-symbol (symbol-name step))))
113 (fset symbol (symbol-function step))
114 symbol))
115 steps)))
116
117(defun sasl-mechanism-name (mechanism)
118 "Return name of MECHANISM, a string."
119 (aref mechanism 0))
120
121(defun sasl-mechanism-steps (mechanism)
122 "Return the authentication steps of MECHANISM, a list of functions."
123 (aref mechanism 1))
124
125(defun sasl-find-mechanism (mechanisms)
126 "Retrieve an apropriate mechanism object from MECHANISMS hints."
127 (let* ((sasl-mechanisms sasl-mechanisms)
128 (mechanism
129 (catch 'done
130 (while sasl-mechanisms
131 (if (member (car sasl-mechanisms) mechanisms)
132 (throw 'done (nth 1 (assoc (car sasl-mechanisms)
133 sasl-mechanism-alist))))
134 (setq sasl-mechanisms (cdr sasl-mechanisms))))))
135 (if mechanism
136 (require mechanism))
137 (get mechanism 'sasl-mechanism)))
138
139;;; @ SASL authentication step
140;;;
141
142(defun sasl-step-data (step)
143 "Return the data which STEP holds, a string."
144 (aref step 1))
145
146(defun sasl-step-set-data (step data)
147 "Store DATA string to STEP."
148 (aset step 1 data))
149
150(defun sasl-next-step (client step)
151 "Evaluate the challenge and prepare an appropriate next response.
152The data type of the value and optional 2nd argument STEP is nil or
153opaque authentication step which holds the reference to the next action
154and the current challenge. At the first time STEP should be set to nil."
155 (let* ((steps
156 (sasl-mechanism-steps
157 (sasl-client-mechanism client)))
158 (function
159 (if (vectorp step)
160 (nth 1 (memq (aref step 0) steps))
161 (car steps))))
162 (if function
163 (vector function (funcall function client step)))))
164
165(defvar sasl-read-passphrase nil)
166(defun sasl-read-passphrase (prompt)
167 (if (not sasl-read-passphrase)
168 (if (functionp 'read-passwd)
169 (setq sasl-read-passphrase 'read-passwd)
170 (if (load "passwd" t)
171 (setq sasl-read-passphrase 'read-passwd)
172 (autoload 'ange-ftp-read-passwd "ange-ftp")
173 (setq sasl-read-passphrase 'ange-ftp-read-passwd))))
174 (funcall sasl-read-passphrase prompt))
175
176(defun sasl-unique-id ()
177 "Compute a data string which must be different each time.
178It contain at least 64 bits of entropy."
179 (concat (funcall sasl-unique-id-function)(funcall sasl-unique-id-function)))
180
181(defvar sasl-unique-id-char nil)
182
183;; stolen (and renamed) from message.el
184(defun sasl-unique-id-function ()
185 ;; Don't use microseconds from (current-time), they may be unsupported.
186 ;; Instead we use this randomly inited counter.
187 (setq sasl-unique-id-char
188 (% (1+ (or sasl-unique-id-char (logand (random t) (1- (lsh 1 20)))))
189 ;; (current-time) returns 16-bit ints,
190 ;; and 2^16*25 just fits into 4 digits i base 36.
191 (* 25 25)))
192 (let ((tm (current-time)))
193 (concat
194 (sasl-unique-id-number-base36
195 (+ (car tm)
196 (lsh (% sasl-unique-id-char 25) 16)) 4)
197 (sasl-unique-id-number-base36
198 (+ (nth 1 tm)
199 (lsh (/ sasl-unique-id-char 25) 16)) 4))))
200
201(defun sasl-unique-id-number-base36 (num len)
202 (if (if (< len 0)
203 (<= num 0)
204 (= len 0))
205 ""
206 (concat (sasl-unique-id-number-base36 (/ num 36) (1- len))
207 (char-to-string (aref "zyxwvutsrqponmlkjihgfedcba9876543210"
208 (% num 36))))))
209
210;;; PLAIN (RFC2595 Section 6)
211(defconst sasl-plain-steps
212 '(sasl-plain-response))
213
214(defun sasl-plain-response (client step)
215 (let ((passphrase
216 (sasl-read-passphrase
217 (format "PLAIN passphrase for %s: " (sasl-client-name client))))
218 (authenticator-name
219 (sasl-client-property
220 client 'authenticator-name))
221 (name (sasl-client-name client)))
222 (unwind-protect
223 (if (and authenticator-name
224 (not (string= authenticator-name name)))
225 (concat authenticator-name "\0" name "\0" passphrase)
226 (concat "\0" name "\0" passphrase))
227 (fillarray passphrase 0))))
228
229(put 'sasl-plain 'sasl-mechanism
230 (sasl-make-mechanism "PLAIN" sasl-plain-steps))
231
232(provide 'sasl-plain)
233
234;;; LOGIN (No specification exists)
235(defconst sasl-login-steps
236 '(ignore ;no initial response
237 sasl-login-response-1
238 sasl-login-response-2))
239
240(defun sasl-login-response-1 (client step)
241;;; (unless (string-match "^Username:" (sasl-step-data step))
242;;; (sasl-error (format "Unexpected response: %s" (sasl-step-data step))))
243 (sasl-client-name client))
244
245(defun sasl-login-response-2 (client step)
246;;; (unless (string-match "^Password:" (sasl-step-data step))
247;;; (sasl-error (format "Unexpected response: %s" (sasl-step-data step))))
248 (sasl-read-passphrase
249 (format "LOGIN passphrase for %s: " (sasl-client-name client))))
250
251(put 'sasl-login 'sasl-mechanism
252 (sasl-make-mechanism "LOGIN" sasl-login-steps))
253
254(provide 'sasl-login)
255
256;;; ANONYMOUS (RFC2245)
257(defconst sasl-anonymous-steps
258 '(ignore ;no initial response
259 sasl-anonymous-response))
260
261(defun sasl-anonymous-response (client step)
262 (or (sasl-client-property client 'trace)
263 (sasl-client-name client)))
264
265(put 'sasl-anonymous 'sasl-mechanism
266 (sasl-make-mechanism "ANONYMOUS" sasl-anonymous-steps))
267
268(provide 'sasl-anonymous)
269
270(provide 'sasl)
271
272;;; arch-tag: 8b3326fa-4978-4fda-93e2-cb2c6255f887
273;;; sasl.el ends here