2
@page libssh_tutor_guided_tour Chapter 1: A typical SSH session
3
@section ssh_session A typical SSH session
5
A SSH session goes through the following steps:
7
- Before connecting to the server, you can set up if you wish one or other
8
server public key authentication, i.e. DSA or RSA. You can choose
9
cryptographic algorithms you trust and compression algorithms if any. You
10
must of course set up the hostname.
12
- The connection is established. A secure handshake is made, and resulting from
13
it, a public key from the server is gained. You MUST verify that the public
14
key is legitimate, using for instance the MD5 fingerprint or the known hosts
17
- The client must authenticate: the classical ways are password, or
18
public keys (from dsa and rsa key-pairs generated by openssh).
19
If a SSH agent is running, it is possible to use it.
21
- Now that the user has been authenticated, you must open one or several
22
channels. Channels are different subways for information into a single ssh
23
connection. Each channel has a standard stream (stdout) and an error stream
24
(stderr). You can theoretically open an infinity of channels.
26
- With the channel you opened, you can do several things:
27
- Execute a single command.
28
- Open a shell. You may want to request a pseudo-terminal before.
29
- Invoke the sftp subsystem to transfer files.
30
- Invoke the scp subsystem to transfer files.
31
- Invoke your own subsystem. This is outside the scope of this document,
34
- When everything is finished, just close the channels, and then the connection.
36
The sftp and scp subsystems use channels, but libssh hides them to
37
the programmer. If you want to use those subsystems, instead of a channel,
38
you'll usually open a "sftp session" or a "scp session".
41
@subsection setup Creating the session and setting options
43
The most important object in a SSH connection is the SSH session. In order
44
to allocate a new SSH session, you use ssh_new(). Don't forget to
45
always verify that the allocation successed.
47
#include <libssh/libssh.h>
52
ssh_session my_ssh_session = ssh_new();
53
if (my_ssh_session == NULL)
56
ssh_free(my_ssh_session);
60
libssh follows the allocate-it-deallocate-it pattern. Each object that you allocate
61
using xxxxx_new() must be deallocated using xxxxx_free(). In this case, ssh_new()
62
does the allocation and ssh_free() does the contrary.
64
The ssh_options_set() function sets the options of the session. The most important options are:
65
- SSH_OPTIONS_HOST: the name of the host you want to connect to
66
- SSH_OPTIONS_PORT: the used port (default is port 22)
67
- SSH_OPTIONS_USER: the system user under which you want to connect
68
- SSH_OPTIONS_LOG_VERBOSITY: the quantity of messages that are printed
70
The complete list of options can be found in the documentation of ssh_options_set().
71
The only mandatory option is SSH_OPTIONS_HOST. If you don't use SSH_OPTIONS_USER,
72
the local username of your account will be used.
74
Here is a small example of how to use it:
77
#include <libssh/libssh.h>
82
ssh_session my_ssh_session;
83
int verbosity = SSH_LOG_PROTOCOL;
86
my_ssh_session = ssh_new();
87
if (my_ssh_session == NULL)
90
ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "localhost");
91
ssh_options_set(my_ssh_session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
92
ssh_options_set(my_ssh_session, SSH_OPTIONS_PORT, &port);
96
ssh_free(my_ssh_session);
100
Please notice that all parameters are passed to ssh_options_set() as pointers,
101
even if you need to set an integer value.
106
@see ssh_options_parse_config
107
@see ssh_options_copy
108
@see ssh_options_getopt
111
@subsection connect Connecting to the server
113
Once all settings have been made, you can connect using ssh_connect(). That
114
function will return SSH_OK if the connection worked, SSH_ERROR otherwise.
116
You can get the English error string with ssh_get_error() in order to show the
117
user what went wrong. Then, use ssh_disconnect() when you want to stop
123
#include <libssh/libssh.h>
129
ssh_session my_ssh_session;
132
my_ssh_session = ssh_new();
133
if (my_ssh_session == NULL)
136
ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "localhost");
138
rc = ssh_connect(my_ssh_session);
141
fprintf(stderr, "Error connecting to localhost: %s\n",
142
ssh_get_error(my_ssh_session));
148
ssh_disconnect(my_ssh_session);
149
ssh_free(my_ssh_session);
154
@subsection serverauth Authenticating the server
156
Once you're connected, the following step is mandatory: you must check that the server
157
you just connected to is known and safe to use (remember, SSH is about security and
160
There are two ways of doing this:
161
- The first way (recommended) is to use the ssh_is_server_known()
162
function. This function will look into the known host file
163
(~/.ssh/known_hosts on UNIX), look for the server hostname's pattern,
164
and determine whether this host is present or not in the list.
165
- The second way is to use ssh_get_pubkey_hash() to get a binary version
166
of the public key hash value. You can then use your own database to check
167
if this public key is known and secure.
169
You can also use the ssh_get_pubkey_hash() to show the public key hash
170
value to the user, in case he knows what the public key hash value is
171
(some paranoid people write their public key hash values on paper before
172
going abroad, just in case ...).
174
If the remote host is being used to for the first time, you can ask the user whether
175
he/she trusts it. Once he/she concluded that the host is valid and worth being
176
added in the known hosts file, you use ssh_write_knownhost() to register it in
177
the known hosts file, or any other way if you use your own database.
179
The following example is part of the examples suite available in the
186
int verify_knownhost(ssh_session session)
189
unsigned char *hash = NULL;
193
state = ssh_is_server_known(session);
195
hlen = ssh_get_pubkey_hash(session, &hash);
201
case SSH_SERVER_KNOWN_OK:
204
case SSH_SERVER_KNOWN_CHANGED:
205
fprintf(stderr, "Host key for server changed: it is now:\n");
206
ssh_print_hexa("Public key hash", hash, hlen);
207
fprintf(stderr, "For security reasons, connection will be stopped\n");
211
case SSH_SERVER_FOUND_OTHER:
212
fprintf(stderr, "The host key for this server was not found but an other"
213
"type of key exists.\n");
214
fprintf(stderr, "An attacker might change the default server key to"
215
"confuse your client into thinking the key does not exist\n");
219
case SSH_SERVER_FILE_NOT_FOUND:
220
fprintf(stderr, "Could not find known host file.\n");
221
fprintf(stderr, "If you accept the host key here, the file will be"
222
"automatically created.\n");
223
/* fallback to SSH_SERVER_NOT_KNOWN behavior */
225
case SSH_SERVER_NOT_KNOWN:
226
hexa = ssh_get_hexa(hash, hlen);
227
fprintf(stderr,"The server is unknown. Do you trust the host key?\n");
228
fprintf(stderr, "Public key hash: %s\n", hexa);
230
if (fgets(buf, sizeof(buf), stdin) == NULL)
235
if (strncasecmp(buf, "yes", 3) != 0)
240
if (ssh_write_knownhost(session) < 0)
242
fprintf(stderr, "Error %s\n", strerror(errno));
248
case SSH_SERVER_ERROR:
249
fprintf(stderr, "Error %s", ssh_get_error(session));
262
@see ssh_get_error_code
263
@see ssh_get_pubkey_hash
264
@see ssh_is_server_known
265
@see ssh_write_knownhost
268
@subsection auth Authenticating the user
270
The authentication process is the way a service provider can identify a
271
user and verify his/her identity. The authorization process is about enabling
272
the authenticated user the access to ressources. In SSH, the two concepts
273
are linked. After authentication, the server can grant the user access to
274
several ressources such as port forwarding, shell, sftp subsystem, and so on.
276
libssh supports several methods of authentication:
277
- "none" method. This method allows to get the available authentications
278
methods. It also gives the server a chance to authenticate the user with
279
just his/her login. Some very old hardware uses this feature to fallback
280
the user on a "telnet over SSH" style of login.
281
- password method. A password is sent to the server, which accepts it or not.
282
- keyboard-interactive method. The server sends several challenges to the
283
user, who must answer correctly. This makes possible the authentication
284
via a codebook for instance ("give code at 23:R on page 3").
285
- public key method. The host knows the public key of the user, and the
286
user must prove he knows the associated private key. This can be done
287
manually, or delegated to the SSH agent as we'll see later.
289
All these methods can be combined. You can for instance force the user to
290
authenticate with at least two of the authentication methods. In that case,
291
one speaks of "Partial authentication". A partial authentication is a
292
response from authentication functions stating that your credential was
293
accepted, but yet another one is required to get in.
295
The example below shows an authentication with password:
298
#include <libssh/libssh.h>
304
ssh_session my_ssh_session;
308
// Open session and set options
309
my_ssh_session = ssh_new();
310
if (my_ssh_session == NULL)
312
ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "localhost");
315
rc = ssh_connect(my_ssh_session);
318
fprintf(stderr, "Error connecting to localhost: %s\n",
319
ssh_get_error(my_ssh_session));
320
ssh_free(my_ssh_session);
324
// Verify the server's identity
325
// For the source code of verify_knowhost(), check previous example
326
if (verify_knownhost(my_ssh_session) < 0)
328
ssh_disconnect(my_ssh_session);
329
ssh_free(my_ssh_session);
333
// Authenticate ourselves
334
password = getpass("Password: ");
335
rc = ssh_userauth_password(my_ssh_session, NULL, password);
336
if (rc != SSH_AUTH_SUCCESS)
338
fprintf(stderr, "Error authenticating with password: %s\n",
339
ssh_get_error(my_ssh_session));
340
ssh_disconnect(my_ssh_session);
341
ssh_free(my_ssh_session);
347
ssh_disconnect(my_ssh_session);
348
ssh_free(my_ssh_session);
352
@see @ref authentication_details
355
@subsection using_ssh Doing something
357
At this point, the authenticity of both server and client is established.
358
Time has come to take advantage of the many possibilities offered by the SSH
359
protocol: execute a remote command, open remote shells, transfer files,
362
The example below shows how to execute a remote command:
365
int show_remote_processes(ssh_session session)
372
channel = ssh_channel_new(session);
376
rc = ssh_channel_open_session(channel);
379
ssh_channel_free(channel);
383
rc = ssh_channel_request_exec(channel, "ps aux");
386
ssh_channel_close(channel);
387
ssh_channel_free(channel);
391
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
394
if (write(1, buffer, nbytes) != nbytes)
396
ssh_channel_close(channel);
397
ssh_channel_free(channel);
400
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
405
ssh_channel_close(channel);
406
ssh_channel_free(channel);
410
ssh_channel_send_eof(channel);
411
ssh_channel_close(channel);
412
ssh_channel_free(channel);
418
@see @ref opening_shell
419
@see @ref remote_command
420
@see @ref sftp_subsystem
421
@see @ref scp_subsystem
424
@subsection errors Handling the errors
426
All the libssh functions which return an error value also set an English error message
427
describing the problem.
429
Error values are typically SSH_ERROR for integer values, or NULL for pointers.
431
The function ssh_get_error() returns a pointer to the static error message.
433
ssh_error_code() returns the error code number : SSH_NO_ERROR,
434
SSH_REQUEST_DENIED, SSH_INVALID_REQUEST, SSH_CONNECTION_LOST, SSH_FATAL,
435
or SSH_INVALID_DATA. SSH_REQUEST_DENIED means the ssh server refused your
436
request, but the situation is recoverable. The others mean something happened
437
to the connection (some encryption problems, server problems, ...).
438
SSH_INVALID_REQUEST means the library got some garbage from server, but
439
might be recoverable. SSH_FATAL means the connection has an important
440
problem and isn't probably recoverable.
442
Most of time, the error returned are SSH_FATAL, but some functions
443
(generaly the ssh_request_xxx ones) may fail because of server denying request.
444
In these cases, SSH_REQUEST_DENIED is returned.
446
ssh_get_error() and ssh_get_error_code() take a ssh_session as a parameter.
447
That's for thread safety, error messages that can be attached to a session
448
aren't static anymore. Any error that happens during ssh_options_xxx()
449
or ssh_connect() (i.e., outside of any session) can be retrieved by
450
giving NULL as argument.
452
The SFTP subsystem has its own error codes, in addition to libssh ones.