| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389 |
- {
- $Project$
- $Workfile$
- $Revision$
- $DateUTC$
- $Id$
- This file is part of the Indy (Internet Direct) project, and is offered
- under the dual-licensing agreement described on the Indy website.
- (http://www.indyproject.org/)
- Copyright:
- (c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
- }
- {
- $Log$
- }
- {
- Rev 1.0 27-03-05 10:04:20 MterWoord
- Second import, first time the filenames weren't prefixed with Id
- Rev 1.0 27-03-05 09:08:54 MterWoord
- Created
- }
- unit IdServerIOHandlerTls;
- interface
- uses
- IdSSL, IdTlsServerOptions, Mono.Security.Protocol.Tls, IdCarrierStream,
- IdSocketStream, System.IO, System.Security.Cryptography, IdGlobal, IdYarn,
- System.Security.Cryptography.X509Certificates, Mono.Security.Authenticode,
- IdIOHandler, IdSocketHandle, IdThread;
- type
- TIdServerIOHandlerTls = class(TIdServerIOHandlerSSLBase)
- protected
- FOptions: TIdTlsServerOptions;
- function NewServerSideIOHandlerTls: TIdSSLIOHandlerSocketBase;
- procedure InitComponent; override;
- public
- function MakeFTPSvrPasv: TIdSSLIOHandlerSocketBase; override;
- function MakeFTPSvrPort: TIdSSLIOHandlerSocketBase; override;
- function MakeClientIOHandler(AYarn: TIdYarn) : TIdIOHandler; override;
- function MakeClientIOHandler: TIdSSLIOHandlerSocketBase; override;
- function Accept(ASocket: TIdSocketHandle; AListenerThread: TIdThread; AYarn: TIdYarn): TIdIOHandler; override;
- published
- property Options: TIdTlsServerOptions read FOptions write FOptions;
- end;
- implementation
- type
- TIdServerSideIOHandlerTls = class(TIdSSLIOHandlerSocketBase)
- protected
- FOptions: TIdTlsServerOptions;
- FTlsServerStream: SslServerStream;
- FTlsClientStream: SslClientStream;
- FCarrierStream: TIdCarrierStream;
- FSocketStream: TIdSocketStream;
- FActiveStream: Stream;
- FPassThrough: Boolean;
- function PrivateKeySelection(certificate: X509Certificate; TargetHost: string): AsymmetricAlgorithm;
- function ReadFromSource(ARaiseExceptionIfDisconnected: Boolean; ATimeout: Integer; ARaiseExceptionOnTimeOut: Boolean): Integer; override;
- procedure SetPassThrough(const AValue: Boolean); override;
- public
- procedure CheckForDataOnSource(ATimeOut: Integer); override;
- procedure StartSSL; override;
- procedure AfterAccept; override;
- procedure CheckForDisconnect(ARaiseExceptionIfDisconnected: Boolean; AIgnoreBuffer: Boolean); override;
- function Clone: TIdSSLIOHandlerSocketBase; override;
- procedure WriteDirect(var ABuffer: TIdBytes); override;
- procedure Close; override;
- published
- property Options: TIdTlsServerOptions read FOptions write FOptions;
- end;
- { TServerSideIOHandlerTls }
- function TIdServerSideIOHandlerTls.Clone: TIdSSLIOHandlerSocketBase;
- var
- TempResult : TIdServerSideIOHandlerTls;
- begin
- TempResult := TIdServerSideIOHandlerTls.Create;
- TempResult.Options.ClientNeedsCertificate := Options.ClientNeedsCertificate;
- TempResult.Options.PrivateKey := Options.PrivateKey;
- TempResult.Options.Protocol := Options.Protocol;
- TempResult.Options.PublicCertificate := Options.PublicCertificate;
- TempResult.IsPeer := IsPeer;
- TempResult.PassThrough := PassThrough;
- Result := TempResult;
- end;
- procedure TIdServerSideIOHandlerTls.StartSSL;
- begin
- inherited;
- PassThrough := False;
- end;
- function TIdServerSideIOHandlerTls.PrivateKeySelection(
- certificate: X509Certificate; TargetHost: string): AsymmetricAlgorithm;
- begin
- Result := FOptions.PrivateKey.RSA;
- end;
- function TIdServerSideIOHandlerTls.ReadFromSource(
- ARaiseExceptionIfDisconnected: Boolean; ATimeout: Integer;
- ARaiseExceptionOnTimeOut: Boolean): Integer;
- var
- TempBuff: array of byte;
- TotalBytesRead: Integer;
- StartTime: Cardinal;
- BytesRead: Integer;
- TempBytes: array of byte;
- begin
- Result := 0;
- if FInputBuffer = nil then
- Exit;
- if FActiveStream <> nil then
- begin
- SetLength(TempBuff, 512);
- TotalBytesRead := 0;
- StartTime := Ticks;
- repeat
- BytesRead := FActiveStream.Read(TempBuff, 0, 512);
- if BytesRead <> 0 then
- begin
- TempBytes := ToBytes(TempBuff, BytesRead);
- FInputBuffer.Write(TempBytes);
- TotalBytesRead := TotalBytesRead + BytesRead;
- end;
- if BytesRead <> 512 then
- begin
- Result := TotalBytesRead;
- Exit;
- end;
- IndySleep(2);
- until ( (Abs(GetTickDiff(StartTime, Ticks)) > ATimeOut)
- and (not ((ATimeOut = IdTimeoutDefault) or (ATimeOut = IdTimeoutInfinite)))
- );
- Result := TotalBytesRead;
- end;
- end;
- procedure TIdServerSideIOHandlerTls.CheckForDisconnect(
- ARaiseExceptionIfDisconnected, AIgnoreBuffer: Boolean);
- begin
- try
- if FActiveStream = nil then
- begin
- if AIgnoreBuffer then
- begin
- CloseGracefully;
- end
- else
- begin
- if FInputBuffer.Size = 0 then
- begin
- CloseGracefully;
- end;
- end;
- end
- else
- begin
- if ( (not FActiveStream.CanRead)
- or (not FActiveStream.CanWrite)
- ) then
- begin
- if AIgnoreBuffer then
- begin
- CloseGracefully;
- end
- else
- begin
- if FInputBuffer.Size = 0 then
- begin
- CloseGracefully;
- end;
- end;
- end;
- end;
- except
- on E: Exception do
- begin
- CloseGracefully;
- end;
- end;
- if ( (ARaiseExceptionIfDisconnected)
- and (ClosedGracefully)
- ) then
- RaiseConnClosedGracefully;
- end;
- procedure TIdServerSideIOHandlerTls.CheckForDataOnSource(ATimeOut: Integer);
- begin
- if Connected then
- begin
- ReadFromSource(false, ATimeOut, false);
- end;
- end;
- procedure TIdServerSideIOHandlerTls.AfterAccept;
- begin
- inherited;
- FSocketStream := TIdSocketStream.Create(Binding.Handle);
- FCarrierStream := TIdCarrierStream.Create(FSocketStream);
- FTlsServerStream := SslServerStream.Create(FCarrierStream, FOptions.PublicCertificate, FOptions.ClientNeedsCertificate, true, FOptions.Protocol);
- GC.SuppressFinalize(FSocketStream);
- GC.SuppressFinalize(FCarrierStream);
- GC.SuppressFinalize(FTlsServerStream);
- FActiveStream := FCarrierStream;
- FTlsServerStream.PrivateKeyCertSelectionDelegate := PrivateKeySelection;
- IsPeer := true;
- PassThrough := true;
- end;
- procedure TIdServerSideIOHandlerTls.Close;
- begin
- if not PassThrough then
- begin
- if IsPeer then
- begin
- if FTlsServerStream <> nil then
- begin
- FTlsServerStream.Close;
- FTlsServerStream := nil;
- end;
- end
- else
- begin
- if FTlsClientStream <> nil then
- begin
- FTlsClientStream.Close;
- FTlsClientStream := nil;
- end;
- end;
- end;
- if FCarrierStream <> nil then
- begin
- FCarrierStream.Close;
- FCarrierStream := nil;
- end;
- if FSocketStream <> nil then
- begin
- FSocketStream.Close;
- FSocketStream := nil;
- end;
- inherited;
- end;
- procedure TIdServerSideIOHandlerTls.WriteDirect(var ABuffer: TIdBytes);
- begin
- if Intercept <> nil then
- Intercept.Send(ABuffer);
- if FActiveStream <> nil then
- begin
- FActiveStream.Write(ABuffer, 0, Length(ABuffer));
- FActiveStream.Flush;
- end
- else
- raise Exception.Create('No active stream!');
- end;
- procedure TIdServerSideIOHandlerTls.SetPassThrough(const AValue: Boolean);
- var
- TempBuff: array[0..0] of byte;
- begin
- inherited;
- if AValue then
- begin
- if FActiveStream <> nil then
- begin
- FActiveStream.Close;
- FActiveStream := nil;
- end;
- FActiveStream := FSocketStream;
- if IsPeer then
- begin
- if FTlsServerStream <> nil then
- begin
- FTlsServerStream.Close;
- FTlsServerStream := nil;
- end;
- FTlsServerStream := SslServerStream.Create(FCarrierStream, FOptions.PublicCertificate, FOptions.ClientNeedsCertificate, true, FOptions.Protocol);
- GC.SuppressFinalize(FTlsServerStream);
- FTlsServerStream.PrivateKeyCertSelectionDelegate := PrivateKeySelection;
- end
- else
- begin
- if FTlsClientStream <> nil then
- begin
- FTlsClientStream.Close;
- FTlsClientStream := nil;
- end;
- FTlsClientStream := SslClientStream.Create(FCarrierStream, Destination, true, FOptions.Protocol);
- GC.SuppressFinalize(FTlsClientStream);
- end;
- end
- else
- begin
- if IsPeer then
- begin
- FActiveStream := FTlsServerStream;
- end
- else
- begin
- FActiveStream := FTlsClientStream;
- end;
- FActiveStream.Read(TempBuff, 0, 0);
- end;
- end;
- { TServerIOHandlerTls }
- procedure TIdServerIOHandlerTls.InitComponent;
- begin
- inherited;
- FOptions := TIdTlsServerOptions.Create;
- end;
- function TIdServerIOHandlerTls.NewServerSideIOHandlerTls: TIdSSLIOHandlerSocketBase;
- var
- TempResult: TIdServerSideIOHandlerTls;
- begin
- TempResult := TIdServerSideIOHandlerTls.Create;
- TempResult.Options := FOptions;
- Result := TempResult;
- end;
- function TIdServerIOHandlerTls.MakeClientIOHandler: TIdSSLIOHandlerSocketBase;
- begin
- Result := NewServerSideIOHandlerTls;
- end;
- function TIdServerIOHandlerTls.MakeClientIOHandler(AYarn: TIdYarn): TIdIOHandler;
- begin
- Result := NewServerSideIOHandlerTls;
- end;
- function TIdServerIOHandlerTls.MakeFTPSvrPort: TIdSSLIOHandlerSocketBase;
- begin
- Result := NewServerSideIOHandlerTls;
- end;
- function TIdServerIOHandlerTls.Accept(ASocket: TIdSocketHandle;
- AListenerThread: TIdThread; AYarn: TIdYarn): TIdIOHandler;
- var
- LIOHandler: TIdServerSideIOHandlerTls;
- begin
- LIOHandler := TIdServerSideIOHandlerTls.Create;
- LIOHandler.Options := FOptions;
- LIOHandler.Open;
- while not AListenerThread.Stopped do
- begin
- try
- if ASocket.Select(250) then
- begin
- if LIOHandler.Binding.Accept(ASocket.Handle) then
- begin
- LIOHandler.AfterAccept;
- Result := LIOHandler;
- Exit;
- end
- else
- begin
- LIOHandler.Close;
- Result := nil;
- Exit;
- end;
- end;
- finally
- if AListenerThread.Stopped then
- begin
- LIOHandler.Close;
- end;
- end;
- end;
- Result := nil;
- end;
- function TIdServerIOHandlerTls.MakeFTPSvrPasv: TIdSSLIOHandlerSocketBase;
- begin
- Result := NewServerSideIOHandlerTls;
- end;
- end.
|