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