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:
Andrew Borodin 2016-02-13 16:40:13 +03:00
commit ab0c2afba5
4 changed files with 69 additions and 54 deletions

View File

@ -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];
}
}

View File

@ -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;
}
}

View File

@ -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

View File

@ -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);
}
/* --------------------------------------------------------------------------------------------- */