diff options
author | Eric Bischoff <eric@bureau-cornavin.com> | 2010-08-23 21:00:35 +0200 |
---|---|---|
committer | Aris Adamantiadis <aris@0xbadc0de.be> | 2010-08-23 21:00:35 +0200 |
commit | 94b689e19d51ab887afe95afd8e9bf50a18af0c4 (patch) | |
tree | 4006c0cdfe0be48e3af0d104221db08d12dda046 /doc/guided_tour.dox | |
parent | 8066100f5360e33f6c02d00ee727a434d8af014e (diff) | |
download | libssh-94b689e19d51ab887afe95afd8e9bf50a18af0c4.tar.gz libssh-94b689e19d51ab887afe95afd8e9bf50a18af0c4.tar.xz libssh-94b689e19d51ab887afe95afd8e9bf50a18af0c4.zip |
New update of doxygen documentation
Diffstat (limited to 'doc/guided_tour.dox')
-rw-r--r-- | doc/guided_tour.dox | 428 |
1 files changed, 428 insertions, 0 deletions
diff --git a/doc/guided_tour.dox b/doc/guided_tour.dox new file mode 100644 index 00000000..08c20583 --- /dev/null +++ b/doc/guided_tour.dox @@ -0,0 +1,428 @@ +@page guided_tour Chapter 1: A typical SSH session +@section ssh_session A typical SSH session + +A SSH session goes through the following steps: + + - Before connecting to the server, you can set up if you wish one or other + server public key authentication, i.e. DSA or RSA. You can choose + cryptographic algorithms you trust and compression algorithms if any. You + must of course set up the hostname. + + - The connection is established. A secure handshake is made, and resulting from + it, a public key from the server is gained. You MUST verify that the public + key is legitimate, using for instance the MD5 fingerprint or the known hosts + file. + + - The client must authenticate: the classical ways are password, or + public keys (from dsa and rsa key-pairs generated by openssh). + If a SSH agent is running, it is possible to use it. + + - Now that the user has been authenticated, you must open one or several + channels. Channels are different subways for information into a single ssh + connection. Each channel has a standard stream (stdout) and an error stream + (stderr). You can theoretically open an infinity of channels. + + - With the channel you opened, you can do several things: + - Execute a single command. + - Open a shell. You may want to request a pseudo-terminal before. + - Invoke the sftp subsystem to transfer files. + - Invoke the scp subsystem to transfer files. + - Invoke your own subsystem. This is outside the scope of this document, + but can be done. + + - When everything is finished, just close the channels, and then the connection. + +The sftp and scp subsystems use channels, but libssh hides them to +the programmer. If you want to use those subsystems, instead of a channel, +you'll usually open a "sftp session" or a "scp session". + +All the libssh functions which return an error code also set an error message. +Error codes are typically SSH_ERROR for integer values, or NULL for pointers. + + +@subsection setup Creating the session and setting options + +The most important object in a SSH connection is the SSH session. In order +to allocate a new SSH session, you use ssh_new(). Don't forget to +always verify that the allocation successed. +@code +#include <libssh/libssh.h> +#include <stdlib.h> + +int main() +{ + ssh_session my_ssh_session = ssh_new(); + if (my_ssh_session == NULL) + exit(-1); + ... + ssh_free(my_ssh_session); +} +@endcode + +libssh follows the allocate-it-deallocate-it pattern. Each object that you allocate +using xxxxx_new() must be deallocated using xxxxx_free(). In this case, ssh_new() +does the allocation and ssh_free() does the contrary. + +The ssh_options_set() function sets the options of the session. The most important options are: + - SSH_OPTIONS_HOST: the name of the host you want to connect to + - SSH_OPTIONS_PORT: the used port (default is port 22) + - SSH_OPTIONS_USER: the system user under which you want to connect + - SSH_OPTIONS_LOG_VERBOSITY: the quantity of messages that are printed + +The complete list of options can be found in the documentation of ssh_options_set(). +The only mandatory option is SSH_OPTIONS_HOST. If you don't use SSH_OPTIONS_USER, +the local username of your account will be used. + +Here is a small example of how to use it: + +@code +#include <libssh/libssh.h> +#include <stdlib.h> + +int main() +{ + ssh_session my_ssh_session; + int verbosity = SSH_LOG_PROTOCOL; + int port = 22; + + my_ssh_session = ssh_new(); + if (my_ssh_session == NULL) + exit(-1); + + ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "localhost"); + ssh_options_set(my_ssh_session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); + ssh_options_set(my_ssh_session, SSH_OPTIONS_PORT, &port); + + ... + + ssh_free(my_ssh_session); +} +@endcode + +Please notice that all parameters are passed to ssh_options_set() as pointers, +even if you need to set an integer value. + +@see ssh_new +@see ssh_free +@see ssh_options_set +@see ssh_options_parse_config +@see ssh_options_copy +@see ssh_options_getopt + + +@subsection connect Connecting to the server + +Once all settings have been made, you can connect using ssh_connect(). That +function will return SSH_OK if the connection worked, SSH_ERROR otherwise. + +You can get the English error string with ssh_get_error() in order to show the +user what went wrong. Then, use ssh_disconnect() when you want to stop +the session. + +Here's an example: + +@code +#include <libssh/libssh.h> +#include <stdlib.h> +#include <stdio.h> + +int main() +{ + ssh_session my_ssh_session; + int rc; + + my_ssh_session = ssh_new(); + if (my_ssh_session == NULL) + exit(-1); + + ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "localhost"); + + rc = ssh_connect(my_ssh_session); + if (rc != SSH_OK) + { + fprintf(stderr, "Error connecting to localhost: %s\n", + ssh_get_error(my_ssh_session)); + exit(-1); + } + + ... + + ssh_disconnect(my_ssh_session); + ssh_free(my_ssh_session); +} +@endcode + + +@subsection serverauth Authenticating the server + +Once you're connected, the following step is mandatory: you must check that the server +you just connected to is known and safe to use (remember, SSH is about security and +authentication). + +There are two ways of doing this: + - The first way (recommended) is to use the ssh_is_server_known() + function. This function will look into the known host file + (~/.ssh/known_hosts on UNIX), look for the server hostname's pattern, + and determine whether this host is present or not in the list. + - The second way is to use ssh_get_pubkey_hash() to get a binary version + of the public key hash value. You can then use your own database to check + if this public key is known and secure. + +You can also use the ssh_get_pubkey_hash() to show the public key hash +value to the user, in case he knows what the public key hash value is +(some paranoid people write their public key hash values on paper before +going abroad, just in case ...). + +If the remote host is being used to for the first time, you can ask the user whether +he/she trusts it. Once he/she concluded that the host is valid and worth being +added in the known hosts file, you use ssh_write_knownhost() to register it in +the known hosts file, or any other way if you use your own database. + +The following example is part of the examples suite available in the +examples/ directory: + +@code +#include <errno.h> +#include <string.h> + +int verify_knownhost(ssh_session session) +{ + int state, hlen; + unsigned char *hash = NULL; + char *hexa; + char buf[10]; + + state = ssh_is_server_known(session); + + hlen = ssh_get_pubkey_hash(session, &hash); + if (hlen < 0) + return -1; + + switch (state) + { + case SSH_SERVER_KNOWN_OK: + break; /* ok */ + + case SSH_SERVER_KNOWN_CHANGED: + fprintf(stderr, "Host key for server changed: it is now:\n"); + ssh_print_hexa("Public key hash", hash, hlen); + fprintf(stderr, "For security reasons, connection will be stopped\n"); + free(hash); + return -1; + + case SSH_SERVER_FOUND_OTHER: + fprintf(stderr, "The host key for this server was not found but an other" + "type of key exists.\n"); + fprintf(stderr, "An attacker might change the default server key to" + "confuse your client into thinking the key does not exist\n"); + free(hash); + return -1; + + case SSH_SERVER_FILE_NOT_FOUND: + fprintf(stderr, "Could not find known host file.\n"); + fprintf(stderr, "If you accept the host key here, the file will be" + "automatically created.\n"); + /* fallback to SSH_SERVER_NOT_KNOWN behavior */ + + case SSH_SERVER_NOT_KNOWN: + hexa = ssh_get_hexa(hash, hlen); + fprintf(stderr,"The server is unknown. Do you trust the host key?\n"); + fprintf(stderr, "Public key hash: %s\n", hexa); + free(hexa); + if (fgets(buf, sizeof(buf), stdin) == NULL) + { + free(hash); + return -1; + } + if (strncasecmp(buf, "yes", 3) != 0) + { + free(hash); + return -1; + } + if (ssh_write_knownhost(session) < 0) + { + fprintf(stderr, "Error %s\n", strerror(errno)); + free(hash); + return -1; + } + break; + + case SSH_SERVER_ERROR: + fprintf(stderr, "Error %s", ssh_get_error(session)); + free(hash); + return -1; + } + + free(hash); + return 0; +} +@endcode + +@see ssh_connect +@see ssh_disconnect +@see ssh_get_error +@see ssh_get_error_code +@see ssh_get_pubkey_hash +@see ssh_is_server_known +@see ssh_write_knownhost + + +@subsection auth Authenticating the user + +The authentication process is the way a service provider can identify a +user and verify his/her identity. The authorization process is about enabling +the authenticated user the access to ressources. In SSH, the two concepts +are linked. After authentication, the server can grant the user access to +several ressources such as port forwarding, shell, sftp subsystem, and so on. + +libssh supports several methods of authentication: + - "none" method. This method allows to get the available authentications + methods. It also gives the server a chance to authenticate the user with + just his/her login. Some very old hardware uses this feature to fallback + the user on a "telnet over SSH" style of login. + - password method. A password is sent to the server, which accepts it or not. + - keyboard-interactive method. The server sends several challenges to the + user, who must answer correctly. This makes possible the authentication + via a codebook for instance ("give code at 23:R on page 3"). + - public key method. The host knows the public key of the user, and the + user must prove he knows the associated private key. This can be done + manually, or delegated to the SSH agent as we'll see later. + +All these methods can be combined. You can for instance force the user to +authenticate with at least two of the authentication methods. In that case, +one speaks of "Partial authentication". A partial authentication is a +response from authentication functions stating that your credential was +accepted, but yet another one is required to get in. + +The example below shows an authentication with password: + +@code +#include <libssh/libssh.h> +#include <stdlib.h> +#include <stdio.h> + +int main() +{ + ssh_session my_ssh_session; + int rc; + char *password; + + // Open session and set options + my_ssh_session = ssh_new(); + if (my_ssh_session == NULL) + exit(-1); + ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "localhost"); + + // Connect to server + rc = ssh_connect(my_ssh_session); + if (rc != SSH_OK) + { + fprintf(stderr, "Error connecting to localhost: %s\n", + ssh_get_error(my_ssh_session)); + ssh_free(my_ssh_session); + exit(-1); + } + + // Verify the server's identity + // For the source code of verify_knowhost(), check previous example + if (verify_knownhost(my_ssh_session) < 0) + { + ssh_disconnect(my_ssh_session); + ssh_free(my_ssh_session); + exit(-1); + } + + // Authenticate ourselves + password = getpass("Password: "); + rc = ssh_userauth_password(my_ssh_session, NULL, password); + if (rc != SSH_AUTH_SUCCESS) + { + fprintf(stderr, "Error authenticating with password: %s\n", + ssh_get_error(my_ssh_session)); + ssh_disconnect(my_ssh_session); + ssh_free(my_ssh_session); + exit(-1); + } + + ... + + ssh_disconnect(my_ssh_session); + ssh_free(my_ssh_session); +} +@endcode + +@see @ref authentication_details + + +@subsection using_ssh Doing something + +At this point, the authenticity of both server and client is established. +Time has come to take advantage of the many possibilities offered by the SSH +protocol: execute remote commands, open remote shells, transfer files, +forward ports, etc. + +The example below shows how to execute a remote command: + +@code +int show_remote_processes(ssh_session session) +{ + ssh_channel channel; + int rc; + char buffer[256]; + unsigned int nbytes; + + channel = ssh_channel_new(session); + if (channel == NULL) + return SSH_ERROR; + + rc = ssh_channel_open_session(channel); + if (rc != SSH_OK) + { + ssh_channel_free(channel); + return rc; + } + + rc = ssh_channel_request_exec(channel, "ps aux"); + if (rc != SSH_OK) + { + ssh_channel_close(channel); + ssh_channel_free(channel); + return rc; + } + + nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0); + while (nbytes > 0) + { + if (write(1, buffer, nbytes) != nbytes) + { + ssh_channel_close(channel); + ssh_channel_free(channel); + return SSH_ERROR; + } + nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0); + } + + if (nbytes < 0) + { + ssh_channel_close(channel); + ssh_channel_free(channel); + return SSH_ERROR; + } + + ssh_channel_send_eof(channel); + ssh_channel_close(channel); + ssh_channel_free(channel); + + return SSH_OK; +} +@endcode + +That's the end of our step-by-step discovery of a SSH connection. +The next chapter describes more in depth the authentication mechanisms. + +@see @ref opening_shell +@see @ref remote_commands +@see @ref sftp_subsystem +@see @ref scp_subsystem + + |