B4A Library Android SFTP based on JSch tutorial

JSch is an open source Java implementation of SSH2. It supports many features.

Currently the Basic4android JSch library supports the SFTP protocol which is SSH File Transfer Protocol or Secured File Transfer Protocol.

SFTP is similar to FTP with the difference that the communication is done over a secured channel.

A good tutorial about SSH authentication is available here: SSH Host Key Protection | Symantec Connect Community

When the client first connects to the SSH server he needs to approve the host key (unless it is in the list of approved keys).

SS-2013-03-05_12.08.04.png


The SFtp object raises a PromptYesNo event for this question:
B4X:
Sub sftp1_PromptYesNo (Message As String)
   Dim res As Int = Msgbox2(Message, "", "Yes", "", "No", Null)
   'The next line might be a bit confusing. It is a condition.
   'The value will be True if res equals to DialogResponse.POSITIVE.
   sftp1.SetPromptResult(res = DialogResponse.POSITIVE)
End Sub
The network thread will wait until you call SetPromptResult or after 60 seconds. In the later case the result will be False.

If you want to automatically accept the host key (which should only be done in a secured local network) then you can write:
B4X:
Sub sftp1_PromptYesNo (Message As String)
   sftp1.SetPromptResult(True)
End Sub

Sftp should be declared as a process global variable and initialized in Activity_Create (or Service_Create):
B4X:
Sub Activity_Create(FirstTime As Boolean)
   If FirstTime Then
      sftp1.Initialize("sftp1", "username", "password", "example.com", 22)
      sftp1.SetKnownHostsStore(File.DirInternal, "hosts.txt")
   End If
   Activity.LoadLayout("1")
End Sub

Calling SetKnownHostsStore sets a file that will save the known keys. Without it the user will need to approve the key each time.

In Activity_Resume we need to call SFtp.Activity_Resume:
B4X:
Sub Activity_Resume
   sftp1.Activity_Resume
End Sub
The purpose of this call is to redisplay the visible prompt if it was visible when the activity was paused. This is relevant for example when the user changes the orientation while the dialog is visible.

SFtp can also show a message to the user in some cases. This is done with the ShowMessage event:
B4X:
Sub sftp1_ShowMessage (Message As String)
   Msgbox(Message, "")
End Sub

The other methods work in the same way as the FTP object: Android FTP tutorial

The library is attached. The open source project is embedded in the jar file.

V1.30 - Based on the latest version of Jsch (0.1.54).
 

Attachments

  • JSch.zip
    274 KB · Views: 776
Last edited:

AscySoft

Active Member
Licensed User
I have a problem with some older devices (android 2.3) and using jsch lib and mobile connection. Those devices cannot connect /send/download anything from sftp server, but when I'm switching on wi-fi, everything is working as expected! Logcat on my app is not showing anything usefull. Is it a ISP problem?
On my personal devices everything is working well, mobile data or wi-fi, too.
How can I debug?
 

AscySoft

Active Member
Licensed User
It must be; I use 2110 port but when switching back to 22 port (standard), then I detect many hacking attempts, all away from China (with love I guess).
But why jsch does not report "connection blocked" on 2110 or something like that? How can I debug this issue?
 

AscySoft

Active Member
Licensed User
Can you post your code (without the server details)?
Are you implying that it could be an logical error in my program? May I ask (only for now) if my program is 100% correct, how could I debug this issue?
I will post here the code (as a zip project), but I must take the code from a larger app, and post it back in a couple of days.
 

Erel

Administrator
Staff member
Licensed User
It can be a logical error in your code. For example if you are not handling the PromptYesNo event correctly.

If your program is 100% correct then it might be a problem in the library or in the open source project. I did check the library code and I didn't find anything related to this problem. A possible workaround is to use a timer which will fire after 15(?) seconds if the event was not raised.
 

AscySoft

Active Member
Licensed User
Working on that. I just need to implement a simplified version of my app on some other devices ... this takes time becouse those devices aren't mine. I will report back.
BTW, my PromptYesNo is basically this
B4X:
Sub sftp1_PromptYesNo (Message As String)
    sftp1.SetPromptResult(True)
End Sub
where sftp1 is declared as sftp...and is always fiered (I tested it with some log files...more complicated to explain here)
 

AscySoft

Active Member
Licensed User
Hmm. I think is initialize every time when a user push the download/upload button (as I recall)??

UPDATE: I put a small app /test app on some of my coleagues devices and from 14 devices, 4 of them are connecting and downloading well, the others does not. (only with this particular mobile carrier).

I must put a log (for tomorrow) in sftp1_PromptYesNo because I see a strange message: The authenticity of host 'my ip' can't be established. Are you sure you want to continue connecting? but
B4X:
sftp1.SetPromptResult(True)
is true

Soon I will post my app here.
And I will change the initialization only once as your advice.
 

AscySoft

Active Member
Licensed User
The connection is established automatically when needed.
UPDATE: I change my app to initilize sftp object only once as in the first post.
Later on, after sftp1_DownloadCompleted success=true, I close the connection: sftp1.close
After that point no connection could be made to my server even if I repeat the test, after sftp.list, no sftp1_ListCompleted event is raised ever.
Did I understand you right that connection will be established automatically?
When should one use Close command?
 

AscySoft

Active Member
Licensed User
I attached the project
The test was conducted on some old devices running 2.3.3 GINGERBREAD, SAMSUNG GT-S6500D. Right now from 8 devices only 4 passed the test, 50% (more data will come later on) On those who don't work logcat says:

sftp1_PromptYesNo (Message =The authenticity of host can't be established. RSA key fingerprint is ... Are you sure you want to continue connecting?

WHY is that? Check the project before answer, please.
I think is something to do with the file that stores known hosts. I just change its name to hosts2.txt. I will se the new results in a few days..

AND A BIG THANKS IN ADVANCE FOR YOUR TIME AND YOUR KINDNESS
 

Attachments

  • sftpTest.zip
    14.6 KB · Views: 181

AscySoft

Active Member
Licensed User
This is the expected message as the server signature is not yet known.
I know this, I figure it out; what I ment by "why" is: since every time sftp1.SetPromptResult is by default set to true, why code execution still hangs/wait on this question? And why only on some devices, and not to all of them.
Why did you add a Try / Catch block there? Did you get any error?
No, and I didn't try to see even if it were such an error. I think I put it there a long time ago(on my larger project) Is it ok?; Shoud I test without Try/Catch?
 

AscySoft

Active Member
Licensed User
Update: after further investigation I realise that on some devices the code hangs just after SetPromptResult is called first time (message says the server signature is not yet known, asking to connect) but I don't see no log telling me that the sftp object could write the signature in known host file (It should return a message saying that the file...does not exist. Create it?) But I don't see this thing happen later on. This is where a Try/Catch method will work. [as a workaround, but not secure a
session.setConfig("StrictHostKeyChecking","no"); could be executed, but it must be wrapped in jsch lib by Erel]

On the other devices(including mine, but only once) the code pass this point, it create the file, but hangs after List command, with the following error in List Completed: success=false (JSchException) com.jcraft.jsch.JSchException: Packet corrupt

And sometimes, on other devices I don't see a ListCompleted event is ever raised.

So I guess this three are some big issues with sftp. They seems to apear randomly (even on my device), but not always.
Funny thing is that from 23 devices 10 passed this test, but the second day only 9!

So I don't get it! Is sftp/jsch reliable? Is there something wrong in my code? I clearly don't see it. It must be other thing... :(
 
Last edited:

AscySoft

Active Member
Licensed User
You should remove the Try / Catch block as it may hide the real error.
I will remove this, but how should I correctly track a error?

Does it really hang or only fails? There is a big difference between the two.
I meant the list completed event gets executed, but Packet corrupt error occurred (2nd type of error) then exiting because success=false, so it fails!
 
Top