aboutsummaryrefslogtreecommitdiff
path: root/doc/tutorial.dox
blob: 862d4531f123946d95b675596750e9349e2a3035 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
/**
 * @page tutorial The Tutorial
 *
 * @section introduction Introduction
 *
 * libssh is a C library that enables you to write a program that uses the
 * SSH protocol. With it, you can remotely execute programs, transfer
 * files, or use a secure and transparent tunnel for your remote programs.
 * The SSH protocol is encrypted, ensures data integrity, and provides strong
 * means of authenticating both the server of the client. The library hides
 * a lot of technical details from the SSH protocol, but this does not
 * mean that you should not try to know about and understand these details.
 *
 * libssh is a Free Software / Open Source project. The libssh library
 * is distributed under LGPL license. The libssh project has nothing to do with
 * "libssh2", which is a completly different and independant project.
 *
 * libssh supports both client and server sides of the SSH protocol.
 * The following document explains how to set up a client-side connection.
 * If you are going to program a server, you should try first to code some
 * client-side programs in order to understand how libssh works.
 *
 * This tutorial describes libssh version 0.5.0.
 *
 *
 * Table of contents:
 *
 * @subpage session
 *
 * @subpage details
 *
 * @subpage tbd
 *
 *
 * @page session 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 virtual 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 it is easy to do.
 *
 *  - When everything is finished, just close the channels, and then the connection.
 *
 * 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 error string using 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 ret;
 *
 *   my_ssh_session = ssh_new();
 *   if (my_ssh_session == NULL)
 *     exit(-1);
 *
 *   ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "localhost");
 *
 *   ret = ssh_connect(my_ssh_session);
 *   if (ret != 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
 * 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 yourself
 *
 * 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 ret;
 *   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
 *   ret = ssh_connect(my_ssh_session);
 *   if (ret != 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: ");
 *   ret = ssh_userauth_password(my_ssh_session, NULL, password);
 *   if (ret != 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 puts the final touch to our step-by-step discovery
 * of a SSH connection:
 *
 * @code
 * /* *** To be replaced with something simpler *** */
 * #include <sys/stat.h>
 *
 * int scp_helloworld(ssh_session session)
 * {
 *   ssh_scp scp_session;
 *   int ret;
 *   const char *helloworld = "Hello, world!\n";
 *   int length = strlen(helloworld);
 *
 *   // Open a scp session
 *   scp_session = ssh_scp_new
 *     (session, SSH_SCP_WRITE | SSH_SCP_RECURSIVE, ".");
 *   if (scp_session == NULL)
 *   {
 *     fprintf(stderr, "Error allocating scp session.\n");
 *     return SSH_ERROR;
 *   }
 *
 *   // Initialize the scp session
 *   ret = ssh_scp_init(scp_session);
 *   if (ret != SSH_OK)
 *   {
 *     fprintf(stderr, "Error initializing scp session.\n");
 *     ssh_scp_free(scp_session);
 *     return ret;
 *   }
 *
 *   // Open the remote file
 *   ret = ssh_scp_push_file
 *     (scp_session, "helloworld.txt", length, S_IRUSR |  S_IWUSR);
 *   if (ret != SSH_OK)
 *   {
 *     fprintf(stderr, "Can't open remote file.\n");
 *     ssh_scp_close(scp_session);
 *     ssh_scp_free(scp_session);
 *     return ret;
 *   }
 *
 *   // Write the data into the remote file
 *   ret = ssh_scp_write(scp_session, helloworld, length);
 *   if (ret != SSH_OK)
 *   {
 *     fprintf(stderr, "Can't write to remote file.\n");
 *     ssh_scp_close(scp_session);
 *     ssh_scp_free(scp_session);
 *     return ret;
 *   }
 *
 *   ssh_scp_close(scp_session);
 *   ssh_scp_free(scp_session);
 *   return ret;
 * }
 * @endcode
 *
 * @see @ref opening_shell
 * @see @ref remote_commands
 * @see @ref sftp_subsystem
 * @see @ref scp_subsystem
 *
 *
 * @page details Chapter 2: A deeper insight on authentication
 * @section authentication_details A deeper insight on authentication
 *
 *
 * @subsection pubkeys Authenticating using public keys
 *
 * The public key authentication is the only method that does not compromise
 * your key if the remote host has been compromised (the server can't do
 * anything more than getting your public key). This is not the
 * case of a password authentication (the server can get your plaintext
 * password). On the other hand, if the client machine is compromised and
 * the private key has no passphrase, then the attacker has gained automatic
 * access to your server. It is not the purpose of this document to do
 * a detailed review of the advantages and drawbacks of each authentication
 * method, so refer to the abundant documentation on this topic on the
 * Internet to fully understand the advantages and risks linked to each method.
 *
 * libssh is fully compatible with the openssh public and private keys. You
 * can either use the automatic public key authentication method provided by
 * libssh, or roll your own using the public key functions.
 *
 * The process of authenticating by public key to a server is the following:
 *  - you scan a list of files that contain public keys. each key is sent to
 *    the SSH server, until the server acknowledges a key (a key it knows can be
 *    used to authenticate the user).
 *  - then, you retrieve the private key for this key and send a message
 *    proving that you know that private key.
 *
 * The function ssh_userauth_autopubkey() does this using the available keys in
 * "~/.ssh/".  The return values are the following:
 *  - SSH_AUTH_ERROR: some serious error happened during authentication
 *  - SSH_AUTH_DENIED: no key matched
 *  - SSH_AUTH_SUCCESS: you are now authenticated
 *  - SSH_AUTH_PARTIAL: some key matched but you still have to provide an other
 *                       mean of authentication (like a password).
 *
 * The ssh_userauth_autopubkey function also tries to authenticate using the
 * SSH agent, if you have one running, or the "none" method otherwise.
 *
 * If you wish to authenticate with public key by your own, follow these steps:
 *  - Retrieve the public key in a ssh_string using publickey_from_file().
 *  - Offer the public key to the SSH server using ssh_userauth_offer_pubkey().
 *    If the return value is SSH_AUTH_SUCCESS, the SSH server accepts to
 *    authenticate using the public key and you can go to the next step.
 *  - Retrieve the private key, using the privatekey_from_file() function. If
 *    a passphrase is needed, either the passphrase specified as argument or
 *    a callback (see callbacks section) will be used.
 *  - Authenticate using ssh_userauth_pubkey() with your public key string
 *    and private key.
 *  - Do not forget cleaning up memory using string_free() and privatekey_free().
 *
 * Here is a minimalistic example of public key authentication:
 *
 * @code
 * int authenticate_pubkey(ssh_session session)
 * {
 *   int rc;
 *
 *   rc = ssh_userauth_autopubkey(session, NULL);
 *
 *   if (rc == SSH_AUTH_ERROR)
 *   {
 *      fprintf(stderr, "Authentication failed: %s\n",
 *        ssh_get_error(session));
 *      return SSH_AUTH_ERROR;
 *   }
 *
 *   return rc;
 * }
 * @endcode
 *
 * @see ssh_userauth_autopubkey
 * @see ssh_userauth_offer_pubkey
 * @see ssh_userauth_pubkey
 * @see publickey_from_file
 * @see publickey_from_privatekey
 * @see string_free
 * @see privatekey_from_file
 * @see privatekey_free
 *
 *
 * @subsection password Authenticating using a password
 *
 * The function ssh_userauth_password() serves the purpose of authenticating
 * using a password. It will return SSH_AUTH_SUCCESS if the password worked,
 * or one of other constants otherwise. It's your work to ask the password
 * and to deallocate it in a secure manner.
 *
 * If your server complains that the password is wrong, but you can still
 * authenticate using openssh's client (issuing password), it's probably
 * because openssh only accept keyboard-interactive. Switch to
 * keyboard-interactive authentication, or try to configure plain text passwords
 * on the SSH server.
 *
 * Here is a small example of password authentication:
 *
 * @code
 * int authenticate_password(ssh_session session)
 * {
 *   char *password;
 *   int rc;
 *
 *   password = getpass("Enter your password: ");
 *   rc = ssh_userauth_password(session, NULL, password);
 *   if (rc == SSH_AUTH_ERROR)
 *   {
 *      fprintf(stderr, "Authentication failed: %s\n",
 *        ssh_get_error(session));
 *      return SSH_AUTH_ERROR;
 *   }
 *
 *   return rc;
 * }
 * @endcode
 *
 * @see ssh_userauth_password
 *
 *
 * @subsection keyb_int The keyboard-interactive authentication method
 *
 * The keyboard-interactive method is, as its name tells, interactive. The
 * server will issue one or more challenges that the user has to answer,
 * until the server takes an authentication decision.
 *
 * ssh_userauth_kbdint() is the the main keyboard-interactive function. 
 * It will return SSH_AUTH_SUCCESS,SSH_AUTH_DENIED, SSH_AUTH_PARTIAL,
 * SSH_AUTH_ERROR, or SSH_AUTH_INFO, depending on the result of the request.
 *
 * The keyboard-interactive authentication method of SSH2 is a feature that
 * permits the server to ask a certain number of questions in an interactive
 * manner to the client, until it decides to accept or deny the login.
 *
 * To begin, you call ssh_userauth_kbdint() (just set user and submethods to
 * NULL) and store the answer.
 *
 * If the answer is SSH_AUTH_INFO, it means that the server has sent a few
 * questions that you should ask the user. You can retrieve these questions
 * with the following functions: ssh_userauth_kbdint_getnprompts(),
 * ssh_userauth_kbdint_getname(), ssh_userauth_kbdint_getinstruction(), and
 * ssh_userauth_kbdint_getprompt().
 *
 * Set the answer for each question in the challenge using
 * ssh_userauth_kbdint_setanswer().
 *
 * Then, call again ssh_userauth_kbdint() and start the process again until
 * these functions returns something else than SSH_AUTH_INFO.
 *
 * Here are a few remarks:
 *  - Even the first call can return SSH_AUTH_DENIED or SSH_AUTH_SUCCESS.
 *  - The server can send an empty question set (this is the default behavior
 *    on my system) after you have sent the answers to the first questions.
 *    You must still parse the answer, it might contain some
 *    message from the server saying hello or such things. Just call
 *    ssh_userauth_kbdint() until needed.
 *  - The meaning of "name", "prompt", "instruction" may be a little
 *    confusing. An explanation is given in the RFC section that follows.
 *
 * Here is a little note about how to use the information from
 * keyboard-interactive authentication, coming from the RFC itself (rfc4256):
 *
 * @verbatim
 *
 *  3.3 User Interface Upon receiving a request message, the client SHOULD
 *  prompt the user as follows: A command line interface (CLI) client SHOULD
 *  print the name and instruction (if non-empty), adding newlines. Then for
 *  each prompt in turn, the client SHOULD display the prompt and read the
 *  user input.
 *
 *  A graphical user interface (GUI) client has many choices on how to prompt
 *  the user. One possibility is to use the name field (possibly prefixed
 *  with the application's name) as the title of a dialog window in which
 *  the prompt(s) are presented. In that dialog window, the instruction field
 *  would be a text message, and the prompts would be labels for text entry
 *  fields. All fields SHOULD be presented to the user, for example an
 *  implementation SHOULD NOT discard the name field because its windows lack
 *  titles; it SHOULD instead find another way to display this information. If
 *  prompts are presented in a dialog window, then the client SHOULD NOT
 *  present each prompt in a separate window.
 *
 *  All clients MUST properly handle an instruction field with embedded
 *  newlines. They SHOULD also be able to display at least 30 characters for
 *  the name and prompts. If the server presents names or prompts longer than 30
 *  characters, the client MAY truncate these fields to the length it can
 *  display. If the client does truncate any fields, there MUST be an obvious
 *  indication that such truncation has occured.
 *
 *  The instruction field SHOULD NOT be truncated. Clients SHOULD use control
 *  character filtering as discussed in [SSH-ARCH] to avoid attacks by
 *  including terminal control characters in the fields to be displayed.
 *
 *  For each prompt, the corresponding echo field indicates whether or not
 *  the user input should be echoed as characters are typed. Clients SHOULD
 *  correctly echo/mask user input for each prompt independently of other
 *  prompts in the request message. If a client does not honor the echo field
 *  for whatever reason, then the client MUST err on the side of
 *  masking input. A GUI client might like to have a checkbox toggling
 *  echo/mask. Clients SHOULD NOT add any additional characters to the prompt
 *  such as ": " (colon-space); the server is responsible for supplying all
 *  text to be displayed to the user. Clients MUST also accept empty responses
 *  from the user and pass them on as empty strings.
 * @endverbatim
 *
 * The following example shows how to perform keyboard-interactive authentication:
 *
 * @code
 * int authenticate_kbdint(ssh_session session)
 * {
 *   int rc;
 *
 *   rc = ssh_userauth_kbdint(session, NULL, NULL);
 *   while (rc == SSH_AUTH_INFO)
 *   {
 *     const char *name, *instruction;
 *     int nprompts, iprompt;
 *
 *     name = ssh_userauth_kbdint_getname(session);
 *     instruction = ssh_userauth_kbdint_getinstruction(session);
 *     nprompts = ssh_userauth_kbdint_getnprompts(session);
 *
 *     if (strlen(name) > 0)
 *       printf("%s\n", name);
 *     if (strlen(instruction) > 0)
 *       printf("%s\n", instruction);
 *     for (iprompt = 0; iprompt < nprompts; iprompt++)
 *     {
 *       const char *prompt;
 *       char echo;
 *
 *       prompt = ssh_userauth_kbdint_getprompt(session, iprompt, &echo);
 *       if (echo)
 *       {
 *         char buffer[128], *ptr;
 *
 *         printf("%s", prompt);
 *         if (fgets(buffer, sizeof(buffer), stdin) == NULL)
 *           return SSH_AUTH_ERROR;
 *         buffer[sizeof(buffer) - 1] = '\0';
 *         if ((ptr = strchr(buffer, '\n')) != NULL)
 *           *ptr = '\0';
 *         if (ssh_userauth_kbdint_setanswer(session, iprompt, buffer) < 0)
 *           return SSH_AUTH_ERROR;
 *         memset(buffer, 0, strlen(buffer));
 *       }
 *       else
 *       {
 *         char *ptr;
 *
 *         ptr = getpass(prompt);
 *         if (ssh_userauth_kbdint_setanswer(session, iprompt, ptr) < 0)
 *           return SSH_AUTH_ERROR;
 *       }
 *     }
 *     rc = ssh_userauth_kbdint(session, NULL, NULL);
 *   }
 *   return rc;
 * }
 * @endcode
 *
 * @see ssh_userauth_kbdint()
 * @see ssh_userauth_kbdint_getnprompts
 * @see ssh_userauth_kbdint_getname 
 * @see ssh_userauth_kbdint_getinstruction
 * @see ssh_userauth_kbdint_getprompt
 * @see ssh_userauth_kbdint_setanswer()
 *
 *
 * @subsection none Authenticating with "none" method
 *
 * The primary purpose of the "none" method is to get authenticated **without**
 * any credential. Don't do that, use one of the other authentication methods,
 * unless you really want to grant anonymous access.
 *
 * If the account has no password, and if the server is configured to let you
 * pass, ssh_userauth_none() might answer SSH_AUTH_SUCCESS.
 *
 * The following example shows how to perform "none" authentication:
 *
 * @code
 * int authenticate_kbdint(ssh_session session)
 * {
 *   int rc;
 *
 *   rc = ssh_userauth_none(session, NULL, NULL);
 *   return rc;
 * }
 * @endcode
 *
 * @subsection auth_list Getting the list of supported authentications
 *
 * You are not meant to choose a given authentication method, you can
 * let the server tell you which methods are available. Once you know them,
 * you try them one after the other.
 *
 * The following example shows how to get the list of available authentication
 * methods with ssh_userauth_list() and how to use the result:
 *
 * @code
 * /* Marche pas sans ssh_userauth_none(), du moins en 0.4.2 */
 * int test_several_auth_methods(ssh_session session)
 * {
 *   int method, rc;
 *
 *   method = ssh_userauth_list(session, NULL);
 *
 *   if (method & SSH_AUTH_METHOD_NONE)
 *   { // For the source code of function authenticate_none(),
 *     // refer to the corresponding example
 *     rc = authenticate_none(session);
 *     if (rc == SSH_AUTH_SUCCESS) return rc;
 *   }
 *   if (method & SSH_AUTH_METHOD_PUBLICKEY)
 *   { // For the source code of function authenticate_pubkey(),
 *     // refer to the corresponding example
 *     rc = authenticate_pubkey(session);
 *     if (rc == SSH_AUTH_SUCCESS) return rc;
 *   }
 *   if (method & SSH_AUTH_METHOD_INTERACTIVE)
 *   { // For the source code of function authenticate_kbdint(),
 *     // refer to the corresponding example
 *     rc = authenticate_kbdint(session);
 *     if (rc == SSH_AUTH_SUCCESS) return rc;
 *   }
 *   if (method & SSH_AUTH_METHOD_PASSWORD)
 *   { // For the source code of function authenticate_password(),
 *     // refer to the corresponding example
 *     rc = authenticate_password(session);
 *     if (rc == SSH_AUTH_SUCCESS) return rc;
 *   }
 *   return SSH_AUTH_ERROR;
 * }
 * @endcode
 *
 *
 * @subsection banner
 *
 * The SSH server might send a banner, which you can retrieve with
 * ssh_get_issue_banner(), then display to the user.
 *
 * The following example shows how to retrieve and dispose the issue banner:
 *
 * @code
 * /* Marche pas sans ssh_userauth_none(), du moins en 0.4.2 */
 * int display_banner(ssh_session session)
 * {
 *   int rc;
 *   char *banner;
 *
 *   rc = ssh_userauth_none(session, NULL);
 *   if (rc == SSH_AUTH_ERROR)
 *     return rc;
 *
 *   banner = ssh_get_issue_banner(session);
 *   if (banner)
 *   {
 *     printf("%s\n", banner);
 *     free(banner);
 *   }
 *
 *   return rc;
 * }
 * @endcode
 *
 *
 * @page tbd Chapter 3: To be done
 * @section opening_shell Opening a shell
 *
 * *** To be written ***
 *
 * @section remote_commands Passing remote commands
 *
 * *** To be written ***
 *
 * @section sftp_subsystem The SFTP subsystem
 *
 * *** To be written ***
 *
 * @section scp_subsystem The SCP subsystem
 *
 * *** To be written ***
 *
 * @section threads Working with threads
 *
 * *** To be written ***
 *
 * @section forwarding_connections Forwarding connections
 *
 * *** To be written ***
 *
 */