Blame doc/guided_tour.dox

Packit 6c0a39
/**
Packit 6c0a39
@page libssh_tutor_guided_tour Chapter 1: A typical SSH session
Packit 6c0a39
@section ssh_session A typical SSH session
Packit 6c0a39
Packit 6c0a39
A SSH session goes through the following steps:
Packit 6c0a39
Packit 6c0a39
 - Before connecting to the server, you can set up if you wish one or other
Packit 6c0a39
   server public key authentication, i.e. DSA or RSA. You can choose
Packit 6c0a39
   cryptographic algorithms you trust and compression algorithms if any. You
Packit 6c0a39
   must of course set up the hostname.
Packit 6c0a39
Packit 6c0a39
 - The connection is established. A secure handshake is made, and resulting from
Packit 6c0a39
   it, a public key from the server is gained. You MUST verify that the public
Packit 6c0a39
   key is legitimate, using for instance the MD5 fingerprint or the known hosts
Packit 6c0a39
   file.
Packit 6c0a39
Packit 6c0a39
 - The client must authenticate: the classical ways are password, or
Packit 6c0a39
   public keys (from dsa and rsa key-pairs generated by openssh).
Packit 6c0a39
   If a SSH agent is running, it is possible to use it.
Packit 6c0a39
Packit 6c0a39
 - Now that the user has been authenticated, you must open one or several
Packit 6c0a39
   channels. Channels are different subways for information into a single ssh
Packit 6c0a39
   connection. Each channel has a standard stream (stdout) and an error stream
Packit 6c0a39
   (stderr). You can theoretically open an infinity of channels.
Packit 6c0a39
Packit 6c0a39
 - With the channel you opened, you can do several things:
Packit 6c0a39
   - Execute a single command.
Packit 6c0a39
   - Open a shell. You may want to request a pseudo-terminal before.
Packit 6c0a39
   - Invoke the sftp subsystem to transfer files.
Packit 6c0a39
   - Invoke the scp subsystem to transfer files.
Packit 6c0a39
   - Invoke your own subsystem. This is outside the scope of this document,
Packit 6c0a39
     but can be done.
Packit 6c0a39
Packit 6c0a39
 - When everything is finished, just close the channels, and then the connection.
Packit 6c0a39
Packit 6c0a39
The sftp and scp subsystems use channels, but libssh hides them to
Packit 6c0a39
the programmer. If you want to use those subsystems, instead of a channel,
Packit 6c0a39
you'll usually open a "sftp session" or a "scp session".
Packit 6c0a39
Packit 6c0a39
Packit 6c0a39
@subsection setup Creating the session and setting options
Packit 6c0a39
Packit 6c0a39
The most important object in a SSH connection is the SSH session. In order
Packit 6c0a39
to allocate a new SSH session, you use ssh_new(). Don't forget to
Packit 6c0a39
always verify that the allocation succeeded.
Packit 6c0a39
@code
Packit 6c0a39
#include <libssh/libssh.h>
Packit 6c0a39
#include <stdlib.h>
Packit 6c0a39
Packit 6c0a39
int main()
Packit 6c0a39
{
Packit 6c0a39
  ssh_session my_ssh_session = ssh_new();
Packit 6c0a39
  if (my_ssh_session == NULL)
Packit 6c0a39
    exit(-1);
Packit 6c0a39
  ...
Packit 6c0a39
  ssh_free(my_ssh_session);
Packit 6c0a39
}
Packit 6c0a39
@endcode
Packit 6c0a39
Packit 6c0a39
libssh follows the allocate-it-deallocate-it pattern. Each object that you allocate
Packit 6c0a39
using xxxxx_new() must be deallocated using xxxxx_free(). In this case, ssh_new()
Packit 6c0a39
does the allocation and ssh_free() does the contrary.
Packit 6c0a39
Packit 6c0a39
The ssh_options_set() function sets the options of the session. The most important options are:
Packit 6c0a39
 - SSH_OPTIONS_HOST: the name of the host you want to connect to
Packit 6c0a39
 - SSH_OPTIONS_PORT: the used port (default is port 22)
Packit 6c0a39
 - SSH_OPTIONS_USER: the system user under which you want to connect
Packit 6c0a39
 - SSH_OPTIONS_LOG_VERBOSITY: the quantity of messages that are printed
Packit 6c0a39
Packit 6c0a39
The complete list of options can be found in the documentation of ssh_options_set().
Packit 6c0a39
The only mandatory option is SSH_OPTIONS_HOST. If you don't use SSH_OPTIONS_USER,
Packit 6c0a39
the local username of your account will be used.
Packit 6c0a39
Packit 6c0a39
Here is a small example of how to use it:
Packit 6c0a39
Packit 6c0a39
@code
Packit 6c0a39
#include <libssh/libssh.h>
Packit 6c0a39
#include <stdlib.h>
Packit 6c0a39
Packit 6c0a39
int main()
Packit 6c0a39
{
Packit 6c0a39
  ssh_session my_ssh_session;
Packit 6c0a39
  int verbosity = SSH_LOG_PROTOCOL;
Packit 6c0a39
  int port = 22;
Packit 6c0a39
Packit 6c0a39
  my_ssh_session = ssh_new();
Packit 6c0a39
  if (my_ssh_session == NULL)
Packit 6c0a39
    exit(-1);
Packit 6c0a39
Packit 6c0a39
  ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "localhost");
Packit 6c0a39
  ssh_options_set(my_ssh_session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
Packit 6c0a39
  ssh_options_set(my_ssh_session, SSH_OPTIONS_PORT, &port);
Packit 6c0a39
Packit 6c0a39
  ...
Packit 6c0a39
Packit 6c0a39
  ssh_free(my_ssh_session);
Packit 6c0a39
}
Packit 6c0a39
@endcode
Packit 6c0a39
Packit 6c0a39
Please notice that all parameters are passed to ssh_options_set() as pointers,
Packit 6c0a39
even if you need to set an integer value.
Packit 6c0a39
Packit 6c0a39
@see ssh_new
Packit 6c0a39
@see ssh_free
Packit 6c0a39
@see ssh_options_set
Packit 6c0a39
@see ssh_options_parse_config
Packit 6c0a39
@see ssh_options_copy
Packit 6c0a39
@see ssh_options_getopt
Packit 6c0a39
Packit 6c0a39
Packit 6c0a39
@subsection connect Connecting to the server
Packit 6c0a39
Packit 6c0a39
Once all settings have been made, you can connect using ssh_connect(). That
Packit 6c0a39
function will return SSH_OK if the connection worked, SSH_ERROR otherwise.
Packit 6c0a39
Packit 6c0a39
You can get the English error string with ssh_get_error() in order to show the
Packit 6c0a39
user what went wrong. Then, use ssh_disconnect() when you want to stop
Packit 6c0a39
the session.
Packit 6c0a39
Packit 6c0a39
Here's an example:
Packit 6c0a39
Packit 6c0a39
@code
Packit 6c0a39
#include <libssh/libssh.h>
Packit 6c0a39
#include <stdlib.h>
Packit 6c0a39
#include <stdio.h>
Packit 6c0a39
Packit 6c0a39
int main()
Packit 6c0a39
{
Packit 6c0a39
  ssh_session my_ssh_session;
Packit 6c0a39
  int rc;
Packit 6c0a39
Packit 6c0a39
  my_ssh_session = ssh_new();
Packit 6c0a39
  if (my_ssh_session == NULL)
Packit 6c0a39
    exit(-1);
Packit 6c0a39
Packit 6c0a39
  ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "localhost");
Packit 6c0a39
Packit 6c0a39
  rc = ssh_connect(my_ssh_session);
Packit 6c0a39
  if (rc != SSH_OK)
Packit 6c0a39
  {
Packit 6c0a39
    fprintf(stderr, "Error connecting to localhost: %s\n",
Packit 6c0a39
            ssh_get_error(my_ssh_session));
Packit 6c0a39
    exit(-1);
Packit 6c0a39
  }
Packit 6c0a39
Packit 6c0a39
  ...
Packit 6c0a39
Packit 6c0a39
  ssh_disconnect(my_ssh_session);
Packit 6c0a39
  ssh_free(my_ssh_session);
Packit 6c0a39
}
Packit 6c0a39
@endcode
Packit 6c0a39
Packit 6c0a39
Packit 6c0a39
@subsection serverauth Authenticating the server
Packit 6c0a39
Packit 6c0a39
Once you're connected, the following step is mandatory: you must check that the server
Packit 6c0a39
you just connected to is known and safe to use (remember, SSH is about security and
Packit 6c0a39
authentication).
Packit 6c0a39
Packit 6c0a39
There are two ways of doing this:
Packit 6c0a39
 - The first way (recommended) is to use the ssh_session_is_known_server()
Packit 6c0a39
   function. This function will look into the known host file
Packit 6c0a39
   (~/.ssh/known_hosts on UNIX), look for the server hostname's pattern,
Packit 6c0a39
   and determine whether this host is present or not in the list.
Packit 6c0a39
 - The second way is to use ssh_get_pubkey_hash() to get a binary version
Packit 6c0a39
   of the public key hash value. You can then use your own database to check
Packit 6c0a39
   if this public key is known and secure.
Packit 6c0a39
Packit 6c0a39
You can also use the ssh_get_pubkey_hash() to show the public key hash
Packit 6c0a39
value to the user, in case he knows what the public key hash value is
Packit 6c0a39
(some paranoid people write their public key hash values on paper before
Packit 6c0a39
going abroad, just in case ...).
Packit 6c0a39
Packit 6c0a39
If the remote host is being used to for the first time, you can ask the user whether
Packit 6c0a39
he/she trusts it. Once he/she concluded that the host is valid and worth being
Packit 6c0a39
added in the known hosts file, you use ssh_write_knownhost() to register it in
Packit 6c0a39
the known hosts file, or any other way if you use your own database.
Packit 6c0a39
Packit 6c0a39
The following example is part of the examples suite available in the
Packit 6c0a39
examples/ directory:
Packit 6c0a39
Packit 6c0a39
@code
Packit 6c0a39
#include <errno.h>
Packit 6c0a39
#include <string.h>
Packit 6c0a39
Packit 6c0a39
int verify_knownhost(ssh_session session)
Packit 6c0a39
{
Packit 6c0a39
    enum ssh_known_hosts_e state;
Packit 6c0a39
    unsigned char *hash = NULL;
Packit 6c0a39
    ssh_key srv_pubkey = NULL;
Packit 6c0a39
    size_t hlen;
Packit 6c0a39
    char buf[10];
Packit 6c0a39
    char *hexa;
Packit 6c0a39
    char *p;
Packit 6c0a39
    int cmp;
Packit 6c0a39
    int rc;
Packit 6c0a39
Packit 6c0a39
    rc = ssh_get_server_publickey(session, &srv_pubkey);
Packit 6c0a39
    if (rc < 0) {
Packit 6c0a39
        return -1;
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    rc = ssh_get_publickey_hash(srv_pubkey,
Packit 6c0a39
                                SSH_PUBLICKEY_HASH_SHA1,
Packit 6c0a39
                                &hash,
Packit 6c0a39
                                &hlen);
Packit 6c0a39
    ssh_key_free(srv_pubkey);
Packit 6c0a39
    if (rc < 0) {
Packit 6c0a39
        return -1;
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    state = ssh_session_is_known_server(session);
Packit 6c0a39
    switch (state) {
Packit 6c0a39
        case SSH_KNOWN_HOSTS_OK:
Packit 6c0a39
            /* OK */
Packit 6c0a39
Packit 6c0a39
            break;
Packit 6c0a39
        case SSH_KNOWN_HOSTS_CHANGED:
Packit 6c0a39
            fprintf(stderr, "Host key for server changed: it is now:\n");
Packit 6c0a39
            ssh_print_hexa("Public key hash", hash, hlen);
Packit 6c0a39
            fprintf(stderr, "For security reasons, connection will be stopped\n");
Packit 6c0a39
            ssh_clean_pubkey_hash(&hash);
Packit 6c0a39
Packit 6c0a39
            return -1;
Packit 6c0a39
        case SSH_KNOWN_HOSTS_OTHER:
Packit 6c0a39
            fprintf(stderr, "The host key for this server was not found but an other"
Packit 6c0a39
                    "type of key exists.\n");
Packit 6c0a39
            fprintf(stderr, "An attacker might change the default server key to"
Packit 6c0a39
                    "confuse your client into thinking the key does not exist\n");
Packit 6c0a39
            ssh_clean_pubkey_hash(&hash);
Packit 6c0a39
Packit 6c0a39
            return -1;
Packit 6c0a39
        case SSH_KNOWN_HOSTS_NOT_FOUND:
Packit 6c0a39
            fprintf(stderr, "Could not find known host file.\n");
Packit 6c0a39
            fprintf(stderr, "If you accept the host key here, the file will be"
Packit 6c0a39
                    "automatically created.\n");
Packit 6c0a39
Packit 6c0a39
            /* FALL THROUGH to SSH_SERVER_NOT_KNOWN behavior */
Packit 6c0a39
Packit 6c0a39
        case SSH_KNOWN_HOSTS_UNKNOWN:
Packit 6c0a39
            hexa = ssh_get_hexa(hash, hlen);
Packit 6c0a39
            fprintf(stderr,"The server is unknown. Do you trust the host key?\n");
Packit 6c0a39
            fprintf(stderr, "Public key hash: %s\n", hexa);
Packit 6c0a39
            ssh_string_free_char(hexa);
Packit 6c0a39
            ssh_clean_pubkey_hash(&hash);
Packit 6c0a39
            p = fgets(buf, sizeof(buf), stdin);
Packit 6c0a39
            if (p == NULL) {
Packit 6c0a39
                return -1;
Packit 6c0a39
            }
Packit 6c0a39
Packit 6c0a39
            cmp = strncasecmp(buf, "yes", 3);
Packit 6c0a39
            if (cmp != 0) {
Packit 6c0a39
                return -1;
Packit 6c0a39
            }
Packit 6c0a39
Packit 6c0a39
            rc = ssh_session_update_known_hosts(session);
Packit 6c0a39
            if (rc < 0) {
Packit 6c0a39
                fprintf(stderr, "Error %s\n", strerror(errno));
Packit 6c0a39
                return -1;
Packit 6c0a39
            }
Packit 6c0a39
Packit 6c0a39
            break;
Packit 6c0a39
        case SSH_KNOWN_HOSTS_ERROR:
Packit 6c0a39
            fprintf(stderr, "Error %s", ssh_get_error(session));
Packit 6c0a39
            ssh_clean_pubkey_hash(&hash);
Packit 6c0a39
            return -1;
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    ssh_clean_pubkey_hash(&hash);
Packit 6c0a39
    return 0;
Packit 6c0a39
}
Packit 6c0a39
@endcode
Packit 6c0a39
Packit 6c0a39
@see ssh_connect
Packit 6c0a39
@see ssh_disconnect
Packit 6c0a39
@see ssh_get_error
Packit 6c0a39
@see ssh_get_error_code
Packit 6c0a39
@see ssh_get_server_publickey
Packit 6c0a39
@see ssh_get_publickey_hash
Packit 6c0a39
@see ssh_session_is_known_server
Packit 6c0a39
@see ssh_session_update_known_hosts
Packit 6c0a39
Packit 6c0a39
Packit 6c0a39
@subsection auth Authenticating the user
Packit 6c0a39
Packit 6c0a39
The authentication process is the way a service provider can identify a
Packit 6c0a39
user and verify his/her identity. The authorization process is about enabling
Packit 6c0a39
the authenticated user the access to resources. In SSH, the two concepts
Packit 6c0a39
are linked. After authentication, the server can grant the user access to
Packit 6c0a39
several resources such as port forwarding, shell, sftp subsystem, and so on.
Packit 6c0a39
Packit 6c0a39
libssh supports several methods of authentication:
Packit 6c0a39
 - "none" method. This method allows to get the available authentications
Packit 6c0a39
   methods. It also gives the server a chance to authenticate the user with
Packit 6c0a39
   just his/her login. Some very old hardware uses this feature to fallback
Packit 6c0a39
   the user on a "telnet over SSH" style of login.
Packit 6c0a39
 - password method. A password is sent to the server, which accepts it or not.
Packit 6c0a39
 - keyboard-interactive method. The server sends several challenges to the
Packit 6c0a39
   user, who must answer correctly. This makes possible the authentication
Packit 6c0a39
   via a codebook for instance ("give code at 23:R on page 3").
Packit 6c0a39
 - public key method. The host knows the public key of the user, and the
Packit 6c0a39
   user must prove he knows the associated private key. This can be done
Packit 6c0a39
   manually, or delegated to the SSH agent as we'll see later.
Packit 6c0a39
Packit 6c0a39
All these methods can be combined. You can for instance force the user to
Packit 6c0a39
authenticate with at least two of the authentication methods. In that case,
Packit 6c0a39
one speaks of "Partial authentication". A partial authentication is a
Packit 6c0a39
response from authentication functions stating that your credential was
Packit 6c0a39
accepted, but yet another one is required to get in.
Packit 6c0a39
Packit 6c0a39
The example below shows an authentication with password:
Packit 6c0a39
Packit 6c0a39
@code
Packit 6c0a39
#include <libssh/libssh.h>
Packit 6c0a39
#include <stdlib.h>
Packit 6c0a39
#include <stdio.h>
Packit 6c0a39
Packit 6c0a39
int main()
Packit 6c0a39
{
Packit 6c0a39
  ssh_session my_ssh_session;
Packit 6c0a39
  int rc;
Packit 6c0a39
  char *password;
Packit 6c0a39
Packit 6c0a39
  // Open session and set options
Packit 6c0a39
  my_ssh_session = ssh_new();
Packit 6c0a39
  if (my_ssh_session == NULL)
Packit 6c0a39
    exit(-1);
Packit 6c0a39
  ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "localhost");
Packit 6c0a39
Packit 6c0a39
  // Connect to server
Packit 6c0a39
  rc = ssh_connect(my_ssh_session);
Packit 6c0a39
  if (rc != SSH_OK)
Packit 6c0a39
  {
Packit 6c0a39
    fprintf(stderr, "Error connecting to localhost: %s\n",
Packit 6c0a39
            ssh_get_error(my_ssh_session));
Packit 6c0a39
    ssh_free(my_ssh_session);
Packit 6c0a39
    exit(-1);
Packit 6c0a39
  }
Packit 6c0a39
Packit 6c0a39
  // Verify the server's identity
Packit 6c0a39
  // For the source code of verify_knownhost(), check previous example
Packit 6c0a39
  if (verify_knownhost(my_ssh_session) < 0)
Packit 6c0a39
  {
Packit 6c0a39
    ssh_disconnect(my_ssh_session);
Packit 6c0a39
    ssh_free(my_ssh_session);
Packit 6c0a39
    exit(-1);
Packit 6c0a39
  }
Packit 6c0a39
Packit 6c0a39
  // Authenticate ourselves
Packit 6c0a39
  password = getpass("Password: ");
Packit 6c0a39
  rc = ssh_userauth_password(my_ssh_session, NULL, password);
Packit 6c0a39
  if (rc != SSH_AUTH_SUCCESS)
Packit 6c0a39
  {
Packit 6c0a39
    fprintf(stderr, "Error authenticating with password: %s\n",
Packit 6c0a39
            ssh_get_error(my_ssh_session));
Packit 6c0a39
    ssh_disconnect(my_ssh_session);
Packit 6c0a39
    ssh_free(my_ssh_session);
Packit 6c0a39
    exit(-1);
Packit 6c0a39
  }
Packit 6c0a39
Packit 6c0a39
  ...
Packit 6c0a39
Packit 6c0a39
  ssh_disconnect(my_ssh_session);
Packit 6c0a39
  ssh_free(my_ssh_session);
Packit 6c0a39
}
Packit 6c0a39
@endcode
Packit 6c0a39
Packit 6c0a39
@see @ref authentication_details
Packit 6c0a39
Packit 6c0a39
Packit 6c0a39
@subsection using_ssh Doing something
Packit 6c0a39
Packit 6c0a39
At this point, the authenticity of both server and client is established.
Packit 6c0a39
Time has come to take advantage of the many possibilities offered by the SSH
Packit 6c0a39
protocol: execute a remote command, open remote shells, transfer files,
Packit 6c0a39
forward ports, etc.
Packit 6c0a39
Packit 6c0a39
The example below shows how to execute a remote command:
Packit 6c0a39
Packit 6c0a39
@code
Packit 6c0a39
int show_remote_processes(ssh_session session)
Packit 6c0a39
{
Packit 6c0a39
  ssh_channel channel;
Packit 6c0a39
  int rc;
Packit 6c0a39
  char buffer[256];
Packit 6c0a39
  int nbytes;
Packit 6c0a39
Packit 6c0a39
  channel = ssh_channel_new(session);
Packit 6c0a39
  if (channel == NULL)
Packit 6c0a39
    return SSH_ERROR;
Packit 6c0a39
Packit 6c0a39
  rc = ssh_channel_open_session(channel);
Packit 6c0a39
  if (rc != SSH_OK)
Packit 6c0a39
  {
Packit 6c0a39
    ssh_channel_free(channel);
Packit 6c0a39
    return rc;
Packit 6c0a39
  }
Packit 6c0a39
Packit 6c0a39
  rc = ssh_channel_request_exec(channel, "ps aux");
Packit 6c0a39
  if (rc != SSH_OK)
Packit 6c0a39
  {
Packit 6c0a39
    ssh_channel_close(channel);
Packit 6c0a39
    ssh_channel_free(channel);
Packit 6c0a39
    return rc;
Packit 6c0a39
  }
Packit 6c0a39
Packit 6c0a39
  nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
Packit 6c0a39
  while (nbytes > 0)
Packit 6c0a39
  {
Packit 6c0a39
    if (write(1, buffer, nbytes) != (unsigned int) nbytes)
Packit 6c0a39
    {
Packit 6c0a39
      ssh_channel_close(channel);
Packit 6c0a39
      ssh_channel_free(channel);
Packit 6c0a39
      return SSH_ERROR;
Packit 6c0a39
    }
Packit 6c0a39
    nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
Packit 6c0a39
  }
Packit 6c0a39
Packit 6c0a39
  if (nbytes < 0)
Packit 6c0a39
  {
Packit 6c0a39
    ssh_channel_close(channel);
Packit 6c0a39
    ssh_channel_free(channel);
Packit 6c0a39
    return SSH_ERROR;
Packit 6c0a39
  }
Packit 6c0a39
Packit 6c0a39
  ssh_channel_send_eof(channel);
Packit 6c0a39
  ssh_channel_close(channel);
Packit 6c0a39
  ssh_channel_free(channel);
Packit 6c0a39
Packit 6c0a39
  return SSH_OK;
Packit 6c0a39
}
Packit 6c0a39
@endcode
Packit 6c0a39
Packit 6c0a39
Each ssh_channel_request_exec() needs to be run on freshly created
Packit 6c0a39
and connected (with ssh_channel_open_session()) channel.
Packit 6c0a39
Packit 6c0a39
@see @ref opening_shell
Packit 6c0a39
@see @ref remote_command
Packit 6c0a39
@see @ref sftp_subsystem
Packit 6c0a39
@see @ref scp_subsystem
Packit 6c0a39
Packit 6c0a39
Packit 6c0a39
@subsection errors Handling the errors
Packit 6c0a39
Packit 6c0a39
All the libssh functions which return an error value also set an English error message
Packit 6c0a39
describing the problem.
Packit 6c0a39
Packit 6c0a39
Error values are typically SSH_ERROR for integer values, or NULL for pointers.
Packit 6c0a39
Packit 6c0a39
The function ssh_get_error() returns a pointer to the static error message.
Packit 6c0a39
Packit 6c0a39
ssh_error_code() returns the error code number : SSH_NO_ERROR,
Packit 6c0a39
SSH_REQUEST_DENIED, SSH_INVALID_REQUEST, SSH_CONNECTION_LOST, SSH_FATAL,
Packit 6c0a39
or SSH_INVALID_DATA. SSH_REQUEST_DENIED means the ssh server refused your
Packit 6c0a39
request, but the situation is recoverable. The others mean something happened
Packit 6c0a39
to the connection (some encryption problems, server problems, ...).
Packit 6c0a39
SSH_INVALID_REQUEST means the library got some garbage from server, but
Packit 6c0a39
might be recoverable. SSH_FATAL means the connection has an important
Packit 6c0a39
problem and isn't probably recoverable.
Packit 6c0a39
Packit 6c0a39
Most of time, the error returned are SSH_FATAL, but some functions
Packit 6c0a39
(generally the ssh_request_xxx ones) may fail because of server denying request.
Packit 6c0a39
In these cases, SSH_REQUEST_DENIED is returned.
Packit 6c0a39
Packit 6c0a39
For thread safety, errors are bound to ssh_session objects.
Packit 6c0a39
As long as your ssh_session object is not NULL, you can retrieve the last error
Packit 6c0a39
message and error code from the ssh_session using ssh_get_error() and
Packit 6c0a39
ssh_get_error_code() respectively.
Packit 6c0a39
Packit 6c0a39
The SFTP subsystem has its own error codes, in addition to libssh ones.
Packit 6c0a39
Packit 6c0a39
Packit 6c0a39
*/