version up
[elisp/flim.git] / sasl.el
1 ;;; sasl.el --- basic functions for SASL
2
3 ;; Copyright (C) 1995, 1996, 1998, 1999 Free Software Foundation, Inc.
4
5 ;; Author: Kenichi OKADA <okada@opaopa.org>
6 ;; Keywords: SMTP, SASL, RFC2222
7
8 ;; This file is part of FLIM (Faithful Library about Internet Message).
9
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.
14
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.
19
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.
24
25 ;;; Code:
26
27 (require 'hmac-md5)
28
29 (defun sasl-cram-md5 (username passphrase challenge)
30   (let ((secure-word (copy-sequence passphrase)))
31     (setq secure-word (unwind-protect
32                           (hmac-md5 challenge secure-word)
33                         (fillarray secure-word 0))
34           secure-word (unwind-protect
35                           (encode-hex-string secure-word)
36                         (fillarray secure-word 0))
37           secure-word (unwind-protect
38                           (concat username " " secure-word)
39                         (fillarray secure-word 0)))))
40                 
41 (defun sasl-plain (authorid authenid passphrase)
42   (concat authorid "\0" authenid "\0" passphrase))
43
44 (defun sasl-number-base36 (num len)
45   (if (if (< len 0)
46           (<= num 0)
47         (= len 0))
48       ""
49     (concat (sasl-number-base36 (/ num 36) (1- len))
50             (char-to-string (aref "zyxwvutsrqponmlkjihgfedcba9876543210"
51                                   (% num 36))))))
52
53 (defvar sasl-unique-id-char nil)
54
55 (defun sasl-unique-id ()
56   ;; Don't use microseconds from (current-time), they may be unsupported.
57   ;; Instead we use this randomly inited counter.
58   (setq sasl-unique-id-char
59         (% (1+ (or sasl-unique-id-char (logand (random t) (1- (lsh 1 20)))))
60            ;; (current-time) returns 16-bit ints,
61            ;; and 2^16*25 just fits into 4 digits i base 36.
62            (* 25 25)))
63   (let ((tm (static-if (fboundp 'current-time)
64                 (current-time)
65               (let* ((cts (split-string (current-time-string) "[ :]"))
66                      (m (cdr (assoc (nth 1 cts)
67                                     '(("Jan" . "01") ("Feb" . "02")
68                                       ("Mar" . "03") ("Apr" . "04")
69                                       ("May" . "05") ("Jun" . "06")
70                                       ("Jul" . "07") ("Aug" . "08")
71                                       ("Sep" . "09") ("Oct" . "10")
72                                       ("Nov" . "11") ("Dec" . "12"))))))
73                 (list (string-to-int (concat (nth 6 cts) m
74                                              (substring (nth 2 cts) 0 1)))
75                       (string-to-int (concat (substring (nth 2 cts) 1)
76                                              (nth 4 cts) (nth 5 cts)
77                                              (nth 6 cts))))))))
78     (concat
79      (if (memq system-type '(ms-dos emx vax-vms))
80          (let ((user (downcase (user-login-name))))
81            (while (string-match "[^a-z0-9_]" user)
82              (aset user (match-beginning 0) ?_))
83            user)
84        (sasl-number-base36 (user-uid) -1))
85      (sasl-number-base36 (+ (car   tm)
86                           (lsh (% sasl-unique-id-char 25) 16)) 4)
87      (sasl-number-base36 (+ (nth 1 tm)
88                           (lsh (/ sasl-unique-id-char 25) 16)) 4)
89      ;; Append the name of the message interface, because while the
90      ;; generated ID is unique to this newsreader, other newsreaders
91      ;; might otherwise generate the same ID via another algorithm.
92      ".sasl")))
93
94 (provide 'sasl)
95
96 ;;; sasl.el ends here