IdIOHandlerTls.pas 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  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.0 27-03-05 10:04:18 MterWoord
  18. Second import, first time the filenames weren't prefixed with Id
  19. Rev 1.0 27-03-05 09:08:50 MterWoord
  20. Created
  21. }
  22. unit IdIOHandlerTls;
  23. interface
  24. uses
  25. System.Collections, System.ComponentModel, System.IO, System.Net.Sockets,
  26. System.Security.Cryptography.X509Certificates, Mono.Security.Protocol.Tls,
  27. IdSSL, IdCarrierStream, IdSocketStream, IdGlobal, IdTlsClientOptions;
  28. {$AUTOBOX ON}
  29. {$HINTS OFF}
  30. {$WARNINGS OFF}
  31. type
  32. TArrayOfInteger = array of Int32;
  33. TIdIOHandlerTls = class(TIdSSLIOHandlerSocketBase)
  34. protected
  35. FOptions: TIdTlsClientOptions;
  36. FTlsStream: SslClientStream;
  37. FCarrierStream: TIdCarrierStream;
  38. FSocketStream: TIdSocketStream;
  39. FActiveStream: Stream;
  40. FOnValidateCertificate: CertificateValidationCallback;
  41. procedure InitComponent; override;
  42. function RecvEnc(var ABuffer: TIdBytes): Integer; override;
  43. function SendEnc(const ABuffer: TIdBytes; const AOffset, ALength: Integer): Integer; override;
  44. procedure SetPassThrough(const AValue: Boolean); override;
  45. procedure SetOnValidateCertificate(const Value: CertificateValidationCallback);
  46. procedure SetOptions(const Value: TIdTlsClientOptions);
  47. public
  48. procedure Open; override;
  49. procedure Close; override;
  50. procedure CheckForDisconnect(ARaiseExceptionIfDisconnected: Boolean = True;
  51. AIgnoreBuffer: Boolean = False); override;
  52. procedure StartSSL; override;
  53. function Clone : TIdSSLIOHandlerSocketBase; override;
  54. function Connected: Boolean; override;
  55. published
  56. property Options: TIdTlsClientOptions read FOptions write SetOptions;
  57. property OnValidateCertificate: CertificateValidationCallback read FOnValidateCertificate write SetOnValidateCertificate;
  58. end;
  59. implementation
  60. uses IdIOHandler;
  61. { TIOHandlerTls }
  62. procedure TIdIOHandlerTls.SetOnValidateCertificate(
  63. const Value: CertificateValidationCallback);
  64. begin
  65. FOnValidateCertificate := Value;
  66. if FTlsStream <> nil then
  67. begin
  68. FTlsStream.ServerCertValidationDelegate := Value;
  69. end;
  70. end;
  71. procedure TIdIOHandlerTls.SetOptions(const Value: TIdTlsClientOptions);
  72. begin
  73. FOptions := Value;
  74. end;
  75. function TIdIOHandlerTls.Connected: Boolean;
  76. begin
  77. Result := ( (Binding <> nil)
  78. and (Binding.Handle <> nil)
  79. and (Binding.Handle.Connected)
  80. and (FSocketStream <> nil)
  81. and (FCarrierStream <> nil)
  82. and ((FTlsStream <> nil) or PassThrough)
  83. );
  84. end;
  85. function TIdIOHandlerTls.Clone: TIdSSLIOHandlerSocketBase;
  86. var
  87. TempResult: TIdIOHandlerTls;
  88. begin
  89. TempResult := TIdIOHandlerTls.Create;
  90. TempResult.Options.CertificateCollection.AddRange(Options.CertificateCollection);
  91. TempResult.Options.Protocol := Options.Protocol;
  92. Result := TempResult;
  93. end;
  94. procedure TIdIOHandlerTls.InitComponent;
  95. begin
  96. inherited;
  97. FOptions := TIdTlsClientOptions.Create;
  98. end;
  99. procedure TIdIOHandlerTls.StartSSL;
  100. begin
  101. inherited;
  102. PassThrough := False;
  103. end;
  104. procedure TIdIOHandlerTls.Open;
  105. begin
  106. inherited;
  107. FSocketStream := TIdSocketStream.Create(Binding.Handle);
  108. FCarrierStream := TIdCarrierStream.Create(FSocketStream);
  109. FActiveStream := FCarrierStream;
  110. GC.SuppressFinalize(FSocketStream);
  111. GC.SuppressFinalize(FCarrierStream);
  112. GC.SuppressFinalize(Binding.Handle);
  113. if not PassThrough then
  114. begin
  115. PassThrough := True;
  116. PassThrough := False;
  117. end;
  118. end;
  119. function TIdIOHandlerTls.RecvEnc(var VBuffer: TIdBytes): Integer;
  120. begin
  121. if FActiveStream <> nil then begin
  122. Result := FActiveStream.Read(VBuffer, 0, Length(VBuffer));
  123. end else begin
  124. Result := 0;
  125. end;
  126. end;
  127. procedure TIdIOHandlerTls.CheckForDisconnect(ARaiseExceptionIfDisconnected: Boolean = True;
  128. AIgnoreBuffer: Boolean = False);
  129. begin
  130. inherited;
  131. try
  132. if FActiveStream = nil then
  133. begin
  134. if AIgnoreBuffer or (FInputBuffer.Size = 0) then begin
  135. CloseGracefully;
  136. end;
  137. end
  138. else if (not FActiveStream.CanRead) or (not FActiveStream.CanWrite) then
  139. begin
  140. if AIgnoreBuffer or (FInputBuffer.Size = 0) then begin
  141. CloseGracefully;
  142. end;
  143. end;
  144. except
  145. on E: Exception do begin
  146. CloseGracefully;
  147. end;
  148. end;
  149. if ARaiseExceptionIfDisconnected and ClosedGracefully then begin
  150. RaiseConnClosedGracefully;
  151. end;
  152. end;
  153. procedure TIdIOHandlerTls.Close;
  154. begin
  155. if not PassThrough then
  156. begin
  157. FTlsStream.Close;
  158. FTlsStream := nil;
  159. end;
  160. FCarrierStream.Close;
  161. FCarrierStream := nil;
  162. FSocketStream.Close;
  163. FSocketStream := nil;
  164. inherited;
  165. end;
  166. function TIdIOHandlerTls.SendEnc(const ABuffer: TIdBytes; const AOffset, ALength: Integer): Integer;
  167. begin
  168. if FActiveStream <> nil then
  169. begin
  170. FActiveStream.Write(ABuffer, AOffset, ALength);
  171. FActiveStream.Flush;
  172. Result := ALength;
  173. end else begin
  174. Result := 0;
  175. end;
  176. end;
  177. procedure TIdIOHandlerTls.SetPassThrough(const AValue: Boolean);
  178. var
  179. TempBuff: array[0..0] of byte;
  180. begin
  181. if PassThrough <> AValue then
  182. begin
  183. inherited;
  184. if FCarrierStream = nil then begin
  185. Exit;
  186. end;
  187. if AValue then
  188. begin
  189. FActiveStream := FSocketStream;
  190. if FTlsStream <> nil then
  191. begin
  192. FTlsStream.Close;
  193. FTlsStream := nil;
  194. end;
  195. end else
  196. begin
  197. FTlsStream := SslClientStream.Create(FCarrierStream, URIToCheck, True, FOptions.Protocol, FOptions.CertificateCollection);
  198. FTlsStream.ServerCertValidationDelegate := FOnValidateCertificate;
  199. GC.SuppressFinalize(FTlsStream);
  200. FActiveStream := FTlsStream;
  201. //FTlsStream.Read(TempBuff, 0, 0);
  202. end;
  203. end;
  204. end;
  205. end.