mirror of
https://github.com/MidnightCommander/mc
synced 2024-12-22 20:36:50 +03:00
Merge branch '3581_sftp_fixes'
* 3581_sftp_fixes: sftpfs: fix bad pointer arithmetic in config parser. (sftpfs_fill_config_entity_from_config): fix read of config file. Use LIBSSH2_INVALID_SOCKET macro. libssh2_session_startup() is deprecated in libssh2 >= 1.2.8. SFTP: refactoring. SFTP: minor refactoring. (sftpfs_close_connection): fix connection memleaks. (sftpfs_close_connection): fix connection memleaks. Ticket #3581: various SFTP fixes.
This commit is contained in:
commit
ab0c2afba5
@ -79,17 +79,18 @@ static struct
|
||||
size_t offset;
|
||||
} config_variables[] =
|
||||
{
|
||||
{"^\\s*User\\s+(.*)$", NULL, STRING, 0},
|
||||
{"^\\s*HostName\\s+(.*)$", NULL, STRING, 0},
|
||||
{"^\\s*IdentitiesOnly\\s+(.*)$", NULL, BOOLEAN, 0},
|
||||
{"^\\s*IdentityFile\\s+(.*)$", NULL, FILENAME, 0},
|
||||
{"^\\s*Port\\s+(.*)$", NULL, INTEGER, 0},
|
||||
{"^\\s*PasswordAuthentication\\s+(.*)$", NULL, BOOLEAN, 0},
|
||||
{"^\\s*PubkeyAuthentication\\s+(.*)$", NULL, STRING, 0},
|
||||
{"^\\s*User\\s+(.*)$", NULL, STRING, offsetof (sftpfs_ssh_config_entity_t, user)},
|
||||
{"^\\s*HostName\\s+(.*)$", NULL, STRING, offsetof (sftpfs_ssh_config_entity_t, real_host)},
|
||||
{"^\\s*IdentitiesOnly\\s+(.*)$", NULL, BOOLEAN, offsetof (sftpfs_ssh_config_entity_t, identities_only)},
|
||||
{"^\\s*IdentityFile\\s+(.*)$", NULL, FILENAME, offsetof (sftpfs_ssh_config_entity_t, identity_file)},
|
||||
{"^\\s*Port\\s+(.*)$", NULL, INTEGER, offsetof (sftpfs_ssh_config_entity_t, port)},
|
||||
{"^\\s*PasswordAuthentication\\s+(.*)$", NULL, BOOLEAN, offsetof (sftpfs_ssh_config_entity_t, password_auth)},
|
||||
{"^\\s*PubkeyAuthentication\\s+(.*)$", NULL, STRING, offsetof (sftpfs_ssh_config_entity_t, pubkey_auth)},
|
||||
{NULL, NULL, 0, 0}
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/*** file scope functions ************************************************************************/
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/**
|
||||
@ -131,9 +132,8 @@ sftpfs_correct_file_name (const char *filename)
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* FIXME: is pointer arith correct here? */
|
||||
#define POINTER_TO_STRUCTURE_MEMBER(type) \
|
||||
((type) (config_entity + (off_t) config_variables[i].offset))
|
||||
((type) ((char *) config_entity + (size_t) config_variables[i].offset))
|
||||
|
||||
/**
|
||||
* Parse string and filling one config entity by parsed data.
|
||||
@ -210,6 +210,7 @@ sftpfs_fill_config_entity_from_config (FILE * ssh_config_handler,
|
||||
gboolean host_block_hit = FALSE;
|
||||
gboolean pattern_block_hit = FALSE;
|
||||
mc_search_t *host_regexp;
|
||||
gboolean ok = TRUE;
|
||||
|
||||
mc_return_val_if_error (mcerror, FALSE);
|
||||
|
||||
@ -217,21 +218,28 @@ sftpfs_fill_config_entity_from_config (FILE * ssh_config_handler,
|
||||
host_regexp->search_type = MC_SEARCH_T_REGEX;
|
||||
host_regexp->is_case_sensitive = FALSE;
|
||||
|
||||
while (!feof (ssh_config_handler))
|
||||
while (TRUE)
|
||||
{
|
||||
char *cr;
|
||||
|
||||
if (fgets (buffer, sizeof (buffer), ssh_config_handler) == NULL)
|
||||
{
|
||||
if (errno != 0)
|
||||
int e;
|
||||
|
||||
e = errno;
|
||||
|
||||
if (!feof (ssh_config_handler))
|
||||
{
|
||||
mc_propagate_error (mcerror, errno,
|
||||
mc_propagate_error (mcerror, e,
|
||||
_("sftp: an error occurred while reading %s: %s"),
|
||||
SFTPFS_SSH_CONFIG, strerror (errno));
|
||||
mc_search_free (host_regexp);
|
||||
return FALSE;
|
||||
SFTPFS_SSH_CONFIG, strerror (e));
|
||||
ok = FALSE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
cr = strrchr (buffer, '\n');
|
||||
if (cr != NULL)
|
||||
*cr = '\0';
|
||||
@ -243,7 +251,7 @@ sftpfs_fill_config_entity_from_config (FILE * ssh_config_handler,
|
||||
|
||||
/* if previous host block exactly describe our connection */
|
||||
if (host_block_hit)
|
||||
return TRUE;
|
||||
goto done;
|
||||
|
||||
host_pattern_offset = mc_search_getstart_result_by_num (host_regexp, 1);
|
||||
host_pattern = &buffer[host_pattern_offset];
|
||||
@ -271,8 +279,10 @@ sftpfs_fill_config_entity_from_config (FILE * ssh_config_handler,
|
||||
sftpfs_fill_config_entity_from_string (config_entity, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
mc_search_free (host_regexp);
|
||||
return TRUE;
|
||||
return ok;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -389,16 +399,6 @@ sftpfs_fill_connection_data_from_config (struct vfs_s_super *super, GError ** mc
|
||||
void
|
||||
sftpfs_init_config_variables_patterns (void)
|
||||
{
|
||||
size_t structure_offsets[] = {
|
||||
offsetof (sftpfs_ssh_config_entity_t, user),
|
||||
offsetof (sftpfs_ssh_config_entity_t, real_host),
|
||||
offsetof (sftpfs_ssh_config_entity_t, identities_only),
|
||||
offsetof (sftpfs_ssh_config_entity_t, identity_file),
|
||||
offsetof (sftpfs_ssh_config_entity_t, port),
|
||||
offsetof (sftpfs_ssh_config_entity_t, password_auth),
|
||||
offsetof (sftpfs_ssh_config_entity_t, pubkey_auth)
|
||||
};
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; config_variables[i].pattern != NULL; i++)
|
||||
@ -407,7 +407,6 @@ sftpfs_init_config_variables_patterns (void)
|
||||
mc_search_new (config_variables[i].pattern, DEFAULT_CHARSET);
|
||||
config_variables[i].pattern_regexp->search_type = MC_SEARCH_T_REGEX;
|
||||
config_variables[i].pattern_regexp->is_case_sensitive = FALSE;
|
||||
config_variables[i].offset = structure_offsets[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,12 +71,12 @@ sftpfs_open_socket (struct vfs_s_super *super, GError ** mcerror)
|
||||
char port[BUF_TINY];
|
||||
int e;
|
||||
|
||||
mc_return_val_if_error (mcerror, -1);
|
||||
mc_return_val_if_error (mcerror, LIBSSH2_INVALID_SOCKET);
|
||||
|
||||
if (super->path_element->host == NULL || *super->path_element->host == '\0')
|
||||
{
|
||||
mc_propagate_error (mcerror, 0, "%s", _("sftp: Invalid host name."));
|
||||
return -1;
|
||||
return LIBSSH2_INVALID_SOCKET;
|
||||
}
|
||||
|
||||
sprintf (port, "%hu", (unsigned short) super->path_element->port);
|
||||
@ -108,7 +108,7 @@ sftpfs_open_socket (struct vfs_s_super *super, GError ** mcerror)
|
||||
if (e != 0)
|
||||
{
|
||||
mc_propagate_error (mcerror, e, _("sftp: %s"), gai_strerror (e));
|
||||
my_socket = -1;
|
||||
my_socket = LIBSSH2_INVALID_SOCKET;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
@ -124,7 +124,7 @@ sftpfs_open_socket (struct vfs_s_super *super, GError ** mcerror)
|
||||
continue;
|
||||
|
||||
vfs_print_message (_("sftp: %s"), unix_error_string (errno));
|
||||
my_socket = -1;
|
||||
my_socket = LIBSSH2_INVALID_SOCKET;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
@ -145,7 +145,7 @@ sftpfs_open_socket (struct vfs_s_super *super, GError ** mcerror)
|
||||
else
|
||||
continue;
|
||||
|
||||
my_socket = -1;
|
||||
my_socket = LIBSSH2_INVALID_SOCKET;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -174,6 +174,7 @@ sftpfs_recognize_auth_types (struct vfs_s_super *super)
|
||||
super_data->auth_type = NONE;
|
||||
|
||||
/* check what authentication methods are available */
|
||||
/* userauthlist is internally managed by libssh2 and freed by libssh2_session_free() */
|
||||
userauthlist = libssh2_userauth_list (super_data->session, super->path_element->user,
|
||||
strlen (super->path_element->user));
|
||||
|
||||
@ -187,8 +188,6 @@ sftpfs_recognize_auth_types (struct vfs_s_super *super)
|
||||
|
||||
if ((super_data->config_auth_type & AGENT) != 0)
|
||||
super_data->auth_type |= AGENT;
|
||||
|
||||
g_free (userauthlist);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -372,23 +371,28 @@ sftpfs_open_connection (struct vfs_s_super *super, GError ** mcerror)
|
||||
|
||||
super_data = (sftpfs_super_data_t *) super->data;
|
||||
|
||||
/* Create a session instance */
|
||||
super_data->session = libssh2_session_init ();
|
||||
if (super_data->session == NULL)
|
||||
return (-1);
|
||||
|
||||
/*
|
||||
* The application code is responsible for creating the socket
|
||||
* and establishing the connection
|
||||
*/
|
||||
super_data->socket_handle = sftpfs_open_socket (super, mcerror);
|
||||
if (super_data->socket_handle == -1)
|
||||
if (super_data->socket_handle == LIBSSH2_INVALID_SOCKET)
|
||||
return (-1);
|
||||
|
||||
/* Create a session instance */
|
||||
super_data->session = libssh2_session_init ();
|
||||
if (super_data->session == NULL)
|
||||
return (-1);
|
||||
|
||||
/* ... start it up. This will trade welcome banners, exchange keys,
|
||||
* and setup crypto, compression, and MAC layers
|
||||
*/
|
||||
#if LIBSSH2_VERSION_NUM < 0x010208
|
||||
rc = libssh2_session_startup (super_data->session, super_data->socket_handle);
|
||||
#else
|
||||
rc = libssh2_session_handshake (super_data->session,
|
||||
(libssh2_socket_t) super_data->socket_handle);
|
||||
#endif
|
||||
if (rc != 0)
|
||||
{
|
||||
mc_propagate_error (mcerror, rc, "%s", _("sftp: Failure establishing SSH session"));
|
||||
@ -434,14 +438,18 @@ sftpfs_close_connection (struct vfs_s_super *super, const char *shutdown_message
|
||||
{
|
||||
sftpfs_super_data_t *super_data;
|
||||
|
||||
mc_return_if_error (mcerror);
|
||||
/* no mc_return_*_if_error() here because of abort open_connection handling too */
|
||||
(void) mcerror;
|
||||
|
||||
super_data = (sftpfs_super_data_t *) super->data;
|
||||
if (super_data == NULL)
|
||||
return;
|
||||
|
||||
vfs_path_element_free (super_data->original_connection_info);
|
||||
super_data->original_connection_info = NULL;
|
||||
if (super_data->sftp_session != NULL)
|
||||
{
|
||||
libssh2_sftp_shutdown (super_data->sftp_session);
|
||||
super_data->sftp_session = NULL;
|
||||
}
|
||||
|
||||
if (super_data->agent != NULL)
|
||||
{
|
||||
@ -450,24 +458,19 @@ sftpfs_close_connection (struct vfs_s_super *super, const char *shutdown_message
|
||||
super_data->agent = NULL;
|
||||
}
|
||||
|
||||
if (super_data->sftp_session != NULL)
|
||||
{
|
||||
libssh2_sftp_shutdown (super_data->sftp_session);
|
||||
super_data->sftp_session = NULL;
|
||||
}
|
||||
super_data->fingerprint = NULL;
|
||||
|
||||
if (super_data->session != NULL)
|
||||
{
|
||||
libssh2_session_disconnect (super_data->session, shutdown_message);
|
||||
libssh2_session_free (super_data->session);
|
||||
super_data->session = NULL;
|
||||
}
|
||||
|
||||
super_data->fingerprint = NULL;
|
||||
|
||||
if (super_data->socket_handle != -1)
|
||||
if (super_data->socket_handle != LIBSSH2_INVALID_SOCKET)
|
||||
{
|
||||
close (super_data->socket_handle);
|
||||
super_data->socket_handle = -1;
|
||||
super_data->socket_handle = LIBSSH2_INVALID_SOCKET;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,11 @@
|
||||
|
||||
#define SFTP_DEFAULT_PORT 22
|
||||
|
||||
/* LIBSSH2_INVALID_SOCKET is defined in libssh2 >= 1.4.1 */
|
||||
#ifndef LIBSSH2_INVALID_SOCKET
|
||||
#define LIBSSH2_INVALID_SOCKET -1
|
||||
#endif
|
||||
|
||||
/*** enums ***************************************************************************************/
|
||||
|
||||
typedef enum
|
||||
|
@ -104,6 +104,7 @@ sftpfs_cb_open_connection (struct vfs_s_super *super,
|
||||
}
|
||||
|
||||
sftpfs_super_data = g_new0 (sftpfs_super_data_t, 1);
|
||||
sftpfs_super_data->socket_handle = LIBSSH2_INVALID_SOCKET;
|
||||
sftpfs_super_data->original_connection_info = vfs_path_element_clone (vpath_element);
|
||||
super->data = sftpfs_super_data;
|
||||
super->path_element = vfs_path_element_clone (vpath_element);
|
||||
@ -137,11 +138,18 @@ static void
|
||||
sftpfs_cb_close_connection (struct vfs_class *me, struct vfs_s_super *super)
|
||||
{
|
||||
GError *mcerror = NULL;
|
||||
sftpfs_super_data_t *sftpfs_super_data;
|
||||
|
||||
(void) me;
|
||||
sftpfs_close_connection (super, "Normal Shutdown", &mcerror);
|
||||
|
||||
sftpfs_super_data = (sftpfs_super_data_t *) super->data;
|
||||
if (sftpfs_super_data != NULL)
|
||||
vfs_path_element_free (sftpfs_super_data->original_connection_info);
|
||||
|
||||
mc_error_message (&mcerror, NULL);
|
||||
g_free (super->data);
|
||||
|
||||
g_free (sftpfs_super_data);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
Loading…
Reference in New Issue
Block a user