aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Fitzsimmons2016-10-01 23:30:07 -0400
committerThomas Fitzsimmons2016-10-05 20:18:17 -0400
commit680e3986adaf1742a6a69ef2eb43a874ca6d5984 (patch)
tree371df1b61dfdd21bbd45df065e91a73fe03e9476
parent9adfb021df482c6aa94a043f07acf1e8eb695bf2 (diff)
downloademacs-680e3986adaf1742a6a69ef2eb43a874ca6d5984.tar.gz
emacs-680e3986adaf1742a6a69ef2eb43a874ca6d5984.zip
lisp/net/ntlm.el: Match Mozilla Type 1 and 3 message behavior
* lisp/net/ntlm.el (ntlm-build-auth-request): Only set "negotiate domain supplied" bit when a domain is supplied. Do not set "negotiate workstation supplied" bit. (ntlm-build-auth-response): Set domain to empty string by default. Set workstation name to "WORKSTATION". Set flags to logical and of Type 1 and Type 2 message flags. Remove four trailing 0 bytes. Always set LM response. Hard-code domain offset. Reorder buffer fields.
-rw-r--r--lisp/net/ntlm.el86
1 files changed, 50 insertions, 36 deletions
diff --git a/lisp/net/ntlm.el b/lisp/net/ntlm.el
index d96f3b1ebea..89f09b07448 100644
--- a/lisp/net/ntlm.el
+++ b/lisp/net/ntlm.el
@@ -101,14 +101,17 @@ is not given."
101 (let ((request-ident (concat "NTLMSSP" (make-string 1 0))) 101 (let ((request-ident (concat "NTLMSSP" (make-string 1 0)))
102 (request-msgType (concat (make-string 1 1) (make-string 3 0))) 102 (request-msgType (concat (make-string 1 1) (make-string 3 0)))
103 ;0x01 0x00 0x00 0x00 103 ;0x01 0x00 0x00 0x00
104 (request-flags (concat (make-string 1 7) (make-string 1 178) 104 (request-flags (concat (make-string 1 7) (make-string 1 130)
105 (make-string 1 8) (make-string 1 0))) 105 (make-string 1 8) (make-string 1 0)))
106 ;0x07 0xb2 0x08 0x00 106 ;0x07 0x82 0x08 0x00
107 lu ld off-d off-u) 107 lu ld off-d off-u)
108 (when (string-match "@" user) 108 (when (and user (string-match "@" user))
109 (unless domain 109 (unless domain
110 (setq domain (substring user (1+ (match-beginning 0))))) 110 (setq domain (substring user (1+ (match-beginning 0)))))
111 (setq user (substring user 0 (match-beginning 0)))) 111 (setq user (substring user 0 (match-beginning 0))))
112 (when (and (stringp domain) (> (length domain) 0))
113 ;; set "negotiate domain supplied" bit
114 (aset request-flags 1 (logior (aref request-flags 1) ?\x10)))
112 ;; set fields offsets within the request struct 115 ;; set fields offsets within the request struct
113 (setq lu (length user)) 116 (setq lu (length user))
114 (setq ld (length domain)) 117 (setq ld (length domain))
@@ -178,6 +181,10 @@ by PASSWORD-HASHES. PASSWORD-HASHES should be a return value of
178 ;;(ident (substring rchallenge 0 8)) ;ident, 8 bytes 181 ;;(ident (substring rchallenge 0 8)) ;ident, 8 bytes
179 ;;(msgType (substring rchallenge 8 12)) ;msgType, 4 bytes 182 ;;(msgType (substring rchallenge 8 12)) ;msgType, 4 bytes
180 (uDomain (substring rchallenge 12 20)) ;uDomain, 8 bytes 183 (uDomain (substring rchallenge 12 20)) ;uDomain, 8 bytes
184 ;; match default setting in `ntlm-build-auth-request'
185 (request-flags (concat (make-string 1 7) (make-string 1 130)
186 (make-string 1 8) (make-string 1 0)))
187 ;0x07 0x82 0x08 0x00
181 (flags (substring rchallenge 20 24)) ;flags, 4 bytes 188 (flags (substring rchallenge 20 24)) ;flags, 4 bytes
182 (challengeData (substring rchallenge 24 32)) ;challengeData, 8 bytes 189 (challengeData (substring rchallenge 24 32)) ;challengeData, 8 bytes
183 uDomain-len uDomain-offs 190 uDomain-len uDomain-offs
@@ -185,19 +192,28 @@ by PASSWORD-HASHES. PASSWORD-HASHES should be a return value of
185 lmRespData ;lmRespData, 24 bytes 192 lmRespData ;lmRespData, 24 bytes
186 ntRespData ;ntRespData, variable length 193 ntRespData ;ntRespData, variable length
187 domain ;ascii domain string 194 domain ;ascii domain string
188 lu ld ln off-lm off-nt off-d off-u off-w off-s) 195 workstation ;ascii workstation string
196 ll ln lu ld lw off-lm off-nt off-u off-d off-w)
189 ;; extract domain string from challenge string 197 ;; extract domain string from challenge string
190 (setq uDomain-len (md4-unpack-int16 (substring uDomain 0 2))) 198 (setq uDomain-len (md4-unpack-int16 (substring uDomain 0 2)))
191 (setq uDomain-offs (md4-unpack-int32 (substring uDomain 4 8))) 199 (setq uDomain-offs (md4-unpack-int32 (substring uDomain 4 8)))
192 (setq domain 200 ;; match Mozilla behavior, which is to send an empty domain string
193 (ntlm-unicode2ascii (substring challenge 201 (setq domain "")
194 (cdr uDomain-offs) 202 ;; match Mozilla behavior, which is to send "WORKSTATION"
195 (+ (cdr uDomain-offs) uDomain-len)) 203 (setq workstation "WORKSTATION")
196 (/ uDomain-len 2)))
197 ;; overwrite domain in case user is given in <user>@<domain> format 204 ;; overwrite domain in case user is given in <user>@<domain> format
198 (when (string-match "@" user) 205 (when (string-match "@" user)
199 (setq domain (substring user (1+ (match-beginning 0)))) 206 (setq domain (substring user (1+ (match-beginning 0))))
200 (setq user (substring user 0 (match-beginning 0)))) 207 (setq user (substring user 0 (match-beginning 0))))
208 (when (and (stringp domain) (> (length domain) 0))
209 ;; set "negotiate domain supplied" bit, since presumably domain
210 ;; was also set in `ntlm-build-auth-request'
211 (aset request-flags 1 (logior (aref request-flags 1) ?\x10)))
212 ;; match Mozilla behavior, which is to send the logical and of the
213 ;; type 1 and type 2 flags
214 (dotimes (index 4)
215 (aset flags index (logand (aref flags index)
216 (aref request-flags index))))
201 217
202 (unless (and (integerp ntlm-compatibility-level) 218 (unless (and (integerp ntlm-compatibility-level)
203 (>= ntlm-compatibility-level 0) 219 (>= ntlm-compatibility-level 0)
@@ -228,17 +244,15 @@ by PASSWORD-HASHES. PASSWORD-HASHES should be a return value of
228 (ntlm-compute-timestamp) ; timestamp 244 (ntlm-compute-timestamp) ; timestamp
229 nonce ; client nonce 245 nonce ; client nonce
230 (make-string 4 0) ; unknown 246 (make-string 4 0) ; unknown
231 targetInfo ; target info 247 targetInfo)) ; target info
232 (make-string 4 0))) ; unknown
233 ;; for reference: LMv2 interim calculation 248 ;; for reference: LMv2 interim calculation
234 ;; (lm-interim (hmac-md5 (concat challengeData nonce) 249 (lm-interim (hmac-md5 (concat challengeData nonce)
235 ;; ntlmv2-hash)) 250 ntlmv2-hash))
236 (nt-interim (hmac-md5 (concat challengeData blob) 251 (nt-interim (hmac-md5 (concat challengeData blob)
237 ntlmv2-hash))) 252 ntlmv2-hash)))
238 ;; for reference: LMv2 field, but match other clients that 253 ;; for reference: LMv2 field, but match other clients that
239 ;; send all zeros 254 ;; send all zeros
240 ;; (setq lmRespData (concat lm-interim nonce)) 255 (setq lmRespData (concat lm-interim nonce))
241 (setq lmRespData (make-string 24 0))
242 (setq ntRespData (concat nt-interim blob)))) 256 (setq ntRespData (concat nt-interim blob))))
243 ;; compatibility level is 2, 1 or 0 257 ;; compatibility level is 2, 1 or 0
244 ;; level 2 should be treated specially but it's not clear how, 258 ;; level 2 should be treated specially but it's not clear how,
@@ -263,23 +277,24 @@ by PASSWORD-HASHES. PASSWORD-HASHES should be a return value of
263 (ntlm-smb-owf-encrypt (cadr password-hashes) challengeData)))) 277 (ntlm-smb-owf-encrypt (cadr password-hashes) challengeData))))
264 278
265 ;; get offsets to fields to pack the response struct in a string 279 ;; get offsets to fields to pack the response struct in a string
280 (setq ll (length lmRespData))
281 (setq ln (length ntRespData))
266 (setq lu (length user)) 282 (setq lu (length user))
267 (setq ld (length domain)) 283 (setq ld (length domain))
268 (setq ln (length ntRespData)) 284 (setq lw (length workstation))
269 (setq off-lm 64) ;offset to string 'lmResponse 285 (setq off-u 64) ;offset to string 'uUser
270 (setq off-nt (+ 64 24)) ;offset to string 'ntResponse 286 (setq off-d (+ off-u (* 2 lu))) ;offset to string 'uDomain
271 (setq off-d (+ 64 24 ln)) ;offset to string 'uDomain 287 (setq off-w (+ off-d (* 2 ld))) ;offset to string 'uWks
272 (setq off-u (+ 64 24 ln (* 2 ld))) ;offset to string 'uUser 288 (setq off-lm (+ off-w (* 2 lw))) ;offset to string 'lmResponse
273 (setq off-w (+ 64 24 ln (* 2 (+ ld lu)))) ;offset to string 'uWks 289 (setq off-nt (+ off-lm ll)) ;offset to string 'ntResponse
274 (setq off-s (+ 64 24 ln (* 2 (+ ld lu lu)))) ;offset to string 'sessionKey
275 ;; pack the response struct in a string 290 ;; pack the response struct in a string
276 (concat "NTLMSSP\0" ;response ident field, 8 bytes 291 (concat "NTLMSSP\0" ;response ident field, 8 bytes
277 (md4-pack-int32 '(0 . 3)) ;response msgType field, 4 bytes 292 (md4-pack-int32 '(0 . 3)) ;response msgType field, 4 bytes
278 293
279 ;; lmResponse field, 8 bytes 294 ;; lmResponse field, 8 bytes
280 ;;AddBytes(response,lmResponse,lmRespData,24); 295 ;;AddBytes(response,lmResponse,lmRespData,24);
281 (md4-pack-int16 24) ;len field 296 (md4-pack-int16 ll) ;len field
282 (md4-pack-int16 24) ;maxlen field 297 (md4-pack-int16 ll) ;maxlen field
283 (md4-pack-int32 (cons 0 off-lm)) ;field offset 298 (md4-pack-int32 (cons 0 off-lm)) ;field offset
284 299
285 ;; ntResponse field, 8 bytes 300 ;; ntResponse field, 8 bytes
@@ -293,7 +308,9 @@ by PASSWORD-HASHES. PASSWORD-HASHES should be a return value of
293 ;;AddBytes(response, uDomain, udomain, 2*ld); 308 ;;AddBytes(response, uDomain, udomain, 2*ld);
294 (md4-pack-int16 (* 2 ld)) ;len field 309 (md4-pack-int16 (* 2 ld)) ;len field
295 (md4-pack-int16 (* 2 ld)) ;maxlen field 310 (md4-pack-int16 (* 2 ld)) ;maxlen field
296 (md4-pack-int32 (cons 0 off-d)) ;field offset 311 ;; match Mozilla behavior, which is to hard-code the
312 ;; domain offset to 64
313 (md4-pack-int32 (cons 0 64)) ;field offset
297 314
298 ;; uUser field, 8 bytes 315 ;; uUser field, 8 bytes
299 ;;AddUnicodeString(response,uUser,u); 316 ;;AddUnicodeString(response,uUser,u);
@@ -304,28 +321,25 @@ by PASSWORD-HASHES. PASSWORD-HASHES should be a return value of
304 321
305 ;; uWks field, 8 bytes 322 ;; uWks field, 8 bytes
306 ;;AddUnicodeString(response,uWks,u); 323 ;;AddUnicodeString(response,uWks,u);
307 (md4-pack-int16 (* 2 lu)) ;len field 324 (md4-pack-int16 (* 2 lw)) ;len field
308 (md4-pack-int16 (* 2 lu)) ;maxlen field 325 (md4-pack-int16 (* 2 lw)) ;maxlen field
309 (md4-pack-int32 (cons 0 off-w)) ;field offset 326 (md4-pack-int32 (cons 0 off-w)) ;field offset
310 327
311 ;; sessionKey field, 8 bytes 328 ;; sessionKey field, blank, 8 bytes
312 ;;AddString(response,sessionKey,NULL); 329 ;;AddString(response,sessionKey,NULL);
313 (md4-pack-int16 0) ;len field 330 (md4-pack-int16 0) ;len field
314 (md4-pack-int16 0) ;maxlen field 331 (md4-pack-int16 0) ;maxlen field
315 (md4-pack-int32 (cons 0 (- off-s off-lm))) ;field offset 332 (md4-pack-int32 (cons 0 0)) ;field offset
316 333
317 ;; flags field, 4 bytes 334 ;; flags field, 4 bytes
318 flags ; 335 flags ;
319 336
320 ;; buffer field 337 ;; buffer field
338 (ntlm-ascii2unicode user lu) ;Unicode user, 2*lu bytes
339 (ntlm-ascii2unicode domain ld) ;Unicode domain, 2*ld bytes
340 (ntlm-ascii2unicode workstation lw) ;Unicode workstation, 2*lw bytes
321 lmRespData ;lmResponse, 24 bytes 341 lmRespData ;lmResponse, 24 bytes
322 ntRespData ;ntResponse, 24 bytes 342 ntRespData ;ntResponse, ln bytes
323 (ntlm-ascii2unicode domain ;Unicode domain string, 2*ld bytes
324 (length domain)) ;
325 (ntlm-ascii2unicode user ;Unicode user string, 2*lu bytes
326 (length user)) ;
327 (ntlm-ascii2unicode user ;Unicode user string, 2*lu bytes
328 (length user)) ;
329 ))) 343 )))
330 344
331(defun ntlm-get-password-hashes (password) 345(defun ntlm-get-password-hashes (password)