Blame doc/guided_tour.dox

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