(defun sasl-scram-md5-make-unique-nonce () ; 8*OCTET, globally unique.
;; For example, concatenated string of process-identifier, system-clock,
;; sequence-number, random-number, and domain-name.
- (let ((sasl-unique-id-function sasl-scram-md5-unique-id-function)
- id)
+ (let* ((sasl-unique-id-function sasl-scram-md5-unique-id-function)
+ (id (sasl-unique-id)))
(unwind-protect
- (concat "<"
- (setq id (sasl-unique-id))
- "@" (system-name) ">")
+ (concat "<" id "@" (system-name) ">")
(fillarray id 0))))
(defun sasl-scram-md5-xor-string (str1 str2)
(defun sasl-scram-md5-parse-server-msg-1 (server-msg-1)
"Parse SERVER-MSG-1 and return a list of (SALT SECURITY-INFO SERVICE-ID)."
- (when (and (> (length server-msg-1) 16)
- (eq (string-match "[^@]+@[^\0]+\0" server-msg-1 12) 12))
- (list (substring server-msg-1 0 8) ; salt
- (substring server-msg-1 8 12) ; server-security-info
- (substring server-msg-1 ; service-id
- 12 (1- (match-end 0))))))
+ (if (and (> (length server-msg-1) 16)
+ (eq (string-match "[^@]+@[^\0]+\0" server-msg-1 12) 12))
+ (list (substring server-msg-1 0 8) ; salt
+ (substring server-msg-1 8 12) ; server-security-info
+ (substring server-msg-1 ; service-id
+ 12 (1- (match-end 0))))
+ (sasl-error (format "Unexpected response: %s" server-msg-1))))
+
+(defun sasl-scram-md5-server-salt (server-msg-1)
+ (car (sasl-scram-md5-parse-server-msg-1 server-msg-1)))
(defun sasl-scram-md5-make-salted-pass (passphrase salt)
(hmac-md5 salt passphrase))
(sasl-client-property client 'nonce))))
(defun sasl-scram-md5-response-2 (client step)
- (sasl-client-set-property
- client 'server-msg-1
- (sasl-step-data step))
- (sasl-client-set-property
- client 'salted-pass
- (sasl-scram-md5-make-salted-pass
- (sasl-read-passphrase
- (format "SCRAM-MD5 passphrase for %s: "
- (sasl-client-name client)))
- (substring
- (sasl-client-property client 'server-msg-1) 0 8)))
- (sasl-client-set-property
- client 'client-msg-2
- (sasl-scram-md5-make-client-msg-2
- (sasl-client-property client 'server-msg-1)
- (sasl-client-property client 'client-msg-1)
- (sasl-client-property client 'salted-pass)
- (or (sasl-client-property client 'client-security-info)
- (sasl-scram-md5-make-security-info nil t 0)))))
+ (let* ((server-msg-1
+ (sasl-client-set-property
+ client 'server-msg-1
+ (sasl-step-data step)))
+ (salted-pass
+ (sasl-client-set-property
+ client 'salted-pass
+ (sasl-scram-md5-make-salted-pass
+ (sasl-read-passphrase
+ (format "SCRAM-MD5 passphrase for %s: "
+ (sasl-client-name client)))
+ (sasl-scram-md5-server-salt server-msg-1)))))
+ (sasl-client-set-property
+ client 'client-msg-2
+ (sasl-scram-md5-make-client-msg-2
+ server-msg-1
+ (sasl-client-property client 'client-msg-1)
+ salted-pass
+ (or (sasl-client-property client 'client-security-info)
+ (sasl-scram-md5-make-security-info nil t 0))))))
(defun sasl-scram-md5-authenticate-server (client step)
(let ((server-msg-2
(sasl-client-property client 'client-msg-1)
(or (sasl-client-property client 'client-security-info)
(sasl-scram-md5-make-security-info nil t 0))
- (car
- (sasl-scram-md5-parse-server-msg-1 server-msg-1))
+ (sasl-scram-md5-server-salt server-msg-1)
(sasl-client-property client 'salted-pass)))
" "
(sasl-error "SCRAM-MD5: authenticate server failed."))))