libssh2 for iOS (iPhone and iPad) – Example app with SSH connection
by Felix Schulze • February 2, 2011 • Encryption, iOS, iPad, iPhone, Software, Tutorials • 50 Comments
This is a tutorial for using self-compiled builds of the libssh2-library for iOS. You can build apps with XCode and the official SDK from Apple with this. I also made a small example-app for using the libraries with XCode and the iPhone/iPhone-Simulator. You can also download the precompiled libssh2-library (1.2.7).
You can get the scripts and the sourcecode here: https://github.com/x2on/libssh2-for-iOS
The example uses libssh2 to make an ssh connection to an ssh server. Then you can execute commands on the server and get the output in your app.
You can build the libssh2 library with openssl or with libgcrypt!
libssh2 with openssl:
./build-all.sh openssllibssh2 with libgcrypt:
./build-all.sh libgcrypt
The demo app crashes when using a server address as a name instead of a numeric address. Any idea why that is?
That is normal becouse libssh2 uses inet_addr(host) – You must convert the url to an ip adress.
Oh that’s my mistake. I was just looking through and hadn’t noticed. Thanks for following up and doing all the work. This is extremely convenient!
// Get host entry info for given host
struct hostent *remoteHostEnt = gethostbyname([host cStringUsingEncoding:NSUTF8StringEncoding]);
// Get address info from host entry
struct in_addr *remoteInAddr = (struct in_addr *) remoteHostEnt->h_addr_list[0];
// Convert numeric addr to ASCII string
char *sRemoteInAddr = inet_ntoa(*remoteInAddr);
NSString *s = [[NSString alloc]
initWithFormat:
@”Remote IP: %sn”,
sRemoteInAddr];
NSLog(@”%@”, s);
isue with message:
Authentication by password failed.
Need some details… perhaps you are using public keys?
no, my .ssh directory is empty
Thanks for putting this out there.
One Q though, any commands that typically use a space (cd /someDir) don’t seem to work. Am I missing something obvious?
I think you must escape the whitespace.
thanks for this~
Any advise for escape from the white space?
if can not use space,it sees usless….
Had trouble getting the escapes to work too. I ended up using
libssh2_sftp_opendir
and
libssh2_sftp_readdir
Thanks for assembling this example. I’m having trouble starting my own example. If I want to start a project from scratch but use the SSHWrapper, what files do I need to include in the new project?
I’ve tried copying over the libcrypto.a, libgcrypto.a, libssl.a, libssh2.a, libgpg-error.a and the importing libz.dlib into my project, but it SSHWrapper complains about the missing .h files from the import statements. I can manually add those files to the project, but I’m afraid I’ll eventually miss something.
Thanks!
You must add the Header Search Path in your projects settings. See the example app.
Awesome! Thanks for the help and quick response.
Another question:
I use SSHWrapper to ssh into a firewall machine, and from that firewall machine I send commands via ssh to other machines (ssh user@machine “myscript.sh”). I’m getting odd characters at the end of my ssh calls to the other machine (x04 = the end of transmission and other random characters that I can’t figure out). Is there a way to strip these termination characters? When we are in the “executeCommand” function, result is a string that is ASCII encoded, is there maybe a different encoding I could use to get rid of these characters?
Thanks!
I’ve got the same problem. Also, when there is a large output, some parts at the beginning are not included the resulting NSString-Object. Unfortunately this behaviour is not deterministic, but in my case happens in 2 out of 3 tries.
Do you have any idea what the problem is?
hi
I have the same problem than dom
isue with message:
Authentication by password failed.
have you any idea?
Always getting wrong password. There is apparently a problem with libssh2_userauth_password. We should be using libssh2_userauth_keyboard_interactive_ex instead according to a lot of people.
Im trying to get this to work with the default mac ssh server and keep getting the password is incorrect message
Its all good. A linux ssh server works fine with it. It must be my own mac ssh settings. Good work on this!
The issue with “authentication by password failed” is because many newer ssh servers are configured to refuse
plaintext password authentication.
On your mac, look in /etc/sshd_conf for
#PasswordAuthentication no
You can turn it on
PasswordAuthentication yes
but that’s not recommended.
I’ve fixed the sample code to perform keyboard-interactive or password authentication as allowed by the server.
I’m working on adding publickey authentication as well.
I’ll add something better than the comment above to decode hostnames or IP addresses, as well.
Has anyone gotten SFTP to work through this? I need a good solution for SFTP on iOS and this seems to be the closest available.
Thanks in advance!
Matthew
I’ve published the changes I made at https://github.com/gonzopancho/libssh2-for-iOS.
Matt, after I finish off pubic key authentication, I’ll work on SFTP, doesn’t seem too difficult. (famous last words)
Hi, I downloaded the sample app and ran it on my iPhone 4 4.3.3 and when I input the information and hit “Execute Command”, the app freezes! Do you have any idea why?
> the app freezes! Do you have any idea why?
has it crashed?
it freezes. doesn’t crash. when i press “execute command” it just freezes so when i touch the keyboard or any input fields they don’t respond.
okay sorry – it froze for sumtime and it did crash!
so… what did you put in the fields?
gonzo, I’m using yours (thanks for the auth addition!) Have you resolved anyway to use whitespaces? It just crashes with bad access. It also crashes if I try to use . or /
Any insight would be awesome.
ah, well it crashes because NSString* result is not a valid object if it never gets set (which it doesn’t at:
if( rc1 > 0 )
{
result = [NSString stringWithCString:buffer encoding:NSASCIIStringEncoding];
}
So I added:
else {
result = nil;
}
and at the end
if(result) return result;
else return @”error – command didn’t work”;
Now I just get that error message.
well, i’m probably doing it wrong but as the command, I left the default command “Ls” and input my user name to the computer which is “iaN” and then as the IP, I input my IP address 192.168.1.x. Then I tried not inputing the password and inputing my password to the computer but nuthing works! any suggestions?
Hello,
The library and example app are both great.
However, everything works fine when I connect to a Debian distro only (and not every time). When I try to connect to an Ubuntu distro…
this portion of code:
—–
for( ;; )
{
/* loop until we block */
int rc1;
do
{
char buffer[0x4000];
rc1 = libssh2_channel_read( channel, buffer, sizeof(buffer) );
if( rc1 > 0 )
{
result = [NSString stringWithCString:buffer encoding:NSASCIIStringEncoding];
}
else {
result = nil;
}
}
while( rc1 > 0 );
/* this is due to blocking that would occur otherwise so we loop on
this condition */
if( rc1 == LIBSSH2_ERROR_EAGAIN )
{
waitsocket(sock, session);
}
else
break;
}
while( (rc = libssh2_channel_close(channel)) == LIBSSH2_ERROR_EAGAIN )
waitsocket(sock, session);
libssh2_channel_free(channel);
channel = NULL;
if(result) return result;
else return @”error – command didn’t work”;
—–
gives me an error because rc > 1 is not satisfied… Why can it be that the library is not returning a command feedback?
Can it be the fact that there is no “time” for the command to be sent and feedback to be returned?
It sounds a bit weird: I can “touch 123.file” and I can see (on my actual Ubuntu server) the new file being created. Yet, the above code will Always return an “error”, for directory listings or anything really.
Does anyone know of any workarounds? Or ways to use more functionality also? E.g. other than just connecting, sending a command, disconnecting.
Here’s an interesting one:
I’ve got it connecting to my server and then executing a bash script – the bash script creates a file, and then uploads it to an ftp, and then echos “all done!”
I get the result “all done” on the iPhone, so I know the script is being run, but the file isn’t being created, nor uploaded to the FTP (I even tried just uploading a file that was already sitting there).
So my question is, is there some sort of permissions issue here, or is it something else completely that is preventing the file creation and the ftp upload (btw, I’m using ncftpput for the FTP upload, and the server is running OS X 10.6).
I think that you have a error in your script…
if I ssh in from another computer and run the script it executes perfectly.
ah, I got it. The commands only executed if I gave them their full path (/usr/local/bin/command). I guess this may be an environment thing, but I’m a bit gray on this sort of stuff.
Any update on the public key or sftp? I’m very interested in the sftp functionality.
Keep the improvements coming!
When I run the demo on IPad simulator, I have an error: “Unable to execute command or shell on remote system: Failed to Execute process” when I exec the ls command. Do I need to modify something? The SFTP is freeSSHd. This server is installed on Window PC.
By the way, are the function libssh2_sftp_open and libssh2_sftp_read supported on IPhone and IPad? Thanks for your reply
Hi and thanks for this lib.
Unfortunatly, I got a problem with the app : at this time, the connection is a success, the execution command looks great, but after that, the app crash with an Exc_Bad_Access. But it doesn’t always crash : it’s bit random, waiting a little and it works. Are there some setting to do on server side or that’s in my app ?
Well, in fact, I think I see my problem : after writing my password (in the simulator, not tested on iPhone yet), if I wait a little to see the last character becoming a •, it works, but if I don’t, it crashes. I hope that won’t be the same on the iPhone.
is running lion a problem. My Xcode is 4.1 with simulator of 4.3 running 64bit but only libgcrypt and libssl compile. libssh2 and libgpg-error doesn’t seem to compile. I run ./build-all.sh libgcrypt and all seems fine.
This is wonderful work. Thank you. How would I go about retrieving the following prompt to the execution response?
Hello, I’ve been having a lot of trouble getting this to compile. Your note talks about fetching precompiled libraries, but no link supplied. Where can we find those?
FInally managed to get the compile. I works with a default installation of XCode with the top-level directory being “Developer.” But since I have multiple dev systems at the same time, I had no default directory. Installing an old build of XCode 3 without doing anything solved it.
I am now getting a password failure. I can ssh over to my server just fine, but not through the demo app.
Duh, should’ve added that I am using XCOde 4.2 and iOS 5B7. Both local and remote machines are macs, the former still using Snow Leopard and the remote on Lion. So machine to machine works, iOS simulator or device with the example app give me the password failure.
I downloaded the example app and have been trying to get it to work as well.
I am running in to the same “Authentication by password failed” error.
I am running Xcode 4.2 with iOS5 SDK. I checked ssh_config,
PasswordAuthentication is set to yes.
Has this issue been resolved? Am I missing something?
Hello, there’s a problem with the last iOS release : in fact at the connection, it crashes, in the simulator and in the device. I tried to isolate the crash with Instruments and, no success.
Great example, I have only one question,
NSString *AAA = [sshWrapper executeCommand:Command];
puts only the last line of the output to AAA, any idea why?
Thanks
I have a problem compiling this to the iPhone Simulator. I’ve linked the ssh2 libraries correctly, but the compiler reports a lot of warnings followed by errors:
ld: warning: ignoring file /opt/local/lib/libcrypto.dylib, file was built for unsupported file format which is not the architecture being linked (i386)
and
“_libssh2_session_init_ex”, referenced from:
-[SSHWrapper connectToHost:port:user:password:] in SSHWrapper.o
etc.
What am I doing wrong?
I downloaded the example iOS app and have been trying to get it to work.
I am running in to the same “Authentication by password failed” error.
I am running Xcode 4.2 with iOS5 SDK, I am also running OSX 10.7.
I checked ssh_config, PasswordAuthentication is set to yes.
I am able to ssh from the terminal but not with the example app.
Has this issue been resolved? Am I missing something?