1 ;;; digest-md5.el --- Compute DIGEST-MD5.
3 ;; Copyright (C) 1999 Kenichi OKADA
5 ;; Author: Kenichi OKADA <okada@opaopa.org>
6 ;; Daiki Ueno <ueno@ueda.info.waseda.ac.jp>
7 ;; Keywords: DIGEST-MD5, HMAC-MD5, SASL, IMAP, POP, ACAP
9 ;; This file is part of FLIM (Faithful Library about Internet Message).
11 ;; This program is free software; you can redistribute it and/or
12 ;; modify it under the terms of the GNU General Public License as
13 ;; published by the Free Software Foundation; either version 2, or
14 ;; (at your option) any later version.
16 ;; This program 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.
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with this program; see the file COPYING. If not, write to
23 ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 ;; Boston, MA 02111-1307, USA.
28 ;; This program is implemented from draft-leach-digest-sasl-05.txt.
30 ;; It is caller's responsibility to base64-decode challenges and
31 ;; base64-encode responses in IMAP4 AUTHENTICATE command.
33 ;; Passphrase should be longer than 16 bytes. (See RFC 2195)
37 ;; (digest-md5-parse-digest-challenge
38 ;; "realm=\"elwood.innosoft.com\",nonce=\"OA6MG9tEQGm2hh\",qop=\"auth\",algorithm=md5-sess,charset=utf-8")
39 ;; => (realm "elwood.innosoft.com" nonce "OA6MG9tEQGm2hh" qop "auth" algorithm md5-sess charset utf-8)
41 ;; (digest-md5-build-response-value
42 ;; "chris" "secret" "OA6MHXh6VqTrRk" "imap/elwood.innosoft.com")
43 ;; => "d388dad90d4bbd760a152321f2143af7"
50 (defvar digest-md5-challenge nil)
52 (defvar digest-md5-parse-digest-challenge-syntax-table
53 (let ((table (make-syntax-table)))
54 (modify-syntax-entry ?= "." table)
55 (modify-syntax-entry ?, "." table)
57 "A syntax table for parsing digest-challenge attributes.")
60 (defun digest-md5-parse-digest-challenge (digest-challenge)
61 ;; return a property list of
62 ;; (realm nonce qop-options stale maxbuf charset
63 ;; algorithm cipher-opts auth-param).
65 (set-syntax-table digest-md5-parse-digest-challenge-syntax-table)
66 (insert digest-challenge)
67 (goto-char (point-min))
69 (while (progn (forward-sexp) (not (eobp)))
74 (setplist 'digest-md5-challenge (read (point-min-marker)))
76 (error "Parse error in digest-challenge.")))))
78 (defun digest-md5-digest-uri (serv-type host &optional serv-name)
79 (concat serv-type "/" host
81 (null (string= host serv-name)))
82 (concat "/" serv-name))))
84 (defmacro digest-md5-cnonce ()
85 ;; It is RECOMMENDED that it
86 ;; contain at least 64 bits of entropy.
87 '(concat (unique-id-m "") (unique-id-m "")))
89 (defmacro digest-md5-challenge (prop)
90 (list 'get ''digest-md5-challenge prop))
92 (defmacro digest-md5-build-response-value
93 (username realm passwd nonce cnonce nonce-count digest-uri qop)
98 (md5-binary (concat (md5-binary
104 (let ((authzid (digest-md5-challenge 'authzid)))
105 (if authzid (concat ":" authzid) nil)))))
107 ":" (format "%08x" ,nonce-count) ":" ,cnonce ":" ,qop ":"
110 (concat "AUTHENTICATE:" ,digest-uri
111 (if (string-equal "auth-int" ,qop)
112 ":00000000000000000000000000000000"
116 (defun digest-md5-digest-response
117 (username realm passwd nonce cnonce nonce-count digest-uri
118 &optional charset qop maxbuf cipher authzid)
120 "username=\"" username "\","
121 "realm=\"" realm "\","
122 "nonce=\"" nonce "\","
123 (format "nc=%08x," nonce-count)
124 "cnonce=\"" cnonce "\","
125 "digest-uri=\"" digest-uri "\","
127 (digest-md5-build-response-value
128 username realm passwd nonce cnonce nonce-count digest-uri
134 (mapcar (lambda (prop)
135 (if (digest-md5-challenge prop)
137 prop (digest-md5-challenge prop))))
138 '(charset qop maxbuf cipher authzid)))
141 (provide 'digest-md5)
143 ;;; digest-md5.el ends here