IdAuthenticationNTLM.pas 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  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.3 2004.02.03 5:44:54 PM czhower
  18. Name changes
  19. Rev 1.2 2/1/2004 3:33:48 AM JPMugaas
  20. Reenabled. Should work in DotNET.
  21. Rev 1.1 2003.10.12 3:36:26 PM czhower
  22. todo item
  23. Rev 1.0 11/14/2002 02:13:44 PM JPMugaas
  24. }
  25. {
  26. Implementation of the NTLM authentication as specified in
  27. http://www.innovation.ch/java/ntlm.html with some fixes
  28. Author: Doychin Bondzhev ([email protected])
  29. Copyright: (c) Chad Z. Hower and The Winshoes Working Group.
  30. S.G. 12/7/2002: Moved the user query one step up: the domain name is required
  31. to properly format the Type 1 message.
  32. }
  33. unit IdAuthenticationNTLM;
  34. interface
  35. {$i IdCompilerDefines.inc}
  36. uses
  37. Classes,
  38. IdAuthentication;
  39. Type
  40. TIdNTLMAuthentication = class(TIdAuthentication)
  41. protected
  42. FNTLMInfo: String;
  43. FHost, FDomain, FUser: String;
  44. function DoNext: TIdAuthWhatsNext; override;
  45. function GetSteps: Integer; override;
  46. procedure SetUserName(const Value: String); override;
  47. public
  48. constructor Create; override;
  49. function Authentication: String; override;
  50. function KeepAlive: Boolean; override;
  51. end;
  52. // RLebeau 4/17/10: this forces C++Builder to link to this unit so
  53. // RegisterAuthenticationMethod can be called correctly at program startup...
  54. {$IFDEF HAS_DIRECTIVE_HPPEMIT_LINKUNIT}
  55. {$HPPEMIT LINKUNIT}
  56. {$ELSE}
  57. {$HPPEMIT '#pragma link "IdAuthenticationNTLM"'}
  58. {$ENDIF}
  59. implementation
  60. uses
  61. IdGlobal,
  62. IdGlobalProtocols,
  63. IdException,
  64. IdCoderMIME,
  65. IdFIPS,
  66. IdNTLM,
  67. SysUtils;
  68. { TIdNTLMAuthentication }
  69. constructor TIdNTLMAuthentication.Create;
  70. begin
  71. inherited Create;
  72. if not LoadNTLMLibrary then begin
  73. // TODO: create a new Exception class for this
  74. // TODO: move this into IdResourceStringsProtocols
  75. raise EIdException.Create('Could not load NTLM library'); {do not localize}
  76. end;
  77. {TODO: add this?
  78. if not IsNTLMFuncsAvail then begin
  79. raise ...;
  80. end;
  81. }
  82. end;
  83. function TIdNTLMAuthentication.DoNext: TIdAuthWhatsNext;
  84. begin
  85. Result := wnDoRequest;
  86. case FCurrentStep of
  87. 0:
  88. begin
  89. if Length(UserName) > 0 then begin
  90. FCurrentStep := 1;
  91. Result := wnDoRequest;
  92. end else begin
  93. Result := wnAskTheProgram;
  94. end;
  95. end;
  96. 1, 2:
  97. begin
  98. Inc(FCurrentStep);
  99. Result := wnDoRequest;
  100. end;
  101. 3:
  102. begin
  103. Reset;
  104. Result := wnFail;
  105. end;
  106. end;
  107. end;
  108. function TIdNTLMAuthentication.Authentication: String;
  109. var
  110. buf: TIdBytes;
  111. Type2: type_2_message_header;
  112. LDecoder: TIdDecoderMIME;
  113. begin
  114. Result := ''; {do not localize}
  115. SetLength(buf, 0);
  116. case FCurrentStep of
  117. 1:
  118. begin
  119. FHost := IndyComputerName;
  120. Result := 'NTLM ' + BuildType1Message(FDomain, FHost); {do not localize}
  121. end;
  122. 2:
  123. begin
  124. if Length(FNTLMInfo) = 0 then
  125. begin
  126. FNTLMInfo := ReadAuthInfo('NTLM'); {do not localize}
  127. Fetch(FNTLMInfo);
  128. end;
  129. if Length(FNTLMInfo) = 0 then
  130. begin
  131. Reset;
  132. Abort;
  133. end;
  134. LDecoder := TIdDecoderMIME.Create;
  135. try
  136. buf := LDecoder.DecodeBytes(FNTLMInfo);
  137. finally
  138. LDecoder.Free;
  139. end;
  140. BytesToRaw(buf, Type2, SizeOf(Type2));
  141. buf := RawToBytes(Type2.Nonce, SizeOf(Type2.Nonce));
  142. Result := 'NTLM ' + BuildType3Message(FDomain, FHost, FUser, Password, buf); {do not localize}
  143. FCurrentStep := 2;
  144. end;
  145. end;
  146. end;
  147. function TIdNTLMAuthentication.KeepAlive: Boolean;
  148. begin
  149. Result := True;
  150. end;
  151. function TIdNTLMAuthentication.GetSteps: Integer;
  152. begin
  153. Result := 3;
  154. end;
  155. procedure TIdNTLMAuthentication.SetUserName(const Value: String);
  156. begin
  157. if Value <> Username then
  158. begin
  159. inherited SetUserName(Value);
  160. GetDomain(Username, FUser, FDomain);
  161. end;
  162. end;
  163. initialization
  164. RegisterAuthenticationMethod('NTLM', TIdNTLMAuthentication); {do not localize}
  165. finalization
  166. UnregisterAuthenticationMethod('NTLM'); {do not localize}
  167. end.