1 ;;; sasl.el --- SASL client framework
3 ;; Copyright (C) 2000 Daiki Ueno
5 ;; Author: Daiki Ueno <ueno@unixuser.org>
8 ;; This file is part of FLIM (Faithful Library about Internet Message).
10 ;; This program is free software; you can redistribute it and/or
11 ;; modify it under the terms of the GNU General Public License as
12 ;; published by the Free Software Foundation; either version 2, or (at
13 ;; your option) any later version.
15 ;; This program is distributed in the hope that it will be useful, but
16 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 ;; General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with this program; see the file COPYING. If not, write to the
22 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
29 (defvar sasl-mechanisms
30 '("CRAM-MD5" "DIGEST-MD5" "PLAIN"))
32 (defvar sasl-mechanism-alist
33 '(("CRAM-MD5" sasl-cram)
34 ("DIGEST-MD5" sasl-digest)
35 ("PLAIN" sasl-plain)))
37 (defvar sasl-unique-id-function #'sasl-unique-id-function)
39 (defun sasl-make-authenticator (mechanism continuations)
42 (lambda (continuation)
43 (let ((symbol (make-symbol (symbol-name continuation))))
44 (fset symbol (symbol-function continuation))
48 (defmacro sasl-authenticator-mechanism-internal (authenticator)
49 `(aref ,authenticator 0))
51 (defmacro sasl-authenticator-continuations-internal (authenticator)
52 `(aref ,authenticator 1))
54 (defmacro sasl-make-principal (name service server &optional realm)
55 `(vector ,name ,realm ,service ,server))
57 (defmacro sasl-principal-name-internal (principal)
60 (defmacro sasl-principal-realm-internal (principal)
63 (defmacro sasl-principal-service-internal (principal)
66 (defmacro sasl-principal-server-internal (principal)
69 (defun sasl-find-authenticator (mechanisms)
70 "Retrieve an apropriate authenticator object from MECHANISMS hints."
71 (let* ((sasl-mechanisms sasl-mechanisms)
74 (while sasl-mechanisms
75 (if (member (car sasl-mechanisms) mechanisms)
76 (throw 'done (nth 1 (assoc (car sasl-mechanisms)
77 sasl-mechanism-alist))))
78 (setq sasl-mechanisms (cdr sasl-mechanisms))))))
81 (get mechanism 'sasl-authenticator))))
83 (defun sasl-evaluate-challenge (authenticator principal &optional challenge)
84 "Evaluate the challenge and prepare an appropriate next response.
85 The data type of the value and the CHALLENGE is nil or a cons cell of the form
86 \(CONTINUATION STRING). At the first time CONTINUATION should be set to nil."
88 (sasl-authenticator-continuations-internal authenticator))
91 (nth 1 (memq (car challenge) continuations))
92 (car continuations))))
94 (list function (funcall function principal challenge)))))
96 (defvar sasl-read-passphrase nil)
97 (defun sasl-read-passphrase (prompt &optional key)
98 (if (not sasl-read-passphrase)
99 (if (functionp 'read-passwd)
100 (setq sasl-read-passphrase 'read-passwd)
101 (if (load "passwd" t)
102 (setq sasl-read-passphrase 'read-passwd)
103 (autoload 'ange-ftp-read-passwd "ange-ftp")
104 (setq sasl-read-passphrase 'ange-ftp-read-passwd))))
105 (funcall sasl-read-passphrase prompt))
107 (defun sasl-unique-id ()
108 "Compute a data string which must be different each time.
109 It contain at least 64 bits of entropy."
110 (concat (funcall sasl-unique-id-function)(funcall sasl-unique-id-function)))
112 (defvar sasl-unique-id-char nil)
114 ;; stolen (and renamed) from message.el
115 (defun sasl-unique-id-function ()
116 ;; Don't use microseconds from (current-time), they may be unsupported.
117 ;; Instead we use this randomly inited counter.
118 (setq sasl-unique-id-char
119 (% (1+ (or sasl-unique-id-char (logand (random t) (1- (lsh 1 20)))))
120 ;; (current-time) returns 16-bit ints,
121 ;; and 2^16*25 just fits into 4 digits i base 36.
123 (let ((tm (current-time)))
125 (sasl-unique-id-number-base36
127 (lsh (% sasl-unique-id-char 25) 16)) 4)
128 (sasl-unique-id-number-base36
130 (lsh (/ sasl-unique-id-char 25) 16)) 4))))
132 (defun sasl-unique-id-number-base36 (num len)
137 (concat (sasl-unique-id-number-base36 (/ num 36) (1- len))
138 (char-to-string (aref "zyxwvutsrqponmlkjihgfedcba9876543210"
141 ;;; PLAIN SASL mechanism (RFC2595 Section 6)
142 (defconst sasl-plain-continuations
143 '(sasl-plain-response))
145 (defun sasl-plain-response (principal challenge)
147 (sasl-read-passphrase
148 (format "PLAIN passphrase for %s: "
149 (sasl-principal-name-internal principal)))))
151 (concat "\0" (sasl-principal-name-internal principal) "\0" passphrase)
152 (fillarray passphrase 0))))
154 (put 'sasl-plain 'sasl-authenticator
155 (sasl-make-authenticator "PLAIN" sasl-plain-continuations))
157 (provide 'sasl-plain)
161 ;;; sasl.el ends here