| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359 |
- {==============================================================================|
- | Project : Ararat Synapse | 001.003.000 |
- |==============================================================================|
- | Content: TELNET and SSH2 client |
- |==============================================================================|
- | Copyright (c)1999-2008, 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-2008. |
- | 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+}
- 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.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.
|