+ string))
+ (defmacro ntlm-string-make-unibyte (string)
+ (if (fboundp 'string-make-unibyte)
+ `(string-make-unibyte ,string)
+ string))
+ (defmacro ntlm-unibyte-string (&rest bytes)
+ (if (fboundp 'unibyte-string)
+ `(unibyte-string ,@bytes)
+ `(concat (vector ,@bytes)))))
+
+(eval-and-compile
+ (autoload 'sha1 "sha1")
+ (if (fboundp 'secure-hash)
+ (defalias 'ntlm-secure-hash 'secure-hash)
+ (defun ntlm-secure-hash (algorithm object &optional start end binary)
+ "Return the secure hash of OBJECT, a buffer or string.
+ALGORITHM is a symbol specifying the hash to use: md5, sha1.
+
+The two optional arguments START and END are positions specifying for
+which part of OBJECT to compute the hash. If nil or omitted, uses the
+whole OBJECT.
+
+If BINARY is non-nil, returns a string in binary form."
+ (cond ((eq algorithm 'md5)
+ (if binary
+ (let* ((hex (md5 object start end))
+ (len (length hex))
+ (beg 0)
+ rest)
+ (while (< beg len)
+ (push (ntlm-string-make-unibyte
+ (char-to-string
+ (string-to-number
+ (substring hex beg (setq beg (+ beg 2)))
+ 16)))
+ rest))
+ (apply #'concat (nreverse rest)))
+ (md5 object start end)))
+ ((eq algorithm 'sha1)
+ (sha1 object start end binary))
+ (t
+ (error "(ntlm-secure-hash) Unsupported algorithm: %s"
+ algorithm))))))
+
+(defun ntlm-compute-timestamp ()
+ "Compute an NTLMv2 timestamp.
+Return a unibyte string representing the number of tenths of a
+microsecond since January 1, 1601 as a 64-bit little-endian
+signed integer."
+ (let* ((s-to-tenths-of-us "mul(add(lsh($1,16),$2),10000000)")
+ (us-to-tenths-of-us "mul($3,10)")
+ (ps-to-tenths-of-us "idiv($4,100000)")
+ (tenths-of-us-since-jan-1-1601
+ (apply 'calc-eval (concat "add(add(add("
+ s-to-tenths-of-us ","
+ us-to-tenths-of-us "),"
+ ps-to-tenths-of-us "),"
+ ;; tenths of microseconds between
+ ;; 1601-01-01 and 1970-01-01
+ "116444736000000000)")
+ ;; add trailing zeros to support old current-time formats
+ 'rawnum (append (current-time) '(0 0))))
+ result-bytes)
+ (dotimes (byte 8)
+ (push (calc-eval "and($1,16#FF)" 'rawnum tenths-of-us-since-jan-1-1601)
+ result-bytes)
+ (setq tenths-of-us-since-jan-1-1601
+ (calc-eval "rsh($1,8,64)" 'rawnum tenths-of-us-since-jan-1-1601)))
+ (apply 'ntlm-unibyte-string (nreverse result-bytes))))
+
+(defun ntlm-generate-nonce ()
+ "Generate a random nonce, not to be used more than once.
+Return a random eight byte unibyte string."
+ (ntlm-unibyte-string
+ (random 256) (random 256) (random 256) (random 256)
+ (random 256) (random 256) (random 256) (random 256)))