IdNTLM.pas 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744
  1. {
  2. $Project$
  3. $Workfile$
  4. $Revision$
  5. $DateUTC$
  6. $Id$
  7. This file is part of the Indy (Internet Direct) project, and is offered
  8. under the dual-licensing agreement described on the Indy website.
  9. (http://www.indyproject.org/)
  10. Copyright:
  11. (c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
  12. }
  13. {
  14. $Log$
  15. }
  16. {
  17. Rev 1.1 6/29/04 12:51:10 PM RLebeau
  18. Updatd SetupLanManagerPassword() to check the password length before
  19. referencing the password data
  20. Rev 1.0 11/13/2002 07:58:08 AM JPMugaas
  21. S.G. 12/7/2002:
  22. - Rewrote Type 1 and Type 2 structures to be closer to the
  23. document referenced in the above URL. (Easier to read and check)
  24. - Corrected falgs accouring to bug ID 577895 and own packet traces.
  25. This was actually only an adjustment to the new data types when
  26. I rewrote the header.
  27. - Initialized structures to #0 before using.
  28. }
  29. {
  30. Implementation of the NTLM authentication as specified in
  31. http://www.innovation.ch/java/ntlm.html with some fixes
  32. Author: Doychin Bondzhev ([email protected])
  33. Copyright: (c) Chad Z. Hower and The Winshoes Working Group.
  34. }
  35. unit IdNTLM;
  36. interface
  37. {$i IdCompilerDefines.inc}
  38. uses
  39. IdGlobal
  40. {$IFDEF DOTNET}
  41. , IdStruct
  42. {$ENDIF}
  43. ;
  44. type
  45. {$IFDEF DOTNET}
  46. ProtocolArray = array [1..8] of AnsiChar;
  47. padArray2 = array[0..1] of Byte;
  48. padArray3 = Array[0..2] of Byte;
  49. padArray7 = Array[0..6] of Byte;
  50. padArray8 = Array[0..7] of Byte;
  51. nonceArray = Array[1..8] of Byte;
  52. ntlm_base = class(TIdStruct)
  53. protected
  54. fprotocol : ProtocolArray;
  55. function GetBytesLen: UInt32; override;
  56. public
  57. procedure ReadStruct(const ABytes : TIdBytes; var VIndex : UInt32); override;
  58. procedure WriteStruct(var VBytes : TIdBytes; var VIndex : UInt32); override;
  59. property protocol: ProtocolArray read fprotocol write fprotocol; // array [1..8] of Char; // 'N', 'T', 'L', 'M', 'S', 'S', 'P', '\0' {Do not Localize}
  60. end;
  61. type_1_message_header = class(ntlm_base)
  62. protected
  63. f_type : UInt8;
  64. fpad : padArray3;
  65. fflags : UInt16;
  66. fpad2 : padArray2;
  67. fdom_len1 : UInt16;
  68. fdom_len2 : UInt16;
  69. fdom_off : UInt32;
  70. fhost_len1 : UInt16;
  71. fhost_len2 : UInt16;
  72. fhost_off : UInt32;
  73. function GetBytesLen: UInt32; override;
  74. public
  75. procedure ReadStruct(const ABytes : TIdBytes; var VIndex : UInt32); override;
  76. procedure WriteStruct(var VBytes : TIdBytes; var VIndex : UInt32); override;
  77. property _type: UInt8 read f_type write f_type; // 0x01
  78. property pad : padArray3 read fpad write fpad; // 0x0
  79. property flags: UInt16 read fflags write fflags; // 0xb203
  80. property pad2 : padArray2 read fpad2 write fpad2; // 0x0
  81. property dom_len1: UInt16 read fdom_len1 write fdom_len1; // domain string length
  82. property dom_len2: UInt16 read fdom_len2 write fdom_len2; // domain string length
  83. property dom_off: UInt32 read fdom_off write fdom_off; // domain string offset
  84. property host_len1: UInt16 read fhost_len1 write fhost_len1; // host string length
  85. property host_len2: UInt16 read fhost_len2 write fhost_len2; // host string length
  86. property host_off: UInt32 read fhost_off write fhost_off; // host string offset (always 0x20)
  87. end;
  88. type_2_message_header = class(ntlm_base)
  89. protected
  90. f_type : UInt8;
  91. fPad: padArray3;
  92. fhost_len1: UInt16;
  93. fhost_len2: UInt16;
  94. fhost_off: UInt32;
  95. fflags: UInt16;
  96. fPad2: padArray2;
  97. fnonce: nonceArray;
  98. freserved: padArray8;
  99. finfo_len1: UInt16;
  100. finfo_len2: UInt16;
  101. finfo_off: UInt32;
  102. function GetBytesLen: UInt32; override;
  103. public
  104. procedure ReadStruct(const ABytes : TIdBytes; var VIndex : UInt32); override;
  105. procedure WriteStruct(var VBytes : TIdBytes; var VIndex : UInt32); override;
  106. property _type: UInt8 read f_type write f_type; // $2
  107. property pad: padArray3 read fPad wrie fPad;
  108. property host_len1: UInt16 read fhost_len1 write fhost_len1;
  109. property host_len2: UInt16 read fhost_len2 write fhost_len2;
  110. property host_off: UInt32 read fhost_off write fhost_off;
  111. property flags: UInt16 read fflags write fflags;
  112. property pad2: padArray2 read fflags write fflags;
  113. property nonce: nonceArray read fnonce write fnonce;
  114. property reserved: padArray8 read freserved write freserved;
  115. property info_len1: UInt16 read finfo_len1 write finfo_len1;
  116. property info_len2: UInt16 read finfo_len2 write finfo_len2;
  117. property info_off: UInt32 read finfo_off write finfo_off;
  118. end;
  119. type_3_message_header = class(ntlm_base)
  120. protected
  121. f_type: UInt32;
  122. flm_resp_len1: UInt16;
  123. flm_resp_len2: UInt16;
  124. flm_resp_off : UInt32;
  125. fnt_resp_len1: UInt16;
  126. fnt_resp_len2: UInt16;
  127. fnt_resp_off: UInt32;
  128. fdom_len1: UInt16;
  129. fdom_len2 : UInt16;
  130. fdom_off : UInt32;
  131. fuser_len1: UInt16;
  132. fuser_len2: UInt16;
  133. fuser_off: UInt32;
  134. fhost_len1: UInt16;
  135. fhost_len2: UInt16;
  136. fhost_off: UInt32;
  137. fkey_len1: UInt16;
  138. fkey_len2: UInt16;
  139. fkey_off: UInt32;
  140. fflags: UInt32;
  141. function GetBytesLen: UInt32; override;
  142. public
  143. procedure ReadStruct(const ABytes : TIdBytes; var VIndex : UInt32); override;
  144. procedure WriteStruct(var VBytes : TIdBytes; var VIndex : UInt32); override;
  145. property _type: UInt32 read f_type write f_type; // 0x03
  146. property lm_resp_len1: UInt16 read flm_resp_len1 write flm_resp_len1; // LanManager response length (always 0x18)
  147. property lm_resp_len2: UInt16 read flm_resp_len2 write flm_resp_len2; // LanManager response length (always 0x18)
  148. property lm_resp_off: UInt32 read flm_resp_off write flm_resp_off; // LanManager response offset
  149. property nt_resp_len1: UInt16 read fnt_resp_len1 write fnt_resp_len1; // NT response length (always 0x18)
  150. property nt_resp_len2: UInt16 read fnt_resp_len2 write fnt_resp_len2; // NT response length (always 0x18)
  151. property nt_resp_off: UInt32 read fnt_resp_off write fnt_resp_off; // NT response offset
  152. property dom_len1: UInt16 read fdom_len1 write fdom_len1; // domain string length
  153. property dom_len2: UInt16 read fdom_len2 write fdom_len2; // domain string length
  154. property dom_off: UInt32 read fdom_off write fdom_off; // domain string offset (always 0x40)
  155. property user_len1: UInt16 read fuser_len1 write fuser_len1; // username string length
  156. property user_len2: UInt16 read fuser_len2 write fuser_len2; // username string length
  157. property user_off: UInt32 read fuser_off write fuser_off; // username string offset
  158. property host_len1: UInt16 read fhost_len1 write fhost_len1; // host string length
  159. property host_len2: UInt16 read fhost_len2 write fhost_len2; // host string length
  160. property host_off: UInt32 read fhost_off write fhost_off; // host string offset
  161. property key_len1: UInt16 read fkey_len1 write fkey_len1; // session key length
  162. property key_len2: UInt16 read fkey_len2 write fkey_len2; // session key length
  163. property key_off: UInt32 read fkey_off write fkey_off; // session key offset
  164. property flags: UInt32 read fflags write fflags; // 0xA0808205
  165. end;
  166. {$ELSE}
  167. type_1_message_header = packed record
  168. protocol: array [1..8] of UInt8; // 'N', 'T', 'L', 'M', 'S', 'S', 'P', '\0' {Do not Localize}
  169. _type: UInt8; // 0x01
  170. pad : packed Array[1..3] of UInt8; // 0x0
  171. flags: UInt16; // 0xb203
  172. pad2 : packed Array[1..2] of UInt8; // 0x0
  173. dom_len1: UInt16; // domain string length
  174. dom_len2: UInt16; // domain string length
  175. dom_off: UInt32; // domain string offset
  176. host_len1: UInt16; // host string length
  177. host_len2: UInt16; // host string length
  178. host_off: UInt32; // host string offset (always 0x20)
  179. end;
  180. type_2_message_header = packed record
  181. protocol: packed array [1..8] of UInt8; // 'N', 'T', 'L', 'M', 'S', 'S', 'P', #0 {Do not Localize}
  182. _type: UInt8; // $2
  183. Pad: packed Array[1..3] of UInt8;
  184. host_len1: UInt16;
  185. host_len2: UInt16;
  186. host_off: UInt32;
  187. flags: UInt16;
  188. Pad2: packed Array[1..2] of UInt8;
  189. nonce: packed Array[1..8] of UInt8;
  190. reserved: packed Array[1..8] of UInt8;
  191. info_len1: UInt16;
  192. info_len2: UInt16;
  193. info_off: UInt32;
  194. end;
  195. type_3_message_header = packed record
  196. protocol: array [1..8] of UInt8; // 'N', 'T', 'L', 'M', 'S', 'S', 'P', '\0' {Do not Localize}
  197. _type: UInt32; // 0x03
  198. lm_resp_len1: UInt16; // LanManager response length (always 0x18)
  199. lm_resp_len2: UInt16; // LanManager response length (always 0x18)
  200. lm_resp_off: UInt32; // LanManager response offset
  201. nt_resp_len1: UInt16; // NT response length (always 0x18)
  202. nt_resp_len2: UInt16; // NT response length (always 0x18)
  203. nt_resp_off: UInt32; // NT response offset
  204. dom_len1: UInt16; // domain string length
  205. dom_len2: UInt16; // domain string length
  206. dom_off: UInt32; // domain string offset (always 0x40)
  207. user_len1: UInt16; // username string length
  208. user_len2: UInt16; // username string length
  209. user_off: UInt32; // username string offset
  210. host_len1: UInt16; // host string length
  211. host_len2: UInt16; // host string length
  212. host_off: UInt32; // host string offset
  213. key_len1: UInt16; // session key length
  214. key_len2: UInt16; // session key length
  215. key_off: UInt32; // session key offset
  216. flags: UInt32; // 0xA0808205
  217. end;
  218. function BuildType1Message(const ADomain, AHost: String): String;
  219. function BuildType3Message(const ADomain, AHost, AUsername: TIdUnicodeString; const APassword: String; const ANonce: TIdBytes): String;
  220. {$ENDIF}
  221. function NTLMFunctionsLoaded : Boolean;
  222. procedure GetDomain(const AUserName : String; var VUserName, VDomain : String);
  223. //IMPORTANT!!!
  224. //
  225. //NTLM is a funny protocol because it was designed for little endian machines.
  226. //Some record values must be in little endian byte-orders.
  227. const
  228. // S.G. 12/7/2002: Changed the flag to $B207 (from BugID 577895 and packet trace)
  229. //was $A000B207; //b203;
  230. //JPM - note that this value has to be little endian. We precalculate
  231. //this for big endian machines.
  232. MSG1_FLAGS : UInt16 = $b207;
  233. // S.G. 12/7/2002: was: flags := $A0808205; (from BugID 577895 and packet trace)
  234. MSG3_FLAGS : UInt32 = $018205;
  235. implementation
  236. uses
  237. SysUtils,
  238. {$IFDEF DOTNET}
  239. System.Text,
  240. {$ENDIF}
  241. IdFIPS,
  242. IdGlobalProtocols,
  243. IdCoderMIME
  244. {$IFDEF HAS_GENERICS_TArray_Copy}
  245. {$IFDEF HAS_UNIT_Generics_Collections}
  246. , System.Generics.Collections
  247. {$ENDIF}
  248. {$ENDIF}
  249. ;
  250. const
  251. cProtocolStr: array[1..8] of Byte = (Ord('N'),Ord('T'),Ord('L'),Ord('M'),Ord('S'),Ord('S'),Ord('P'),$0); {Do not Localize}
  252. procedure GetDomain(const AUserName : String; var VUserName, VDomain : String);
  253. {$IFDEF USE_INLINE} inline; {$ENDIF}
  254. var
  255. i: Integer;
  256. begin
  257. i := Pos('\', AUsername);
  258. if i > -1 then
  259. begin
  260. VDomain := Copy(AUsername, 1, i - 1);
  261. VUserName := Copy(AUsername, i + 1, Length(AUserName));
  262. end else
  263. begin
  264. VDomain := ' '; {do not localize}
  265. VUserName := AUserName;
  266. end;
  267. end;
  268. {$IFDEF DOTNET}
  269. function NTLMFunctionsLoaded : Boolean;
  270. {$IFDEF USE_INLINE} inline; {$ENDIF}
  271. begin
  272. Result := True;
  273. end;
  274. {$ELSE}
  275. function NTLMFunctionsLoaded : Boolean;
  276. begin
  277. Result := LoadNTLMLibrary;
  278. if Result then begin
  279. Result := IsNTLMFuncsAvail;
  280. end;
  281. end;
  282. {$ENDIF}
  283. {$IFNDEF DOTNET}
  284. function BuildUnicode(const S: String): TIdBytes;
  285. {$IFDEF STRING_IS_UNICODE}
  286. {$IFDEF USE_INLINE}inline;{$ENDIF}
  287. {$ELSE}
  288. var
  289. i: integer;
  290. {$ENDIF}
  291. begin
  292. {$IFDEF STRING_IS_UNICODE}
  293. Result := IndyTextEncoding_UTF16LE.GetBytes(S);
  294. {$ELSE}
  295. // RLebeau: TODO - should this use UTF-16 as well? This logic will
  296. // not produce a valid Unicode string if non-ASCII characters are present!
  297. SetLength(Result, Length(S) * SizeOf(WideChar));
  298. for i := 0 to Length(S)-1 do begin
  299. Result[i*2] := Byte(S[i+1]);
  300. Result[(i*2)+1] := Byte(#0);
  301. end;
  302. {$ENDIF}
  303. end;
  304. function BuildType1Message(const ADomain, AHost: String): String;
  305. var
  306. LEncoding: IIdTextEncoding;
  307. Type_1_Message: type_1_message_header;
  308. lDomain: TIdBytes;
  309. lHost: TIdBytes;
  310. buf: TIdBytes;
  311. begin
  312. LEncoding := IndyTextEncoding_ASCII;
  313. lDomain := ToBytes(UpperCase(ADomain), LEncoding);
  314. lHost := ToBytes(UpperCase(AHost), LEncoding);
  315. LEncoding := nil;
  316. FillChar(Type_1_Message, SizeOf(Type_1_Message), #0);
  317. {$IFDEF HAS_GENERICS_TArray_Copy}
  318. TArray.Copy<Byte>(cProtocolStr, Type_1_Message.protocol, 8);
  319. {$ELSE}
  320. {$IFDEF USE_MARSHALLED_PTRS}
  321. buf := cProtocolStr;
  322. TMarshal.Copy(TBytesPtr(@buf)^, 0, TPtrWrapper.Create(@Type_1_Message.protocol[1]), 8);
  323. {$ELSE}
  324. Move(cProtocolStr[1], Type_1_Message.protocol[1], 8);
  325. {$ENDIF}
  326. {$ENDIF}
  327. Type_1_Message._type := 1;
  328. // S.G. 12/7/2002: Changed the flag to $B207 (from BugID 577895 and packet trace)
  329. Type_1_Message.flags := MSG1_FLAGS; //was $A000B207; //b203;
  330. Type_1_Message.dom_len1 := UInt16(Length(lDomain));
  331. // dom_off := 0;
  332. Type_1_Message.dom_off := 32;
  333. Type_1_Message.host_len1 := UInt16(Length(lHost));
  334. Type_1_Message.host_off := UInt32(Type_1_Message.dom_off + Type_1_Message.dom_len1);
  335. Type_1_Message._type := HostToLittleEndian(Type_1_Message._type);
  336. Type_1_Message.flags := HostToLittleEndian(Type_1_Message.flags);
  337. Type_1_Message.dom_len1 := HostToLittleEndian(Type_1_Message.dom_len1);
  338. Type_1_Message.dom_len2 := Type_1_Message.dom_len1;
  339. Type_1_Message.dom_off := HostToLittleEndian(Type_1_Message.dom_off);
  340. Type_1_Message.host_len1 := HostToLittleEndian(Type_1_Message.host_len1);
  341. Type_1_Message.host_len2 := Type_1_Message.host_len1;
  342. Type_1_Message.host_off := HostToLittleEndian(Type_1_Message.host_off);
  343. buf := RawToBytes(Type_1_Message, SizeOf(Type_1_Message));
  344. AppendBytes(buf, lDomain);
  345. AppendBytes(buf, lHost);
  346. Result := TIdEncoderMIME.EncodeBytes(buf);
  347. end;
  348. function BuildType3Message(const ADomain, AHost, AUsername: TIdUnicodeString;
  349. const APassword: String; const ANonce: TIdBytes): String;
  350. var
  351. type3: type_3_message_header;
  352. buf: TIdBytes;
  353. lm_password: TIdBytes;
  354. nt_password: TIdBytes;
  355. lDomain: TIdBytes;
  356. lHost: TIdBytes;
  357. lUsername: TIdBytes;
  358. begin
  359. lm_password := IdFIPS.NTLMGetLmChallengeResponse(APassword, ANonce);
  360. nt_password := IdFIPS.NTLMGetNtChallengeResponse(APassword, ANonce);
  361. lDomain := BuildUnicode(UpperCase(ADomain));
  362. lHost := BuildUnicode(UpperCase(AHost));
  363. lUsername := BuildUnicode(AUsername);
  364. {$IFDEF HAS_GENERICS_TArray_Copy}
  365. TArray.Copy<Byte>(cProtocolStr, Type3.protocol, 8);
  366. {$ELSE}
  367. {$IFDEF USE_MARSHALLED_PTRS}
  368. buf := cProtocolStr;
  369. TMarshal.Copy(TBytesPtr(@buf)^, 0, TPtrWrapper.Create(@Type3.protocol[1]), 8);
  370. {$ELSE}
  371. Move(cProtocolStr[1], Type3.protocol[1], 8);
  372. {$ENDIF}
  373. {$ENDIF}
  374. Type3._type := 3;
  375. Type3.lm_resp_len1 := UInt16(Length(lm_password));
  376. Type3.lm_resp_off := $40;
  377. Type3.nt_resp_len1 := UInt16(Length(nt_password));
  378. Type3.nt_resp_off := UInt32(Type3.lm_resp_off + Type3.lm_resp_len1);
  379. Type3.dom_len1 := UInt16(Length(lDomain));
  380. Type3.dom_off := UInt32(Type3.nt_resp_off + Type3.nt_resp_len1);
  381. Type3.user_len1 := UInt16(Length(lUsername));
  382. Type3.user_off := UInt32(Type3.dom_off + Type3.dom_len1);
  383. Type3.host_len1 := UInt16(Length(lHost));
  384. Type3.host_off := UInt32(Type3.user_off + Type3.user_len1);
  385. Type3.key_len1 := 0;
  386. Type3.key_off := UInt32(Type3.user_len1 + Type3.host_len1);
  387. Type3.flags := MSG3_FLAGS;
  388. Type3._type := HostToLittleEndian(Type3._type);
  389. Type3.lm_resp_len1 := HostToLittleEndian(Type3.lm_resp_len1);
  390. Type3.lm_resp_len2 := Type3.lm_resp_len1;
  391. Type3.lm_resp_off := HostToLittleEndian(Type3.lm_resp_off);
  392. Type3.nt_resp_len1 := HostToLittleEndian(Type3.nt_resp_len1);
  393. Type3.nt_resp_len2 := Type3.nt_resp_len1;
  394. Type3.nt_resp_off := HostToLittleEndian(Type3.nt_resp_off);
  395. Type3.dom_len1 := HostToLittleEndian(Type3.dom_len1);
  396. Type3.dom_len2 := Type3.dom_len1;
  397. Type3.dom_off := HostToLittleEndian(Type3.dom_off);
  398. Type3.user_len1 := HostToLittleEndian(Type3.user_len1);
  399. Type3.user_len2 := Type3.user_len1;
  400. Type3.user_off := HostToLittleEndian(Type3.user_off);
  401. Type3.host_len1 := HostToLittleEndian(Type3.host_len1);
  402. Type3.host_len2 := Type3.host_len1;
  403. Type3.host_off := HostToLittleEndian(Type3.host_off);
  404. Type3.key_len1 := HostToLittleEndian(Type3.key_len1);
  405. Type3.key_len2 := Type3.key_len1;
  406. Type3.key_off := HostToLittleEndian(Type3.key_off);
  407. Type3.flags := HostToLittleEndian(Type3.flags);
  408. buf := RawToBytes(Type3, SizeOf(Type3));
  409. AppendBytes(buf, lm_password);
  410. AppendBytes(buf, nt_password);
  411. AppendBytes(buf, lDomain);
  412. AppendBytes(buf, lUsername);
  413. AppendBytes(buf, lHost);
  414. Result := TIdEncoderMIME.EncodeBytes(buf);
  415. end;
  416. {$ELSE}
  417. procedure BytesToCharArray(const ABytes : TIdBytes; var VArray : Array of Char; const AIndex : Integer = 0);
  418. var
  419. i, ll, lh : Integer;
  420. begin
  421. ll := Low(VArray);
  422. lh := High(Varray);
  423. for i := ll to lh do begin
  424. VArray[i] := Char(ABytes[ (i - ll)+ AIndex]);
  425. end;
  426. end;
  427. procedure BytesToByteArray(const ABytes : TIdBytes; var VArray : Array of Byte; const AIndex : Integer = 0);
  428. var
  429. i, ll, lh : Integer;
  430. begin
  431. ll := Low(VArray);
  432. lh := High(Varray);
  433. for i := ll to lh do begin
  434. VArray[i] := ABytes[ (i - ll)+ AIndex];
  435. end;
  436. end;
  437. procedure ByteArrayToBytes(const VArray : array of Byte; const ABytes : TIdBytes; const AIndex : Integer = 0);
  438. var
  439. i, ll, lh : Integer;
  440. begin
  441. ll := Low(VArray);
  442. lh := High(Varray);
  443. for i := ll to lh do begin
  444. ABytes[ (i - ll)+ AIndex] := VArray[i];
  445. end;
  446. end;
  447. function ntlm_base.GetBytesLen: UInt32;
  448. begin
  449. Result := 8;
  450. end;
  451. procedure ntlm_base.ReadStruct(const ABytes : TIdBytes; var VIndex : UInt32);
  452. var
  453. i : Integer;
  454. begin
  455. inherited ReadStruct(ABytes,VIndex);
  456. for i := 1 to Length(fprotocol) do
  457. begin
  458. fprotocol[i] := Char(ABytes[i+VIndex]);
  459. end;
  460. Inc(VIndex, Length(fprotocol));
  461. end;
  462. procedure ntlm_base.WriteStruct(var VBytes : TIdBytes; var VIndex : UInt32);
  463. var
  464. LLen : Integer;
  465. LBytes : TIdBytes;
  466. begin
  467. inherited WriteStruct(VBytes,VIndex);
  468. LBytes := System.Text.ASCIIEncoding.GetBytes(fprotocol);
  469. LLen := Length(fprotocol);
  470. CopyTIdBytes(LBytes, VIndex, VBytes, VIndex, LLen);
  471. Inc(VIndex, LLen);
  472. end;
  473. function type_1_message_header.GetBytesLen: UInt32;
  474. begin
  475. Result := inherited GetByesLen() + 24;
  476. end;
  477. procedure type_1_message_header.ReadStruct(const ABytes : TIdBytes; var VIndex : UInt32);
  478. begin
  479. inherited ReadStruct(ABytes, VIndex);
  480. f_type := ABytes[VIndex];
  481. Inc(VIndex);
  482. BytesToByteArray(ABytes, fpad, VIndex);
  483. Inc(VIndex, Length(fpad));
  484. fflags := BytesToUInt16(ABytes, VIndex);
  485. Inc(VIndex, 2);
  486. BytesToByteArray(ABytes, fpad2, VIndex);
  487. Inc(VIndex, Length(fpad2));
  488. fdom_len1 := BytesToUInt16(ABytes, VIndex);
  489. Inc(VIndex, 2);
  490. fdom_len2 := BytesToUInt16(ABytes, VIndex);
  491. Inc(VIndex, 2);
  492. fdom_off := BytesToUInt32(ABytes, VIndex);
  493. Inc(VIndex, 4);
  494. fhost_len1 := BytesToUInt16(ABytes, VIndex);
  495. Inc(VIndex, 2);
  496. fhost_len2 := BytesToUInt16(ABytes, VIndex);
  497. Inc(VIndex, 2);
  498. fhost_off := BytesToUInt32(ABytes, VIndex);
  499. Inc(VIndex, 4);
  500. end;
  501. procedure type_1_message_header.WriteStruct(var VBytes : TIdBytes; var VIndex : UInt32);
  502. begin
  503. inherited WriteStruct(VBytes, VIndex);
  504. VBytes[VIndex] := f_type;
  505. Inc(VIndex);
  506. ByteArrayToBytes(fpad, VBytes, VIndex);
  507. Inc(VIndex, Length(fpad));
  508. CopyTIdUInt16(fflags, VBytes, VIndex);
  509. Inc(VIndex, 2);
  510. ByteArrayToBytes(fpad2, VBytes, VIndex);
  511. Inc(VIndex, Length(fpad2));
  512. CopyTIdUInt16(fdom_len1, VBytes, VIndex);
  513. Inc(VIndex, 2);
  514. CopyTIdUInt16(fdom_len2, VBytes, VIndex);
  515. Inc(VIndex, 2);
  516. CopyTIdUInt32(fdom_off, VBytes, VIndex);
  517. Inc(VIndex, 4);
  518. CopyTIdUInt16(fhost_len1, VBytes, VIndex);
  519. Inc(VIndex, 2);
  520. CopyTIdUInt16(fhost_len2, VBytes, VIndex);
  521. Inc(VIndex, 2);
  522. CopyTIdUInt32(fhost_off, VBytes, VIndex);
  523. Inc(VIndex, 4);
  524. end;
  525. function type_2_message_header.GetBytesLen: UInt32;
  526. begin
  527. Result := inherited GetBytesLen() + 40;
  528. end;
  529. procedure type_2_message_header.ReadStruct(const ABytes : TIdBytes; var VIndex : UInt32);
  530. begin
  531. inherited ReadStruct(ABytes, VIndex);
  532. f_type := ABytes[VIndex];
  533. Inc(VIndex);
  534. BytesToByteArray(ABytes, fpad, VIndex);
  535. Inc(VIndex, Length(fpad));
  536. fhost_len1 := BytesToUInt16(ABytes, VIndex);
  537. Inc(VIndex, 2);
  538. fhost_len2 := BytesToUInt16(ABytes, VIndex);
  539. Inc(VIndex, 2);
  540. fhost_off := BytesToUInt32(ABytes, VIndex);
  541. Inc(VIndex, 4);
  542. fflags := BytesToUInt16(ABytes, VIndex);
  543. Inc(VIndex, 2);
  544. BytesToByteArray(ABytes, fPad2, VIndex);
  545. Inc(VIndex, Length(fpad2));
  546. BytesToByteArray(ABytes, fnonce, VIndex);
  547. Inc(VIndex, Length(fnonce));
  548. BytesToByteArray(ABytes, freserved, VIndex);
  549. Inc(VIndex, Length(freserved));
  550. finfo_len1 := BytesToUInt16(ABytes, VIndex);
  551. Inc(VIndex, 2);
  552. finfo_len2 := BytesToUInt16(ABytes, VIndex);
  553. Inc(VIndex, 2);
  554. finfo_off := BytesToUInt32(ABytes, VIndex);
  555. Inc(VIndex, 4);
  556. end;
  557. procedure type_2_message_header.WriteStruct(var VBytes : TIdBytes; var VIndex : UInt32);
  558. begin
  559. inherited WriteStruct(VBytes, VIndex);
  560. VBytes[VIndex] := f_type;
  561. Inc(VIndex);
  562. ByteArrayToBytes(fPad, VBytes, VIndex);
  563. Inc(VIndex, Length(fpad));
  564. CopyTIdUInt16(fhost_len1, VBytes, VIndex);
  565. Inc(VIndex, 2);
  566. CopyTIdUInt16(fhost_len2, VBytes, VIndex);
  567. Inc(VIndex, 2);
  568. CopyTIdUInt32(fhost_off, VBytes, VIndex);
  569. Inc(VIndex, 4);
  570. CopyTIdUInt16(fflags, VBytes, VIndex);
  571. Inc(VIndex, 2);
  572. ByteArrayToBytes(fPad2, VBytes, VIndex);
  573. Inc(VIndex, Length(fPad2));
  574. ByteArrayToBytes(fnonce, VBytes, VIndex);
  575. Inc(VIndex, Length(fnonce));
  576. ByteArrayToBytes(freserved, VBytes, VIndex);
  577. Inc(VIndex, Length(freserved));
  578. CopyTIdUInt16(finfo_len1, VBytes, VIndex);
  579. Inc(VIndex, 2);
  580. CopyTIdUInt16(finfo_len2, VBytes, VIndex);
  581. Inc(VIndex, 2);
  582. CopyTIdUInt32(finfo_off, VBytes, VIndex);
  583. Inc(VIndex, 4);
  584. end;
  585. function type_3_message_header.GetBytesLen: UInt32;
  586. begin
  587. Result := inherited GetByteLen() + ? ;
  588. end;
  589. procedure type_3_message_header.ReadStruct(const ABytes : TIdBytes; var VIndex : UInt32);
  590. begin
  591. {
  592. _type: UInt32; // 0x03
  593. lm_resp_len1: UInt16; // LanManager response length (always 0x18)
  594. lm_resp_len2: UInt16; // LanManager response length (always 0x18)
  595. lm_resp_off: UInt32; // LanManager response offset
  596. nt_resp_len1: UInt16; // NT response length (always 0x18)
  597. nt_resp_len2: UInt16; // NT response length (always 0x18)
  598. nt_resp_off: UInt32; // NT response offset
  599. dom_len1: UInt16; // domain string length
  600. dom_len2: UInt16; // domain string length
  601. dom_off: UInt32; // domain string offset (always 0x40)
  602. user_len1: UInt16; // username string length
  603. user_len2: UInt16; // username string length
  604. user_off: UInt32; // username string offset
  605. host_len1: UInt16; // host string length
  606. host_len2: UInt16; // host string length
  607. host_off: UInt32; // host string offset
  608. zero: UInt32;
  609. msg_len: UInt32; // message length
  610. flags: UInt32; // 0xA0808205
  611. }
  612. end;
  613. procedure type_3_message_header.WriteStruct(var VBytes : TIdBytes; var VIndex : UInt32);
  614. begin
  615. {
  616. _type: UInt32; // 0x03
  617. lm_resp_len1: UInt16; // LanManager response length (always 0x18)
  618. lm_resp_len2: UInt16; // LanManager response length (always 0x18)
  619. lm_resp_off: UInt32; // LanManager response offset
  620. nt_resp_len1: UInt16; // NT response length (always 0x18)
  621. nt_resp_len2: UInt16; // NT response length (always 0x18)
  622. nt_resp_off: UInt32; // NT response offset
  623. dom_len1: UInt16; // domain string length
  624. dom_len2: UInt16; // domain string length
  625. dom_off: UInt32; // domain string offset (always 0x40)
  626. user_len1: UInt16; // username string length
  627. user_len2: UInt16; // username string length
  628. user_off: UInt32; // username string offset
  629. host_len1: UInt16; // host string length
  630. host_len2: UInt16; // host string length
  631. host_off: UInt32; // host string offset
  632. zero: UInt32;
  633. msg_len: UInt32; // message length
  634. flags: UInt32; // 0xA0808205
  635. }
  636. end;
  637. {$ENDIF}
  638. end.