IdAuthenticationDigest.pas 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. { $HDR$}
  2. {**********************************************************************}
  3. { Unit archived using Team Coherence }
  4. { Team Coherence is Copyright 2002 by Quality Software Components }
  5. { }
  6. { For further information / comments, visit our WEB site at }
  7. { http://www.TeamCoherence.com }
  8. {**********************************************************************}
  9. {}
  10. { $Log: 10073: IdAuthenticationDigest.pas
  11. {
  12. { Rev 1.0 2002.11.12 10:30:44 PM czhower
  13. }
  14. {
  15. Implementation of the digest authentication as specified in
  16. RFC2617
  17. (See NOTE below for details of what is exactly implemented)
  18. Author: Doychin Bondzhev ([email protected])
  19. Copyright: (c) Chad Z. Hower and The Winshoes Working Group.
  20. NOTE:
  21. This is compleatly untested authtentication. Use it on your own risk.
  22. I'm sure it won't work from the first time like all normal programs wich
  23. have never been tested in real life ;-))))
  24. I'm still looking for web server that I could use to make these tests.
  25. If you have or know such server and wish to help me in this, just send
  26. me an e-mail with account informationa (login and password) and the server URL.<G>
  27. Doychin Bondzhev ([email protected])
  28. }
  29. unit IdAuthenticationDigest;
  30. interface
  31. Uses
  32. Classes,
  33. SysUtils,
  34. IdException,
  35. IdGlobal,
  36. IdAuthentication,
  37. IdHashMessageDigest,
  38. IdHeaderList;
  39. Type
  40. EIdInvalidAlgorithm = class(EIdException);
  41. TIdDigestAuthentication = class(TIDAuthentication)
  42. protected
  43. FRealm: String;
  44. FStale: Boolean;
  45. FOpaque: String;
  46. FDomain: TStringList;
  47. Fnonce: String;
  48. FAlgorithm: String;
  49. FQopOptions: TStringList;
  50. FOther: TStringList;
  51. function DoNext: TIdAuthWhatsNext; override;
  52. public
  53. destructor Destroy; override;
  54. function Authentication: String; override;
  55. end;
  56. implementation
  57. uses
  58. IdHash, IdResourceStrings;
  59. { TIdDigestAuthentication }
  60. destructor TIdDigestAuthentication.Destroy;
  61. begin
  62. if Assigned(FDomain) then
  63. FDomain.Free;
  64. if Assigned(FQopOptions) then
  65. FQopOptions.Free;
  66. inherited Destroy;
  67. end;
  68. function TIdDigestAuthentication.Authentication: String;
  69. function ResultString(s: String): String;
  70. Var
  71. MDValue: T4x4LongWordRecord;
  72. PC: PChar;
  73. i: Integer;
  74. S1: String;
  75. begin
  76. with TIdHashMessageDigest5.Create do begin
  77. MDValue := HashValue(S);
  78. Free;
  79. end;
  80. PC := PChar(@MDValue[0]);
  81. for i := 0 to 15 do begin
  82. S1 := S1 + Format('%02x', [Byte(PC[i])]);
  83. end;
  84. while Pos(' ', S1) > 0 do S1[Pos(' ', S1)] := '0';
  85. result := S1;
  86. end;
  87. begin
  88. result := 'Digest ' + {do not localize}
  89. 'username="' + Username + '" ' + {do not localize}
  90. 'realm="' + FRealm + '" ' + {do not localize}
  91. 'result="' + ResultString('') + '"';
  92. end;
  93. function TIdDigestAuthentication.DoNext: TIdAuthWhatsNext;
  94. Var
  95. S: String;
  96. Params: TStringList;
  97. begin
  98. result := wnAskTheProgram;
  99. case FCurrentStep of
  100. 0: begin
  101. if not Assigned(FDomain) then begin
  102. FDomain := TStringList.Create;
  103. end
  104. else FDomain.Clear;
  105. if not Assigned(FQopOptions) then begin
  106. FQopOptions := TStringList.Create;
  107. end
  108. else
  109. FQopOptions.Clear;
  110. S := ReadAuthInfo('Digest');
  111. Fetch(S);
  112. Params := TStringList.Create;
  113. while Length(S) > 0 do begin
  114. Params.Add(Fetch(S, ', '));
  115. end;
  116. FRealm := Copy(Params.Values['realm'], 2, Length(Params.Values['realm']) - 2);
  117. Fnonce := Copy(Params.Values['nonce'], 2, Length(Params.Values['nonce']) - 2);
  118. S := Copy(Params.Values['domain'], 2, Length(Params.Values['domain']) - 2);
  119. while Length(S) > 0 do
  120. FDomain.Add(Fetch(S));
  121. Fopaque := Copy(Params.Values['opaque'], 2, Length(Params.Values['opaque']) - 2);
  122. FStale := (Copy(Params.Values['stale'], 2, Length(Params.Values['stale']) - 2) = 'true');
  123. FAlgorithm := Params.Values['algorithm'];
  124. FQopOptions.CommaText := Copy(Params.Values['qop'], 2, Length(Params.Values['qop']) - 2);
  125. if not AnsiSameText(FAlgorithm, 'MD5') then begin
  126. raise EIdInvalidAlgorithm.Create(RSHTTPAuthInvalidHash);
  127. end;
  128. Params.Free;
  129. result := wnAskTheProgram;
  130. FCurrentStep := 1;
  131. end;
  132. 1: begin
  133. result := wnDoRequest;
  134. FCurrentStep := 0;
  135. end;
  136. end;
  137. end;
  138. initialization
  139. // This comment will be removed when the Digest authentication is ready
  140. // RegisterAuthenticationMethod('Digest', TIdDigestAuthentication);
  141. end.