Having some issues with sftpserver (Onclosefile)

Discussion of open issues, suggestions and bugs regarding network security and data protection solution - SecureBridge
Post Reply
snorkel
Posts: 384
Joined: Tue 08 Aug 2006 15:10
Location: Milwaukee WI USA

Having some issues with sftpserver (Onclosefile)

Post by snorkel » Thu 25 Feb 2016 21:08

Ok, here is what I want to do:
I want to be able to know when a file has been closed for reading(download) and writing (upload)

The OnCloseFile should be the optimal place to do this but the problem is with
TScHandle, it only exposes it's Fhandle field via the property Handle. It's has the fullfilename there as well, but it is protected and no property exits to get at it.

Ok, I had to modify the source code to add the FullFilename property to TScHandle, now in the OnCloseFile I have this: (I am not sure if this correct as the default Onclosefile has some stuff in there about tsearchrec which I don't' have in my handler.

procedure TForm1.ScSFTPServer1CloseFile(Sender: TObject;
SFTPSessionInfo: TScSFTPSessionInfo; Data: TObject; var Error: TScSFTPError);
var
afilename:string;
begin
if Data <> nil then
if Data is TScHandle then
begin
afilename:=TScHandle(Data).FullFileName;
FileClose(TScHandle(Data).Handle);
InitError(Error, erOk);
end;
end;

The only problem now is I dont' know if the file was opened for reading or writing.
This seems like it could be solved if another field could be added to TscHandle with a property to expose it that would indicate the mode the file was opened in.

Would someone at Devart be able to assist me with this? I think I am on the correct track here.

snorkel
Posts: 384
Joined: Tue 08 Aug 2006 15:10
Location: Milwaukee WI USA

Re: Having some issues with sftpserver (Onclosefile)

Post by snorkel » Thu 25 Feb 2016 22:05

I think I got this working:

First I had to modify TscHandle in ScSFTPServer:

TScHandle = class
protected
FHandle: THandle;
FFullFileName: string;
FInAppendMode: boolean;
FInTextMode: boolean;
FBlockMode:TScSFTPBlockMode;
public
constructor Create(Handle: THandle);
property Handle: THandle read FHandle write FHandle;
property FullFileName:string read FFullFileName write FFullFileName;
property InAppendMode:boolean read FInAppendMode write FInAppendMode;
property InTextMode:boolean read FInTextMode write FInTextMode;
Property BlockMode:TScSFTPBlockMode read FBlockMode write FBlockMode;
end;


Then:

procedure TForm1.ScSFTPServer1OpenFile(Sender: TObject;
SFTPSessionInfo: TScSFTPSessionInfo; const FileName: string;
const OpenAttributes: TScSFTPFileOpenAttributes; var Data: TObject;
var Error: TScSFTPError);

const
FILE_FLAG_OPEN_REPARSE_POINT = $00200000;

var

dwDesiredAccess, dwShareMode, dwCreationDisposition, dwFlagsAndAttributes: DWORD;
Blockmode:TScSFTPBlockMode;

FullFileName: string;
aHandle: THandle;
begin
FullFileName := TScSFTPServer(sender).GetFullPath(SFTPSessionInfo, FileName);
dwDesiredAccess := ConvertAceMaskToSFTPValue(OpenAttributes.DesiredAccess);
dwShareMode := 0;
if not (bmRead in OpenAttributes.BlockModes) then
begin
blockmode:=bmRead;
dwShareMode := dwShareMode or FILE_SHARE_READ;
end;
if not (bmWrite in OpenAttributes.BlockModes) then
begin
blockmode:=bmwrite;
dwShareMode := dwShareMode or FILE_SHARE_WRITE;
end;
if not (bmDelete in OpenAttributes.BlockModes) then
dwShareMode := dwShareMode or FILE_SHARE_DELETE;

case OpenAttributes.Mode of
fmCreateNew:
dwCreationDisposition := CREATE_NEW;
fmCreateOrTruncate:
dwCreationDisposition := CREATE_ALWAYS;
fmOpenExisting:
dwCreationDisposition := OPEN_EXISTING;
fmOpenOrCreate:
dwCreationDisposition := OPEN_ALWAYS;
fmTruncateExisting:
dwCreationDisposition := TRUNCATE_EXISTING;
else
dwCreationDisposition := 0;
Assert(False);
end;

dwFlagsAndAttributes := FILE_ATTRIBUTE_NORMAL;
if ofDeleteOnClose in OpenAttributes.Flags then
dwFlagsAndAttributes := dwFlagsAndAttributes or FILE_FLAG_DELETE_ON_CLOSE;
if ofNoFollow in OpenAttributes.Flags then
dwFlagsAndAttributes := dwFlagsAndAttributes or FILE_FLAG_OPEN_REPARSE_POINT;

aHandle := CreateFile(PChar(FullFileName),
dwDesiredAccess, dwShareMode, nil, dwCreationDisposition, dwFlagsAndAttributes, 0);


if Handle <> INVALID_HANDLE_VALUE then begin
Data := TScHandle.Create(aHandle);
TScHandle(Data).FullFileName := FullFileName;
TScHandle(Data).InAppendMode := (ofAppendData in OpenAttributes.Flags) or (ofAppendDataAtomic in OpenAttributes.Flags);
TScHandle(Data).InTextMode := ofTextMode in OpenAttributes.Flags;
TScHandle(Data).BlockMode:=blockmode;
InitError(Error, erOk);
end
else
InitError(Error, erFailure, SysErrorMessage(GetLastError));
end;


then:

procedure TForm1.ScSFTPServer1CloseFile(Sender: TObject;
SFTPSessionInfo: TScSFTPSessionInfo; Data: TObject; var Error: TScSFTPError);
var
afilename:string;
arec:TSearchRec;
begin
if Data is TScSearchRec then
begin
arec:= TScSearchRec(data).SearchRec;
SysUtils.FindClose(arec);
InitError(Error, erOk);
end else
if Data is TScHandle then
begin
FileClose(TScHandle(Data).Handle);
afilename:=TScHandle(Data).FullFileName;
if TScHandle(data).BlockMode = bmread then
begin
showmessage('File Uploaded');
end;
InitError(Error, erOk);
end;
end;



Does this look correct? It seems to work but I have no idea if it's how devart would have done it.

ViktorV
Devart Team
Posts: 3168
Joined: Wed 30 Jul 2014 07:16

Re: Having some issues with sftpserver (Onclosefile)

Post by ViktorV » Fri 26 Feb 2016 11:13

If your test shows that the code works correctly, then you can use it in your projects.

snorkel
Posts: 384
Joined: Tue 08 Aug 2006 15:10
Location: Milwaukee WI USA

Re: Having some issues with sftpserver (Onclosefile)

Post by snorkel » Sat 27 Feb 2016 15:32

Seems to be working ok.
What I ended up doing so as not to modify SB code, I just made a new class called
MyTScHandle that inherits from TScHandle, then I just added the missing properties and added a new one for file size.

I only see a couple of issues now:
1. OnCheckKey is being called twice when the client uses Pub Key auth.
2. The time between establishing a session and get the directory listing can be very slow.
It seems faster if I connect and then disconnect, then on the second connection it's fast. I don't see
why the first connection would be slower at establishing the session. If Keyboard interactive is disabled it's even slower with up to 6 seconds between session and dir listing with both server and client on localhost.

ViktorV
Devart Team
Posts: 3168
Joined: Wed 30 Jul 2014 07:16

Re: Having some issues with sftpserver (Onclosefile)

Post by ViktorV » Wed 13 Apr 2016 06:49


Post Reply