Now that we've ensured that libssh is correctly installed, it's time to attempt an actual SSH connection.
You'll need to have access to an SSH server before continuing. OpenSSH is a popular server that is available for Linux, macOS, and Windows 10. It works well for testing but be sure to understand the security implementations before installing it on your device. Refer to your operating system's documentation for more information.
If you would rather test with a remote system, Linux Virtual Private Servers (VPS) running OpenSSH are available from many providers. They typically cost only a few dollars a month.
Let's continue by implementing a program that uses libssh to open an SSH connection.
We structure the rest of the programs in this chapter to take the SSH server's hostname and port number as command-line arguments. Our program starts with the following code, which checks these arguments:
/*ssh_connect.c*/
#include "chap11.h"
int main(int argc, char *argv[])
{
const char *hostname = 0;
int port = 22;
if (argc < 2) {
fprintf(stderr, "Usage: ssh_connect hostname port\n");
return 1;
}
hostname = argv[1];
if (argc > 2) port = atol(argv[2]);
In the preceding code, argc is checked to see whether at least the hostname was passed in as a command-line argument. If it wasn't, a usage message is displayed instead. Otherwise, the server's hostname is stored in the hostname variable. If a port number was passed in, it is stored in the port variable. Otherwise, the default port 22 is stored instead.
SSH often provides complete and total access to a server. For this reason, some internet criminals randomly scan IP addresses for SSH connections. When they successfully establish a connection, they attempt to guess login credentials, and if successful, they take control of the server. These attacks aren't successful against properly secured servers, but they are a common nuisance, nonetheless. Using SSH on a port other than the default (22) often avoids these automated attacks. This is one reason why we want to ensure our programs work well with non-default port numbers.
Once our program has obtained the hostname and connection port number, we continue by creating an SSH session object. This is done with a call to ssh_new() as shown in the following code:
/*ssh_connect.c continued*/
ssh_session ssh = ssh_new();
if (!ssh) {
fprintf(stderr, "ssh_new() failed.\n");
return 1;
}
The preceding code creates a new SSH session object and stores it in the ssh variable.
Once the SSH session is created, we need to specify some options before completing the connection. The ssh_options_set() function is used to set options. The following code shows setting the remote hostname and port:
/*ssh_connect.c continued*/
ssh_options_set(ssh, SSH_OPTIONS_HOST, hostname);
ssh_options_set(ssh, SSH_OPTIONS_PORT, &port);
libssh includes useful debugging tools. By setting the SSH_OPTIONS_LOG_VERBOSITY option, we tell libssh to print almost everything it does. The following code causes libssh to log a lot of information about which actions it takes:
/*ssh_connect.c continued*/
int verbosity = SSH_LOG_PROTOCOL;
ssh_options_set(ssh, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
This logging is useful to see, but it can also be distracting. I recommend you try it once and then disable it unless you run into problems. The rest of this chapter's examples won't use it.
We can now use ssh_connect() to initiate the SSH connection. The following code shows this:
/*ssh_connect.c continued*/
int ret = ssh_connect(ssh);
if (ret != SSH_OK) {
fprintf(stderr, "ssh_connect() failed.\n%s\n", ssh_get_error(ssh));
return -1;
}
Note that ssh_connect() returns SSH_OK on success. On failure, we use the ssh_get_error() function to detail what went wrong.
Next, our code prints out that the connection was successful:
/*ssh_connect.c continued*/
printf("Connected to %s on port %d.\n", hostname, port);
The SSH protocol allows servers to send a message to clients upon connecting. This message is called the banner. It is typically used to identify the server or provide short access rules. We can print the banner using the following code:
/*ssh_connect.c continued*/
printf("Banner:\n%s\n", ssh_get_serverbanner(ssh));
This is as far as our ssh_connect.c example goes. Our program simply disconnects and frees the SSH session before terminating. The following code concludes ssh_connect.c:
/*ssh_connect.c continued*/
ssh_disconnect(ssh);
ssh_free(ssh);
return 0;
}
You can compile ssh_connect.c with the following command on Windows using MinGW:
gcc ssh_connect.c -o ssh_connect.exe -lssh
On Linux and macOS, the command to compile ssh_connect.c is as follows:
gcc ssh_connect.c -o ssh_connect -lssh
The following screenshot shows ssh_connect.c being successfully compiled and run on Linux:
In the preceding screenshot, you can see that ssh_connect was able to connect to the OpenSSH server running locally.
Now that we've established a connection, let's continue by authenticating with the server.