Imported Upstream version 7.59.0
[platform/upstream/curl.git] / tests / python_dependencies / impacket / ntlm.py
1 # Copyright (c) 2003-2016 CORE Security Technologies:
2 #
3 # This software is provided under under a slightly modified version
4 # of the Apache Software License. See the accompanying LICENSE file
5 # for more information.
6 #
7 import base64
8 import struct
9 import calendar
10 import time
11 import hashlib
12 import random
13 import string
14 import binascii
15
16 from impacket.structure import Structure
17 from impacket import LOG
18
19
20 # This is important. NTLMv2 is not negotiated by the client or server. 
21 # It is used if set locally on both sides. Change this item if you don't want to use 
22 # NTLMv2 by default and fall back to NTLMv1 (with EXTENDED_SESSION_SECURITY or not)
23 # Check the following links:
24 # http://davenport.sourceforge.net/ntlm.html
25 # http://blogs.msdn.com/b/openspecification/archive/2010/04/20/ntlm-keys-and-sundry-stuff.aspx
26 # http://social.msdn.microsoft.com/Forums/en-US/os_interopscenarios/thread/c8f488ed-1b96-4e06-bd65-390aa41138d1/
27 # So I'm setting a global variable to control this, this can also be set programmatically
28
29 USE_NTLMv2 = True # if false will fall back to NTLMv1 (or NTLMv1 with ESS a.k.a NTLM2)
30
31
32 def computeResponse(flags, serverChallenge, clientChallenge, serverName, domain, user, password, lmhash='', nthash='',
33                     use_ntlmv2=USE_NTLMv2):
34     if use_ntlmv2:
35         return computeResponseNTLMv2(flags, serverChallenge, clientChallenge, serverName, domain, user, password,
36                                      lmhash, nthash, use_ntlmv2=use_ntlmv2)
37     else:
38         return computeResponseNTLMv1(flags, serverChallenge, clientChallenge, serverName, domain, user, password,
39                                      lmhash, nthash, use_ntlmv2=use_ntlmv2)
40 try:
41     POW = None
42     from Crypto.Cipher import ARC4
43     from Crypto.Cipher import DES
44     from Crypto.Hash import MD4
45 except Exception:
46     try:
47         import POW
48     except Exception:
49         LOG.critical("Warning: You don't have any crypto installed. You need PyCrypto")
50         LOG.critical("See http://www.pycrypto.org/")
51
52 NTLM_AUTH_NONE          = 1
53 NTLM_AUTH_CONNECT       = 2
54 NTLM_AUTH_CALL          = 3
55 NTLM_AUTH_PKT           = 4
56 NTLM_AUTH_PKT_INTEGRITY = 5
57 NTLM_AUTH_PKT_PRIVACY   = 6
58
59 # If set, requests 56-bit encryption. If the client sends NTLMSSP_NEGOTIATE_SEAL or NTLMSSP_NEGOTIATE_SIGN
60 # with NTLMSSP_NEGOTIATE_56 to the server in the NEGOTIATE_MESSAGE, the server MUST return NTLMSSP_NEGOTIATE_56 to
61 # the client in the CHALLENGE_MESSAGE. Otherwise it is ignored. If both NTLMSSP_NEGOTIATE_56 and NTLMSSP_NEGOTIATE_128
62 # are requested and supported by the client and server, NTLMSSP_NEGOTIATE_56 and NTLMSSP_NEGOTIATE_128 will both be
63 # returned to the client. Clients and servers that set NTLMSSP_NEGOTIATE_SEAL SHOULD set NTLMSSP_NEGOTIATE_56 if it is
64 # supported. An alternate name for this field is NTLMSSP_NEGOTIATE_56.
65 NTLMSSP_NEGOTIATE_56                       = 0x80000000
66
67 # If set, requests an explicit key exchange. This capability SHOULD be used because it improves security for message
68 # integrity or confidentiality. See sections 3.2.5.1.2, 3.2.5.2.1, and 3.2.5.2.2 for details. An alternate name for
69 # this field is NTLMSSP_NEGOTIATE_KEY_EXCH.
70 NTLMSSP_NEGOTIATE_KEY_EXCH                 = 0x40000000
71
72 # If set, requests 128-bit session key negotiation. An alternate name for this field is NTLMSSP_NEGOTIATE_128.
73 # If the client sends NTLMSSP_NEGOTIATE_128 to the server in the NEGOTIATE_MESSAGE, the server MUST return
74 # NTLMSSP_NEGOTIATE_128 to the client in the CHALLENGE_MESSAGE only if the client sets NTLMSSP_NEGOTIATE_SEAL or
75 # NTLMSSP_NEGOTIATE_SIGN. Otherwise it is ignored. If both NTLMSSP_NEGOTIATE_56 and NTLMSSP_NEGOTIATE_128 are
76 # requested and supported by the client and server, NTLMSSP_NEGOTIATE_56 and NTLMSSP_NEGOTIATE_128 will both be
77 # returned to the client. Clients and servers that set NTLMSSP_NEGOTIATE_SEAL SHOULD set NTLMSSP_NEGOTIATE_128 if it
78 # is supported. An alternate name for this field is NTLMSSP_NEGOTIATE_128
79 NTLMSSP_NEGOTIATE_128                      = 0x20000000
80
81 NTLMSSP_RESERVED_1                         = 0x10000000
82 NTLMSSP_RESERVED_2                         = 0x08000000
83 NTLMSSP_RESERVED_3                         = 0x04000000
84
85 # If set, requests the protocol version number. The data corresponding to this flag is provided in the Version field
86 # of the NEGOTIATE_MESSAGE, the CHALLENGE_MESSAGE, and the AUTHENTICATE_MESSAGE.<22> An alternate name for this field
87 # is NTLMSSP_NEGOTIATE_VERSION
88 NTLMSSP_NEGOTIATE_VERSION                  = 0x02000000
89 NTLMSSP_RESERVED_4                         = 0x01000000
90
91 # If set, indicates that the TargetInfo fields in the CHALLENGE_MESSAGE (section 2.2.1.2) are populated.
92 # An alternate name for this field is NTLMSSP_NEGOTIATE_TARGET_INFO.
93 NTLMSSP_NEGOTIATE_TARGET_INFO              = 0x00800000
94
95 # If set, requests the usage of the LMOWF (section 3.3). An alternate name for this field is
96 # NTLMSSP_REQUEST_NON_NT_SESSION_KEY.
97 NTLMSSP_REQUEST_NON_NT_SESSION_KEY         = 0x00400000
98 NTLMSSP_RESERVED_5                         = 0x00200000
99
100 # If set, requests an identify level token. An alternate name for this field is NTLMSSP_NEGOTIATE_IDENTIFY
101 NTLMSSP_NEGOTIATE_IDENTIFY                 = 0x00100000
102
103 # If set, requests usage of the NTLM v2 session security. NTLM v2 session security is a misnomer because it is not
104 # NTLM v2. It is NTLM v1 using the extended session security that is also in NTLM v2. NTLMSSP_NEGOTIATE_LM_KEY and
105 # NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY are mutually exclusive. If both NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY
106 # and NTLMSSP_NEGOTIATE_LM_KEY are requested, NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY alone MUST be returned to the
107 # client. NTLM v2 authentication session key generation MUST be supported by both the client and the DC in order to be
108 # used, and extended session security signing and sealing requires support from the client and the server in order to
109 # be used.<23> An alternate name for this field is NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY
110 NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY = 0x00080000
111 NTLMSSP_NEGOTIATE_NTLM2                    = 0x00080000
112 NTLMSSP_TARGET_TYPE_SHARE                  = 0x00040000
113
114 # If set, TargetName MUST be a server name. The data corresponding to this flag is provided by the server in the
115 # TargetName field of the CHALLENGE_MESSAGE. If this bit is set, then NTLMSSP_TARGET_TYPE_DOMAIN MUST NOT be set.
116 # This flag MUST be ignored in the NEGOTIATE_MESSAGE and the AUTHENTICATE_MESSAGE. An alternate name for this field
117 # is NTLMSSP_TARGET_TYPE_SERVER
118 NTLMSSP_TARGET_TYPE_SERVER                 = 0x00020000
119
120 # If set, TargetName MUST be a domain name. The data corresponding to this flag is provided by the server in the
121 # TargetName field of the CHALLENGE_MESSAGE. If set, then NTLMSSP_TARGET_TYPE_SERVER MUST NOT be set. This flag MUST
122 # be ignored in the NEGOTIATE_MESSAGE and the AUTHENTICATE_MESSAGE. An alternate name for this field is
123 # NTLMSSP_TARGET_TYPE_DOMAIN.
124 NTLMSSP_TARGET_TYPE_DOMAIN                 = 0x00010000
125
126 # If set, requests the presence of a signature block on all messages. NTLMSSP_NEGOTIATE_ALWAYS_SIGN MUST be set in the
127 # NEGOTIATE_MESSAGE to the server and the CHALLENGE_MESSAGE to the client. NTLMSSP_NEGOTIATE_ALWAYS_SIGN is overridden
128 # by NTLMSSP_NEGOTIATE_SIGN and NTLMSSP_NEGOTIATE_SEAL, if they are supported. An alternate name for this field is
129 # NTLMSSP_NEGOTIATE_ALWAYS_SIGN.
130 NTLMSSP_NEGOTIATE_ALWAYS_SIGN              = 0x00008000       # forces the other end to sign packets
131 NTLMSSP_RESERVED_6                         = 0x00004000
132
133 # This flag indicates whether the Workstation field is present. If this flag is not set, the Workstation field MUST be
134 # ignored. If this flag is set, the length field of the Workstation field specifies whether the workstation name is
135 # nonempty or not.<24> An alternate name for this field is NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED.
136 NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED = 0x00002000
137
138 # If set, the domain name is provided (section 2.2.1.1).<25> An alternate name for this field is
139 # NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED
140 NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED      = 0x00001000
141 NTLMSSP_RESERVED_7                         = 0x00000800
142
143
144 # If set, LM authentication is not allowed and only NT authentication is used.
145 NTLMSSP_NEGOTIATE_NT_ONLY                  = 0x00000400
146
147 # If set, requests usage of the NTLM v1 session security protocol. NTLMSSP_NEGOTIATE_NTLM MUST be set in the
148 # NEGOTIATE_MESSAGE to the server and the CHALLENGE_MESSAGE to the client. An alternate name for this field is
149 # NTLMSSP_NEGOTIATE_NTLM
150 NTLMSSP_NEGOTIATE_NTLM                     = 0x00000200
151 NTLMSSP_RESERVED_8                         = 0x00000100
152
153 # If set, requests LAN Manager (LM) session key computation. NTLMSSP_NEGOTIATE_LM_KEY and
154 # NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY are mutually exclusive. If both NTLMSSP_NEGOTIATE_LM_KEY and
155 # NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY are requested, NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY alone MUST be
156 # returned to the client. NTLM v2 authentication session key generation MUST be supported by both the client and the
157 # DC in order to be used, and extended session security signing and sealing requires support from the client and the
158 # server to be used. An alternate name for this field is NTLMSSP_NEGOTIATE_LM_KEY.
159 NTLMSSP_NEGOTIATE_LM_KEY                   = 0x00000080
160
161 # If set, requests connectionless authentication. If NTLMSSP_NEGOTIATE_DATAGRAM is set, then NTLMSSP_NEGOTIATE_KEY_EXCH
162 # MUST always be set in the AUTHENTICATE_MESSAGE to the server and the CHALLENGE_MESSAGE to the client. An alternate
163 # name for this field is NTLMSSP_NEGOTIATE_DATAGRAM.
164 NTLMSSP_NEGOTIATE_DATAGRAM                 = 0x00000040
165
166 # If set, requests session key negotiation for message confidentiality. If the client sends NTLMSSP_NEGOTIATE_SEAL to
167 # the server in the NEGOTIATE_MESSAGE, the server MUST return NTLMSSP_NEGOTIATE_SEAL to the client in the
168 # CHALLENGE_MESSAGE. Clients and servers that set NTLMSSP_NEGOTIATE_SEAL SHOULD always set NTLMSSP_NEGOTIATE_56 and
169 # NTLMSSP_NEGOTIATE_128, if they are supported. An alternate name for this field is NTLMSSP_NEGOTIATE_SEAL.
170 NTLMSSP_NEGOTIATE_SEAL                     = 0x00000020
171
172 # If set, requests session key negotiation for message signatures. If the client sends NTLMSSP_NEGOTIATE_SIGN to the
173 # server in the NEGOTIATE_MESSAGE, the server MUST return NTLMSSP_NEGOTIATE_SIGN to the client in the CHALLENGE_MESSAGE.
174 # An alternate name for this field is NTLMSSP_NEGOTIATE_SIGN.
175 NTLMSSP_NEGOTIATE_SIGN                     = 0x00000010       # means packet is signed, if verifier is wrong it fails
176 NTLMSSP_RESERVED_9                         = 0x00000008
177
178 # If set, a TargetName field of the CHALLENGE_MESSAGE (section 2.2.1.2) MUST be supplied. An alternate name for this
179 # field is NTLMSSP_REQUEST_TARGET.
180 NTLMSSP_REQUEST_TARGET                     = 0x00000004
181
182 # If set, requests OEM character set encoding. An alternate name for this field is NTLM_NEGOTIATE_OEM. See bit A for
183 # details.
184 NTLM_NEGOTIATE_OEM                         = 0x00000002
185
186 # If set, requests Unicode character set encoding. An alternate name for this field is NTLMSSP_NEGOTIATE_UNICODE.
187 NTLMSSP_NEGOTIATE_UNICODE                  = 0x00000001
188
189 # AV_PAIR constants
190 NTLMSSP_AV_EOL              = 0x00
191 NTLMSSP_AV_HOSTNAME         = 0x01
192 NTLMSSP_AV_DOMAINNAME       = 0x02
193 NTLMSSP_AV_DNS_HOSTNAME     = 0x03
194 NTLMSSP_AV_DNS_DOMAINNAME   = 0x04
195 NTLMSSP_AV_DNS_TREENAME     = 0x05
196 NTLMSSP_AV_FLAGS            = 0x06
197 NTLMSSP_AV_TIME             = 0x07
198 NTLMSSP_AV_RESTRICTIONS     = 0x08
199 NTLMSSP_AV_TARGET_NAME      = 0x09
200 NTLMSSP_AV_CHANNEL_BINDINGS = 0x0a
201
202 class AV_PAIRS():
203     def __init__(self, data = None):
204         self.fields = {}
205         if data is not None:
206             self.fromString(data)
207
208     def __setitem__(self,key,value):
209         self.fields[key] = (len(value),value)
210
211     def __getitem__(self, key):
212         if self.fields.has_key(key):
213            return self.fields[key]
214         return None
215
216     def __delitem__(self, key):
217         del self.fields[key]
218
219     def __len__(self):
220         return len(self.getData())
221
222     def __str__(self):
223         return len(self.getData())
224
225     def fromString(self, data):
226         tInfo = data
227         fType = 0xff
228         while fType is not NTLMSSP_AV_EOL:
229             fType = struct.unpack('<H',tInfo[:struct.calcsize('<H')])[0]
230             tInfo = tInfo[struct.calcsize('<H'):]
231             length = struct.unpack('<H',tInfo[:struct.calcsize('<H')])[0]
232             tInfo = tInfo[struct.calcsize('<H'):]
233             content = tInfo[:length]
234             self.fields[fType]=(length,content)
235             tInfo = tInfo[length:]
236
237     def dump(self):
238         for i in self.fields.keys():
239             print "%s: {%r}" % (i,self[i])
240
241     def getData(self):
242         if self.fields.has_key(NTLMSSP_AV_EOL):
243             del self.fields[NTLMSSP_AV_EOL]
244         ans = ''
245         for i in self.fields.keys():
246             ans+= struct.pack('<HH', i, self[i][0])
247             ans+= self[i][1]
248  
249         # end with a NTLMSSP_AV_EOL
250         ans += struct.pack('<HH', NTLMSSP_AV_EOL, 0)
251
252         return ans
253
254 class NTLMAuthMixin:
255     def get_os_version(self):
256         if self['os_version'] == '':
257             return None
258         else:
259             mayor_v = struct.unpack('B',self['os_version'][0])[0]
260             minor_v = struct.unpack('B',self['os_version'][1])[0]
261             build_v = struct.unpack('H',self['os_version'][2:4])
262             return (mayor_v,minor_v,build_v)
263         
264 class NTLMAuthNegotiate(Structure, NTLMAuthMixin):
265
266     structure = (
267         ('','"NTLMSSP\x00'),
268         ('message_type','<L=1'),
269         ('flags','<L'),
270         ('domain_len','<H-domain_name'),
271         ('domain_max_len','<H-domain_name'),
272         ('domain_offset','<L=0'),
273         ('host_len','<H-host_name'),
274         ('host_maxlen','<H-host_name'),
275         ('host_offset','<L=0'),
276         ('os_version',':'),
277         ('host_name',':'),
278         ('domain_name',':'))
279                                                                                 
280     def __init__(self):
281         Structure.__init__(self)
282         self['flags']= (
283                NTLMSSP_NEGOTIATE_128     |
284                NTLMSSP_NEGOTIATE_KEY_EXCH|
285                # NTLMSSP_LM_KEY      |
286                NTLMSSP_NEGOTIATE_NTLM    |
287                NTLMSSP_NEGOTIATE_UNICODE     |
288                # NTLMSSP_ALWAYS_SIGN |
289                NTLMSSP_NEGOTIATE_SIGN        |
290                NTLMSSP_NEGOTIATE_SEAL        |
291                # NTLMSSP_TARGET      |
292                0)
293         self['host_name']=''
294         self['domain_name']=''
295         self['os_version']=''
296     
297     def getData(self):
298         if len(self.fields['host_name']) > 0:
299             self['flags'] |= NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED
300         if len(self.fields['domain_name']) > 0:
301             self['flags'] |= NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED
302         if len(self.fields['os_version']) > 0:
303             self['flags'] |= NTLMSSP_NEGOTIATE_VERSION
304         if (self['flags'] & NTLMSSP_NEGOTIATE_VERSION) == NTLMSSP_NEGOTIATE_VERSION:
305             version_len = 8
306         else:
307             version_len = 0
308         if (self['flags'] & NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED) == NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED:
309             self['host_offset']=32 + version_len
310         if (self['flags'] & NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED) == NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED:
311             self['domain_offset']=32+len(self['host_name']) + version_len
312         return Structure.getData(self)
313
314     def fromString(self,data):
315         Structure.fromString(self,data)
316
317         domain_offset = self['domain_offset']
318         domain_end    = self['domain_len'] + domain_offset
319         self['domain_name'] = data[ domain_offset : domain_end ]
320
321         host_offset = self['host_offset']
322         host_end    = self['host_len'] + host_offset
323         self['host_name'] = data[ host_offset : host_end ]
324
325         hasOsInfo = self['flags'] & NTLMSSP_NEGOTIATE_VERSION
326         if len(data) >= 36 and hasOsInfo:
327             self['os_version'] = data[32:40]
328         else:
329             self['os_version'] = ''
330
331 class NTLMAuthChallenge(Structure):
332
333     structure = (
334         ('','"NTLMSSP\x00'),
335         ('message_type','<L=2'),
336         ('domain_len','<H-domain_name'),
337         ('domain_max_len','<H-domain_name'),
338         ('domain_offset','<L=40'),
339         ('flags','<L=0'),
340         ('challenge','8s'),
341         ('reserved','8s=""'),
342         ('TargetInfoFields_len','<H-TargetInfoFields'),
343         ('TargetInfoFields_max_len','<H-TargetInfoFields'),
344         ('TargetInfoFields_offset','<L'),
345         ('VersionLen','_-Version','self.checkVersion(self["flags"])'), 
346         ('Version',':'),
347         ('domain_name',':'),
348         ('TargetInfoFields',':'))
349
350     def checkVersion(self, flags):
351         if flags is not None:
352            if flags & NTLMSSP_NEGOTIATE_VERSION == 0:
353               return 0
354         return 8
355
356     def getData(self):
357         if self['TargetInfoFields'] is not None and type(self['TargetInfoFields']) is not str:
358             raw_av_fields = self['TargetInfoFields'].getData()
359             self['TargetInfoFields'] = raw_av_fields
360         return Structure.getData(self)
361
362     def fromString(self,data):
363         Structure.fromString(self,data)
364         # Just in case there's more data after the TargetInfoFields
365         self['TargetInfoFields'] = self['TargetInfoFields'][:self['TargetInfoFields_len']]
366         # We gotta process the TargetInfoFields
367         #if self['TargetInfoFields_len'] > 0:
368         #    av_pairs = AV_PAIRS(self['TargetInfoFields'][:self['TargetInfoFields_len']]) 
369         #    self['TargetInfoFields'] = av_pairs
370
371         return self
372         
373 class NTLMAuthChallengeResponse(Structure, NTLMAuthMixin):
374
375     structure = (
376         ('','"NTLMSSP\x00'),
377         ('message_type','<L=3'),
378         ('lanman_len','<H-lanman'),
379         ('lanman_max_len','<H-lanman'),
380         ('lanman_offset','<L'),
381         ('ntlm_len','<H-ntlm'),
382         ('ntlm_max_len','<H-ntlm'),
383         ('ntlm_offset','<L'),
384         ('domain_len','<H-domain_name'),
385         ('domain_max_len','<H-domain_name'),
386         ('domain_offset','<L'),
387         ('user_len','<H-user_name'),
388         ('user_max_len','<H-user_name'),
389         ('user_offset','<L'),
390         ('host_len','<H-host_name'),
391         ('host_max_len','<H-host_name'),
392         ('host_offset','<L'),
393         ('session_key_len','<H-session_key'),
394         ('session_key_max_len','<H-session_key'),
395         ('session_key_offset','<L'),
396         ('flags','<L'),
397         ('VersionLen','_-Version','self.checkVersion(self["flags"])'), 
398         ('Version',':=""'),
399         ('MICLen','_-MIC','self.checkMIC(self["flags"])'),
400         ('MIC',':=""'),
401         ('domain_name',':'),
402         ('user_name',':'),
403         ('host_name',':'),
404         ('lanman',':'),
405         ('ntlm',':'),
406         ('session_key',':'))
407
408     def __init__(self, username = '', password = '', challenge = '', lmhash = '', nthash = '', flags = 0):
409         Structure.__init__(self)
410         self['session_key']=''
411         self['user_name']=username.encode('utf-16le')
412         self['domain_name']='' #"CLON".encode('utf-16le')
413         self['host_name']='' #"BETS".encode('utf-16le')
414         self['flags'] = (   #authResp['flags']
415                 # we think (beto & gera) that his flags force a memory conten leakage when a windows 2000 answers using uninitializaed verifiers
416            NTLMSSP_NEGOTIATE_128     |
417            NTLMSSP_NEGOTIATE_KEY_EXCH|
418            # NTLMSSP_LM_KEY      |
419            NTLMSSP_NEGOTIATE_NTLM    |
420            NTLMSSP_NEGOTIATE_UNICODE     |
421            # NTLMSSP_ALWAYS_SIGN |
422            NTLMSSP_NEGOTIATE_SIGN        |
423            NTLMSSP_NEGOTIATE_SEAL        |
424            # NTLMSSP_TARGET      |
425            0)
426         # Here we do the stuff
427         if username and ( lmhash != '' or nthash != ''):            
428             self['lanman'] = get_ntlmv1_response(lmhash, challenge)
429             self['ntlm'] = get_ntlmv1_response(nthash, challenge)
430         elif (username and password):
431             lmhash = compute_lmhash(password)
432             nthash = compute_nthash(password)
433             self['lanman']=get_ntlmv1_response(lmhash, challenge)
434             self['ntlm']=get_ntlmv1_response(nthash, challenge)    # This is not used for LM_KEY nor NTLM_KEY
435         else:
436             self['lanman'] = ''
437             self['ntlm'] = ''
438             if not self['host_name']:
439                 self['host_name'] = 'NULL'.encode('utf-16le')      # for NULL session there must be a hostname
440
441     def checkVersion(self, flags):
442         if flags is not None:
443            if flags & NTLMSSP_NEGOTIATE_VERSION == 0:
444               return 0
445         return 8
446
447     def checkMIC(self, flags):
448         # TODO: Find a proper way to check the MIC is in there
449         if flags is not None:
450            if flags & NTLMSSP_NEGOTIATE_VERSION == 0:
451               return 0
452         return 16
453                                                                                 
454     def getData(self):
455         self['domain_offset']=64+self.checkMIC(self["flags"])+self.checkVersion(self["flags"])
456         self['user_offset']=64+self.checkMIC(self["flags"])+self.checkVersion(self["flags"])+len(self['domain_name'])
457         self['host_offset']=self['user_offset']+len(self['user_name'])
458         self['lanman_offset']=self['host_offset']+len(self['host_name'])
459         self['ntlm_offset']=self['lanman_offset']+len(self['lanman'])
460         self['session_key_offset']=self['ntlm_offset']+len(self['ntlm'])
461         return Structure.getData(self)
462
463     def fromString(self,data):
464         Structure.fromString(self,data)
465         # [MS-NLMP] page 27
466         # Payload data can be present in any order within the Payload field, 
467         # with variable-length padding before or after the data
468
469         domain_offset = self['domain_offset']
470         domain_end = self['domain_len'] + domain_offset
471         self['domain_name'] = data[ domain_offset : domain_end ]
472
473         host_offset = self['host_offset']
474         host_end    = self['host_len'] + host_offset
475         self['host_name'] = data[ host_offset: host_end ]
476
477         user_offset = self['user_offset']
478         user_end    = self['user_len'] + user_offset
479         self['user_name'] = data[ user_offset: user_end ]
480
481         ntlm_offset = self['ntlm_offset'] 
482         ntlm_end    = self['ntlm_len'] + ntlm_offset 
483         self['ntlm'] = data[ ntlm_offset : ntlm_end ]
484
485         lanman_offset = self['lanman_offset'] 
486         lanman_end    = self['lanman_len'] + lanman_offset
487         self['lanman'] = data[ lanman_offset : lanman_end]
488
489         #if len(data) >= 36: 
490         #    self['os_version'] = data[32:36]
491         #else:
492         #    self['os_version'] = ''
493
494 class ImpacketStructure(Structure):
495     def set_parent(self, other):
496         self.parent = other
497
498     def get_packet(self):
499         return str(self)
500
501     def get_size(self):
502         return len(self)
503
504 class ExtendedOrNotMessageSignature(Structure):
505     def __init__(self, flags = 0, **kargs):
506         if flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY:
507             self.structure = self.extendedMessageSignature
508         else:
509             self.structure = self.MessageSignature
510         return Structure.__init__(self, **kargs)
511
512 class NTLMMessageSignature(ExtendedOrNotMessageSignature):
513       extendedMessageSignature = (
514           ('Version','<L=1'),
515           ('Checksum','<q'),
516           ('SeqNum','<i'),
517       )
518
519       MessageSignature = (
520           ('Version','<L=1'),
521           ('RandomPad','<i=0'),
522           ('Checksum','<i'),
523           ('SeqNum','<i'),
524       )
525
526 KNOWN_DES_INPUT = "KGS!@#$%"
527
528 def __expand_DES_key( key):
529     # Expand the key from a 7-byte password key into a 8-byte DES key
530     key  = key[:7]
531     key += '\x00'*(7-len(key))
532     s = chr(((ord(key[0]) >> 1) & 0x7f) << 1)
533     s = s + chr(((ord(key[0]) & 0x01) << 6 | ((ord(key[1]) >> 2) & 0x3f)) << 1)
534     s = s + chr(((ord(key[1]) & 0x03) << 5 | ((ord(key[2]) >> 3) & 0x1f)) << 1)
535     s = s + chr(((ord(key[2]) & 0x07) << 4 | ((ord(key[3]) >> 4) & 0x0f)) << 1)
536     s = s + chr(((ord(key[3]) & 0x0f) << 3 | ((ord(key[4]) >> 5) & 0x07)) << 1)
537     s = s + chr(((ord(key[4]) & 0x1f) << 2 | ((ord(key[5]) >> 6) & 0x03)) << 1)
538     s = s + chr(((ord(key[5]) & 0x3f) << 1 | ((ord(key[6]) >> 7) & 0x01)) << 1)
539     s = s + chr((ord(key[6]) & 0x7f) << 1)
540     return s
541
542 def __DES_block(key, msg):
543     if POW:
544         cipher = POW.Symmetric(POW.DES_ECB)
545         cipher.encryptInit(__expand_DES_key(key))
546         return cipher.update(msg)
547     else:
548         cipher = DES.new(__expand_DES_key(key),DES.MODE_ECB)
549         return cipher.encrypt(msg)
550
551 def ntlmssp_DES_encrypt(key, challenge):
552     answer  = __DES_block(key[:7], challenge)
553     answer += __DES_block(key[7:14], challenge)
554     answer += __DES_block(key[14:], challenge)
555     return answer
556
557 # High level functions to use NTLMSSP
558
559 def getNTLMSSPType1(workstation='', domain='', signingRequired = False, use_ntlmv2 = USE_NTLMv2):
560     # Let's do some encoding checks before moving on. Kind of dirty, but found effective when dealing with
561     # international characters.
562     import sys
563     encoding = sys.getfilesystemencoding()
564     if encoding is not None:
565         try:
566             workstation.encode('utf-16le')
567         except:
568             workstation = workstation.decode(encoding)
569         try:
570             domain.encode('utf-16le')
571         except:
572             domain = domain.decode(encoding)
573
574     # Let's prepare a Type 1 NTLMSSP Message
575     auth = NTLMAuthNegotiate()
576     auth['flags']=0
577     if signingRequired:
578        auth['flags'] = NTLMSSP_NEGOTIATE_KEY_EXCH | NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_ALWAYS_SIGN | NTLMSSP_NEGOTIATE_SEAL
579     if use_ntlmv2:
580        auth['flags'] |= NTLMSSP_NEGOTIATE_TARGET_INFO
581     auth['flags'] |= NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY | NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |  NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_56
582     auth['domain_name'] = domain.encode('utf-16le')
583     return auth
584
585 def getNTLMSSPType3(type1, type2, user, password, domain, lmhash = '', nthash = '', use_ntlmv2 = USE_NTLMv2):
586
587     # Let's do some encoding checks before moving on. Kind of dirty, but found effective when dealing with
588     # international characters.
589     import sys
590     encoding = sys.getfilesystemencoding()
591     if encoding is not None:
592         try:
593             user.encode('utf-16le')
594         except:
595             user = user.decode(encoding)
596         try:
597             password.encode('utf-16le')
598         except:
599             password = password.decode(encoding)
600         try:
601             domain.encode('utf-16le')
602         except:
603             domain = user.decode(encoding)
604
605     ntlmChallenge = NTLMAuthChallenge(type2)
606
607     # Let's start with the original flags sent in the type1 message
608     responseFlags = type1['flags']
609
610     # Token received and parsed. Depending on the authentication 
611     # method we will create a valid ChallengeResponse
612     ntlmChallengeResponse = NTLMAuthChallengeResponse(user, password, ntlmChallenge['challenge'])
613
614     clientChallenge = "".join([random.choice(string.digits+string.letters) for i in xrange(8)])
615
616     serverName = ntlmChallenge['TargetInfoFields']
617
618     ntResponse, lmResponse, sessionBaseKey = computeResponse(ntlmChallenge['flags'], ntlmChallenge['challenge'], clientChallenge, serverName, domain, user, password, lmhash, nthash, use_ntlmv2 )
619
620     # Let's check the return flags
621     if (ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY) == 0:
622         # No extended session security, taking it out
623         responseFlags &= 0xffffffff ^ NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY
624     if (ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_128 ) == 0:
625         # No support for 128 key len, taking it out
626         responseFlags &= 0xffffffff ^ NTLMSSP_NEGOTIATE_128
627     if (ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_KEY_EXCH) == 0:
628         # No key exchange supported, taking it out
629         responseFlags &= 0xffffffff ^ NTLMSSP_NEGOTIATE_KEY_EXCH
630     if (ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_SEAL) == 0:
631         # No sign available, taking it out
632         responseFlags &= 0xffffffff ^ NTLMSSP_NEGOTIATE_SEAL
633     if (ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_SIGN) == 0:
634         # No sign available, taking it out
635         responseFlags &= 0xffffffff ^ NTLMSSP_NEGOTIATE_SIGN
636     if (ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_ALWAYS_SIGN) == 0:
637         # No sign available, taking it out
638         responseFlags &= 0xffffffff ^ NTLMSSP_NEGOTIATE_ALWAYS_SIGN
639
640     keyExchangeKey = KXKEY(ntlmChallenge['flags'],sessionBaseKey, lmResponse, ntlmChallenge['challenge'], password, lmhash, nthash,use_ntlmv2)
641
642     # Special case for anonymous login
643     if user == '' and password == '' and lmhash == '' and nthash == '':
644       keyExchangeKey = '\x00'*16
645
646     # If we set up key exchange, let's fill the right variables
647     if ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_KEY_EXCH:
648        # not exactly what I call random tho :\
649        # exportedSessionKey = this is the key we should use to sign
650        exportedSessionKey = "".join([random.choice(string.digits+string.letters) for i in xrange(16)])
651        #exportedSessionKey = "A"*16
652        #print "keyExchangeKey %r" % keyExchangeKey
653        # Let's generate the right session key based on the challenge flags
654        #if responseFlags & NTLMSSP_NTLM2_KEY:
655            # Extended session security enabled
656        #    if responseFlags & NTLMSSP_KEY_128:
657                # Full key
658        #        exportedSessionKey = exportedSessionKey
659        #    elif responseFlags & NTLMSSP_KEY_56:
660                # Only 56-bit key
661        #        exportedSessionKey = exportedSessionKey[:7]
662        #    else:
663        #        exportedSessionKey = exportedSessionKey[:5]
664        #elif responseFlags & NTLMSSP_KEY_56:
665            # No extended session security, just 56 bits key
666        #    exportedSessionKey = exportedSessionKey[:7] + '\xa0'
667        #else:
668        #    exportedSessionKey = exportedSessionKey[:5] + '\xe5\x38\xb0'
669
670        encryptedRandomSessionKey = generateEncryptedSessionKey(keyExchangeKey, exportedSessionKey)
671     else:
672        encryptedRandomSessionKey = None
673        # [MS-NLMP] page 46
674        exportedSessionKey        = keyExchangeKey
675
676     ntlmChallengeResponse['flags'] = responseFlags
677     ntlmChallengeResponse['domain_name'] = domain.encode('utf-16le')
678     ntlmChallengeResponse['lanman'] = lmResponse
679     ntlmChallengeResponse['ntlm'] = ntResponse
680     if encryptedRandomSessionKey is not None: 
681         ntlmChallengeResponse['session_key'] = encryptedRandomSessionKey
682
683     return ntlmChallengeResponse, exportedSessionKey
684
685
686 # NTLMv1 Algorithm
687
688 def generateSessionKeyV1(password, lmhash, nthash):
689     if POW:
690         hash = POW.Digest(POW.MD4_DIGEST)
691     else:        
692         hash = MD4.new()
693     hash.update(NTOWFv1(password, lmhash, nthash))
694     return hash.digest()
695     
696 def computeResponseNTLMv1(flags, serverChallenge, clientChallenge, serverName, domain, user, password, lmhash='', nthash='', use_ntlmv2 = USE_NTLMv2):
697     if (user == '' and password == ''): 
698         # Special case for anonymous authentication
699         lmResponse = ''
700         ntResponse = ''
701     else:
702         lmhash = LMOWFv1(password, lmhash, nthash)
703         nthash = NTOWFv1(password, lmhash, nthash)
704         if flags & NTLMSSP_NEGOTIATE_LM_KEY:
705            ntResponse = ''
706            lmResponse = get_ntlmv1_response(lmhash, serverChallenge)
707         elif flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY:
708            md5 = hashlib.new('md5')
709            chall = (serverChallenge + clientChallenge)
710            md5.update(chall)
711            ntResponse = ntlmssp_DES_encrypt(nthash, md5.digest()[:8])
712            lmResponse = clientChallenge + '\x00'*16
713         else:
714            ntResponse = get_ntlmv1_response(nthash,serverChallenge)
715            lmResponse = get_ntlmv1_response(lmhash, serverChallenge)
716    
717     sessionBaseKey = generateSessionKeyV1(password, lmhash, nthash)
718     return ntResponse, lmResponse, sessionBaseKey
719
720 def compute_lmhash(password):
721     # This is done according to Samba's encryption specification (docs/html/ENCRYPTION.html)
722     password = password.upper()
723     lmhash  = __DES_block(password[:7], KNOWN_DES_INPUT)
724     lmhash += __DES_block(password[7:14], KNOWN_DES_INPUT)
725     return lmhash
726
727 def NTOWFv1(password, lmhash = '', nthash=''):
728     if nthash != '':
729        return nthash
730     return compute_nthash(password)   
731
732 def LMOWFv1(password, lmhash = '', nthash=''):
733     if lmhash != '':
734        return lmhash
735     return compute_lmhash(password)
736
737 def compute_nthash(password):
738     # This is done according to Samba's encryption specification (docs/html/ENCRYPTION.html)
739     try:
740         password = unicode(password).encode('utf_16le')
741     except UnicodeDecodeError:
742         import sys
743         password = password.decode(sys.getfilesystemencoding()).encode('utf_16le')
744
745     if POW:
746         hash = POW.Digest(POW.MD4_DIGEST)
747     else:        
748         hash = MD4.new()
749     hash.update(password)
750     return hash.digest()
751
752 def get_ntlmv1_response(key, challenge):
753     return ntlmssp_DES_encrypt(key, challenge)
754
755 # NTLMv2 Algorithm - as described in MS-NLMP Section 3.3.2
756
757 # Crypto Stuff
758
759 def MAC(flags, handle, signingKey, seqNum, message):
760    # [MS-NLMP] Section 3.4.4
761    # Returns the right messageSignature depending on the flags
762    messageSignature = NTLMMessageSignature(flags)
763    if flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY:
764        if flags & NTLMSSP_NEGOTIATE_KEY_EXCH:
765            messageSignature['Version'] = 1
766            messageSignature['Checksum'] = struct.unpack('<q',handle(hmac_md5(signingKey, struct.pack('<i',seqNum)+message)[:8]))[0]
767            messageSignature['SeqNum'] = seqNum
768            seqNum += 1
769        else:
770            messageSignature['Version'] = 1
771            messageSignature['Checksum'] = struct.unpack('<q',hmac_md5(signingKey, struct.pack('<i',seqNum)+message)[:8])[0]
772            messageSignature['SeqNum'] = seqNum
773            seqNum += 1
774    else:
775        messageSignature['Version'] = 1
776        messageSignature['Checksum'] = struct.pack('<i',binascii.crc32(message))
777        messageSignature['RandomPad'] = 0
778        messageSignature['RandomPad'] = handle(struct.pack('<i',messageSignature['RandomPad']))
779        messageSignature['Checksum'] = struct.unpack('<i',handle(messageSignature['Checksum']))[0]
780        messageSignature['SeqNum'] = handle('\x00\x00\x00\x00')
781        messageSignature['SeqNum'] = struct.unpack('<i',messageSignature['SeqNum'])[0] ^ seqNum
782        messageSignature['RandomPad'] = 0
783        
784    return messageSignature
785
786 def SEAL(flags, signingKey, sealingKey, messageToSign, messageToEncrypt, seqNum, handle):
787    sealedMessage = handle(messageToEncrypt)
788    signature = MAC(flags, handle, signingKey, seqNum, messageToSign)
789    return sealedMessage, signature
790
791 def SIGN(flags, signingKey, message, seqNum, handle):
792    return MAC(flags, handle, signingKey, seqNum, message)
793
794 def SIGNKEY(flags, randomSessionKey, mode = 'Client'):
795    if flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY:
796        if mode == 'Client':
797            md5 = hashlib.new('md5')
798            md5.update(randomSessionKey + "session key to client-to-server signing key magic constant\x00")
799            signKey = md5.digest()
800        else:
801            md5 = hashlib.new('md5')
802            md5.update(randomSessionKey + "session key to server-to-client signing key magic constant\x00")
803            signKey = md5.digest()
804    else:
805        signKey = None
806    return signKey
807
808 def SEALKEY(flags, randomSessionKey, mode = 'Client'):
809    if flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY:
810        if flags & NTLMSSP_NEGOTIATE_128:
811            sealKey = randomSessionKey
812        elif flags & NTLMSSP_NEGOTIATE_56:
813            sealKey = randomSessionKey[:7]
814        else:
815            sealKey = randomSessionKey[:5]
816
817        if mode == 'Client':
818                md5 = hashlib.new('md5')
819                md5.update(sealKey + 'session key to client-to-server sealing key magic constant\x00')
820                sealKey = md5.digest()
821        else:
822                md5 = hashlib.new('md5')
823                md5.update(sealKey + 'session key to server-to-client sealing key magic constant\x00')
824                sealKey = md5.digest()
825
826    elif flags & NTLMSSP_NEGOTIATE_56:
827        sealKey = randomSessionKey[:7] + '\xa0'
828    else:
829        sealKey = randomSessionKey[:5] + '\xe5\x38\xb0'
830
831    return sealKey
832
833
834 def generateEncryptedSessionKey(keyExchangeKey, exportedSessionKey):
835    if POW:
836        cipher = POW.Symmetric(POW.RC4)
837        cipher.encryptInit(keyExchangeKey)
838        cipher_encrypt = cipher.update
839    else:
840        cipher = ARC4.new(keyExchangeKey)
841        cipher_encrypt = cipher.encrypt
842
843    sessionKey = cipher_encrypt(exportedSessionKey)
844    return sessionKey
845
846 def KXKEY(flags, sessionBaseKey, lmChallengeResponse, serverChallenge, password, lmhash, nthash, use_ntlmv2 = USE_NTLMv2):
847    if use_ntlmv2:
848        return sessionBaseKey
849
850    if flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY:
851        if flags & NTLMSSP_NEGOTIATE_NTLM:
852           keyExchangeKey = hmac_md5(sessionBaseKey, serverChallenge + lmChallengeResponse[:8])
853        else:
854           keyExchangeKey = sessionBaseKey
855    elif flags & NTLMSSP_NEGOTIATE_NTLM:
856        if flags & NTLMSSP_NEGOTIATE_LM_KEY:
857           keyExchangeKey = __DES_block(LMOWFv1(password,lmhash)[:7], lmChallengeResponse[:8]) + __DES_block(LMOWFv1(password,lmhash)[7] + '\xBD\xBD\xBD\xBD\xBD\xBD', lmChallengeResponse[:8])
858        elif flags & NTLMSSP_REQUEST_NON_NT_SESSION_KEY:
859           keyExchangeKey = LMOWFv1(password,lmhash)[:8] + '\x00'*8
860        else:
861           keyExchangeKey = sessionBaseKey
862    else:
863        raise "Can't create a valid KXKEY!"
864
865    return keyExchangeKey
866       
867 def hmac_md5(key, data):
868     if POW:
869         h = POW.Hmac(POW.MD5_DIGEST, key)
870         h.update(data)
871         result = h.mac()
872     else:
873         import hmac
874         h = hmac.new(key)
875         h.update(data)
876         result = h.digest()
877     return result
878
879 def NTOWFv2( user, password, domain, hash = ''):
880     if hash != '':
881        theHash = hash 
882     else:
883        theHash = compute_nthash(password)
884     return hmac_md5(theHash, user.upper().encode('utf-16le') + domain.encode('utf-16le'))
885
886 def LMOWFv2( user, password, domain, lmhash = ''):
887     return NTOWFv2( user, password, domain, lmhash)
888
889
890 def computeResponseNTLMv2(flags, serverChallenge, clientChallenge,  serverName, domain, user, password, lmhash = '', nthash = '', use_ntlmv2 = USE_NTLMv2):
891
892     responseServerVersion = '\x01'
893     hiResponseServerVersion = '\x01'
894     responseKeyNT = NTOWFv2(user, password, domain, nthash)
895     responseKeyLM = LMOWFv2(user, password, domain, lmhash)
896
897     # If you're running test-ntlm, comment the following lines and uncoment the ones that are commented. Don't forget to turn it back after the tests!
898     ######################
899     av_pairs = AV_PAIRS(serverName)
900     # In order to support SPN target name validation, we have to add this to the serverName av_pairs. Otherwise we will get access denied
901     # This is set at Local Security Policy -> Local Policies -> Security Options -> Server SPN target name validation level
902     av_pairs[NTLMSSP_AV_TARGET_NAME] = 'cifs/'.encode('utf-16le') + av_pairs[NTLMSSP_AV_HOSTNAME][1]
903     if av_pairs[NTLMSSP_AV_TIME] is not None:
904        aTime = av_pairs[NTLMSSP_AV_TIME][1]
905     else:
906        aTime = struct.pack('<q', (116444736000000000 + calendar.timegm(time.gmtime()) * 10000000) )
907        #aTime = '\x00'*8
908        av_pairs[NTLMSSP_AV_TIME] = aTime
909     serverName = av_pairs.getData()
910           
911     ######################
912     #aTime = '\x00'*8
913     ######################
914     temp = responseServerVersion + hiResponseServerVersion + '\x00' * 6 + aTime + clientChallenge + '\x00' * 4 + serverName + '\x00' * 4
915
916     ntProofStr = hmac_md5(responseKeyNT, serverChallenge + temp)
917
918     ntChallengeResponse = ntProofStr + temp
919     lmChallengeResponse = hmac_md5(responseKeyNT, serverChallenge + clientChallenge) + clientChallenge
920     sessionBaseKey = hmac_md5(responseKeyNT, ntProofStr)
921
922     if (user == '' and password == ''):
923         # Special case for anonymous authentication
924         ntChallengeResponse = ''
925         lmChallengeResponse = ''
926
927     return ntChallengeResponse, lmChallengeResponse, sessionBaseKey
928
929 class NTLM_HTTP(object):
930     '''Parent class for NTLM HTTP classes.'''
931     MSG_TYPE = None
932
933     @classmethod
934     def get_instace(cls,msg_64):
935         msg = None
936         msg_type = 0
937         if msg_64 != '':
938             msg = base64.b64decode(msg_64[5:]) # Remove the 'NTLM '
939             msg_type = ord(msg[8])
940     
941         for _cls in NTLM_HTTP.__subclasses__():
942             if msg_type == _cls.MSG_TYPE:
943                 instance = _cls()
944                 instance.fromString(msg)
945                 return instance
946
947     
948 class NTLM_HTTP_AuthRequired(NTLM_HTTP):
949     commonHdr = ()
950     # Message 0 means the first HTTP request e.g. 'GET /bla.png'
951     MSG_TYPE = 0
952
953     def fromString(self,data): 
954         pass
955
956
957 class NTLM_HTTP_AuthNegotiate(NTLM_HTTP, NTLMAuthNegotiate):
958     commonHdr = ()
959     MSG_TYPE = 1
960
961     def __init__(self):
962         NTLMAuthNegotiate.__init__(self)
963
964
965 class NTLM_HTTP_AuthChallengeResponse(NTLM_HTTP, NTLMAuthChallengeResponse):
966     commonHdr = ()
967     MSG_TYPE = 3
968
969     def __init__(self):
970         NTLMAuthChallengeResponse.__init__(self)
971