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" "elwood.innosoft.com" "secret" "OA6MG9tEQGm2hh"
43 ;; "OA6MHXh6VqTrRk" 1 "imap/elwood.innosoft.com" "auth")
44 ;; => "d388dad90d4bbd760a152321f2143af7"
51 (defvar digest-md5-challenge nil)
53 (defvar digest-md5-parse-digest-challenge-syntax-table
54 (let ((table (make-syntax-table)))
55 (modify-syntax-entry ?= "." table)
56 (modify-syntax-entry ?, "." table)
58 "A syntax table for parsing digest-challenge attributes.")
61 (defun digest-md5-parse-digest-challenge (digest-challenge)
62 ;; return a property list of
63 ;; (realm nonce qop-options stale maxbuf charset
64 ;; algorithm cipher-opts auth-param).
66 (set-syntax-table digest-md5-parse-digest-challenge-syntax-table)
67 (insert digest-challenge)
68 (goto-char (point-min))
70 (while (progn (forward-sexp) (not (eobp)))
75 (setplist 'digest-md5-challenge (read (point-min-marker)))
77 (error "Parse error in digest-challenge.")))))
79 (defun digest-md5-digest-uri (serv-type host &optional serv-name)
80 (concat serv-type "/" host
82 (null (string= host serv-name)))
83 (concat "/" serv-name))))
85 (defmacro digest-md5-cnonce ()
86 ;; It is RECOMMENDED that it
87 ;; contain at least 64 bits of entropy.
88 '(concat (unique-id-m "") (unique-id-m "")))
90 (defmacro digest-md5-challenge (prop)
91 (list 'get ''digest-md5-challenge prop))
93 (defmacro digest-md5-build-response-value
94 (username realm passwd nonce cnonce nonce-count digest-uri qop)
99 (md5-binary (concat (md5-binary
105 (let ((authzid (digest-md5-challenge 'authzid)))
106 (if authzid (concat ":" authzid) nil)))))
108 ":" (format "%08x" ,nonce-count) ":" ,cnonce ":" ,qop ":"
111 (concat "AUTHENTICATE:" ,digest-uri
112 (if (string-equal "auth-int" ,qop)
113 ":00000000000000000000000000000000"
117 (defun digest-md5-digest-response
118 (username realm passwd nonce cnonce nonce-count digest-uri
119 &optional charset qop maxbuf cipher authzid)
121 "username=\"" username "\","
122 "realm=\"" realm "\","
123 "nonce=\"" nonce "\","
124 (format "nc=%08x," nonce-count)
125 "cnonce=\"" cnonce "\","
126 "digest-uri=\"" digest-uri "\","
128 (digest-md5-build-response-value
129 username realm passwd nonce cnonce nonce-count digest-uri
135 (mapcar (lambda (prop)
136 (if (digest-md5-challenge prop)
138 prop (digest-md5-challenge prop))))
139 '(charset qop maxbuf cipher authzid)))
142 (provide 'digest-md5)
144 ;;; digest-md5.el ends here