Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/vfs/sftpfs/config_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ typedef struct
gboolean password_auth; // FALSE - no passwords allowed (default TRUE)
gboolean identities_only; // TRUE - no ssh agent (default FALSE)
gboolean pubkey_auth; // FALSE - disable public key authentication (default TRUE)
gboolean kbd_int_auth; // FALSE - disable keyboard interactive authentication (default TRUE)
char *identity_file; // A file from which the user's DSA, ECDSA or DSA authentication identity
// is read.
} sftpfs_ssh_config_entity_t;
Expand Down Expand Up @@ -104,6 +105,12 @@ static struct
FILENAME,
offsetof (sftpfs_ssh_config_entity_t, identity_file),
},
{
"^\\s*(?:KbdInteractiveAuthentication|ChallengeResponseAuthentication)\\s+(.*)$",
NULL,
BOOLEAN,
offsetof (sftpfs_ssh_config_entity_t, kbd_int_auth),
},
{
"^\\s*Port\\s+(.*)$",
NULL,
Expand Down Expand Up @@ -356,6 +363,7 @@ sftpfs_get_config_entity (const vfs_path_element_t *vpath_element, GError **mcer
config_entity->password_auth = TRUE;
config_entity->identities_only = FALSE;
config_entity->pubkey_auth = TRUE;
config_entity->kbd_int_auth = TRUE;
config_entity->port = SFTP_DEFAULT_PORT;

config_filename = sftpfs_correct_file_name (SFTPFS_SSH_CONFIG);
Expand Down Expand Up @@ -415,6 +423,7 @@ sftpfs_fill_connection_data_from_config (struct vfs_s_super *super, GError **mce
sftpfs_super->config_auth_type = (config_entity->pubkey_auth) ? PUBKEY : 0;
sftpfs_super->config_auth_type |= (config_entity->identities_only) ? 0 : AGENT;
sftpfs_super->config_auth_type |= (config_entity->password_auth) ? PASSWORD : 0;
sftpfs_super->config_auth_type |= (config_entity->kbd_int_auth) ? KEYBOARD_INTERACTIVE : 0;

if (super->path_element->port == 0)
super->path_element->port = config_entity->port;
Expand Down
117 changes: 58 additions & 59 deletions src/vfs/sftpfs/connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,6 @@ static const char *default_hostkey_methods =
*
*/

static const char *kbi_passwd = NULL;
static const struct vfs_s_super *kbi_super = NULL;

/* --------------------------------------------------------------------------------------------- */
/*** file scope functions ************************************************************************/
/* --------------------------------------------------------------------------------------------- */
Expand Down Expand Up @@ -641,8 +638,7 @@ sftpfs_recognize_auth_types (struct vfs_s_super *super)
if (userauthlist == NULL)
return FALSE;

if ((strstr (userauthlist, "password") != NULL
|| strstr (userauthlist, "keyboard-interactive") != NULL)
if (strstr (userauthlist, "password") != NULL
&& (sftpfs_super->config_auth_type & PASSWORD) != 0)
sftpfs_super->auth_type |= PASSWORD;

Expand All @@ -653,6 +649,10 @@ sftpfs_recognize_auth_types (struct vfs_s_super *super)
if ((sftpfs_super->config_auth_type & AGENT) != 0)
sftpfs_super->auth_type |= AGENT;

if (strstr (userauthlist, "keyboard-interactive") != NULL
&& (sftpfs_super->config_auth_type & KEYBOARD_INTERACTIVE) != 0)
sftpfs_super->auth_type |= KEYBOARD_INTERACTIVE;

return TRUE;
}

Expand Down Expand Up @@ -762,13 +762,13 @@ sftpfs_open_connection_ssh_key (struct vfs_s_super *super, GError **mcerror)
* Keyboard-interactive password helper for opening connection to host by
* sftpfs_open_connection_ssh_password
*
* Uses global kbi_super (data with existing connection) and kbi_passwd (password)
* Prompts the user for each server challenge and collects the response.
*
* @param name username
* @param name_len length of @name
* @param instruction unused
* @param instruction_len unused
* @param num_prompts number of possible problems to process
* @param name username. It's usually NULL, though, so unused
* @param name_len length of @name. Unused
* @param instruction optional instruction
* @param instruction_len length of @instruction
* @param num_prompts number of possible prompts to process
* @param prompts array of prompts to process
* @param responses array of responses, one per prompt
* @param abstract unused
Expand All @@ -777,27 +777,58 @@ sftpfs_open_connection_ssh_key (struct vfs_s_super *super, GError **mcerror)
static LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC (sftpfs_keyboard_interactive_helper)
{
int i;
size_t len;

(void) instruction;
(void) instruction_len;
(void) name;
(void) name_len;
(void) abstract;

if (kbi_super == NULL || kbi_passwd == NULL)
return;

if (strncmp (name, kbi_super->path_element->user, name_len) != 0)
return;
for (i = 0; i < num_prompts; ++i)
{
char *full_prompt;
char *passwd;

// assume these are password prompts
len = strlen (kbi_passwd);
full_prompt = (instruction_len > 0 && i == 0)
? g_strdup_printf ("%.*s\n%.*s", instruction_len, instruction, (int) prompts[i].length,
prompts[i].text)
: g_strndup ((const char *) prompts[i].text, prompts[i].length);
passwd = input_dialog (_ ("SFTP authentication"), full_prompt, "mc.vfs.password",
prompts[i].echo != 0 ? "" : INPUT_PASSWORD, INPUT_COMPLETE_NONE);

for (i = 0; i < num_prompts; ++i)
if (memcmp (prompts[i].text, "Password: ", prompts[i].length) == 0)
if (passwd != NULL)
{
responses[i].text = strdup (kbi_passwd);
responses[i].length = len;
// libssh2 is going to free(3) the text.
// Allocate it using libc's strdup(3) to stay on the safe side.
responses[i].text = strdup (passwd);
responses[i].length = strlen (passwd);
g_free (passwd);
}
g_free (full_prompt);
}
}

/**
* Open connection to host using keyboard-interactive auth.
*
* @param super connection data
* @param mcerror pointer to the error handler
* @return TRUE if connection was successfully opened, FALSE otherwise
*/

static gboolean
sftpfs_open_connection_ssh_keyboard_interactive (struct vfs_s_super *super, GError **mcerror)
{
sftpfs_super_t *sftpfs_super = SFTP_SUPER (super);
int rc;

mc_return_val_if_error (mcerror, FALSE);

if ((sftpfs_super->auth_type & KEYBOARD_INTERACTIVE) == 0)
return FALSE;

rc = libssh2_userauth_keyboard_interactive (sftpfs_super->session, super->path_element->user,
sftpfs_keyboard_interactive_helper);
// A kbi auth failure is not fatal here; password auth may still succeed
return rc == 0;
}

/* --------------------------------------------------------------------------------------------- */
Expand Down Expand Up @@ -830,21 +861,6 @@ sftpfs_open_connection_ssh_password (struct vfs_s_super *super, GError **mcerror
;
if (rc == 0)
return TRUE;

kbi_super = super;
kbi_passwd = super->path_element->password;

while ((rc = libssh2_userauth_keyboard_interactive (sftpfs_super->session,
super->path_element->user,
sftpfs_keyboard_interactive_helper))
== LIBSSH2_ERROR_EAGAIN)
;

kbi_super = NULL;
kbi_passwd = NULL;

if (rc == 0)
return TRUE;
}

p = g_strdup_printf (_ ("sftp: Enter password for %s "), super->path_element->user);
Expand All @@ -855,25 +871,7 @@ sftpfs_open_connection_ssh_password (struct vfs_s_super *super, GError **mcerror
mc_propagate_error (mcerror, 0, "%s", _ ("sftp: Password is empty."));
else
{
while ((rc = libssh2_userauth_password (sftpfs_super->session, super->path_element->user,
passwd))
== LIBSSH2_ERROR_EAGAIN)
;

if (rc != 0)
{
kbi_super = super;
kbi_passwd = passwd;

while ((rc = libssh2_userauth_keyboard_interactive (sftpfs_super->session,
super->path_element->user,
sftpfs_keyboard_interactive_helper))
== LIBSSH2_ERROR_EAGAIN)
;

kbi_super = NULL;
kbi_passwd = NULL;
}
rc = libssh2_userauth_password (sftpfs_super->session, super->path_element->user, passwd);

if (rc == 0)
{
Expand Down Expand Up @@ -950,6 +948,7 @@ sftpfs_open_connection (struct vfs_s_super *super, GError **mcerror)

if (!sftpfs_open_connection_ssh_agent (super, mcerror)
&& !sftpfs_open_connection_ssh_key (super, mcerror)
&& !sftpfs_open_connection_ssh_keyboard_interactive (super, mcerror)
&& !sftpfs_open_connection_ssh_password (super, mcerror))
return (-1);

Expand Down
3 changes: 2 additions & 1 deletion src/vfs/sftpfs/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ typedef enum
NONE = 0,
PUBKEY = (1 << 0),
PASSWORD = (1 << 1),
AGENT = (1 << 2)
AGENT = (1 << 2),
KEYBOARD_INTERACTIVE = (1 << 3),
} sftpfs_auth_type_t;

/*** structures declarations (and typedefs of structures)*****************************************/
Expand Down
Loading