1 /* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
4 * Redistribution and use in source and binary forms,
5 * with or without modification, are permitted provided
6 * that the following conditions are met:
8 * Redistributions of source code must retain the above
9 * copyright notice, this list of conditions and the
10 * following disclaimer.
12 * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials
15 * provided with the distribution.
17 * Neither the name of the copyright holder nor the names
18 * of any other contributors may be used to endorse or
19 * promote products derived from this software without
20 * specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
23 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
34 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
38 #include "libssh2_priv.h"
43 /* Needed for struct iovec on some platforms */
49 /* {{{ proto libssh2_userauth_list
50 * List authentication methods
51 * Will yield successful login if "none" happens to be allowable for this user
52 * Not a common configuration for any SSH server though
53 * username should be NULL, or a null terminated string
56 libssh2_userauth_list(LIBSSH2_SESSION
* session
, const char *username
,
57 unsigned int username_len
)
59 static const unsigned char reply_codes
[3] =
60 { SSH_MSG_USERAUTH_SUCCESS
, SSH_MSG_USERAUTH_FAILURE
, 0 };
61 /* packet_type(1) + username_len(4) + service_len(4) +
62 service(14)"ssh-connection" + method_len(4) + method(4)"none" */
63 unsigned long methods_len
;
67 if (session
->userauth_list_state
== libssh2_NB_state_idle
) {
68 /* Zero the whole thing out */
69 memset(&session
->userauth_list_packet_requirev_state
, 0,
70 sizeof(session
->userauth_list_packet_requirev_state
));
72 session
->userauth_list_data_len
= username_len
+ 31;
74 s
= session
->userauth_list_data
=
75 LIBSSH2_ALLOC(session
, session
->userauth_list_data_len
);
76 if (!session
->userauth_list_data
) {
77 libssh2_error(session
, LIBSSH2_ERROR_ALLOC
,
78 "Unable to allocate memory for userauth_list", 0);
82 *(s
++) = SSH_MSG_USERAUTH_REQUEST
;
83 libssh2_htonu32(s
, username_len
);
86 memcpy(s
, username
, username_len
);
90 libssh2_htonu32(s
, 14);
92 memcpy(s
, "ssh-connection", 14);
95 libssh2_htonu32(s
, 4);
100 session
->userauth_list_state
= libssh2_NB_state_created
;
103 if (session
->userauth_list_state
== libssh2_NB_state_created
) {
104 rc
= libssh2_packet_write(session
, session
->userauth_list_data
,
105 session
->userauth_list_data_len
);
106 if (rc
== PACKET_EAGAIN
) {
107 libssh2_error(session
, LIBSSH2_ERROR_EAGAIN
,
108 "Would block requesting userauth list", 0);
111 libssh2_error(session
, LIBSSH2_ERROR_SOCKET_SEND
,
112 "Unable to send userauth-none request", 0);
113 LIBSSH2_FREE(session
, session
->userauth_list_data
);
114 session
->userauth_list_data
= NULL
;
115 session
->userauth_list_state
= libssh2_NB_state_idle
;
118 LIBSSH2_FREE(session
, session
->userauth_list_data
);
119 session
->userauth_list_data
= NULL
;
121 session
->userauth_list_state
= libssh2_NB_state_sent
;
124 if (session
->userauth_list_state
== libssh2_NB_state_sent
) {
125 rc
= libssh2_packet_requirev_ex(session
, reply_codes
,
126 &session
->userauth_list_data
,
127 &session
->userauth_list_data_len
, 0,
130 userauth_list_packet_requirev_state
);
131 if (rc
== PACKET_EAGAIN
) {
132 libssh2_error(session
, LIBSSH2_ERROR_EAGAIN
,
133 "Would block requesting userauth list", 0);
136 libssh2_error(session
, LIBSSH2_ERROR_NONE
, "No error", 0);
137 session
->userauth_list_state
= libssh2_NB_state_idle
;
141 if (session
->userauth_list_data
[0] == SSH_MSG_USERAUTH_SUCCESS
) {
142 /* Wow, who'dve thought... */
143 libssh2_error(session
, LIBSSH2_ERROR_NONE
, "No error", 0);
144 LIBSSH2_FREE(session
, session
->userauth_list_data
);
145 session
->userauth_list_data
= NULL
;
146 session
->state
|= LIBSSH2_STATE_AUTHENTICATED
;
147 session
->userauth_list_state
= libssh2_NB_state_idle
;
151 methods_len
= libssh2_ntohu32(session
->userauth_list_data
+ 1);
152 memcpy(session
->userauth_list_data
, session
->userauth_list_data
+ 5,
154 session
->userauth_list_data
[methods_len
] = '\0';
155 _libssh2_debug(session
, LIBSSH2_DBG_AUTH
, "Permitted auth methods: %s",
156 session
->userauth_list_data
);
159 session
->userauth_list_state
= libssh2_NB_state_idle
;
160 return (char *) session
->userauth_list_data
;
165 /* {{{ libssh2_userauth_authenticated
166 * 0 if not yet authenticated
167 * non-zero is already authenticated
170 libssh2_userauth_authenticated(LIBSSH2_SESSION
* session
)
172 return session
->state
& LIBSSH2_STATE_AUTHENTICATED
;
177 /* {{{ libssh2_userauth_password
181 libssh2_userauth_password_ex(LIBSSH2_SESSION
* session
, const char *username
,
182 unsigned int username_len
, const char *password
,
183 unsigned int password_len
,
184 LIBSSH2_PASSWD_CHANGEREQ_FUNC((*passwd_change_cb
)))
187 static const unsigned char reply_codes
[4] =
188 { SSH_MSG_USERAUTH_SUCCESS
, SSH_MSG_USERAUTH_FAILURE
,
189 SSH_MSG_USERAUTH_PASSWD_CHANGEREQ
, 0
193 if (session
->userauth_pswd_state
== libssh2_NB_state_idle
) {
194 /* Zero the whole thing out */
195 memset(&session
->userauth_pswd_packet_requirev_state
, 0,
196 sizeof(session
->userauth_pswd_packet_requirev_state
));
199 * 40 = acket_type(1) + username_len(4) + service_len(4) +
200 * service(14)"ssh-connection" + method_len(4) + method(8)"password" +
201 * chgpwdbool(1) + password_len(4) */
202 session
->userauth_pswd_data_len
= username_len
+ password_len
+ 40;
204 session
->userauth_pswd_data0
= ~SSH_MSG_USERAUTH_PASSWD_CHANGEREQ
;
206 s
= session
->userauth_pswd_data
=
207 LIBSSH2_ALLOC(session
, session
->userauth_pswd_data_len
);
208 if (!session
->userauth_pswd_data
) {
209 libssh2_error(session
, LIBSSH2_ERROR_ALLOC
,
210 "Unable to allocate memory for userauth-password request",
215 *(s
++) = SSH_MSG_USERAUTH_REQUEST
;
216 libssh2_htonu32(s
, username_len
);
218 memcpy(s
, username
, username_len
);
221 libssh2_htonu32(s
, sizeof("ssh-connection") - 1);
223 memcpy(s
, "ssh-connection", sizeof("ssh-connection") - 1);
224 s
+= sizeof("ssh-connection") - 1;
226 libssh2_htonu32(s
, sizeof("password") - 1);
228 memcpy(s
, "password", sizeof("password") - 1);
229 s
+= sizeof("password") - 1;
234 libssh2_htonu32(s
, password_len
);
236 memcpy(s
, password
, password_len
);
239 _libssh2_debug(session
, LIBSSH2_DBG_AUTH
,
240 "Attempting to login using password authentication");
242 session
->userauth_pswd_state
= libssh2_NB_state_created
;
245 if (session
->userauth_pswd_state
== libssh2_NB_state_created
) {
246 rc
= libssh2_packet_write(session
, session
->userauth_pswd_data
,
247 session
->userauth_pswd_data_len
);
248 if (rc
== PACKET_EAGAIN
) {
249 return PACKET_EAGAIN
;
251 libssh2_error(session
, LIBSSH2_ERROR_SOCKET_SEND
,
252 "Unable to send userauth-password request", 0);
253 LIBSSH2_FREE(session
, session
->userauth_pswd_data
);
254 session
->userauth_pswd_data
= NULL
;
255 session
->userauth_pswd_state
= libssh2_NB_state_idle
;
258 LIBSSH2_FREE(session
, session
->userauth_pswd_data
);
259 session
->userauth_pswd_data
= NULL
;
261 session
->userauth_pswd_state
= libssh2_NB_state_sent
;
266 if ((session
->userauth_pswd_state
== libssh2_NB_state_sent
)
267 || (session
->userauth_pswd_state
== libssh2_NB_state_sent1
)
268 || (session
->userauth_pswd_state
== libssh2_NB_state_sent2
)) {
269 if (session
->userauth_pswd_state
== libssh2_NB_state_sent
) {
270 rc
= libssh2_packet_requirev_ex(session
, reply_codes
,
271 &session
->userauth_pswd_data
,
272 &session
->userauth_pswd_data_len
,
275 userauth_pswd_packet_requirev_state
);
276 if (rc
== PACKET_EAGAIN
) {
277 return PACKET_EAGAIN
;
279 session
->userauth_pswd_state
= libssh2_NB_state_idle
;
283 if (session
->userauth_pswd_data
[0] == SSH_MSG_USERAUTH_SUCCESS
) {
284 _libssh2_debug(session
, LIBSSH2_DBG_AUTH
,
285 "Password authentication successful");
286 LIBSSH2_FREE(session
, session
->userauth_pswd_data
);
287 session
->userauth_pswd_data
= NULL
;
288 session
->state
|= LIBSSH2_STATE_AUTHENTICATED
;
289 session
->userauth_pswd_state
= libssh2_NB_state_idle
;
293 session
->userauth_pswd_newpw
= NULL
;
294 session
->userauth_pswd_newpw_len
= 0;
296 session
->userauth_pswd_state
= libssh2_NB_state_sent1
;
299 if ((session
->userauth_pswd_data
[0] ==
300 SSH_MSG_USERAUTH_PASSWD_CHANGEREQ
)
301 || (session
->userauth_pswd_data0
==
302 SSH_MSG_USERAUTH_PASSWD_CHANGEREQ
)) {
303 session
->userauth_pswd_data0
= SSH_MSG_USERAUTH_PASSWD_CHANGEREQ
;
305 if ((session
->userauth_pswd_state
== libssh2_NB_state_sent1
) ||
306 (session
->userauth_pswd_state
== libssh2_NB_state_sent2
)) {
307 if (session
->userauth_pswd_state
== libssh2_NB_state_sent1
) {
308 _libssh2_debug(session
, LIBSSH2_DBG_AUTH
,
309 "Password change required");
310 LIBSSH2_FREE(session
, session
->userauth_pswd_data
);
311 session
->userauth_pswd_data
= NULL
;
313 if (passwd_change_cb
) {
314 if (session
->userauth_pswd_state
== libssh2_NB_state_sent1
) {
315 passwd_change_cb(session
,
316 &session
->userauth_pswd_newpw
,
317 &session
->userauth_pswd_newpw_len
,
319 if (!session
->userauth_pswd_newpw
) {
320 libssh2_error(session
,
321 LIBSSH2_ERROR_PASSWORD_EXPIRED
,
322 "Password expired, and callback failed",
327 /* basic data_len + newpw_len(4) */
328 session
->userauth_pswd_data_len
=
329 username_len
+ password_len
+ 44 +
330 session
->userauth_pswd_newpw_len
;
332 s
= session
->userauth_pswd_data
=
333 LIBSSH2_ALLOC(session
,
334 session
->userauth_pswd_data_len
);
335 if (!session
->userauth_pswd_data
) {
336 libssh2_error(session
, LIBSSH2_ERROR_ALLOC
,
337 "Unable to allocate memory for userauth-password-change request",
339 LIBSSH2_FREE(session
,
340 session
->userauth_pswd_newpw
);
341 session
->userauth_pswd_newpw
= NULL
;
345 *(s
++) = SSH_MSG_USERAUTH_REQUEST
;
346 libssh2_htonu32(s
, username_len
);
348 memcpy(s
, username
, username_len
);
351 libssh2_htonu32(s
, sizeof("ssh-connection") - 1);
353 memcpy(s
, "ssh-connection",
354 sizeof("ssh-connection") - 1);
355 s
+= sizeof("ssh-connection") - 1;
357 libssh2_htonu32(s
, sizeof("password") - 1);
359 memcpy(s
, "password", sizeof("password") - 1);
360 s
+= sizeof("password") - 1;
365 libssh2_htonu32(s
, password_len
);
367 memcpy(s
, password
, password_len
);
370 libssh2_htonu32(s
, session
->userauth_pswd_newpw_len
);
372 memcpy(s
, session
->userauth_pswd_newpw
,
373 session
->userauth_pswd_newpw_len
);
374 s
+= session
->userauth_pswd_newpw_len
;
376 session
->userauth_pswd_state
= libssh2_NB_state_sent2
;
379 if (session
->userauth_pswd_state
== libssh2_NB_state_sent2
) {
380 rc
= libssh2_packet_write(session
,
381 session
->userauth_pswd_data
,
383 userauth_pswd_data_len
);
384 if (rc
== PACKET_EAGAIN
) {
385 return PACKET_EAGAIN
;
387 libssh2_error(session
, LIBSSH2_ERROR_SOCKET_SEND
,
388 "Unable to send userauth-password-change request",
390 LIBSSH2_FREE(session
, session
->userauth_pswd_data
);
391 session
->userauth_pswd_data
= NULL
;
392 LIBSSH2_FREE(session
,
393 session
->userauth_pswd_newpw
);
394 session
->userauth_pswd_newpw
= NULL
;
397 LIBSSH2_FREE(session
, session
->userauth_pswd_data
);
398 session
->userauth_pswd_data
= NULL
;
399 LIBSSH2_FREE(session
, session
->userauth_pswd_newpw
);
400 session
->userauth_pswd_newpw
= NULL
;
403 * Ugliest use of goto ever. Blame it on the
404 * askN => requirev migration.
406 session
->userauth_pswd_state
= libssh2_NB_state_sent
;
407 goto password_response
;
411 libssh2_error(session
, LIBSSH2_ERROR_PASSWORD_EXPIRED
,
412 "Password Expired, and no callback specified",
414 session
->userauth_pswd_state
= libssh2_NB_state_idle
;
421 LIBSSH2_FREE(session
, session
->userauth_pswd_data
);
422 session
->userauth_pswd_data
= NULL
;
423 session
->userauth_pswd_state
= libssh2_NB_state_idle
;
429 /* {{{ libssh2_file_read_publickey
430 * Read a public key from an id_???.pub style file
433 libssh2_file_read_publickey(LIBSSH2_SESSION
* session
, unsigned char **method
,
434 unsigned long *method_len
,
435 unsigned char **pubkeydata
,
436 unsigned long *pubkeydata_len
,
437 const char *pubkeyfile
)
441 unsigned char *pubkey
= NULL
, *sp1
, *sp2
, *tmp
;
442 size_t pubkey_len
= 0;
443 unsigned int tmp_len
;
445 _libssh2_debug(session
, LIBSSH2_DBG_AUTH
, "Loading public key file: %s",
447 /* Read Public Key */
448 fd
= fopen(pubkeyfile
, "r");
450 libssh2_error(session
, LIBSSH2_ERROR_FILE
,
451 "Unable to open public key file", 0);
454 while (!feof(fd
) && (c
= fgetc(fd
)) != '\r' && c
!= '\n')
457 /* the last character was EOF */
462 if (pubkey_len
<= 1) {
463 libssh2_error(session
, LIBSSH2_ERROR_FILE
,
464 "Invalid data in public key file", 0);
469 pubkey
= LIBSSH2_ALLOC(session
, pubkey_len
);
471 libssh2_error(session
, LIBSSH2_ERROR_ALLOC
,
472 "Unable to allocate memory for public key data", 0);
476 if (fread(pubkey
, 1, pubkey_len
, fd
) != pubkey_len
) {
477 libssh2_error(session
, LIBSSH2_ERROR_FILE
,
478 "Unable to read public key from file", 0);
479 LIBSSH2_FREE(session
, pubkey
);
485 * Remove trailing whitespace
487 while (pubkey_len
&& isspace(pubkey
[pubkey_len
- 1]))
491 libssh2_error(session
, LIBSSH2_ERROR_FILE
, "Missing public key data",
493 LIBSSH2_FREE(session
, pubkey
);
497 if ((sp1
= memchr(pubkey
, ' ', pubkey_len
)) == NULL
) {
498 libssh2_error(session
, LIBSSH2_ERROR_FILE
, "Invalid public key data",
500 LIBSSH2_FREE(session
, pubkey
);
503 /* Wasting some bytes here (okay, more than some),
504 * but since it's likely to be freed soon anyway,
505 * we'll just avoid the extra free/alloc and call it a wash */
507 *method_len
= sp1
- pubkey
;
511 if ((sp2
= memchr(sp1
, ' ', pubkey_len
- *method_len
)) == NULL
) {
512 /* Assume that the id string is missing, but that it's okay */
513 sp2
= pubkey
+ pubkey_len
;
516 if (libssh2_base64_decode
517 (session
, (char **) &tmp
, &tmp_len
, (char *) sp1
, sp2
- sp1
)) {
518 libssh2_error(session
, LIBSSH2_ERROR_FILE
,
519 "Invalid key data, not base64 encoded", 0);
520 LIBSSH2_FREE(session
, pubkey
);
524 *pubkeydata_len
= tmp_len
;
531 /* {{{ libssh2_file_read_privatekey
532 * Read a PEM encoded private key from an id_??? style file
535 libssh2_file_read_privatekey(LIBSSH2_SESSION
* session
,
536 const LIBSSH2_HOSTKEY_METHOD
** hostkey_method
,
537 void **hostkey_abstract
,
538 const unsigned char *method
, int method_len
,
539 const char *privkeyfile
, const char *passphrase
)
541 const LIBSSH2_HOSTKEY_METHOD
**hostkey_methods_avail
=
542 libssh2_hostkey_methods();
544 _libssh2_debug(session
, LIBSSH2_DBG_AUTH
, "Loading private key file: %s",
546 *hostkey_method
= NULL
;
547 *hostkey_abstract
= NULL
;
548 while (*hostkey_methods_avail
&& (*hostkey_methods_avail
)->name
) {
549 if ((*hostkey_methods_avail
)->initPEM
550 && strncmp((*hostkey_methods_avail
)->name
, (const char *) method
,
552 *hostkey_method
= *hostkey_methods_avail
;
555 hostkey_methods_avail
++;
557 if (!*hostkey_method
) {
558 libssh2_error(session
, LIBSSH2_ERROR_METHOD_NONE
,
559 "No handler for specified private key", 0);
563 if ((*hostkey_method
)->
564 initPEM(session
, privkeyfile
, (unsigned char *) passphrase
,
566 libssh2_error(session
, LIBSSH2_ERROR_FILE
,
567 "Unable to initialize private key from file", 0);
576 /* {{{ libssh2_userauth_hostbased_fromfile_ex
577 * Authenticate using a keypair found in the named files
580 libssh2_userauth_hostbased_fromfile_ex(LIBSSH2_SESSION
* session
,
581 const char *username
,
582 unsigned int username_len
,
583 const char *publickey
,
584 const char *privatekey
,
585 const char *passphrase
,
586 const char *hostname
,
587 unsigned int hostname_len
,
588 const char *local_username
,
589 unsigned int local_username_len
)
591 const LIBSSH2_HOSTKEY_METHOD
*privkeyobj
;
593 unsigned char buf
[5];
594 struct iovec datavec
[4];
595 unsigned char *pubkeydata
, *sig
;
596 static const unsigned char reply_codes
[3] =
597 { SSH_MSG_USERAUTH_SUCCESS
, SSH_MSG_USERAUTH_FAILURE
, 0 };
598 unsigned long pubkeydata_len
, sig_len
, data_len
;
601 if (session
->userauth_host_state
== libssh2_NB_state_idle
) {
602 /* Zero the whole thing out */
603 memset(&session
->userauth_host_packet_requirev_state
, 0,
604 sizeof(session
->userauth_host_packet_requirev_state
));
606 if (libssh2_file_read_publickey
607 (session
, &session
->userauth_host_method
,
608 &session
->userauth_host_method_len
, &pubkeydata
, &pubkeydata_len
,
614 * 48 = packet_type(1) + username_len(4) + servicename_len(4) +
615 * service_name(14)"ssh-connection" + authmethod_len(4) +
616 * authmethod(9)"hostbased" + method_len(4) + pubkeydata_len(4) +
617 * local_username_len(4)
619 session
->userauth_host_packet_len
=
620 username_len
+ session
->userauth_host_method_len
+ hostname_len
+
621 local_username_len
+ pubkeydata_len
+ 48;
624 * Preallocate space for an overall length, method name again,
625 * and the signature, which won't be any larger than the size of
626 * the publickeydata itself
628 session
->userauth_host_s
= session
->userauth_host_packet
=
629 LIBSSH2_ALLOC(session
,
630 session
->userauth_host_packet_len
+ 4 + (4 +
632 userauth_host_method_len
)
633 + (4 + pubkeydata_len
));
634 if (!session
->userauth_host_packet
) {
635 LIBSSH2_FREE(session
, session
->userauth_host_method
);
636 session
->userauth_host_method
= NULL
;
640 *(session
->userauth_host_s
++) = SSH_MSG_USERAUTH_REQUEST
;
641 libssh2_htonu32(session
->userauth_host_s
, username_len
);
642 session
->userauth_host_s
+= 4;
643 memcpy(session
->userauth_host_s
, username
, username_len
);
644 session
->userauth_host_s
+= username_len
;
646 libssh2_htonu32(session
->userauth_host_s
, 14);
647 session
->userauth_host_s
+= 4;
648 memcpy(session
->userauth_host_s
, "ssh-connection", 14);
649 session
->userauth_host_s
+= 14;
651 libssh2_htonu32(session
->userauth_host_s
, 9);
652 session
->userauth_host_s
+= 4;
653 memcpy(session
->userauth_host_s
, "hostbased", 9);
654 session
->userauth_host_s
+= 9;
656 libssh2_htonu32(session
->userauth_host_s
,
657 session
->userauth_host_method_len
);
658 session
->userauth_host_s
+= 4;
659 memcpy(session
->userauth_host_s
, session
->userauth_host_method
,
660 session
->userauth_host_method_len
);
661 session
->userauth_host_s
+= session
->userauth_host_method_len
;
663 libssh2_htonu32(session
->userauth_host_s
, pubkeydata_len
);
664 session
->userauth_host_s
+= 4;
665 memcpy(session
->userauth_host_s
, pubkeydata
, pubkeydata_len
);
666 session
->userauth_host_s
+= pubkeydata_len
;
668 libssh2_htonu32(session
->userauth_host_s
, hostname_len
);
669 session
->userauth_host_s
+= 4;
670 memcpy(session
->userauth_host_s
, hostname
, hostname_len
);
671 session
->userauth_host_s
+= hostname_len
;
673 libssh2_htonu32(session
->userauth_host_s
, local_username_len
);
674 session
->userauth_host_s
+= 4;
675 memcpy(session
->userauth_host_s
, local_username
, local_username_len
);
676 session
->userauth_host_s
+= local_username_len
;
678 if (libssh2_file_read_privatekey
679 (session
, &privkeyobj
, &abstract
, session
->userauth_host_method
,
680 session
->userauth_host_method_len
, privatekey
, passphrase
)) {
681 LIBSSH2_FREE(session
, session
->userauth_host_method
);
682 session
->userauth_host_method
= NULL
;
683 LIBSSH2_FREE(session
, session
->userauth_host_packet
);
684 session
->userauth_host_packet
= NULL
;
688 libssh2_htonu32(buf
, session
->session_id_len
);
689 datavec
[0].iov_base
= buf
;
690 datavec
[0].iov_len
= 4;
691 datavec
[1].iov_base
= session
->session_id
;
692 datavec
[1].iov_len
= session
->session_id_len
;
693 datavec
[2].iov_base
= session
->userauth_host_packet
;
694 datavec
[2].iov_len
= session
->userauth_host_packet_len
;
696 if (privkeyobj
->signv(session
, &sig
, &sig_len
, 3, datavec
, &abstract
)) {
697 LIBSSH2_FREE(session
, session
->userauth_host_method
);
698 session
->userauth_host_method
= NULL
;
699 LIBSSH2_FREE(session
, session
->userauth_host_packet
);
700 session
->userauth_host_packet
= NULL
;
701 if (privkeyobj
->dtor
) {
702 privkeyobj
->dtor(session
, &abstract
);
707 if (privkeyobj
->dtor
) {
708 privkeyobj
->dtor(session
, &abstract
);
711 if (sig_len
> pubkeydata_len
) {
712 unsigned char *newpacket
;
713 /* Should *NEVER* happen, but...well.. better safe than sorry */
714 newpacket
= LIBSSH2_REALLOC(session
, session
->userauth_host_packet
, session
->userauth_host_packet_len
+ 4 + (4 + session
->userauth_host_method_len
) + (4 + sig_len
)); /* PK sigblob */
716 libssh2_error(session
, LIBSSH2_ERROR_ALLOC
,
717 "Failed allocating additional space for userauth-hostbased packet",
719 LIBSSH2_FREE(session
, sig
);
720 LIBSSH2_FREE(session
, session
->userauth_host_packet
);
721 session
->userauth_host_packet
= NULL
;
722 LIBSSH2_FREE(session
, session
->userauth_host_method
);
723 session
->userauth_host_method
= NULL
;
726 session
->userauth_host_packet
= newpacket
;
729 session
->userauth_host_s
=
730 session
->userauth_host_packet
+ session
->userauth_host_packet_len
;
732 libssh2_htonu32(session
->userauth_host_s
,
733 4 + session
->userauth_host_method_len
+ 4 + sig_len
);
734 session
->userauth_host_s
+= 4;
736 libssh2_htonu32(session
->userauth_host_s
,
737 session
->userauth_host_method_len
);
738 session
->userauth_host_s
+= 4;
739 memcpy(session
->userauth_host_s
, session
->userauth_host_method
,
740 session
->userauth_host_method_len
);
741 session
->userauth_host_s
+= session
->userauth_host_method_len
;
742 LIBSSH2_FREE(session
, session
->userauth_host_method
);
743 session
->userauth_host_method
= NULL
;
745 libssh2_htonu32(session
->userauth_host_s
, sig_len
);
746 session
->userauth_host_s
+= 4;
747 memcpy(session
->userauth_host_s
, sig
, sig_len
);
748 session
->userauth_host_s
+= sig_len
;
749 LIBSSH2_FREE(session
, sig
);
751 _libssh2_debug(session
, LIBSSH2_DBG_AUTH
,
752 "Attempting hostbased authentication");
754 session
->userauth_host_state
= libssh2_NB_state_created
;
757 if (session
->userauth_host_state
== libssh2_NB_state_created
) {
758 rc
= libssh2_packet_write(session
, session
->userauth_host_packet
,
759 session
->userauth_host_s
-
760 session
->userauth_host_packet
);
761 if (rc
== PACKET_EAGAIN
) {
762 return PACKET_EAGAIN
;
764 libssh2_error(session
, LIBSSH2_ERROR_SOCKET_SEND
,
765 "Unable to send userauth-hostbased request", 0);
766 LIBSSH2_FREE(session
, session
->userauth_host_packet
);
767 session
->userauth_host_packet
= NULL
;
768 session
->userauth_host_state
= libssh2_NB_state_idle
;
771 LIBSSH2_FREE(session
, session
->userauth_host_packet
);
772 session
->userauth_host_packet
= NULL
;
774 session
->userauth_host_state
= libssh2_NB_state_sent
;
777 if (session
->userauth_host_state
== libssh2_NB_state_sent
) {
778 rc
= libssh2_packet_requirev_ex(session
, reply_codes
,
779 &session
->userauth_host_data
,
780 &data_len
, 0, NULL
, 0,
782 userauth_host_packet_requirev_state
);
783 if (rc
== PACKET_EAGAIN
) {
784 return PACKET_EAGAIN
;
786 session
->userauth_host_state
= libssh2_NB_state_idle
;
790 if (session
->userauth_host_data
[0] == SSH_MSG_USERAUTH_SUCCESS
) {
791 _libssh2_debug(session
, LIBSSH2_DBG_AUTH
,
792 "Hostbased authentication successful");
793 /* We are us and we've proved it. */
794 LIBSSH2_FREE(session
, session
->userauth_host_data
);
795 session
->userauth_host_data
= NULL
;
796 session
->state
|= LIBSSH2_STATE_AUTHENTICATED
;
797 session
->userauth_host_state
= libssh2_NB_state_idle
;
802 /* This public key is not allowed for this user on this server */
803 LIBSSH2_FREE(session
, session
->userauth_host_data
);
804 session
->userauth_host_data
= NULL
;
805 libssh2_error(session
, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED
,
806 "Invalid signature for supplied public key, or bad username/public key combination",
808 session
->userauth_host_state
= libssh2_NB_state_idle
;
814 /* {{{ libssh2_userauth_publickey_fromfile_ex
815 * Authenticate using a keypair found in the named files
818 libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION
* session
,
819 const char *username
,
820 unsigned int username_len
,
821 const char *publickey
,
822 const char *privatekey
,
823 const char *passphrase
)
825 const LIBSSH2_HOSTKEY_METHOD
*privkeyobj
;
827 unsigned char buf
[5];
828 struct iovec datavec
[4];
829 unsigned char *pubkeydata
, *sig
;
830 unsigned char reply_codes
[4] =
831 { SSH_MSG_USERAUTH_SUCCESS
, SSH_MSG_USERAUTH_FAILURE
,
832 SSH_MSG_USERAUTH_PK_OK
, 0
834 unsigned long pubkeydata_len
, sig_len
;
837 if (session
->userauth_pblc_state
== libssh2_NB_state_idle
) {
838 /* Zero the whole thing out */
839 memset(&session
->userauth_pblc_packet_requirev_state
, 0,
840 sizeof(session
->userauth_pblc_packet_requirev_state
));
842 if (libssh2_file_read_publickey
843 (session
, &session
->userauth_pblc_method
,
844 &session
->userauth_pblc_method_len
, &pubkeydata
, &pubkeydata_len
,
850 * 45 = packet_type(1) + username_len(4) + servicename_len(4) +
851 * service_name(14)"ssh-connection" + authmethod_len(4) +
852 * authmethod(9)"publickey" + sig_included(1)'\0' + algmethod_len(4) +
855 session
->userauth_pblc_packet_len
=
856 username_len
+ session
->userauth_pblc_method_len
+ pubkeydata_len
+
860 * Preallocate space for an overall length, method name again, and
861 * the signature, which won't be any larger than the size of the
862 * publickeydata itself
864 session
->userauth_pblc_s
= session
->userauth_pblc_packet
=
865 LIBSSH2_ALLOC(session
,
866 session
->userauth_pblc_packet_len
+ 4 + (4 +
868 userauth_pblc_method_len
)
869 + (4 + pubkeydata_len
));
870 if (!session
->userauth_pblc_packet
) {
871 LIBSSH2_FREE(session
, session
->userauth_pblc_method
);
872 session
->userauth_pblc_method
= NULL
;
873 LIBSSH2_FREE(session
, pubkeydata
);
877 *(session
->userauth_pblc_s
++) = SSH_MSG_USERAUTH_REQUEST
;
878 libssh2_htonu32(session
->userauth_pblc_s
, username_len
);
879 session
->userauth_pblc_s
+= 4;
880 memcpy(session
->userauth_pblc_s
, username
, username_len
);
881 session
->userauth_pblc_s
+= username_len
;
883 libssh2_htonu32(session
->userauth_pblc_s
, 14);
884 session
->userauth_pblc_s
+= 4;
885 memcpy(session
->userauth_pblc_s
, "ssh-connection", 14);
886 session
->userauth_pblc_s
+= 14;
888 libssh2_htonu32(session
->userauth_pblc_s
, 9);
889 session
->userauth_pblc_s
+= 4;
890 memcpy(session
->userauth_pblc_s
, "publickey", 9);
891 session
->userauth_pblc_s
+= 9;
893 session
->userauth_pblc_b
= session
->userauth_pblc_s
;
894 /* Not sending signature with *this* packet */
895 *(session
->userauth_pblc_s
++) = 0;
897 libssh2_htonu32(session
->userauth_pblc_s
,
898 session
->userauth_pblc_method_len
);
899 session
->userauth_pblc_s
+= 4;
900 memcpy(session
->userauth_pblc_s
, session
->userauth_pblc_method
,
901 session
->userauth_pblc_method_len
);
902 session
->userauth_pblc_s
+= session
->userauth_pblc_method_len
;
904 libssh2_htonu32(session
->userauth_pblc_s
, pubkeydata_len
);
905 session
->userauth_pblc_s
+= 4;
906 memcpy(session
->userauth_pblc_s
, pubkeydata
, pubkeydata_len
);
907 session
->userauth_pblc_s
+= pubkeydata_len
;
908 LIBSSH2_FREE(session
, pubkeydata
);
910 _libssh2_debug(session
, LIBSSH2_DBG_AUTH
,
911 "Attempting publickey authentication");
913 session
->userauth_pblc_state
= libssh2_NB_state_created
;
916 if (session
->userauth_pblc_state
== libssh2_NB_state_created
) {
917 rc
= libssh2_packet_write(session
, session
->userauth_pblc_packet
,
918 session
->userauth_pblc_packet_len
);
919 if (rc
== PACKET_EAGAIN
) {
920 return PACKET_EAGAIN
;
922 libssh2_error(session
, LIBSSH2_ERROR_SOCKET_SEND
,
923 "Unable to send userauth-publickey request", 0);
924 LIBSSH2_FREE(session
, session
->userauth_pblc_packet
);
925 session
->userauth_pblc_packet
= NULL
;
926 LIBSSH2_FREE(session
, session
->userauth_pblc_method
);
927 session
->userauth_pblc_method
= NULL
;
928 session
->userauth_pblc_state
= libssh2_NB_state_idle
;
932 session
->userauth_pblc_state
= libssh2_NB_state_sent
;
935 if (session
->userauth_pblc_state
== libssh2_NB_state_sent
) {
936 rc
= libssh2_packet_requirev_ex(session
, reply_codes
,
937 &session
->userauth_pblc_data
,
938 &session
->userauth_pblc_data_len
, 0,
941 userauth_pblc_packet_requirev_state
);
942 if (rc
== PACKET_EAGAIN
) {
943 return PACKET_EAGAIN
;
945 LIBSSH2_FREE(session
, session
->userauth_pblc_packet
);
946 session
->userauth_pblc_packet
= NULL
;
947 LIBSSH2_FREE(session
, session
->userauth_pblc_method
);
948 session
->userauth_pblc_method
= NULL
;
949 session
->userauth_pblc_state
= libssh2_NB_state_idle
;
953 if (session
->userauth_pblc_data
[0] == SSH_MSG_USERAUTH_SUCCESS
) {
954 _libssh2_debug(session
, LIBSSH2_DBG_AUTH
,
955 "Pubkey authentication prematurely successful");
957 * God help any SSH server that allows an UNVERIFIED
958 * public key to validate the user
960 LIBSSH2_FREE(session
, session
->userauth_pblc_data
);
961 session
->userauth_pblc_data
= NULL
;
962 LIBSSH2_FREE(session
, session
->userauth_pblc_packet
);
963 session
->userauth_pblc_packet
= NULL
;
964 LIBSSH2_FREE(session
, session
->userauth_pblc_method
);
965 session
->userauth_pblc_method
= NULL
;
966 session
->state
|= LIBSSH2_STATE_AUTHENTICATED
;
967 session
->userauth_pblc_state
= libssh2_NB_state_idle
;
971 if (session
->userauth_pblc_data
[0] == SSH_MSG_USERAUTH_FAILURE
) {
972 /* This public key is not allowed for this user on this server */
973 LIBSSH2_FREE(session
, session
->userauth_pblc_data
);
974 session
->userauth_pblc_data
= NULL
;
975 LIBSSH2_FREE(session
, session
->userauth_pblc_packet
);
976 session
->userauth_pblc_packet
= NULL
;
977 LIBSSH2_FREE(session
, session
->userauth_pblc_method
);
978 session
->userauth_pblc_method
= NULL
;
979 libssh2_error(session
, LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED
,
980 "Username/PublicKey combination invalid", 0);
981 session
->userauth_pblc_state
= libssh2_NB_state_idle
;
986 LIBSSH2_FREE(session
, session
->userauth_pblc_data
);
987 session
->userauth_pblc_data
= NULL
;
989 if (libssh2_file_read_privatekey
990 (session
, &privkeyobj
, &abstract
, session
->userauth_pblc_method
,
991 session
->userauth_pblc_method_len
, privatekey
, passphrase
)) {
992 LIBSSH2_FREE(session
, session
->userauth_pblc_method
);
993 session
->userauth_pblc_method
= NULL
;
994 LIBSSH2_FREE(session
, session
->userauth_pblc_packet
);
995 session
->userauth_pblc_packet
= NULL
;
996 session
->userauth_pblc_state
= libssh2_NB_state_idle
;
1000 *session
->userauth_pblc_b
= 0x01;
1002 libssh2_htonu32(buf
, session
->session_id_len
);
1003 datavec
[0].iov_base
= buf
;
1004 datavec
[0].iov_len
= 4;
1005 datavec
[1].iov_base
= session
->session_id
;
1006 datavec
[1].iov_len
= session
->session_id_len
;
1007 datavec
[2].iov_base
= session
->userauth_pblc_packet
;
1008 datavec
[2].iov_len
= session
->userauth_pblc_packet_len
;
1010 if (privkeyobj
->signv(session
, &sig
, &sig_len
, 3, datavec
, &abstract
)) {
1011 LIBSSH2_FREE(session
, session
->userauth_pblc_method
);
1012 session
->userauth_pblc_method
= NULL
;
1013 LIBSSH2_FREE(session
, session
->userauth_pblc_packet
);
1014 session
->userauth_pblc_packet
= NULL
;
1015 if (privkeyobj
->dtor
) {
1016 privkeyobj
->dtor(session
, &abstract
);
1018 session
->userauth_pblc_state
= libssh2_NB_state_idle
;
1022 if (privkeyobj
->dtor
) {
1023 privkeyobj
->dtor(session
, &abstract
);
1026 if (sig_len
> pubkeydata_len
) {
1027 unsigned char *newpacket
;
1028 /* Should *NEVER* happen, but...well.. better safe than sorry */
1029 newpacket
= LIBSSH2_REALLOC(session
, session
->userauth_pblc_packet
, session
->userauth_pblc_packet_len
+ 4 + (4 + session
->userauth_pblc_method_len
) + (4 + sig_len
)); /* PK sigblob */
1031 libssh2_error(session
, LIBSSH2_ERROR_ALLOC
,
1032 "Failed allocating additional space for userauth-publickey packet",
1034 LIBSSH2_FREE(session
, sig
);
1035 LIBSSH2_FREE(session
, session
->userauth_pblc_packet
);
1036 session
->userauth_pblc_packet
= NULL
;
1037 LIBSSH2_FREE(session
, session
->userauth_pblc_method
);
1038 session
->userauth_pblc_method
= NULL
;
1039 session
->userauth_pblc_state
= libssh2_NB_state_idle
;
1042 session
->userauth_pblc_packet
= newpacket
;
1045 session
->userauth_pblc_s
=
1046 session
->userauth_pblc_packet
+ session
->userauth_pblc_packet_len
;
1048 libssh2_htonu32(session
->userauth_pblc_s
,
1049 4 + session
->userauth_pblc_method_len
+ 4 + sig_len
);
1050 session
->userauth_pblc_s
+= 4;
1052 libssh2_htonu32(session
->userauth_pblc_s
,
1053 session
->userauth_pblc_method_len
);
1054 session
->userauth_pblc_s
+= 4;
1055 memcpy(session
->userauth_pblc_s
, session
->userauth_pblc_method
,
1056 session
->userauth_pblc_method_len
);
1057 session
->userauth_pblc_s
+= session
->userauth_pblc_method_len
;
1058 LIBSSH2_FREE(session
, session
->userauth_pblc_method
);
1059 session
->userauth_pblc_method
= NULL
;
1061 libssh2_htonu32(session
->userauth_pblc_s
, sig_len
);
1062 session
->userauth_pblc_s
+= 4;
1063 memcpy(session
->userauth_pblc_s
, sig
, sig_len
);
1064 session
->userauth_pblc_s
+= sig_len
;
1065 LIBSSH2_FREE(session
, sig
);
1067 _libssh2_debug(session
, LIBSSH2_DBG_AUTH
,
1068 "Attempting publickey authentication -- phase 2");
1070 session
->userauth_pblc_state
= libssh2_NB_state_sent1
;
1073 if (session
->userauth_pblc_state
== libssh2_NB_state_sent1
) {
1074 rc
= libssh2_packet_write(session
, session
->userauth_pblc_packet
,
1075 session
->userauth_pblc_s
-
1076 session
->userauth_pblc_packet
);
1077 if (rc
== PACKET_EAGAIN
) {
1078 return PACKET_EAGAIN
;
1080 libssh2_error(session
, LIBSSH2_ERROR_SOCKET_SEND
,
1081 "Unable to send userauth-publickey request", 0);
1082 LIBSSH2_FREE(session
, session
->userauth_pblc_packet
);
1083 session
->userauth_pblc_packet
= NULL
;
1084 session
->userauth_pblc_state
= libssh2_NB_state_idle
;
1087 LIBSSH2_FREE(session
, session
->userauth_pblc_packet
);
1088 session
->userauth_pblc_packet
= NULL
;
1090 session
->userauth_pblc_state
= libssh2_NB_state_sent2
;
1093 /* PK_OK is no longer valid */
1096 rc
= libssh2_packet_requirev_ex(session
, reply_codes
,
1097 &session
->userauth_pblc_data
,
1098 &session
->userauth_pblc_data_len
, 0, NULL
,
1101 userauth_pblc_packet_requirev_state
);
1102 if (rc
== PACKET_EAGAIN
) {
1103 return PACKET_EAGAIN
;
1105 session
->userauth_pblc_state
= libssh2_NB_state_idle
;
1109 if (session
->userauth_pblc_data
[0] == SSH_MSG_USERAUTH_SUCCESS
) {
1110 _libssh2_debug(session
, LIBSSH2_DBG_AUTH
,
1111 "Publickey authentication successful");
1112 /* We are us and we've proved it. */
1113 LIBSSH2_FREE(session
, session
->userauth_pblc_data
);
1114 session
->userauth_pblc_data
= NULL
;
1115 session
->state
|= LIBSSH2_STATE_AUTHENTICATED
;
1116 session
->userauth_pblc_state
= libssh2_NB_state_idle
;
1120 /* This public key is not allowed for this user on this server */
1121 LIBSSH2_FREE(session
, session
->userauth_pblc_data
);
1122 session
->userauth_pblc_data
= NULL
;
1123 libssh2_error(session
, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED
,
1124 "Invalid signature for supplied public key, or bad username/public key combination",
1126 session
->userauth_pblc_state
= libssh2_NB_state_idle
;
1132 /* {{{ libssh2_userauth_keyboard_interactive
1133 * Authenticate using a challenge-response authentication
1136 libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION
* session
,
1137 const char *username
,
1138 unsigned int username_len
,
1139 LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC((*response_callback
)))
1144 static const unsigned char reply_codes
[4] = { SSH_MSG_USERAUTH_SUCCESS
,
1145 SSH_MSG_USERAUTH_FAILURE
, SSH_MSG_USERAUTH_INFO_REQUEST
, 0
1147 unsigned int language_tag_len
;
1150 if (session
->userauth_kybd_state
== libssh2_NB_state_idle
) {
1151 session
->userauth_kybd_auth_name
= NULL
;
1152 session
->userauth_kybd_auth_instruction
= NULL
;
1153 session
->userauth_kybd_num_prompts
= 0;
1154 session
->userauth_kybd_auth_failure
= 1;
1155 session
->userauth_kybd_prompts
= NULL
;
1156 session
->userauth_kybd_responses
= NULL
;
1158 /* Zero the whole thing out */
1159 memset(&session
->userauth_kybd_packet_requirev_state
, 0,
1160 sizeof(session
->userauth_kybd_packet_requirev_state
));
1162 session
->userauth_kybd_packet_len
= 1 /* byte SSH_MSG_USERAUTH_REQUEST */
1163 + 4 + username_len
/* string user name (ISO-10646 UTF-8, as defined in [RFC-3629]) */
1164 + 4 + 14 /* string service name (US-ASCII) */
1165 + 4 + 20 /* string "keyboard-interactive" (US-ASCII) */
1166 + 4 + 0 /* string language tag (as defined in [RFC-3066]) */
1167 + 4 + 0 /* string submethods (ISO-10646 UTF-8) */
1170 session
->userauth_kybd_data
= s
=
1171 LIBSSH2_ALLOC(session
, session
->userauth_kybd_packet_len
);
1173 libssh2_error(session
, LIBSSH2_ERROR_ALLOC
,
1174 "Unable to allocate memory for keyboard-interactive authentication",
1179 *s
++ = SSH_MSG_USERAUTH_REQUEST
;
1182 libssh2_htonu32(s
, username_len
);
1184 memcpy(s
, username
, username_len
);
1188 libssh2_htonu32(s
, sizeof("ssh-connection") - 1);
1190 memcpy(s
, "ssh-connection", sizeof("ssh-connection") - 1);
1191 s
+= sizeof("ssh-connection") - 1;
1193 /* "keyboard-interactive" */
1194 libssh2_htonu32(s
, sizeof("keyboard-interactive") - 1);
1196 memcpy(s
, "keyboard-interactive", sizeof("keyboard-interactive") - 1);
1197 s
+= sizeof("keyboard-interactive") - 1;
1200 libssh2_htonu32(s
, 0);
1204 libssh2_htonu32(s
, 0);
1207 _libssh2_debug(session
, LIBSSH2_DBG_AUTH
,
1208 "Attempting keyboard-interactive authentication");
1210 session
->userauth_kybd_state
= libssh2_NB_state_created
;
1213 if (session
->userauth_kybd_state
== libssh2_NB_state_created
) {
1214 rc
= libssh2_packet_write(session
, session
->userauth_kybd_data
,
1215 session
->userauth_kybd_packet_len
);
1216 if (rc
== PACKET_EAGAIN
) {
1217 return PACKET_EAGAIN
;
1219 libssh2_error(session
, LIBSSH2_ERROR_SOCKET_SEND
,
1220 "Unable to send keyboard-interactive request", 0);
1221 LIBSSH2_FREE(session
, session
->userauth_kybd_data
);
1222 session
->userauth_kybd_data
= NULL
;
1223 session
->userauth_kybd_state
= libssh2_NB_state_idle
;
1226 LIBSSH2_FREE(session
, session
->userauth_kybd_data
);
1227 session
->userauth_kybd_data
= NULL
;
1229 session
->userauth_kybd_state
= libssh2_NB_state_sent
;
1233 if (session
->userauth_kybd_state
== libssh2_NB_state_sent
) {
1234 rc
= libssh2_packet_requirev_ex(session
, reply_codes
,
1235 &session
->userauth_kybd_data
,
1236 &session
->userauth_kybd_data_len
,
1239 userauth_kybd_packet_requirev_state
);
1240 if (rc
== PACKET_EAGAIN
) {
1241 return PACKET_EAGAIN
;
1243 session
->userauth_kybd_state
= libssh2_NB_state_idle
;
1247 if (session
->userauth_kybd_data
[0] == SSH_MSG_USERAUTH_SUCCESS
) {
1248 _libssh2_debug(session
, LIBSSH2_DBG_AUTH
,
1249 "Keyboard-interactive authentication successful");
1250 LIBSSH2_FREE(session
, session
->userauth_kybd_data
);
1251 session
->userauth_kybd_data
= NULL
;
1252 session
->state
|= LIBSSH2_STATE_AUTHENTICATED
;
1253 session
->userauth_kybd_state
= libssh2_NB_state_idle
;
1257 if (session
->userauth_kybd_data
[0] == SSH_MSG_USERAUTH_FAILURE
) {
1258 LIBSSH2_FREE(session
, session
->userauth_kybd_data
);
1259 session
->userauth_kybd_data
= NULL
;
1260 session
->userauth_kybd_state
= libssh2_NB_state_idle
;
1264 /* server requested PAM-like conversation */
1266 s
= session
->userauth_kybd_data
+ 1;
1268 /* string name (ISO-10646 UTF-8) */
1269 session
->userauth_kybd_auth_name_len
= libssh2_ntohu32(s
);
1271 session
->userauth_kybd_auth_name
=
1272 LIBSSH2_ALLOC(session
, session
->userauth_kybd_auth_name_len
);
1273 if (!session
->userauth_kybd_auth_name
) {
1274 libssh2_error(session
, LIBSSH2_ERROR_ALLOC
,
1275 "Unable to allocate memory for keyboard-interactive 'name' request field",
1279 memcpy(session
->userauth_kybd_auth_name
, s
,
1280 session
->userauth_kybd_auth_name_len
);
1281 s
+= session
->userauth_kybd_auth_name_len
;
1283 /* string instruction (ISO-10646 UTF-8) */
1284 session
->userauth_kybd_auth_instruction_len
= libssh2_ntohu32(s
);
1286 session
->userauth_kybd_auth_instruction
=
1287 LIBSSH2_ALLOC(session
,
1288 session
->userauth_kybd_auth_instruction_len
);
1289 if (!session
->userauth_kybd_auth_instruction
) {
1290 libssh2_error(session
, LIBSSH2_ERROR_ALLOC
,
1291 "Unable to allocate memory for keyboard-interactive 'instruction' request field",
1295 memcpy(session
->userauth_kybd_auth_instruction
, s
,
1296 session
->userauth_kybd_auth_instruction_len
);
1297 s
+= session
->userauth_kybd_auth_instruction_len
;
1299 /* string language tag (as defined in [RFC-3066]) */
1300 language_tag_len
= libssh2_ntohu32(s
);
1302 /* ignoring this field as deprecated */
1303 s
+= language_tag_len
;
1305 /* int num-prompts */
1306 session
->userauth_kybd_num_prompts
= libssh2_ntohu32(s
);
1309 session
->userauth_kybd_prompts
=
1310 LIBSSH2_ALLOC(session
,
1311 sizeof(LIBSSH2_USERAUTH_KBDINT_PROMPT
) *
1312 session
->userauth_kybd_num_prompts
);
1313 if (!session
->userauth_kybd_prompts
) {
1314 libssh2_error(session
, LIBSSH2_ERROR_ALLOC
,
1315 "Unable to allocate memory for keyboard-interactive prompts array",
1319 memset(session
->userauth_kybd_prompts
, 0,
1320 sizeof(LIBSSH2_USERAUTH_KBDINT_PROMPT
) *
1321 session
->userauth_kybd_num_prompts
);
1323 session
->userauth_kybd_responses
=
1324 LIBSSH2_ALLOC(session
,
1325 sizeof(LIBSSH2_USERAUTH_KBDINT_RESPONSE
) *
1326 session
->userauth_kybd_num_prompts
);
1327 if (!session
->userauth_kybd_responses
) {
1328 libssh2_error(session
, LIBSSH2_ERROR_ALLOC
,
1329 "Unable to allocate memory for keyboard-interactive responses array",
1333 memset(session
->userauth_kybd_responses
, 0,
1334 sizeof(LIBSSH2_USERAUTH_KBDINT_RESPONSE
) *
1335 session
->userauth_kybd_num_prompts
);
1337 for(i
= 0; i
!= session
->userauth_kybd_num_prompts
; ++i
) {
1338 /* string prompt[1] (ISO-10646 UTF-8) */
1339 session
->userauth_kybd_prompts
[i
].length
= libssh2_ntohu32(s
);
1341 session
->userauth_kybd_prompts
[i
].text
=
1342 LIBSSH2_ALLOC(session
,
1343 session
->userauth_kybd_prompts
[i
].length
);
1344 if (!session
->userauth_kybd_prompts
[i
].text
) {
1345 libssh2_error(session
, LIBSSH2_ERROR_ALLOC
,
1346 "Unable to allocate memory for keyboard-interactive prompt message",
1350 memcpy(session
->userauth_kybd_prompts
[i
].text
, s
,
1351 session
->userauth_kybd_prompts
[i
].length
);
1352 s
+= session
->userauth_kybd_prompts
[i
].length
;
1354 /* boolean echo[1] */
1355 session
->userauth_kybd_prompts
[i
].echo
= *s
++;
1358 response_callback(session
->userauth_kybd_auth_name
,
1359 session
->userauth_kybd_auth_name_len
,
1360 session
->userauth_kybd_auth_instruction
,
1361 session
->userauth_kybd_auth_instruction_len
,
1362 session
->userauth_kybd_num_prompts
,
1363 session
->userauth_kybd_prompts
,
1364 session
->userauth_kybd_responses
,
1365 &session
->abstract
);
1367 _libssh2_debug(session
, LIBSSH2_DBG_AUTH
,
1368 "Keyboard-interactive response callback function invoked");
1370 session
->userauth_kybd_packet_len
= 1 /* byte SSH_MSG_USERAUTH_INFO_RESPONSE */
1371 + 4 /* int num-responses */
1374 for(i
= 0; i
!= session
->userauth_kybd_num_prompts
; ++i
) {
1375 /* string response[1] (ISO-10646 UTF-8) */
1376 session
->userauth_kybd_packet_len
+=
1377 4 + session
->userauth_kybd_responses
[i
].length
;
1380 session
->userauth_kybd_data
= s
=
1381 LIBSSH2_ALLOC(session
, session
->userauth_kybd_packet_len
);
1383 libssh2_error(session
, LIBSSH2_ERROR_ALLOC
,
1384 "Unable to allocate memory for keyboard-interactive response packet",
1389 *s
= SSH_MSG_USERAUTH_INFO_RESPONSE
;
1391 libssh2_htonu32(s
, session
->userauth_kybd_num_prompts
);
1394 for(i
= 0; i
!= session
->userauth_kybd_num_prompts
; ++i
) {
1395 libssh2_htonu32(s
, session
->userauth_kybd_responses
[i
].length
);
1397 memcpy(s
, session
->userauth_kybd_responses
[i
].text
,
1398 session
->userauth_kybd_responses
[i
].length
);
1399 s
+= session
->userauth_kybd_responses
[i
].length
;
1402 session
->userauth_kybd_state
= libssh2_NB_state_sent1
;
1405 if (session
->userauth_kybd_state
== libssh2_NB_state_sent1
) {
1406 rc
= libssh2_packet_write(session
, session
->userauth_kybd_data
,
1407 session
->userauth_kybd_packet_len
);
1408 if (rc
== PACKET_EAGAIN
) {
1409 return PACKET_EAGAIN
;
1412 libssh2_error(session
, LIBSSH2_ERROR_SOCKET_SEND
,
1413 "Unable to send userauth-keyboard-interactive request",
1418 session
->userauth_kybd_auth_failure
= 0;
1423 * It's safe to clean all the data here, because unallocated pointers
1424 * are filled by zeroes
1427 LIBSSH2_FREE(session
, session
->userauth_kybd_data
);
1428 session
->userauth_kybd_data
= NULL
;
1430 if (session
->userauth_kybd_prompts
) {
1431 for(i
= 0; i
!= session
->userauth_kybd_num_prompts
; ++i
) {
1432 LIBSSH2_FREE(session
, session
->userauth_kybd_prompts
[i
].text
);
1433 session
->userauth_kybd_prompts
[i
].text
= NULL
;
1437 if (session
->userauth_kybd_responses
) {
1438 for(i
= 0; i
!= session
->userauth_kybd_num_prompts
; ++i
) {
1439 LIBSSH2_FREE(session
,
1440 session
->userauth_kybd_responses
[i
].text
);
1441 session
->userauth_kybd_responses
[i
].text
= NULL
;
1445 LIBSSH2_FREE(session
, session
->userauth_kybd_prompts
);
1446 session
->userauth_kybd_prompts
= NULL
;
1447 LIBSSH2_FREE(session
, session
->userauth_kybd_responses
);
1448 session
->userauth_kybd_responses
= NULL
;
1450 if (session
->userauth_kybd_auth_failure
) {
1451 session
->userauth_kybd_state
= libssh2_NB_state_idle
;
1455 session
->userauth_kybd_state
= libssh2_NB_state_sent
;