~ubuntu-branches/ubuntu/precise/libssh/precise

« back to all changes in this revision

Viewing changes to doc/guided_tour.dox

  • Committer: Bazaar Package Importer
  • Author(s): Laurent Bigonville
  • Date: 2011-06-15 15:48:07 UTC
  • mfrom: (1.1.10 upstream) (4.1.12 sid)
  • Revision ID: james.westby@ubuntu.com-20110615154807-3muklcqfftr1vtch
Tags: 0.5.0-2
* debian/patches/0002-Check-for-NULL-pointers-in-string-c.patch:
  Consolidate patch (Should fix previous REJECT)
* Support multiarch spec

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
@page libssh_tutor_guided_tour Chapter 1: A typical SSH session
 
3
@section ssh_session A typical SSH session
 
4
 
 
5
A SSH session goes through the following steps:
 
6
 
 
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.
 
11
 
 
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
 
15
   file.
 
16
 
 
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.
 
20
 
 
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.
 
25
 
 
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,
 
32
     but can be done.
 
33
 
 
34
 - When everything is finished, just close the channels, and then the connection. 
 
35
 
 
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".
 
39
 
 
40
 
 
41
@subsection setup Creating the session and setting options
 
42
 
 
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.
 
46
@code
 
47
#include <libssh/libssh.h> 
 
48
#include <stdlib.h>
 
49
 
 
50
int main()
 
51
{
 
52
  ssh_session my_ssh_session = ssh_new();
 
53
  if (my_ssh_session == NULL)
 
54
    exit(-1);
 
55
  ...
 
56
  ssh_free(my_ssh_session);
 
57
}
 
58
@endcode
 
59
 
 
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.
 
63
 
 
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
 
69
 
 
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. 
 
73
 
 
74
Here is a small example of how to use it:
 
75
 
 
76
@code
 
77
#include <libssh/libssh.h> 
 
78
#include <stdlib.h>
 
79
 
 
80
int main()
 
81
{
 
82
  ssh_session my_ssh_session;
 
83
  int verbosity = SSH_LOG_PROTOCOL;
 
84
  int port = 22;
 
85
 
 
86
  my_ssh_session = ssh_new();
 
87
  if (my_ssh_session == NULL)
 
88
    exit(-1);
 
89
 
 
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);
 
93
 
 
94
  ...
 
95
 
 
96
  ssh_free(my_ssh_session);
 
97
}
 
98
@endcode
 
99
 
 
100
Please notice that all parameters are passed to ssh_options_set() as pointers,
 
101
even if you need to set an integer value.
 
102
 
 
103
@see ssh_new
 
104
@see ssh_free
 
105
@see ssh_options_set
 
106
@see ssh_options_parse_config
 
107
@see ssh_options_copy
 
108
@see ssh_options_getopt
 
109
 
 
110
 
 
111
@subsection connect Connecting to the server
 
112
 
 
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.
 
115
 
 
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
 
118
the session.
 
119
 
 
120
Here's an example:
 
121
 
 
122
@code
 
123
#include <libssh/libssh.h>
 
124
#include <stdlib.h>
 
125
#include <stdio.h> 
 
126
 
 
127
int main()
 
128
{
 
129
  ssh_session my_ssh_session;
 
130
  int rc;
 
131
 
 
132
  my_ssh_session = ssh_new();
 
133
  if (my_ssh_session == NULL)
 
134
    exit(-1);
 
135
 
 
136
  ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "localhost");
 
137
 
 
138
  rc = ssh_connect(my_ssh_session);
 
139
  if (rc != SSH_OK)
 
140
  {
 
141
    fprintf(stderr, "Error connecting to localhost: %s\n",
 
142
            ssh_get_error(my_ssh_session));
 
143
    exit(-1);
 
144
  }
 
145
 
 
146
  ...
 
147
 
 
148
  ssh_disconnect(my_ssh_session);
 
149
  ssh_free(my_ssh_session);
 
150
}
 
151
@endcode
 
152
 
 
153
 
 
154
@subsection serverauth Authenticating the server
 
155
 
 
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
 
158
authentication).
 
159
 
 
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.
 
168
 
 
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 ...).
 
173
 
 
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.
 
178
 
 
179
The following example is part of the examples suite available in the
 
180
examples/ directory:
 
181
 
 
182
@code
 
183
#include <errno.h>
 
184
#include <string.h>
 
185
 
 
186
int verify_knownhost(ssh_session session)
 
187
{
 
188
  int state, hlen;
 
189
  unsigned char *hash = NULL;
 
190
  char *hexa;
 
191
  char buf[10];
 
192
 
 
193
  state = ssh_is_server_known(session);
 
194
 
 
195
  hlen = ssh_get_pubkey_hash(session, &hash);
 
196
  if (hlen < 0)
 
197
    return -1;
 
198
 
 
199
  switch (state)
 
200
  {
 
201
    case SSH_SERVER_KNOWN_OK:
 
202
      break; /* ok */
 
203
 
 
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");
 
208
      free(hash);
 
209
      return -1;
 
210
 
 
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");
 
216
      free(hash);
 
217
      return -1;
 
218
 
 
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 */
 
224
 
 
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);
 
229
      free(hexa);
 
230
      if (fgets(buf, sizeof(buf), stdin) == NULL)
 
231
      {
 
232
        free(hash);
 
233
        return -1;
 
234
      }
 
235
      if (strncasecmp(buf, "yes", 3) != 0)
 
236
      {
 
237
        free(hash);
 
238
        return -1;
 
239
      }
 
240
      if (ssh_write_knownhost(session) < 0)
 
241
      {
 
242
        fprintf(stderr, "Error %s\n", strerror(errno));
 
243
        free(hash);
 
244
        return -1;
 
245
      }
 
246
      break;
 
247
 
 
248
    case SSH_SERVER_ERROR:
 
249
      fprintf(stderr, "Error %s", ssh_get_error(session));
 
250
      free(hash);
 
251
      return -1;
 
252
  }
 
253
 
 
254
  free(hash);
 
255
  return 0;
 
256
}
 
257
@endcode
 
258
 
 
259
@see ssh_connect
 
260
@see ssh_disconnect
 
261
@see ssh_get_error
 
262
@see ssh_get_error_code
 
263
@see ssh_get_pubkey_hash
 
264
@see ssh_is_server_known
 
265
@see ssh_write_knownhost
 
266
 
 
267
 
 
268
@subsection auth Authenticating the user
 
269
 
 
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.
 
275
 
 
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.
 
288
 
 
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.
 
294
 
 
295
The example below shows an authentication with password:
 
296
 
 
297
@code
 
298
#include <libssh/libssh.h>
 
299
#include <stdlib.h>
 
300
#include <stdio.h> 
 
301
 
 
302
int main()
 
303
{
 
304
  ssh_session my_ssh_session;
 
305
  int rc;
 
306
  char *password;
 
307
 
 
308
  // Open session and set options
 
309
  my_ssh_session = ssh_new();
 
310
  if (my_ssh_session == NULL)
 
311
    exit(-1);
 
312
  ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "localhost");
 
313
 
 
314
  // Connect to server
 
315
  rc = ssh_connect(my_ssh_session);
 
316
  if (rc != SSH_OK)
 
317
  {
 
318
    fprintf(stderr, "Error connecting to localhost: %s\n",
 
319
            ssh_get_error(my_ssh_session));
 
320
    ssh_free(my_ssh_session);
 
321
    exit(-1);
 
322
  }
 
323
 
 
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)
 
327
  {
 
328
    ssh_disconnect(my_ssh_session);
 
329
    ssh_free(my_ssh_session);
 
330
    exit(-1);
 
331
  }
 
332
 
 
333
  // Authenticate ourselves
 
334
  password = getpass("Password: ");
 
335
  rc = ssh_userauth_password(my_ssh_session, NULL, password);
 
336
  if (rc != SSH_AUTH_SUCCESS)
 
337
  {
 
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);
 
342
    exit(-1);
 
343
  }
 
344
 
 
345
  ...
 
346
 
 
347
  ssh_disconnect(my_ssh_session);
 
348
  ssh_free(my_ssh_session);
 
349
}
 
350
@endcode
 
351
 
 
352
@see @ref authentication_details
 
353
 
 
354
 
 
355
@subsection using_ssh Doing something
 
356
 
 
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,
 
360
forward ports, etc.
 
361
 
 
362
The example below shows how to execute a remote command:
 
363
 
 
364
@code
 
365
int show_remote_processes(ssh_session session)
 
366
{
 
367
  ssh_channel channel;
 
368
  int rc;
 
369
  char buffer[256];
 
370
  unsigned int nbytes;
 
371
 
 
372
  channel = ssh_channel_new(session);
 
373
  if (channel == NULL)
 
374
    return SSH_ERROR;
 
375
 
 
376
  rc = ssh_channel_open_session(channel);
 
377
  if (rc != SSH_OK)
 
378
  {
 
379
    ssh_channel_free(channel);
 
380
    return rc;
 
381
  }
 
382
 
 
383
  rc = ssh_channel_request_exec(channel, "ps aux");
 
384
  if (rc != SSH_OK)
 
385
  {
 
386
    ssh_channel_close(channel);
 
387
    ssh_channel_free(channel);
 
388
    return rc;
 
389
  }
 
390
 
 
391
  nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
 
392
  while (nbytes > 0)
 
393
  {
 
394
    if (write(1, buffer, nbytes) != nbytes)
 
395
    {
 
396
      ssh_channel_close(channel);
 
397
      ssh_channel_free(channel);
 
398
      return SSH_ERROR;
 
399
    }
 
400
    nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
 
401
  }
 
402
    
 
403
  if (nbytes < 0)
 
404
  {
 
405
    ssh_channel_close(channel);
 
406
    ssh_channel_free(channel);
 
407
    return SSH_ERROR;
 
408
  }
 
409
 
 
410
  ssh_channel_send_eof(channel);
 
411
  ssh_channel_close(channel);
 
412
  ssh_channel_free(channel);
 
413
 
 
414
  return SSH_OK;
 
415
}
 
416
@endcode
 
417
 
 
418
@see @ref opening_shell
 
419
@see @ref remote_command
 
420
@see @ref sftp_subsystem
 
421
@see @ref scp_subsystem
 
422
 
 
423
 
 
424
@subsection errors Handling the errors
 
425
 
 
426
All the libssh functions which return an error value also set an English error message
 
427
describing the problem.
 
428
 
 
429
Error values are typically SSH_ERROR for integer values, or NULL for pointers.
 
430
 
 
431
The function ssh_get_error() returns a pointer to the static error message.
 
432
 
 
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.
 
441
 
 
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.
 
445
 
 
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.
 
451
 
 
452
The SFTP subsystem has its own error codes, in addition to libssh ones.
 
453
 
 
454
 
 
455
*/