;;; Commentary:
-;; NOW BUILDING.
-
;; This program is implemented from draft-leach-digest-sasl-05.txt.
;;
;; It is caller's responsibility to base64-decode challenges and
;; => (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")
+;; "chris" "elwood.innosoft.com" "secret" "OA6MG9tEQGm2hh"
+;; "OA6MHXh6VqTrRk" 1 "imap/elwood.innosoft.com" "auth")
;; => "d388dad90d4bbd760a152321f2143af7"
;;; Code:
(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)))
(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 "")))
+ '(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 passwd cnonce digest-uri)
+(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
- ":" (digest-md5-challenge 'realm)
+ ":" ,realm
":" ,passwd))
- ":" (digest-md5-challenge 'nonce)
+ ":" ,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) ":"
+ ":" ,nonce
+ ":" (format "%08x" ,nonce-count) ":" ,cnonce ":" ,qop ":"
(encode-hex-string
(md5-binary
(concat "AUTHENTICATE:" ,digest-uri
- (if (member "auth" (split-string
- (digest-md5-challenge 'qop)
- ","))
- nil
- ":00000000000000000000000000000000"))))))))
+ (if (string-equal "auth-int" ,qop)
+ ":00000000000000000000000000000000"
+ nil))))))))
;;;###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)))
- ","))))
+(defun digest-md5-digest-response
+ (username realm passwd nonce cnonce nonce-count digest-uri
+ &optional charset qop maxbuf cipher authzid)
+ (concat
+ "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)