initial commit from lost SVN repo
This commit is contained in:
364
common/synapse/tlntsend.pas
Normal file
364
common/synapse/tlntsend.pas
Normal file
@@ -0,0 +1,364 @@
|
||||
{==============================================================================|
|
||||
| Project : Ararat Synapse | 001.003.001 |
|
||||
|==============================================================================|
|
||||
| Content: TELNET and SSH2 client |
|
||||
|==============================================================================|
|
||||
| Copyright (c)1999-2010, Lukas Gebauer |
|
||||
| All rights reserved. |
|
||||
| |
|
||||
| Redistribution and use in source and binary forms, with or without |
|
||||
| modification, are permitted provided that the following conditions are met: |
|
||||
| |
|
||||
| Redistributions of source code must retain the above copyright notice, this |
|
||||
| list of conditions and the following disclaimer. |
|
||||
| |
|
||||
| Redistributions in binary form must reproduce the above copyright notice, |
|
||||
| this list of conditions and the following disclaimer in the documentation |
|
||||
| and/or other materials provided with the distribution. |
|
||||
| |
|
||||
| Neither the name of Lukas Gebauer nor the names of its contributors may |
|
||||
| be used to endorse or promote products derived from this software without |
|
||||
| specific prior written permission. |
|
||||
| |
|
||||
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
||||
| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
||||
| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
||||
| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
|
||||
| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|
||||
| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
|
||||
| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
|
||||
| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
||||
| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
|
||||
| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
|
||||
| DAMAGE. |
|
||||
|==============================================================================|
|
||||
| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
|
||||
| Portions created by Lukas Gebauer are Copyright (c)2002-2010. |
|
||||
| All Rights Reserved. |
|
||||
|==============================================================================|
|
||||
| Contributor(s): |
|
||||
|==============================================================================|
|
||||
| History: see HISTORY.HTM from distribution package |
|
||||
| (Found at URL: http://www.ararat.cz/synapse/) |
|
||||
|==============================================================================}
|
||||
|
||||
{:@abstract(Telnet script client)
|
||||
|
||||
Used RFC: RFC-854
|
||||
}
|
||||
|
||||
{$IFDEF FPC}
|
||||
{$MODE DELPHI}
|
||||
{$ENDIF}
|
||||
{$H+}
|
||||
|
||||
{$IFDEF UNICODE}
|
||||
{$WARN IMPLICIT_STRING_CAST OFF}
|
||||
{$WARN IMPLICIT_STRING_CAST_LOSS OFF}
|
||||
{$ENDIF}
|
||||
|
||||
unit tlntsend;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
SysUtils, Classes,
|
||||
blcksock, synautil;
|
||||
|
||||
const
|
||||
cTelnetProtocol = '23';
|
||||
cSSHProtocol = '22';
|
||||
|
||||
TLNT_EOR = #239;
|
||||
TLNT_SE = #240;
|
||||
TLNT_NOP = #241;
|
||||
TLNT_DATA_MARK = #242;
|
||||
TLNT_BREAK = #243;
|
||||
TLNT_IP = #244;
|
||||
TLNT_AO = #245;
|
||||
TLNT_AYT = #246;
|
||||
TLNT_EC = #247;
|
||||
TLNT_EL = #248;
|
||||
TLNT_GA = #249;
|
||||
TLNT_SB = #250;
|
||||
TLNT_WILL = #251;
|
||||
TLNT_WONT = #252;
|
||||
TLNT_DO = #253;
|
||||
TLNT_DONT = #254;
|
||||
TLNT_IAC = #255;
|
||||
|
||||
type
|
||||
{:@abstract(State of telnet protocol). Used internaly by TTelnetSend.}
|
||||
TTelnetState =(tsDATA, tsIAC, tsIAC_SB, tsIAC_WILL, tsIAC_DO, tsIAC_WONT,
|
||||
tsIAC_DONT, tsIAC_SBIAC, tsIAC_SBDATA, tsSBDATA_IAC);
|
||||
|
||||
{:@abstract(Class with implementation of Telnet/SSH script client.)
|
||||
|
||||
Note: Are you missing properties for specify server address and port? Look to
|
||||
parent @link(TSynaClient) too!}
|
||||
TTelnetSend = class(TSynaClient)
|
||||
private
|
||||
FSock: TTCPBlockSocket;
|
||||
FBuffer: Ansistring;
|
||||
FState: TTelnetState;
|
||||
FSessionLog: Ansistring;
|
||||
FSubNeg: Ansistring;
|
||||
FSubType: Ansichar;
|
||||
FTermType: Ansistring;
|
||||
function Connect: Boolean;
|
||||
function Negotiate(const Buf: Ansistring): Ansistring;
|
||||
procedure FilterHook(Sender: TObject; var Value: AnsiString);
|
||||
public
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
|
||||
{:Connects to Telnet server.}
|
||||
function Login: Boolean;
|
||||
|
||||
{:Connects to SSH2 server and login by Username and Password properties.
|
||||
|
||||
You must use some of SSL plugins with SSH support. For exammple CryptLib.}
|
||||
function SSHLogin: Boolean;
|
||||
|
||||
{:Logout from telnet server.}
|
||||
procedure Logout;
|
||||
|
||||
{:Send this data to telnet server.}
|
||||
procedure Send(const Value: string);
|
||||
|
||||
{:Reading data from telnet server until Value is readed. If it is not readed
|
||||
until timeout, result is @false. Otherwise result is @true.}
|
||||
function WaitFor(const Value: string): Boolean;
|
||||
|
||||
{:Read data terminated by terminator from telnet server.}
|
||||
function RecvTerminated(const Terminator: string): string;
|
||||
|
||||
{:Read string from telnet server.}
|
||||
function RecvString: string;
|
||||
published
|
||||
{:Socket object used for TCP/IP operation. Good for seting OnStatus hook, etc.}
|
||||
property Sock: TTCPBlockSocket read FSock;
|
||||
|
||||
{:all readed datas in this session (from connect) is stored in this large
|
||||
string.}
|
||||
property SessionLog: Ansistring read FSessionLog write FSessionLog;
|
||||
|
||||
{:Terminal type indentification. By default is 'SYNAPSE'.}
|
||||
property TermType: Ansistring read FTermType write FTermType;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
constructor TTelnetSend.Create;
|
||||
begin
|
||||
inherited Create;
|
||||
FSock := TTCPBlockSocket.Create;
|
||||
FSock.Owner := self;
|
||||
FSock.OnReadFilter := FilterHook;
|
||||
FTimeout := 60000;
|
||||
FTargetPort := cTelnetProtocol;
|
||||
FSubNeg := '';
|
||||
FSubType := #0;
|
||||
FTermType := 'SYNAPSE';
|
||||
end;
|
||||
|
||||
destructor TTelnetSend.Destroy;
|
||||
begin
|
||||
FSock.Free;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function TTelnetSend.Connect: Boolean;
|
||||
begin
|
||||
// Do not call this function! It is calling by LOGIN method!
|
||||
FBuffer := '';
|
||||
FSessionLog := '';
|
||||
FState := tsDATA;
|
||||
FSock.CloseSocket;
|
||||
FSock.LineBuffer := '';
|
||||
FSock.Bind(FIPInterface, cAnyPort);
|
||||
FSock.Connect(FTargetHost, FTargetPort);
|
||||
Result := FSock.LastError = 0;
|
||||
end;
|
||||
|
||||
function TTelnetSend.RecvTerminated(const Terminator: string): string;
|
||||
begin
|
||||
Result := FSock.RecvTerminated(FTimeout, Terminator);
|
||||
end;
|
||||
|
||||
function TTelnetSend.RecvString: string;
|
||||
begin
|
||||
Result := FSock.RecvTerminated(FTimeout, CRLF);
|
||||
end;
|
||||
|
||||
function TTelnetSend.WaitFor(const Value: string): Boolean;
|
||||
begin
|
||||
Result := FSock.RecvTerminated(FTimeout, Value) <> '';
|
||||
end;
|
||||
|
||||
procedure TTelnetSend.FilterHook(Sender: TObject; var Value: AnsiString);
|
||||
begin
|
||||
Value := Negotiate(Value);
|
||||
FSessionLog := FSessionLog + Value;
|
||||
end;
|
||||
|
||||
function TTelnetSend.Negotiate(const Buf: Ansistring): Ansistring;
|
||||
var
|
||||
n: integer;
|
||||
c: Ansichar;
|
||||
Reply: Ansistring;
|
||||
SubReply: Ansistring;
|
||||
begin
|
||||
Result := '';
|
||||
for n := 1 to Length(Buf) do
|
||||
begin
|
||||
c := Buf[n];
|
||||
Reply := '';
|
||||
case FState of
|
||||
tsData:
|
||||
if c = TLNT_IAC then
|
||||
FState := tsIAC
|
||||
else
|
||||
Result := Result + c;
|
||||
|
||||
tsIAC:
|
||||
case c of
|
||||
TLNT_IAC:
|
||||
begin
|
||||
FState := tsData;
|
||||
Result := Result + TLNT_IAC;
|
||||
end;
|
||||
TLNT_WILL:
|
||||
FState := tsIAC_WILL;
|
||||
TLNT_WONT:
|
||||
FState := tsIAC_WONT;
|
||||
TLNT_DONT:
|
||||
FState := tsIAC_DONT;
|
||||
TLNT_DO:
|
||||
FState := tsIAC_DO;
|
||||
TLNT_EOR:
|
||||
FState := tsDATA;
|
||||
TLNT_SB:
|
||||
begin
|
||||
FState := tsIAC_SB;
|
||||
FSubType := #0;
|
||||
FSubNeg := '';
|
||||
end;
|
||||
else
|
||||
FState := tsData;
|
||||
end;
|
||||
|
||||
tsIAC_WILL:
|
||||
begin
|
||||
case c of
|
||||
#3: //suppress GA
|
||||
Reply := TLNT_DO;
|
||||
else
|
||||
Reply := TLNT_DONT;
|
||||
end;
|
||||
FState := tsData;
|
||||
end;
|
||||
|
||||
tsIAC_WONT:
|
||||
begin
|
||||
Reply := TLNT_DONT;
|
||||
FState := tsData;
|
||||
end;
|
||||
|
||||
tsIAC_DO:
|
||||
begin
|
||||
case c of
|
||||
#24: //termtype
|
||||
Reply := TLNT_WILL;
|
||||
else
|
||||
Reply := TLNT_WONT;
|
||||
end;
|
||||
FState := tsData;
|
||||
end;
|
||||
|
||||
tsIAC_DONT:
|
||||
begin
|
||||
Reply := TLNT_WONT;
|
||||
FState := tsData;
|
||||
end;
|
||||
|
||||
tsIAC_SB:
|
||||
begin
|
||||
FSubType := c;
|
||||
FState := tsIAC_SBDATA;
|
||||
end;
|
||||
|
||||
tsIAC_SBDATA:
|
||||
begin
|
||||
if c = TLNT_IAC then
|
||||
FState := tsSBDATA_IAC
|
||||
else
|
||||
FSubNeg := FSubNeg + c;
|
||||
end;
|
||||
|
||||
tsSBDATA_IAC:
|
||||
case c of
|
||||
TLNT_IAC:
|
||||
begin
|
||||
FState := tsIAC_SBDATA;
|
||||
FSubNeg := FSubNeg + c;
|
||||
end;
|
||||
TLNT_SE:
|
||||
begin
|
||||
SubReply := '';
|
||||
case FSubType of
|
||||
#24: //termtype
|
||||
begin
|
||||
if (FSubNeg <> '') and (FSubNeg[1] = #1) then
|
||||
SubReply := #0 + FTermType;
|
||||
end;
|
||||
end;
|
||||
Sock.SendString(TLNT_IAC + TLNT_SB + FSubType + SubReply + TLNT_IAC + TLNT_SE);
|
||||
FState := tsDATA;
|
||||
end;
|
||||
else
|
||||
FState := tsDATA;
|
||||
end;
|
||||
|
||||
else
|
||||
FState := tsData;
|
||||
end;
|
||||
if Reply <> '' then
|
||||
Sock.SendString(TLNT_IAC + Reply + c);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
procedure TTelnetSend.Send(const Value: string);
|
||||
begin
|
||||
Sock.SendString(ReplaceString(Value, TLNT_IAC, TLNT_IAC + TLNT_IAC));
|
||||
end;
|
||||
|
||||
function TTelnetSend.Login: Boolean;
|
||||
begin
|
||||
Result := False;
|
||||
if not Connect then
|
||||
Exit;
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
function TTelnetSend.SSHLogin: Boolean;
|
||||
begin
|
||||
Result := False;
|
||||
if Connect then
|
||||
begin
|
||||
FSock.SSL.SSLType := LT_SSHv2;
|
||||
FSock.SSL.Username := FUsername;
|
||||
FSock.SSL.Password := FPassword;
|
||||
FSock.SSLDoConnect;
|
||||
Result := FSock.LastError = 0;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TTelnetSend.Logout;
|
||||
begin
|
||||
FSock.CloseSocket;
|
||||
end;
|
||||
|
||||
|
||||
end.
|
||||
Reference in New Issue
Block a user