restemplate/indy/Protocols/IdTelnetServer.pas

232 lines
6.4 KiB
Plaintext

{
$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.13 12/2/2004 4:24:00 PM JPMugaas
Adjusted for changes in Core.
Rev 1.12 2004.02.03 5:44:32 PM czhower
Name changes
Rev 1.11 2004.01.22 2:33:58 PM czhower
Matched visibility of DoConnect
Rev 1.10 1/21/2004 4:20:52 PM JPMugaas
InitComponent
Rev 1.9 2003.10.21 9:13:16 PM czhower
Now compiles.
Rev 1.8 9/19/2003 04:27:02 PM JPMugaas
Removed IdFTPServer so Indy can compile with Kudzu's new changes.
Rev 1.7 7/6/2003 7:55:36 PM BGooijen
Removed unused units from the uses
Rev 1.6 2/24/2003 10:32:50 PM JPMugaas
Rev 1.5 1/17/2003 07:11:04 PM JPMugaas
Now compiles under new framework.
Rev 1.4 1/17/2003 04:05:40 PM JPMugaas
Now compiles under new design.
Rev 1.3 1/9/2003 06:09:42 AM JPMugaas
Updated for IdContext API change.
Rev 1.2 1/8/2003 05:53:58 PM JPMugaas
Switched stuff to IdContext.
Rev 1.1 12/7/2002 06:43:36 PM JPMugaas
These should now compile except for Socks server. IPVersion has to be a
property someplace for that.
Rev 1.0 11/13/2002 08:02:56 AM JPMugaas
}
unit IdTelnetServer;
interface
{$i IdCompilerDefines.inc}
uses
Classes,
IdGlobal,
IdBaseComponent,
IdAssignedNumbers, IdContext,
IdCustomTCPServer,
IdTCPConnection, IdYarn;
const
GLoginAttempts = 3;
type
// SG 16/02/2001: Moved the TTelnetData object from TIdPeerThread to custom TIdPeerThread descendant
TTelnetData = class(TObject)
public
Username, Password: String;
HUserToken: UInt32;
end;
// Custom Peer thread class
TIdTelnetServerContext = class(TIdServerContext)
private
FTelnetData: TTelnetData;
public
constructor Create(
AConnection: TIdTCPConnection;
AYarn: TIdYarn;
AList: TIdContextThreadList = nil
); override;
destructor Destroy; override;
Property TelnetData: TTelnetData read FTelnetData;
end; //class
TIdTelnetNegotiateEvent = procedure(AContext: TIdContext) of object;
TAuthenticationEvent = procedure(AContext: TIdContext;
const AUsername, APassword: string; var AAuthenticated: Boolean) of object;
TIdTelnetServer = class(TIdCustomTCPServer)
protected
FLoginAttempts: Integer;
FOnAuthentication: TAuthenticationEvent;
FLoginMessage: string;
FOnNegotiate: TIdTelnetNegotiateEvent;
//
procedure DoConnect(AContext: TIdContext); override;
procedure InitComponent; override;
public
{$IFDEF WORKAROUND_INLINE_CONSTRUCTORS}
constructor Create(AOwner: TComponent); reintroduce; overload;
{$ENDIF}
function DoAuthenticate(AContext: TIdContext; const AUsername, APassword: string)
: boolean; virtual;
procedure DoNegotiate(AContext: TIdContext); virtual;
published
property DefaultPort default IdPORT_TELNET;
property LoginAttempts: Integer read FLoginAttempts write FLoginAttempts Default GLoginAttempts;
property LoginMessage: String read FLoginMessage write FLoginMessage;
property OnAuthentication: TAuthenticationEvent read FOnAuthentication write FOnAuthentication;
property OnNegotiate: TIdTelnetNegotiateEvent read FOnNegotiate write FOnNegotiate;
property OnExecute;
end;
implementation
uses
IdException, IdResourceStringsProtocols, SysUtils;
{$IFDEF WORKAROUND_INLINE_CONSTRUCTORS}
constructor TIdTelnetServer.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
end;
{$ENDIF}
procedure TIdTelnetServer.InitComponent;
begin
inherited InitComponent;
LoginAttempts := GLoginAttempts;
LoginMessage := RSTELNETSRVWelcomeString;
DefaultPort := IdPORT_TELNET;
FContextClass := TIdTelnetServerContext;
end;
function TIdTelnetServer.DoAuthenticate;
begin
if not Assigned(OnAuthentication) then begin
raise EIdException.Create(RSTELNETSRVNoAuthHandler);
end;
Result := False;
OnAuthentication(AContext, AUsername, APassword, result);
end;
procedure TIdTelnetServer.DoConnect(AContext: TIdContext);
Var
Data: TTelnetData;
i: integer;
begin
try
inherited;
Data := (AContext as TIdTelnetServerContext).TelnetData;
// do protocol negotiation first
DoNegotiate(AContext);
// Welcome the user
if Length(LoginMessage) > 0 then
begin
AContext.Connection.IOHandler.WriteLn(LoginMessage);
AContext.Connection.IOHandler.WriteLn; {Do not Localize}
end;
// Only prompt for creditentials if there is an authentication handler
if Assigned(OnAuthentication) then
begin
// ask for username/password.
for i := 1 to LoginAttempts do
begin
// UserName
AContext.Connection.IOHandler.Write(RSTELNETSRVUsernamePrompt);
Data.Username := AContext.Connection.IOHandler.InputLn;
// Password
AContext.Connection.IOHandler.Write(RSTELNETSRVPasswordPrompt);
Data.Password := AContext.Connection.IOHandler.InputLn('*'); {Do not Localize}
AContext.Connection.IOHandler.WriteLn;
// Check authentication
if DoAuthenticate(AContext, Data.Username, Data.Password) then begin
Break; // exit the loop
end;
AContext.Connection.IOHandler.WriteLn(RSTELNETSRVInvalidLogin); // translate
if i = FLoginAttempts then begin
raise EIdException.Create(RSTELNETSRVMaxloginAttempt); // translate
end;
end;
end;
except
on E: Exception do begin
AContext.Connection.IOHandler.WriteLn(E.Message);
AContext.Connection.Disconnect;
end;
end;
end;
procedure TIdTelnetServer.DoNegotiate(AContext: TIdContext);
begin
if Assigned(FOnNegotiate) then begin
FOnNegotiate(AContext);
end;
end;
{ TIdTelnetServerContext }
constructor TIdTelnetServerContext.Create(AConnection: TIdTCPConnection;
AYarn: TIdYarn; AList: TIdContextThreadList = nil);
begin
inherited Create(AConnection, AYarn, AList);
FTelnetData := TTelnetData.Create;
end;
destructor TIdTelnetServerContext.Destroy;
begin
FreeAndNil(FTelnetData);
inherited Destroy;
end;
end.