ADD: FTP - show fingerprint in all formats

This commit is contained in:
Alexander Koblov 2019-10-07 19:08:32 +00:00
commit 57ce976cb2
2 changed files with 67 additions and 38 deletions

View file

@ -10,8 +10,9 @@ uses
const
//* Hash Types */
LIBSSH2_HOSTKEY_HASH_MD5 = 1;
LIBSSH2_HOSTKEY_HASH_SHA1 = 2;
LIBSSH2_HOSTKEY_HASH_MD5 = 1;
LIBSSH2_HOSTKEY_HASH_SHA1 = 2;
LIBSSH2_HOSTKEY_HASH_SHA256 = 3;
//* Disconnect Codes (defined by SSH protocol) */
SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT = 1;
@ -194,6 +195,7 @@ var
//* Global API */
libssh2_init: function(flags: cint): cint; cdecl;
libssh2_exit: procedure(); cdecl;
libssh2_version: function(required_version: cint): PAnsiChar; cdecl;
//* Session API */
libssh2_session_init_ex: function(my_alloc: LIBSSH2_ALLOC_FUNC;
my_free: LIBSSH2_FREE_FUNC;
@ -514,6 +516,7 @@ begin
//* Global API */
libssh2_init:= SafeGetProcAddress(libssh2, 'libssh2_init');
libssh2_exit:= SafeGetProcAddress(libssh2, 'libssh2_exit');
libssh2_version:= SafeGetProcAddress(libssh2, 'libssh2_version');
//* Session API */
libssh2_session_init_ex:= SafeGetProcAddress(libssh2, 'libssh2_session_init_ex');
libssh2_session_handshake:= SafeGetProcAddress(libssh2, 'libssh2_session_handshake');

View file

@ -3,7 +3,7 @@
-------------------------------------------------------------------------
Wfx plugin for working with File Transfer Protocol
Copyright (C) 2013-2018 Alexander Koblov (alexx2000@mail.ru)
Copyright (C) 2013-2019 Alexander Koblov (alexx2000@mail.ru)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@ -88,7 +88,7 @@ implementation
uses
CTypes, LazUTF8, FtpFunc, DCStrUtils, DCClassesUtf8, DCOSUtils, DCDateTimeUtils,
DCBasicTypes, DCConvertEncoding, FileUtil, Base64, LConvEncoding;
DCBasicTypes, DCConvertEncoding, FileUtil, Base64, LConvEncoding, SynaCode, StrUtils;
const
SMB_BUFFER_SIZE = 131072;
@ -278,7 +278,7 @@ begin
begin
SetLength(Password, MAX_PATH + 1);
Message:= 'Private key pass phrase:';
Title+= 'ssh://' + UTF8ToUTF16(FUserName + '@' + FTargetHost);
Title:= 'ssh://' + UTF8ToUTF16(FUserName + '@' + FTargetHost);
if RequestProc(PluginNumber, RT_Password, PWideChar(Title), PWideChar(Message), PWideChar(Password), MAX_PATH) then
begin
Passphrase:= ClientToServer(Password);
@ -292,13 +292,16 @@ end;
function TScpSend.Connect: Boolean;
const
HOSTKEY_SIZE = 20;
HASH_SIZE: array[1..3] of Byte = (16, 20, 32);
HASH_NAME: array[1..3] of String = ('(MD5) ', '(SHA1) ', '(SHA256) ');
var
I: Integer;
S: String = '';
S: String;
F: String = '';
SS: String = '';
I, J, Finish: Integer;
Message: UnicodeString;
FingerPrint: PAnsiChar;
userauthlist: PAnsiChar;
FingerPrint: array [0..Pred(HOSTKEY_SIZE)] of AnsiChar;
begin
FSock.CloseSocket;
DoStatus(False, 'Connecting to: ' + FTargetHost);
@ -322,29 +325,52 @@ begin
LogProc(PluginNumber, MSGTYPE_CONNECT, nil);
DoStatus(False, 'Connection established');
FingerPrint := libssh2_hostkey_hash(FSession, LIBSSH2_HOSTKEY_HASH_SHA1);
for I:= Low(FingerPrint) to High(FingerPrint) do
begin
S+= IntToHex(Ord(FingerPrint[I]), 2) + #32;
if libssh2_version($010900) = nil then
Finish:= LIBSSH2_HOSTKEY_HASH_SHA1
else begin
Finish:= LIBSSH2_HOSTKEY_HASH_SHA256;
end;
for J:= LIBSSH2_HOSTKEY_HASH_MD5 to Finish do
begin
FingerPrint := libssh2_hostkey_hash(FSession, J);
if Assigned(FingerPrint) then
begin
if (J >= LIBSSH2_HOSTKEY_HASH_SHA256) then
begin
SetString(S, FingerPrint, HASH_SIZE[J]);
S := TrimRightSet(EncodeBase64(S), ['=']);
end
else begin
S:= EmptyStr;
for I:= 0 to HASH_SIZE[J] - 1 do
begin
S+= IntToHex(Ord(FingerPrint[I]), 2) + #32;
end;
SetLength(S, Length(S) - 1); // Remove space
end;
SS += HASH_NAME[J] + S + LineEnding;
DoStatus(False, 'Server fingerprint: ' + HASH_NAME[J] + S);
if (J > LIBSSH2_HOSTKEY_HASH_MD5) and (Length(F) = 0) then F:= S;
end;
end;
SetLength(S, Length(S) - 1); // Remove space
DoStatus(False, 'Server fingerprint: ' + S);
// Verify server fingerprint
if FFingerPrint <> S then
if FFingerPrint <> F then
begin
if FFingerprint = EmptyStr then
Message:= 'You are using this connection for the first time.' + LineEnding + 'Please verify that the following host fingerprint matches the fingerprint of your server:'
else begin
Message:= 'WARNING!' + LineEnding + 'The fingerprint of the host has changed!' + LineEnding + 'Please make sure that the new fingerprint matches your server:';
end;
Message += UnicodeString(LineEnding + LineEnding + S);
Message += UnicodeString(LineEnding + LineEnding + SS);
if not RequestProc(PluginNumber, RT_MsgYesNo, nil, PWideChar(Message), nil, 0) then
begin
LogProc(PluginNumber, msgtype_importanterror, 'Wrong server fingerprint!');
Exit(False);
end;
FFingerprint:= S;
FFingerprint:= F;
end;
//* check what authentication methods are available */
@ -599,13 +625,13 @@ end;
function TScpSend.RetrieveFile(const FileName: string; FileSize: Int64;
Restore: Boolean): Boolean;
var
FBuffer: PByte;
BytesRead: PtrInt;
BytesToRead: Integer;
RetrStream: TFileStreamEx;
TotalBytesToRead: Int64 = 0;
SourceHandle: PLIBSSH2_CHANNEL;
var
FBuffer: PByte;
BytesRead: PtrInt;
BytesToRead: Integer;
RetrStream: TFileStreamEx;
TotalBytesToRead: Int64 = 0;
SourceHandle: PLIBSSH2_CHANNEL;
begin
RetrStream := TFileStreamEx.Create(FDirectFileName, fmCreate or fmShareDenyWrite);
@ -627,20 +653,20 @@ begin
end;
until not ((SourceHandle = nil) and (FLastError = LIBSSH2_ERROR_EAGAIN));
FBuffer:= GetMem(SMB_BUFFER_SIZE);
TotalBytesToRead:= FileSize - TotalBytesToRead;
try
BytesToRead:= SMB_BUFFER_SIZE;
while TotalBytesToRead > 0 do
begin
if (BytesToRead > TotalBytesToRead) then begin
BytesToRead := TotalBytesToRead;
end;
repeat
BytesRead := libssh2_channel_read(SourceHandle, PAnsiChar(FBuffer), BytesToRead);
if BytesRead = LIBSSH2_ERROR_EAGAIN then begin
DoProgress((FileSize - TotalBytesToRead) * 100 div FileSize);
FSock.CanRead(10);
FBuffer:= GetMem(SMB_BUFFER_SIZE);
TotalBytesToRead:= FileSize - TotalBytesToRead;
try
BytesToRead:= SMB_BUFFER_SIZE;
while TotalBytesToRead > 0 do
begin
if (BytesToRead > TotalBytesToRead) then begin
BytesToRead := TotalBytesToRead;
end;
repeat
BytesRead := libssh2_channel_read(SourceHandle, PAnsiChar(FBuffer), BytesToRead);
if BytesRead = LIBSSH2_ERROR_EAGAIN then begin
DoProgress((FileSize - TotalBytesToRead) * 100 div FileSize);
FSock.CanRead(10);
end;
until BytesRead <> LIBSSH2_ERROR_EAGAIN;