* digest-md5.el (digest-md5-challenge): New variable.
authorueno <ueno>
Mon, 13 Dec 1999 12:48:41 +0000 (12:48 +0000)
committerueno <ueno>
Mon, 13 Dec 1999 12:48:41 +0000 (12:48 +0000)
(digest-md5-nonce-count): New variable.
(digest-md5-parse-digest-challenge-syntax-table): Fix document.
(digest-md5-parse-digest-challenge): Add autoload cookie.
(digest-md5-challenge): New macro.
(digest-md5-build-response-value): New macro.
(digest-md5-digest-response): Use it; Add autoload cookie.

digest-md5.el

index e6f87dc..21c552c 100644 (file)
@@ -3,6 +3,7 @@
 ;; Copyright (C) 1999 Kenichi OKADA
 
 ;; Author: Kenichi OKADA <okada@opaopa.org>
+;;     Daiki Ueno <ueno@ueda.info.waseda.ac.jp>
 ;; Keywords: DIGEST-MD5, HMAC-MD5, SASL, IMAP, POP, ACAP
 
 ;; This file is part of FLIM (Faithful Library about Internet Message).
 
 ;; Examples.
 ;;
-;; (digest-md5-digest-response "chris" "elwood.innosoft.com"
-;;                       "OA6MG9tEQGm2hh" "OA6MHXh6VqTrRk"
-;;                       "imap/elwood.innosoft.com"
-;;                       "d388dad90d4bbd760a152321f2143af7"
-;;                       1 "auth" nil "utf-8")
-;; => "charset=utf-8,username=\"chris\",realm=\"elwood.innosoft.com\",nonce=\"OA6MG9tEQGm2hh\",nc=00000001,cnonce=\"OA6MHXh6VqTrRk\",digest-uri=\"imap/elwood.innosoft.com\",response=d388dad90d4bbd760a152321f2143af7,qop=auth"
-;;
+;; (digest-md5-parse-digest-challenge 
+;;   "realm=\"elwood.innosoft.com\",nonce=\"OA6MG9tEQGm2hh\",qop=\"auth\",algorithm=md5-sess,charset=utf-8")
+;; => (realm "elwood.innosoft.com" nonce "OA6MG9tEQGm2hh" qop "auth" algorithm md5-sess charset utf-8)
+
+;; (digest-md5-build-response-value
+;;   "chris" "secret" "OA6MHXh6VqTrRk" "imap/elwood.innosoft.com")
+;; => "d388dad90d4bbd760a152321f2143af7"
 
 ;;; Code:
 
 (require 'hmac-md5)
 (require 'unique-id)
 
+(defvar digest-md5-challenge nil)
+(defvar digest-md5-nonce-count 1)
+
 (defvar digest-md5-parse-digest-challenge-syntax-table
   (let ((table (make-syntax-table)))
     (modify-syntax-entry ?= "." table)
     (modify-syntax-entry ?, "." table)
     table)
-  "A syntax table for parsing sgml attributes.")
+  "A syntax table for parsing digest-challenge attributes.")
 
+;;;###autoload
 (defun digest-md5-parse-digest-challenge (digest-challenge)
   ;; return a property list of 
   ;; (realm nonce qop-options stale maxbuf charset 
@@ -69,7 +74,7 @@
       (insert " "))
     (insert ")")
     (condition-case nil
-       (read (point-min-marker))
+       (setplist 'digest-md5-challenge (read (point-min-marker)))
       (end-of-file
        (error "Parse error in digest-challenge.")))))
 
   ;; contain at least 64 bits of entropy.
   (concat (unique-id-m "") (unique-id-m "")))
 
-(defun digest-md5-digest-response (username 
-                                  realm nonce cnonce
-                                  digest-uri response 
-                                  &optional nonce-count qop 
-                                  maxbuf charset cipher authzid)
-  (concat
-   (if charset
-       (concat "charset=" charset ","))
-   "username=\"" username "\""
-   ",realm=\"" realm "\""
-   ",nonce=\"" nonce "\""
-   (format ",nc=%08x"
-          (or nonce-count 1))
-   ",cnonce=\"" cnonce "\""
-   ",digest-uri=\"" digest-uri "\""
-   ",response=" response
-   (if qop
-       (concat ",qop=" qop))
-   (if maxbuf
-       (concat ",maxbuf=" maxbuf))
-   (if cipher
-       (concat ",cipher=" cipher))
-   (if authzid
-       (concat ",authzid=\"" authzid "\""))))
-
+(defmacro digest-md5-challenge (prop)
+  (list 'get ''digest-md5-challenge prop))
+
+(defmacro digest-md5-build-response-value (username passwd cnonce digest-uri)
+  `(encode-hex-string
+    (md5-binary
+     (concat
+      (encode-hex-string
+       (md5-binary (concat (md5-binary 
+                           (concat ,username 
+                                   ":" (digest-md5-challenge 'realm)
+                                   ":" ,passwd))
+                          ":" (digest-md5-challenge 'nonce)
+                          ":" ,cnonce
+                          (let ((authzid (digest-md5-challenge 'authzid)))
+                            (if authzid (concat ":" authzid) nil)))))
+      ":" (digest-md5-challenge 'nonce)
+      ":" (format "%08x" digest-md5-nonce-count) ":" ,cnonce 
+      ":" (digest-md5-challenge 'qop) ":"
+      (encode-hex-string
+       (md5-binary
+       (concat "AUTHENTICATE:" ,digest-uri
+               (if (member "auth" (split-string
+                                   (digest-md5-challenge 'qop) 
+                                   ","))
+                   nil
+                 ":00000000000000000000000000000000"))))))))
+
+;;;###autoload
+(defun digest-md5-digest-response (username passwd digest-uri)
+  (let ((cnonce (digest-md5-cnonce)))
+    (concat
+     "username=\"" username "\","
+     "realm=\"" (digest-md5-challenge 'realm) "\","
+     "nonce=\"" (digest-md5-challenge 'nonce) "\","
+     (format "nc=%08x," digest-md5-nonce-count)
+     "cnonce=\"" cnonce "\","
+     "digest-uri=\"" digest-uri "\","
+     "response=" 
+     (digest-md5-build-response-value username passwd cnonce digest-uri)
+     ","
+     (mapconcat 
+      #'identity
+      (delq nil 
+           (mapcar (lambda (prop)
+                     (if (digest-md5-challenge prop)
+                         (format "%s=%s"
+                                 prop (digest-md5-challenge prop))))
+                   '(charset qop maxbuf cipher authzid)))
+      ","))))
   
 (provide 'digest-md5)