This source file includes following definitions.
- sftpfs_open_socket
- sftpfs_read_known_hosts
- sftpfs_update_known_hosts
- sftpfs_compute_fingerprint_hash
- sftpfs_process_known_host
- sftpfs_recognize_auth_types
- sftpfs_open_connection_ssh_agent
- sftpfs_open_connection_ssh_key
- LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC
- sftpfs_open_connection_ssh_password
- sftpfs_open_connection
- sftpfs_close_connection
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 #include <config.h>
28 #include <errno.h>
29
30 #include <netdb.h>
31 #include <sys/socket.h>
32 #include <netinet/in.h>
33 #ifdef HAVE_ARPA_INET_H
34 # include <arpa/inet.h>
35 #endif
36
37 #include <libssh2.h>
38 #include <libssh2_sftp.h>
39
40 #include "lib/global.h"
41
42 #include "lib/util.h"
43 #include "lib/tty/tty.h"
44 #include "lib/vfs/utilvfs.h"
45 #include "lib/mcconfig.h"
46 #include "lib/widget.h"
47
48 #include "internal.h"
49
50
51
52
53
54 #define SHA1_DIGEST_LENGTH 20
55
56
57
58
59
60
61
62 #ifdef LIBSSH2_KNOWNHOST_KEY_ED25519
63 static const char *const hostkey_method_ssh_ed25519 = "ssh-ed25519";
64 #endif
65 #ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_521
66 static const char *const hostkey_method_ssh_ecdsa_521 = "ecdsa-sha2-nistp521";
67 #endif
68 #ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_384
69 static const char *const hostkey_method_ssh_ecdsa_384 = "ecdsa-sha2-nistp384";
70 #endif
71 #ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_256
72 static const char *const hostkey_method_ssh_ecdsa_256 = "ecdsa-sha2-nistp256";
73 #endif
74 static const char *const hostkey_method_ssh_rsa = "ssh-rsa";
75 static const char *const hostkey_method_ssh_dss = "ssh-dss";
76
77 static const char *default_hostkey_methods =
78 #ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_256
79 "ecdsa-sha2-nistp256,"
80 #endif
81 #ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_384
82 "ecdsa-sha2-nistp384,"
83 #endif
84 #ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_521
85 "ecdsa-sha2-nistp521,"
86 #endif
87 #ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_256
88 "ecdsa-sha2-nistp256-cert-v01@openssh.com,"
89 #endif
90 #ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_384
91 "ecdsa-sha2-nistp384-cert-v01@openssh.com,"
92 #endif
93 #ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_521
94 "ecdsa-sha2-nistp521-cert-v01@openssh.com,"
95 #endif
96 #ifdef LIBSSH2_KNOWNHOST_KEY_ED25519
97 "ssh-ed25519,"
98 "ssh-ed25519-cert-v01@openssh.com,"
99 #endif
100 "rsa-sha2-256,"
101 "rsa-sha2-512,"
102 "ssh-rsa,"
103 "ssh-rsa-cert-v01@openssh.com,"
104 "ssh-dss";
105
106
107
108
109
110
111
112
113
114
115
116 static const char *kbi_passwd = NULL;
117 static const struct vfs_s_super *kbi_super = NULL;
118
119
120
121
122
123
124
125
126
127
128
129
130 static int
131 sftpfs_open_socket (struct vfs_s_super *super, GError **mcerror)
132 {
133 sftpfs_super_t *sftpfs_super = SFTP_SUPER (super);
134 struct addrinfo hints, *res = NULL, *curr_res;
135 int my_socket = 0;
136 char port[BUF_TINY];
137 static char address_ipv4[INET_ADDRSTRLEN];
138 static char address_ipv6[INET6_ADDRSTRLEN];
139 int e;
140
141 mc_return_val_if_error (mcerror, LIBSSH2_INVALID_SOCKET);
142
143 if (super->path_element->host == NULL || *super->path_element->host == '\0')
144 {
145 mc_propagate_error (mcerror, 0, "%s", _ ("sftp: Invalid host name."));
146 return LIBSSH2_INVALID_SOCKET;
147 }
148
149 sprintf (port, "%hu", (unsigned short) super->path_element->port);
150
151 tty_enable_interrupt_key ();
152
153 memset (&hints, 0, sizeof (hints));
154 hints.ai_family = AF_UNSPEC;
155 hints.ai_socktype = SOCK_STREAM;
156
157 #ifdef AI_ADDRCONFIG
158
159
160
161 hints.ai_flags = AI_ADDRCONFIG;
162 #endif
163
164 e = getaddrinfo (super->path_element->host, port, &hints, &res);
165
166 #ifdef AI_ADDRCONFIG
167 if (e == EAI_BADFLAGS)
168 {
169
170 hints.ai_flags = 0;
171 e = getaddrinfo (super->path_element->host, port, &hints, &res);
172 }
173 #endif
174
175 if (e != 0)
176 {
177 mc_propagate_error (mcerror, e, _ ("sftp: %s"), gai_strerror (e));
178 my_socket = LIBSSH2_INVALID_SOCKET;
179 goto ret;
180 }
181
182 for (curr_res = res; curr_res != NULL; curr_res = curr_res->ai_next)
183 {
184 int save_errno;
185
186 switch (curr_res->ai_addr->sa_family)
187 {
188 case AF_INET:
189 sftpfs_super->ip_address =
190 inet_ntop (AF_INET, &((struct sockaddr_in *) curr_res->ai_addr)->sin_addr,
191 address_ipv4, INET_ADDRSTRLEN);
192 break;
193 case AF_INET6:
194 sftpfs_super->ip_address =
195 inet_ntop (AF_INET6, &((struct sockaddr_in6 *) curr_res->ai_addr)->sin6_addr,
196 address_ipv6, INET6_ADDRSTRLEN);
197 break;
198 default:
199 sftpfs_super->ip_address = NULL;
200 }
201
202 if (sftpfs_super->ip_address == NULL)
203 {
204 mc_propagate_error (
205 mcerror, 0, "%s",
206 _ ("sftp: failed to convert remote host IP address into text form"));
207 my_socket = LIBSSH2_INVALID_SOCKET;
208 goto ret;
209 }
210
211 my_socket = socket (curr_res->ai_family, curr_res->ai_socktype, curr_res->ai_protocol);
212
213 if (my_socket < 0)
214 {
215 if (curr_res->ai_next != NULL)
216 continue;
217
218 vfs_print_message (_ ("sftp: %s"), unix_error_string (errno));
219 my_socket = LIBSSH2_INVALID_SOCKET;
220 goto ret;
221 }
222
223 vfs_print_message (_ ("sftp: making connection to %s"), super->path_element->host);
224
225 if (connect (my_socket, curr_res->ai_addr, curr_res->ai_addrlen) >= 0)
226 break;
227
228 save_errno = errno;
229
230 close (my_socket);
231
232 if (save_errno == EINTR && tty_got_interrupt ())
233 mc_propagate_error (mcerror, 0, "%s", _ ("sftp: connection interrupted by user"));
234 else if (res->ai_next == NULL)
235 mc_propagate_error (mcerror, save_errno, _ ("sftp: connection to server failed: %s"),
236 unix_error_string (save_errno));
237 else
238 continue;
239
240 my_socket = LIBSSH2_INVALID_SOCKET;
241 break;
242 }
243
244 ret:
245 if (res != NULL)
246 freeaddrinfo (res);
247 tty_disable_interrupt_key ();
248 return my_socket;
249 }
250
251
252
253
254
255
256
257
258
259
260
261
262 static gboolean
263 sftpfs_read_known_hosts (struct vfs_s_super *super, GError **mcerror)
264 {
265 sftpfs_super_t *sftpfs_super = SFTP_SUPER (super);
266 struct libssh2_knownhost *store = NULL;
267 int rc;
268 gboolean found = FALSE;
269
270 sftpfs_super->known_hosts = libssh2_knownhost_init (sftpfs_super->session);
271 if (sftpfs_super->known_hosts == NULL)
272 goto err;
273
274 sftpfs_super->known_hosts_file =
275 mc_build_filename (mc_config_get_home_dir (), ".ssh", "known_hosts", (char *) NULL);
276 rc = libssh2_knownhost_readfile (sftpfs_super->known_hosts, sftpfs_super->known_hosts_file,
277 LIBSSH2_KNOWNHOST_FILE_OPENSSH);
278 if (rc > 0)
279 {
280 const char *kh_name_end = NULL;
281
282 while (!found && libssh2_knownhost_get (sftpfs_super->known_hosts, &store, store) == 0)
283 {
284
285
286 if (store == NULL)
287 continue;
288
289 if (store->name == NULL)
290
291 continue;
292
293 if (store->name[0] != '[')
294 found = strcmp (store->name, super->path_element->host) == 0;
295 else
296 {
297 int port;
298
299 kh_name_end = strstr (store->name, "]:");
300 if (kh_name_end == NULL)
301
302 continue;
303
304 port = (int) g_ascii_strtoll (kh_name_end + 2, NULL, 10);
305 if (port == super->path_element->port)
306 {
307 size_t kh_name_size;
308
309 kh_name_size = strlen (store->name) - 1 - strlen (kh_name_end);
310 found = strncmp (store->name + 1, super->path_element->host, kh_name_size) == 0;
311 }
312 }
313 }
314 }
315
316 if (found)
317 {
318 int mask;
319 const char *hostkey_method = NULL;
320 char *hostkey_methods;
321
322 mask = store->typemask & LIBSSH2_KNOWNHOST_KEY_MASK;
323
324 switch (mask)
325 {
326 #ifdef LIBSSH2_KNOWNHOST_KEY_ED25519
327 case LIBSSH2_KNOWNHOST_KEY_ED25519:
328 hostkey_method = hostkey_method_ssh_ed25519;
329 break;
330 #endif
331 #ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_521
332 case LIBSSH2_KNOWNHOST_KEY_ECDSA_521:
333 hostkey_method = hostkey_method_ssh_ecdsa_521;
334 break;
335 #endif
336 #ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_384
337 case LIBSSH2_KNOWNHOST_KEY_ECDSA_384:
338 hostkey_method = hostkey_method_ssh_ecdsa_384;
339 break;
340 #endif
341 #ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_256
342 case LIBSSH2_KNOWNHOST_KEY_ECDSA_256:
343 hostkey_method = hostkey_method_ssh_ecdsa_256;
344 break;
345 #endif
346 case LIBSSH2_KNOWNHOST_KEY_SSHRSA:
347 hostkey_method = hostkey_method_ssh_rsa;
348 break;
349 case LIBSSH2_KNOWNHOST_KEY_SSHDSS:
350 hostkey_method = hostkey_method_ssh_dss;
351 break;
352 case LIBSSH2_KNOWNHOST_KEY_RSA1:
353 mc_propagate_error (mcerror, 0, "%s",
354 _ ("sftp: found host key of unsupported type: RSA1"));
355 return FALSE;
356 default:
357 mc_propagate_error (mcerror, 0, "%s 0x%x", _ ("sftp: unknown host key type:"),
358 (unsigned int) mask);
359 return FALSE;
360 }
361
362
363
364
365
366
367 hostkey_methods = g_strdup_printf ("%s,%s", hostkey_method, default_hostkey_methods);
368 rc = libssh2_session_method_pref (sftpfs_super->session, LIBSSH2_METHOD_HOSTKEY,
369 hostkey_methods);
370 g_free (hostkey_methods);
371 if (rc < 0)
372 goto err;
373 }
374
375 return TRUE;
376
377 err:
378 {
379 int sftp_errno;
380
381 sftp_errno = libssh2_session_last_errno (sftpfs_super->session);
382 sftpfs_ssherror_to_gliberror (sftpfs_super, sftp_errno, mcerror);
383 }
384 return FALSE;
385 }
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400 static int
401 sftpfs_update_known_hosts (struct vfs_s_super *super, const char *remote_key, size_t remote_key_len,
402 int type_mask)
403 {
404 sftpfs_super_t *sftpfs_super = SFTP_SUPER (super);
405 int rc;
406
407
408 rc = libssh2_knownhost_addc (sftpfs_super->known_hosts, super->path_element->host, NULL,
409 remote_key, remote_key_len, NULL, 0, type_mask, NULL);
410 if (rc < 0)
411 return rc;
412
413
414 rc = libssh2_knownhost_writefile (sftpfs_super->known_hosts, sftpfs_super->known_hosts_file,
415 LIBSSH2_KNOWNHOST_FILE_OPENSSH);
416
417 if (rc < 0)
418 return rc;
419
420 (void) message (D_NORMAL, _ ("Information"),
421 _ ("Permanently added\n%s (%s)\nto the list of known hosts."),
422 super->path_element->host, sftpfs_super->ip_address);
423
424 return 0;
425 }
426
427
428
429
430
431
432
433
434 static const char *
435 sftpfs_compute_fingerprint_hash (LIBSSH2_SESSION *session)
436 {
437 static char result[SHA1_DIGEST_LENGTH * 3 + 1];
438 const char *fingerprint;
439 size_t i;
440
441
442 fingerprint = libssh2_hostkey_hash (session, LIBSSH2_HOSTKEY_HASH_SHA1);
443 if (fingerprint == NULL)
444 return NULL;
445
446 for (i = 0; i < SHA1_DIGEST_LENGTH && i * 3 < sizeof (result) - 1; i++)
447 g_snprintf ((gchar *) (result + i * 3), 4, "%02x:", (guint8) fingerprint[i]);
448
449
450 result[i * 3 - 1] = '\0';
451
452 return result;
453 }
454
455
456
457
458
459
460
461
462
463
464
465
466 static gboolean
467 sftpfs_process_known_host (struct vfs_s_super *super, GError **mcerror)
468 {
469 sftpfs_super_t *sftpfs_super = SFTP_SUPER (super);
470 const char *remote_key;
471 const char *key_type;
472 const char *fingerprint_hash;
473 size_t remote_key_len = 0;
474 int remote_key_type = LIBSSH2_HOSTKEY_TYPE_UNKNOWN;
475 int keybit = 0;
476 struct libssh2_knownhost *host = NULL;
477 int rc;
478 char *msg = NULL;
479 gboolean handle_query = FALSE;
480
481 remote_key = libssh2_session_hostkey (sftpfs_super->session, &remote_key_len, &remote_key_type);
482 if (remote_key == NULL || remote_key_len == 0
483 || remote_key_type == LIBSSH2_HOSTKEY_TYPE_UNKNOWN)
484 {
485 mc_propagate_error (mcerror, 0, "%s", _ ("sftp: cannot get the remote host key"));
486 return FALSE;
487 }
488
489 switch (remote_key_type)
490 {
491 case LIBSSH2_HOSTKEY_TYPE_RSA:
492 keybit = LIBSSH2_KNOWNHOST_KEY_SSHRSA;
493 key_type = "RSA";
494 break;
495 case LIBSSH2_HOSTKEY_TYPE_DSS:
496 keybit = LIBSSH2_KNOWNHOST_KEY_SSHDSS;
497 key_type = "DSS";
498 break;
499 #ifdef LIBSSH2_HOSTKEY_TYPE_ECDSA_256
500 case LIBSSH2_HOSTKEY_TYPE_ECDSA_256:
501 keybit = LIBSSH2_KNOWNHOST_KEY_ECDSA_256;
502 key_type = "ECDSA";
503 break;
504 #endif
505 #ifdef LIBSSH2_HOSTKEY_TYPE_ECDSA_384
506 case LIBSSH2_HOSTKEY_TYPE_ECDSA_384:
507 keybit = LIBSSH2_KNOWNHOST_KEY_ECDSA_384;
508 key_type = "ECDSA";
509 break;
510 #endif
511 #ifdef LIBSSH2_HOSTKEY_TYPE_ECDSA_521
512 case LIBSSH2_HOSTKEY_TYPE_ECDSA_521:
513 keybit = LIBSSH2_KNOWNHOST_KEY_ECDSA_521;
514 key_type = "ECDSA";
515 break;
516 #endif
517 #ifdef LIBSSH2_HOSTKEY_TYPE_ED25519
518 case LIBSSH2_HOSTKEY_TYPE_ED25519:
519 keybit = LIBSSH2_KNOWNHOST_KEY_ED25519;
520 key_type = "ED25519";
521 break;
522 #endif
523 default:
524 mc_propagate_error (mcerror, 0, "%s",
525 _ ("sftp: unsupported key type, can't check remote host key"));
526 return FALSE;
527 }
528
529 fingerprint_hash = sftpfs_compute_fingerprint_hash (sftpfs_super->session);
530 if (fingerprint_hash == NULL)
531 {
532 mc_propagate_error (mcerror, 0, "%s", _ ("sftp: can't compute host key fingerprint hash"));
533 return FALSE;
534 }
535
536 rc = libssh2_knownhost_checkp (
537 sftpfs_super->known_hosts, super->path_element->host, super->path_element->port, remote_key,
538 remote_key_len, LIBSSH2_KNOWNHOST_TYPE_PLAIN | LIBSSH2_KNOWNHOST_KEYENC_RAW | keybit,
539 &host);
540
541 switch (rc)
542 {
543 default:
544 case LIBSSH2_KNOWNHOST_CHECK_FAILURE:
545
546 goto err;
547
548 case LIBSSH2_KNOWNHOST_CHECK_MATCH:
549
550 break;
551
552 case LIBSSH2_KNOWNHOST_CHECK_NOTFOUND:
553
554 msg = g_strdup_printf (
555 _ ("The authenticity of host\n%s (%s)\ncan't be established!\n"
556 "%s key fingerprint hash is\nSHA1:%s.\n"
557 "Do you want to add it to the list of known hosts and continue connecting?"),
558 super->path_element->host, sftpfs_super->ip_address, key_type, fingerprint_hash);
559
560 query_set_sel (2);
561 rc = query_dialog (_ ("Warning"), msg, D_NORMAL, 3, _ ("&Yes"), _ ("&Ignore"), _ ("&No"));
562 g_free (msg);
563 handle_query = TRUE;
564 break;
565
566 case LIBSSH2_KNOWNHOST_CHECK_MISMATCH:
567 msg = g_strdup_printf (_ ("%s (%s)\nis found in the list of known hosts but\n"
568 "KEYS DO NOT MATCH! THIS COULD BE A MITM ATTACK!\n"
569 "Are you sure you want to add it to the list of known hosts and "
570 "continue connecting?"),
571 super->path_element->host, sftpfs_super->ip_address);
572
573 query_set_sel (2);
574 rc = query_dialog (MSG_ERROR, msg, D_ERROR, 3, _ ("&Yes"), _ ("&Ignore"), _ ("&No"));
575 g_free (msg);
576 handle_query = TRUE;
577 break;
578 }
579
580 if (handle_query)
581 switch (rc)
582 {
583 case 0:
584
585 if (sftpfs_update_known_hosts (super, remote_key, remote_key_len,
586 LIBSSH2_KNOWNHOST_TYPE_PLAIN
587 | LIBSSH2_KNOWNHOST_KEYENC_RAW | keybit)
588 < 0)
589 goto err;
590 break;
591 case 1:
592
593 break;
594 case 2:
595 default:
596 mc_propagate_error (mcerror, 0, "%s", _ ("sftp: host key verification failed"));
597
598 goto err;
599 }
600
601 return TRUE;
602
603 err:
604 {
605 int sftp_errno;
606
607 sftp_errno = libssh2_session_last_errno (sftpfs_super->session);
608 sftpfs_ssherror_to_gliberror (sftpfs_super, sftp_errno, mcerror);
609 }
610
611 return FALSE;
612 }
613
614
615
616
617
618
619
620
621
622 static gboolean
623 sftpfs_recognize_auth_types (struct vfs_s_super *super)
624 {
625 char *userauthlist;
626 sftpfs_super_t *sftpfs_super = SFTP_SUPER (super);
627
628
629
630 userauthlist = libssh2_userauth_list (sftpfs_super->session, super->path_element->user,
631 strlen (super->path_element->user));
632
633 if (userauthlist == NULL)
634 return FALSE;
635
636 if ((strstr (userauthlist, "password") != NULL
637 || strstr (userauthlist, "keyboard-interactive") != NULL)
638 && (sftpfs_super->config_auth_type & PASSWORD) != 0)
639 sftpfs_super->auth_type |= PASSWORD;
640
641 if (strstr (userauthlist, "publickey") != NULL
642 && (sftpfs_super->config_auth_type & PUBKEY) != 0)
643 sftpfs_super->auth_type |= PUBKEY;
644
645 if ((sftpfs_super->config_auth_type & AGENT) != 0)
646 sftpfs_super->auth_type |= AGENT;
647
648 return TRUE;
649 }
650
651
652
653
654
655
656
657
658
659
660 static gboolean
661 sftpfs_open_connection_ssh_agent (struct vfs_s_super *super, GError **mcerror)
662 {
663 sftpfs_super_t *sftpfs_super = SFTP_SUPER (super);
664 struct libssh2_agent_publickey *identity, *prev_identity = NULL;
665 int rc;
666
667 mc_return_val_if_error (mcerror, FALSE);
668
669 sftpfs_super->agent = NULL;
670
671 if ((sftpfs_super->auth_type & AGENT) == 0)
672 return FALSE;
673
674
675 sftpfs_super->agent = libssh2_agent_init (sftpfs_super->session);
676 if (sftpfs_super->agent == NULL)
677 return FALSE;
678
679 if (libssh2_agent_connect (sftpfs_super->agent) != 0)
680 return FALSE;
681
682 if (libssh2_agent_list_identities (sftpfs_super->agent) != 0)
683 return FALSE;
684
685 while (TRUE)
686 {
687 rc = libssh2_agent_get_identity (sftpfs_super->agent, &identity, prev_identity);
688 if (rc == 1)
689 break;
690
691 if (rc < 0)
692 return FALSE;
693
694 if (libssh2_agent_userauth (sftpfs_super->agent, super->path_element->user, identity) == 0)
695 break;
696
697 prev_identity = identity;
698 }
699
700 return (rc == 0);
701 }
702
703
704
705
706
707
708
709
710
711
712 static gboolean
713 sftpfs_open_connection_ssh_key (struct vfs_s_super *super, GError **mcerror)
714 {
715 sftpfs_super_t *sftpfs_super = SFTP_SUPER (super);
716 char *p, *passwd;
717 gboolean ret_value = FALSE;
718
719 mc_return_val_if_error (mcerror, FALSE);
720
721 if ((sftpfs_super->auth_type & PUBKEY) == 0)
722 return FALSE;
723
724 if (sftpfs_super->privkey == NULL)
725 return FALSE;
726
727 if (libssh2_userauth_publickey_fromfile (sftpfs_super->session, super->path_element->user,
728 sftpfs_super->pubkey, sftpfs_super->privkey,
729 super->path_element->password)
730 == 0)
731 return TRUE;
732
733 p = g_strdup_printf (_ ("sftp: Enter passphrase for %s "), super->path_element->user);
734 passwd = vfs_get_password (p);
735 g_free (p);
736
737 if (passwd == NULL)
738 mc_propagate_error (mcerror, 0, "%s", _ ("sftp: Passphrase is empty."));
739 else
740 {
741 ret_value = (libssh2_userauth_publickey_fromfile (
742 sftpfs_super->session, super->path_element->user, sftpfs_super->pubkey,
743 sftpfs_super->privkey, passwd)
744 == 0);
745 g_free (passwd);
746 }
747
748 return ret_value;
749 }
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769 static LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC (sftpfs_keyboard_interactive_helper)
770 {
771 int i;
772 size_t len;
773
774 (void) instruction;
775 (void) instruction_len;
776 (void) abstract;
777
778 if (kbi_super == NULL || kbi_passwd == NULL)
779 return;
780
781 if (strncmp (name, kbi_super->path_element->user, name_len) != 0)
782 return;
783
784
785 len = strlen (kbi_passwd);
786
787 for (i = 0; i < num_prompts; ++i)
788 if (memcmp (prompts[i].text, "Password: ", prompts[i].length) == 0)
789 {
790 responses[i].text = strdup (kbi_passwd);
791 responses[i].length = len;
792 }
793 }
794
795
796
797
798
799
800
801
802
803
804 static gboolean
805 sftpfs_open_connection_ssh_password (struct vfs_s_super *super, GError **mcerror)
806 {
807 sftpfs_super_t *sftpfs_super = SFTP_SUPER (super);
808 char *p, *passwd;
809 gboolean ret_value = FALSE;
810 int rc;
811
812 mc_return_val_if_error (mcerror, FALSE);
813
814 if ((sftpfs_super->auth_type & PASSWORD) == 0)
815 return FALSE;
816
817 if (super->path_element->password != NULL)
818 {
819 while ((rc = libssh2_userauth_password (sftpfs_super->session, super->path_element->user,
820 super->path_element->password))
821 == LIBSSH2_ERROR_EAGAIN)
822 ;
823 if (rc == 0)
824 return TRUE;
825
826 kbi_super = super;
827 kbi_passwd = super->path_element->password;
828
829 while ((rc = libssh2_userauth_keyboard_interactive (sftpfs_super->session,
830 super->path_element->user,
831 sftpfs_keyboard_interactive_helper))
832 == LIBSSH2_ERROR_EAGAIN)
833 ;
834
835 kbi_super = NULL;
836 kbi_passwd = NULL;
837
838 if (rc == 0)
839 return TRUE;
840 }
841
842 p = g_strdup_printf (_ ("sftp: Enter password for %s "), super->path_element->user);
843 passwd = vfs_get_password (p);
844 g_free (p);
845
846 if (passwd == NULL)
847 mc_propagate_error (mcerror, 0, "%s", _ ("sftp: Password is empty."));
848 else
849 {
850 while ((rc = libssh2_userauth_password (sftpfs_super->session, super->path_element->user,
851 passwd))
852 == LIBSSH2_ERROR_EAGAIN)
853 ;
854
855 if (rc != 0)
856 {
857 kbi_super = super;
858 kbi_passwd = passwd;
859
860 while ((rc = libssh2_userauth_keyboard_interactive (sftpfs_super->session,
861 super->path_element->user,
862 sftpfs_keyboard_interactive_helper))
863 == LIBSSH2_ERROR_EAGAIN)
864 ;
865
866 kbi_super = NULL;
867 kbi_passwd = NULL;
868 }
869
870 if (rc == 0)
871 {
872 ret_value = TRUE;
873 g_free (super->path_element->password);
874 super->path_element->password = passwd;
875 }
876 else
877 g_free (passwd);
878 }
879
880 return ret_value;
881 }
882
883
884
885
886
887
888
889
890
891
892
893
894 int
895 sftpfs_open_connection (struct vfs_s_super *super, GError **mcerror)
896 {
897 int rc;
898 sftpfs_super_t *sftpfs_super = SFTP_SUPER (super);
899
900 mc_return_val_if_error (mcerror, -1);
901
902
903
904
905
906 sftpfs_super->socket_handle = sftpfs_open_socket (super, mcerror);
907 if (sftpfs_super->socket_handle == LIBSSH2_INVALID_SOCKET)
908 return (-1);
909
910
911 sftpfs_super->session = libssh2_session_init ();
912 if (sftpfs_super->session == NULL)
913 return (-1);
914
915 if (!sftpfs_read_known_hosts (super, mcerror))
916 return (-1);
917
918
919
920
921 while ((rc = libssh2_session_handshake (sftpfs_super->session,
922 (libssh2_socket_t) sftpfs_super->socket_handle))
923 == LIBSSH2_ERROR_EAGAIN)
924 ;
925 if (rc != 0)
926 {
927 mc_propagate_error (mcerror, rc, "%s", _ ("sftp: failure establishing SSH session"));
928 return (-1);
929 }
930
931 if (!sftpfs_process_known_host (super, mcerror))
932 return (-1);
933
934 if (!sftpfs_recognize_auth_types (super))
935 {
936 int sftp_errno;
937
938 sftp_errno = libssh2_session_last_errno (sftpfs_super->session);
939 sftpfs_ssherror_to_gliberror (sftpfs_super, sftp_errno, mcerror);
940 return (-1);
941 }
942
943 if (!sftpfs_open_connection_ssh_agent (super, mcerror)
944 && !sftpfs_open_connection_ssh_key (super, mcerror)
945 && !sftpfs_open_connection_ssh_password (super, mcerror))
946 return (-1);
947
948 sftpfs_super->sftp_session = libssh2_sftp_init (sftpfs_super->session);
949
950 if (sftpfs_super->sftp_session == NULL)
951 return (-1);
952
953
954 libssh2_session_set_blocking (sftpfs_super->session, 1);
955
956 return 0;
957 }
958
959
960
961
962
963
964
965
966
967
968 void
969 sftpfs_close_connection (struct vfs_s_super *super, const char *shutdown_message, GError **mcerror)
970 {
971 sftpfs_super_t *sftpfs_super = SFTP_SUPER (super);
972
973
974 (void) mcerror;
975
976 if (sftpfs_super->sftp_session != NULL)
977 {
978 libssh2_sftp_shutdown (sftpfs_super->sftp_session);
979 sftpfs_super->sftp_session = NULL;
980 }
981
982 if (sftpfs_super->agent != NULL)
983 {
984 libssh2_agent_disconnect (sftpfs_super->agent);
985 libssh2_agent_free (sftpfs_super->agent);
986 sftpfs_super->agent = NULL;
987 }
988
989 if (sftpfs_super->known_hosts != NULL)
990 {
991 libssh2_knownhost_free (sftpfs_super->known_hosts);
992 sftpfs_super->known_hosts = NULL;
993 }
994
995 MC_PTR_FREE (sftpfs_super->known_hosts_file);
996
997 if (sftpfs_super->session != NULL)
998 {
999 libssh2_session_disconnect (sftpfs_super->session, shutdown_message);
1000 libssh2_session_free (sftpfs_super->session);
1001 sftpfs_super->session = NULL;
1002 }
1003
1004 if (sftpfs_super->socket_handle != LIBSSH2_INVALID_SOCKET)
1005 {
1006 close (sftpfs_super->socket_handle);
1007 sftpfs_super->socket_handle = LIBSSH2_INVALID_SOCKET;
1008 }
1009 }
1010
1011