summaryrefslogtreecommitdiff
path: root/lisp/net/ntlm.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/net/ntlm.el')
-rw-r--r--lisp/net/ntlm.el160
1 files changed, 88 insertions, 72 deletions
diff --git a/lisp/net/ntlm.el b/lisp/net/ntlm.el
index d96f3b1ebea..e272002cfe7 100644
--- a/lisp/net/ntlm.el
+++ b/lisp/net/ntlm.el
@@ -5,7 +5,7 @@
;; Author: Taro Kawagishi <tarok@transpulse.org>
;; Maintainer: Thomas Fitzsimmons <fitzsim@fitzsim.org>
;; Keywords: NTLM, SASL, comm
-;; Version: 2.0.0
+;; Version: 2.1.0
;; Created: February 2001
;; This file is part of GNU Emacs.
@@ -49,10 +49,12 @@
;;
;; 1. Open a network connection to the Exchange server at the IMAP port (143)
;; 2. Receive an opening message such as:
-;; "* OK Microsoft Exchange IMAP4rev1 server version 5.5.2653.7 (XXXX) ready"
+;; "* OK Microsoft Exchange IMAP4rev1 server
+;; version 5.5.2653.7 (XXXX) ready"
;; 3. Ask for IMAP server capability by sending "NNN capability"
;; 4. Receive a capability message such as:
-;; "* CAPABILITY IMAP4 IMAP4rev1 IDLE LITERAL+ LOGIN-REFERRALS MAILBOX-REFERRALS NAMESPACE AUTH=NTLM"
+;; "* CAPABILITY IMAP4 IMAP4rev1 IDLE LITERAL+
+;; LOGIN-REFERRALS MAILBOX-REFERRALS NAMESPACE AUTH=NTLM"
;; 5. Ask for NTLM authentication by sending a string
;; "NNN authenticate ntlm"
;; 6. Receive continuation acknowledgment "+"
@@ -101,31 +103,34 @@ is not given."
(let ((request-ident (concat "NTLMSSP" (make-string 1 0)))
(request-msgType (concat (make-string 1 1) (make-string 3 0)))
;0x01 0x00 0x00 0x00
- (request-flags (concat (make-string 1 7) (make-string 1 178)
+ (request-flags (concat (make-string 1 7) (make-string 1 130)
(make-string 1 8) (make-string 1 0)))
- ;0x07 0xb2 0x08 0x00
+ ;0x07 0x82 0x08 0x00
lu ld off-d off-u)
- (when (string-match "@" user)
+ (when (and user (string-match "@" user))
(unless domain
(setq domain (substring user (1+ (match-beginning 0)))))
(setq user (substring user 0 (match-beginning 0))))
+ (when (and (stringp domain) (> (length domain) 0))
+ ;; set "negotiate domain supplied" bit
+ (aset request-flags 1 (logior (aref request-flags 1) ?\x10)))
;; set fields offsets within the request struct
(setq lu (length user))
(setq ld (length domain))
(setq off-u 32) ;offset to the string 'user
(setq off-d (+ 32 lu)) ;offset to the string 'domain
;; pack the request struct in a string
- (concat request-ident ;8 bytes
- request-msgType ;4 bytes
- request-flags ;4 bytes
- (md4-pack-int16 lu) ;user field, count field
- (md4-pack-int16 lu) ;user field, max count field
- (md4-pack-int32 (cons 0 off-u)) ;user field, offset field
- (md4-pack-int16 ld) ;domain field, count field
- (md4-pack-int16 ld) ;domain field, max count field
- (md4-pack-int32 (cons 0 off-d)) ;domain field, offset field
- user ;buffer field
- domain ;buffer field
+ (concat request-ident ;8 bytes
+ request-msgType ;4 bytes
+ request-flags ;4 bytes
+ (md4-pack-int16 lu) ;user field, count field
+ (md4-pack-int16 lu) ;user field, max count field
+ (md4-pack-int32 (cons 0 off-u)) ;user field, offset field
+ (md4-pack-int16 ld) ;domain field, count field
+ (md4-pack-int16 ld) ;domain field, max count field
+ (md4-pack-int32 (cons 0 off-d)) ;domain field, offset field
+ user ;buffer field
+ domain ;buffer field
)))
(eval-when-compile
@@ -178,6 +183,10 @@ by PASSWORD-HASHES. PASSWORD-HASHES should be a return value of
;;(ident (substring rchallenge 0 8)) ;ident, 8 bytes
;;(msgType (substring rchallenge 8 12)) ;msgType, 4 bytes
(uDomain (substring rchallenge 12 20)) ;uDomain, 8 bytes
+ ;; match default setting in `ntlm-build-auth-request'
+ (request-flags (concat (make-string 1 7) (make-string 1 130)
+ (make-string 1 8) (make-string 1 0)))
+ ;0x07 0x82 0x08 0x00
(flags (substring rchallenge 20 24)) ;flags, 4 bytes
(challengeData (substring rchallenge 24 32)) ;challengeData, 8 bytes
uDomain-len uDomain-offs
@@ -185,19 +194,28 @@ by PASSWORD-HASHES. PASSWORD-HASHES should be a return value of
lmRespData ;lmRespData, 24 bytes
ntRespData ;ntRespData, variable length
domain ;ascii domain string
- lu ld ln off-lm off-nt off-d off-u off-w off-s)
+ workstation ;ascii workstation string
+ ll ln lu ld lw off-lm off-nt off-u off-d off-w)
;; extract domain string from challenge string
(setq uDomain-len (md4-unpack-int16 (substring uDomain 0 2)))
(setq uDomain-offs (md4-unpack-int32 (substring uDomain 4 8)))
- (setq domain
- (ntlm-unicode2ascii (substring challenge
- (cdr uDomain-offs)
- (+ (cdr uDomain-offs) uDomain-len))
- (/ uDomain-len 2)))
+ ;; match Mozilla behavior, which is to send an empty domain string
+ (setq domain "")
+ ;; match Mozilla behavior, which is to send "WORKSTATION"
+ (setq workstation "WORKSTATION")
;; overwrite domain in case user is given in <user>@<domain> format
(when (string-match "@" user)
(setq domain (substring user (1+ (match-beginning 0))))
(setq user (substring user 0 (match-beginning 0))))
+ (when (and (stringp domain) (> (length domain) 0))
+ ;; set "negotiate domain supplied" bit, since presumably domain
+ ;; was also set in `ntlm-build-auth-request'
+ (aset request-flags 1 (logior (aref request-flags 1) ?\x10)))
+ ;; match Mozilla behavior, which is to send the logical and of the
+ ;; type 1 and type 2 flags
+ (dotimes (index 4)
+ (aset flags index (logand (aref flags index)
+ (aref request-flags index))))
(unless (and (integerp ntlm-compatibility-level)
(>= ntlm-compatibility-level 0)
@@ -223,22 +241,20 @@ by PASSWORD-HASHES. PASSWORD-HASHES should be a return value of
(cadr password-hashes)))
(nonce (ntlm-generate-nonce))
(blob (concat (make-string 2 1)
- (make-string 2 0) ; blob signature
- (make-string 4 0) ; reserved value
- (ntlm-compute-timestamp) ; timestamp
- nonce ; client nonce
- (make-string 4 0) ; unknown
- targetInfo ; target info
- (make-string 4 0))) ; unknown
+ (make-string 2 0) ;blob signature
+ (make-string 4 0) ;reserved value
+ (ntlm-compute-timestamp) ;timestamp
+ nonce ;client nonce
+ (make-string 4 0) ;unknown
+ targetInfo)) ;target info
;; for reference: LMv2 interim calculation
- ;; (lm-interim (hmac-md5 (concat challengeData nonce)
- ;; ntlmv2-hash))
+ (lm-interim (hmac-md5 (concat challengeData nonce)
+ ntlmv2-hash))
(nt-interim (hmac-md5 (concat challengeData blob)
ntlmv2-hash)))
;; for reference: LMv2 field, but match other clients that
;; send all zeros
- ;; (setq lmRespData (concat lm-interim nonce))
- (setq lmRespData (make-string 24 0))
+ (setq lmRespData (concat lm-interim nonce))
(setq ntRespData (concat nt-interim blob))))
;; compatibility level is 2, 1 or 0
;; level 2 should be treated specially but it's not clear how,
@@ -263,69 +279,69 @@ by PASSWORD-HASHES. PASSWORD-HASHES should be a return value of
(ntlm-smb-owf-encrypt (cadr password-hashes) challengeData))))
;; get offsets to fields to pack the response struct in a string
+ (setq ll (length lmRespData))
+ (setq ln (length ntRespData))
(setq lu (length user))
(setq ld (length domain))
- (setq ln (length ntRespData))
- (setq off-lm 64) ;offset to string 'lmResponse
- (setq off-nt (+ 64 24)) ;offset to string 'ntResponse
- (setq off-d (+ 64 24 ln)) ;offset to string 'uDomain
- (setq off-u (+ 64 24 ln (* 2 ld))) ;offset to string 'uUser
- (setq off-w (+ 64 24 ln (* 2 (+ ld lu)))) ;offset to string 'uWks
- (setq off-s (+ 64 24 ln (* 2 (+ ld lu lu)))) ;offset to string 'sessionKey
+ (setq lw (length workstation))
+ (setq off-u 64) ;offset to string 'uUser
+ (setq off-d (+ off-u (* 2 lu))) ;offset to string 'uDomain
+ (setq off-w (+ off-d (* 2 ld))) ;offset to string 'uWks
+ (setq off-lm (+ off-w (* 2 lw))) ;offset to string 'lmResponse
+ (setq off-nt (+ off-lm ll)) ;offset to string 'ntResponse
;; pack the response struct in a string
- (concat "NTLMSSP\0" ;response ident field, 8 bytes
- (md4-pack-int32 '(0 . 3)) ;response msgType field, 4 bytes
+ (concat "NTLMSSP\0" ;response ident field, 8 bytes
+ (md4-pack-int32 '(0 . 3)) ;response msgType field, 4 bytes
;; lmResponse field, 8 bytes
;;AddBytes(response,lmResponse,lmRespData,24);
- (md4-pack-int16 24) ;len field
- (md4-pack-int16 24) ;maxlen field
- (md4-pack-int32 (cons 0 off-lm)) ;field offset
+ (md4-pack-int16 ll) ;len field
+ (md4-pack-int16 ll) ;maxlen field
+ (md4-pack-int32 (cons 0 off-lm)) ;field offset
;; ntResponse field, 8 bytes
;;AddBytes(response,ntResponse,ntRespData,ln);
- (md4-pack-int16 ln) ;len field
- (md4-pack-int16 ln) ;maxlen field
- (md4-pack-int32 (cons 0 off-nt)) ;field offset
+ (md4-pack-int16 ln) ;len field
+ (md4-pack-int16 ln) ;maxlen field
+ (md4-pack-int32 (cons 0 off-nt)) ;field offset
;; uDomain field, 8 bytes
;;AddUnicodeString(response,uDomain,domain);
;;AddBytes(response, uDomain, udomain, 2*ld);
- (md4-pack-int16 (* 2 ld)) ;len field
- (md4-pack-int16 (* 2 ld)) ;maxlen field
- (md4-pack-int32 (cons 0 off-d)) ;field offset
+ (md4-pack-int16 (* 2 ld)) ;len field
+ (md4-pack-int16 (* 2 ld)) ;maxlen field
+ ;; match Mozilla behavior, which is to hard-code the
+ ;; domain offset to 64
+ (md4-pack-int32 (cons 0 64)) ;field offset
;; uUser field, 8 bytes
;;AddUnicodeString(response,uUser,u);
;;AddBytes(response, uUser, uuser, 2*lu);
- (md4-pack-int16 (* 2 lu)) ;len field
- (md4-pack-int16 (* 2 lu)) ;maxlen field
- (md4-pack-int32 (cons 0 off-u)) ;field offset
+ (md4-pack-int16 (* 2 lu)) ;len field
+ (md4-pack-int16 (* 2 lu)) ;maxlen field
+ (md4-pack-int32 (cons 0 off-u)) ;field offset
;; uWks field, 8 bytes
;;AddUnicodeString(response,uWks,u);
- (md4-pack-int16 (* 2 lu)) ;len field
- (md4-pack-int16 (* 2 lu)) ;maxlen field
- (md4-pack-int32 (cons 0 off-w)) ;field offset
+ (md4-pack-int16 (* 2 lw)) ;len field
+ (md4-pack-int16 (* 2 lw)) ;maxlen field
+ (md4-pack-int32 (cons 0 off-w)) ;field offset
- ;; sessionKey field, 8 bytes
+ ;; sessionKey field, blank, 8 bytes
;;AddString(response,sessionKey,NULL);
- (md4-pack-int16 0) ;len field
- (md4-pack-int16 0) ;maxlen field
- (md4-pack-int32 (cons 0 (- off-s off-lm))) ;field offset
+ (md4-pack-int16 0) ;len field
+ (md4-pack-int16 0) ;maxlen field
+ (md4-pack-int32 (cons 0 0)) ;field offset
;; flags field, 4 bytes
- flags ;
+ flags
;; buffer field
- lmRespData ;lmResponse, 24 bytes
- ntRespData ;ntResponse, 24 bytes
- (ntlm-ascii2unicode domain ;Unicode domain string, 2*ld bytes
- (length domain)) ;
- (ntlm-ascii2unicode user ;Unicode user string, 2*lu bytes
- (length user)) ;
- (ntlm-ascii2unicode user ;Unicode user string, 2*lu bytes
- (length user)) ;
+ (ntlm-ascii2unicode user lu) ;Unicode user, 2*lu bytes
+ (ntlm-ascii2unicode domain ld) ;Unicode domain, 2*ld bytes
+ (ntlm-ascii2unicode workstation lw) ;Unicode workstation, 2*lw bytes
+ lmRespData ;lmResponse, 24 bytes
+ ntRespData ;ntResponse, ln bytes
)))
(defun ntlm-get-password-hashes (password)
@@ -544,7 +560,7 @@ length of STR is LEN."
(concat (substring str c len) (substring str 0 c))))
(defsubst ntlm-string-xor (in1 in2 n)
- "Return exclusive-or of sequences in1 and in2"
+ "Return exclusive-or of sequences in1 and in2."
(let ((w (make-string n 0)) (i 0))
(while (< i n)
(aset w i (logxor (aref in1 i) (aref in2 i)))