sync up flim-chao-1_14_1
[elisp/flim.git] / digest-md5.el
index e6f87dc..e72c535 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).
@@ -24,8 +25,6 @@
 
 ;;; Commentary:
 
-;; NOW BUILDING.
-
 ;; This program is implemented from draft-leach-digest-sasl-05.txt.
 ;;
 ;; It is caller's responsibility to base64-decode challenges and
 
 ;; 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" "elwood.innosoft.com" "secret" "OA6MG9tEQGm2hh"
+;;   "OA6MHXh6VqTrRk" 1 "imap/elwood.innosoft.com" "auth")
+;; => "d388dad90d4bbd760a152321f2143af7"
 
 ;;; Code:
 
 (require 'hmac-md5)
 (require 'unique-id)
 
+(defvar digest-md5-challenge nil)
+
 (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 +72,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.")))))
 
                   (null (string= host serv-name)))
              (concat "/" serv-name))))
 
-(defun digest-md5-cnonce ()
+(defmacro digest-md5-cnonce ()
   ;; It is RECOMMENDED that it 
   ;; 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 (unique-id-m "") (unique-id-m "")))
+
+(defmacro digest-md5-challenge (prop)
+  (list 'get ''digest-md5-challenge prop))
+
+(defmacro digest-md5-build-response-value
+  (username realm passwd nonce cnonce nonce-count digest-uri qop)
+  `(encode-hex-string
+    (md5-binary
+     (concat
+      (encode-hex-string
+       (md5-binary (concat (md5-binary 
+                           (concat ,username 
+                                   ":" ,realm
+                                   ":" ,passwd))
+                          ":" ,nonce
+                          ":" ,cnonce
+                          (let ((authzid (digest-md5-challenge 'authzid)))
+                            (if authzid (concat ":" authzid) nil)))))
+      ":" ,nonce
+      ":" (format "%08x" ,nonce-count) ":" ,cnonce ":" ,qop ":"
+      (encode-hex-string
+       (md5-binary
+       (concat "AUTHENTICATE:" ,digest-uri
+               (if (string-equal "auth-int" ,qop)
+                   ":00000000000000000000000000000000"
+                 nil))))))))
+
+;;;###autoload
+(defun digest-md5-digest-response
+  (username realm passwd nonce cnonce nonce-count digest-uri
+           &optional charset qop maxbuf 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 "\""))))
-
+   "username=\"" username "\","
+   "realm=\"" realm "\","
+   "nonce=\"" nonce "\","
+   (format "nc=%08x," nonce-count)
+   "cnonce=\"" cnonce "\","
+   "digest-uri=\"" digest-uri "\","
+   "response=" 
+   (digest-md5-build-response-value
+    username realm passwd nonce cnonce nonce-count digest-uri
+    (or qop "auth"))
+   ","
+   (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)