Experimental support for LibSSH2 by ssl_libssh2.pas plugin. (Alexey Suhinin)
git-svn-id: https://svn.code.sf.net/p/synalist/code/trunk@177 7c85be65-684b-0410-a082-b2ed4fbef004
This commit is contained in:
		
							
								
								
									
										245
									
								
								ssl_libssh2.pas
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										245
									
								
								ssl_libssh2.pas
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,245 @@ | ||||
| {==============================================================================| | ||||
| | Project : Ararat Synapse                                       | 001.000.000 | | ||||
| |==============================================================================| | ||||
| | Content: SSH support by LibSSH2                                              | | ||||
| |==============================================================================| | ||||
| | Copyright (c)1999-2013, 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 Alexey Suhinin.                | | ||||
| | Portions created by Alexey Suhinin are Copyright (c)2012-2013.                | | ||||
| | Portions created by Lukas Gebauer are Copyright (c)2013-2013.                | | ||||
| | All Rights Reserved.                                                         | | ||||
| |==============================================================================| | ||||
| | Contributor(s):                                                              | | ||||
| |==============================================================================| | ||||
| | History: see HISTORY.HTM from distribution package                           | | ||||
| |          (Found at URL: http://www.ararat.cz/synapse/)                       | | ||||
| |==============================================================================} | ||||
|  | ||||
| //requires LibSSH2 libraries! http://libssh2.org | ||||
|  | ||||
| {:@abstract(SSH plugin for LibSSH2) | ||||
|  | ||||
| Require libssh2.dll or libssh2.so. You can download binaries it as part | ||||
| of CURL project from http://curl.haxx.se/download.html | ||||
|  | ||||
| You need pascal bindongs for library too! You can found one at: | ||||
|  http://www.lazarus.freepascal.org/index.php/topic,15935.msg86465.html#msg86465 | ||||
|  | ||||
| This plugin implementing client part only. | ||||
| } | ||||
|  | ||||
| {$IFDEF FPC} | ||||
|   {$MODE DELPHI} | ||||
| {$ENDIF} | ||||
| {$H+} | ||||
|  | ||||
| unit ssl_libssh2; | ||||
|  | ||||
| interface | ||||
|   | ||||
| uses | ||||
|   SysUtils, | ||||
|   blcksock, synsock, | ||||
|   libssh2; | ||||
|   | ||||
| type | ||||
|   {:@abstract(class implementing LibSSH2 SSH plugin.) | ||||
|    Instance of this class will be created for each @link(TTCPBlockSocket). | ||||
|    You not need to create instance of this class, all is done by Synapse itself!} | ||||
|   TSSLLibSSH2 = class(TCustomSSL) | ||||
|   protected | ||||
|     FSession: PLIBSSH2_SESSION; | ||||
|     FChannel: PLIBSSH2_CHANNEL; | ||||
|     function SSHCheck(Value: integer): Boolean; | ||||
|     function DeInit: Boolean; | ||||
|   public | ||||
|     {:See @inherited} | ||||
|     constructor Create(const Value: TTCPBlockSocket); override; | ||||
|     destructor Destroy; override; | ||||
|     {:See @inherited} | ||||
|     function LibVersion: String; override; | ||||
|     {:See @inherited} | ||||
|     function LibName: String; override; | ||||
|     {:See @inherited} | ||||
|     function Connect: boolean; override; | ||||
|     {:See @inherited} | ||||
|     function Shutdown: boolean; override; | ||||
|     {:See @inherited} | ||||
|     function BiShutdown: boolean; override; | ||||
|     {:See @inherited} | ||||
|     function SendBuffer(Buffer: TMemory; Len: Integer): Integer; override; | ||||
|     {:See @inherited} | ||||
|     function RecvBuffer(Buffer: TMemory; Len: Integer): Integer; override; | ||||
|     {:See @inherited} | ||||
|     function WaitingData: Integer; override; | ||||
|     {:See @inherited} | ||||
|     function GetSSLVersion: string; override; | ||||
|   published | ||||
|   end; | ||||
|   | ||||
| implementation | ||||
|   | ||||
| {==============================================================================} | ||||
| function TSSLLibSSH2.SSHCheck(Value: integer): Boolean; | ||||
| var | ||||
|   PLastError: PAnsiChar; | ||||
|   ErrMsgLen: Integer; | ||||
| begin | ||||
|   Result := true; | ||||
|   FLastError := 0; | ||||
|   FLastErrorDesc := ''; | ||||
|   if Value<0 then | ||||
|   begin | ||||
|     FLastError := libssh2_session_last_error(FSession, PLastError, ErrMsglen, 0); | ||||
|     FLastErrorDesc := PLastError; | ||||
|     Result := false; | ||||
|   end; | ||||
| end; | ||||
|   | ||||
|   | ||||
| function TSSLLibSSH2.DeInit: Boolean; | ||||
| begin | ||||
|   if Assigned(FChannel) then | ||||
|   begin | ||||
|     libssh2_channel_free(FChannel); | ||||
|     FChannel := nil; | ||||
|   end; | ||||
|   if Assigned(FSession) then | ||||
|   begin | ||||
|     libssh2_session_disconnect(FSession,'Goodbye'); | ||||
|     libssh2_session_free(FSession); | ||||
|     FSession := nil; | ||||
|   end; | ||||
|   FSSLEnabled := False; | ||||
|   Result := true; | ||||
| end; | ||||
|   | ||||
| constructor TSSLLibSSH2.Create(const Value: TTCPBlockSocket); | ||||
| begin | ||||
|   inherited Create(Value); | ||||
|   FSession := nil; | ||||
|   FChannel := nil; | ||||
| end; | ||||
|   | ||||
| destructor TSSLLibSSH2.Destroy; | ||||
| begin | ||||
|   DeInit; | ||||
|   inherited Destroy; | ||||
| end; | ||||
|   | ||||
| function TSSLLibSSH2.Connect: boolean; | ||||
| begin | ||||
|   Result := False; | ||||
|   if SSLEnabled then DeInit; | ||||
|   if (FSocket.Socket <> INVALID_SOCKET) and (FSocket.SSL.SSLType = LT_SSHv2) then | ||||
|     begin | ||||
|       FSession := libssh2_session_init(); | ||||
|       if not Assigned(FSession) then | ||||
|       begin | ||||
|         FLastError := -999; | ||||
|         FLastErrorDesc := 'Cannot initialize SSH session'; | ||||
|         exit; | ||||
|       end; | ||||
|       if not SSHCheck(libssh2_session_startup(FSession, FSocket.Socket)) then | ||||
|         exit; | ||||
|       if FSocket.SSL.PrivateKeyFile<>'' then | ||||
|         if (not SSHCheck(libssh2_userauth_publickey_fromfile(FSession, PChar(FSocket.SSL.Username), nil, PChar(FSocket.SSL.PrivateKeyFile), PChar(FSocket.SSL.KeyPassword)))) | ||||
|           and (not SSHCheck(libssh2_userauth_password(FSession, PChar(FSocket.SSL.Username), PChar(FSocket.SSL.Password)))) then | ||||
|           exit; | ||||
|       FChannel := libssh2_channel_open_session(FSession); | ||||
|       if not assigned(FChannel) then | ||||
|       begin | ||||
| //        SSHCheck(-1); | ||||
|         FLastError:=-999; | ||||
|         FLastErrorDesc := 'Cannot open session'; | ||||
|         exit; | ||||
|       end; | ||||
|       if not SSHCheck(libssh2_channel_request_pty(FChannel, 'vanilla')) then | ||||
|         exit; | ||||
|       if not SSHCheck(libssh2_channel_shell(FChannel)) then | ||||
|         exit; | ||||
|       FSSLEnabled := True; | ||||
|       Result := True; | ||||
|     end; | ||||
| end; | ||||
|  | ||||
| function TSSLLibSSH2.LibName: String; | ||||
| begin | ||||
|   Result := 'ssl_libssh2'; | ||||
| end; | ||||
|   | ||||
| function TSSLLibSSH2.Shutdown: boolean; | ||||
| begin | ||||
|   Result := DeInit; | ||||
| end; | ||||
|   | ||||
|   | ||||
| function TSSLLibSSH2.BiShutdown: boolean; | ||||
| begin | ||||
|   Result := DeInit; | ||||
| end; | ||||
|   | ||||
| function TSSLLibSSH2.SendBuffer(Buffer: TMemory; Len: Integer): Integer; | ||||
| begin | ||||
|   Result:=libssh2_channel_write(FChannel, PAnsiChar(Buffer), Len); | ||||
|   SSHCheck(Result); | ||||
| end; | ||||
|  | ||||
| function TSSLLibSSH2.RecvBuffer(Buffer: TMemory; Len: Integer): Integer; | ||||
| begin | ||||
|   result:=libssh2_channel_read(FChannel, PAnsiChar(Buffer), Len); | ||||
|   SSHCheck(Result); | ||||
| end; | ||||
|   | ||||
| function TSSLLibSSH2.WaitingData: Integer; | ||||
| begin | ||||
|   if libssh2_poll_channel_read(FChannel, Result) <> 1 then | ||||
|     Result := 0; | ||||
| end; | ||||
|   | ||||
| function TSSLLibSSH2.GetSSLVersion: string; | ||||
| begin | ||||
|   Result := 'SSH2'; | ||||
| end; | ||||
|  | ||||
| function TSSLLibSSH2.LibVersion: String; | ||||
| begin | ||||
|   Result := libssh2_version(0); | ||||
| end; | ||||
|  | ||||
| initialization | ||||
|   if libssh2_init(0)=0 then | ||||
| 		SSLImplementation := TSSLLibSSH2; | ||||
|   | ||||
| finalization | ||||
|   libssh2_exit; | ||||
|   | ||||
| end. | ||||
		Reference in New Issue
	
	Block a user