Ticket #2760: The password for session ftp remains in input history

Signed-off-by: Slava Zanko <slavazanko@gmail.com>
This commit is contained in:
Slava Zanko 2012-04-05 12:51:06 +03:00
parent 504705a172
commit 4184555b82
8 changed files with 70 additions and 46 deletions

View File

@ -203,53 +203,65 @@ do_show_hist (WInput * in)
in->history_changed = TRUE;
}
/* --------------------------------------------------------------------------------------------- */
/** Strip password from incomplete url (just user:pass@host without VFS prefix).
*
* @param url partial URL
* @return newly allocated string without password
*/
static char *
input_history_strip_password (const char *url)
{
char *at, *delim, *colon;
at = strrchr (url, '@');
if (at == NULL)
return g_strdup (url);
/* TODO: handle ':' and '@' in password */
delim = strstr (url, VFS_PATH_URL_DELIMITER);
if (delim != NULL)
colon = strchr (delim + strlen (VFS_PATH_URL_DELIMITER), ':');
else
colon = strchr (url, ':');
if (colon == NULL)
return g_strdup (url);
*colon = '\0';
return g_strconcat (url, at, NULL);
}
/* --------------------------------------------------------------------------------------------- */
static void
push_history (WInput * in, const char *text)
{
/* input widget where urls with passwords are entered without any
vfs prefix */
const char *password_input_fields[] = {
" Link to a remote machine ",
" FTP to machine ",
" SMB link to machine "
};
const size_t ELEMENTS = (sizeof (password_input_fields) / sizeof (password_input_fields[0]));
char *t;
size_t i;
gboolean empty;
if (text == NULL)
return;
#ifdef ENABLE_NLS
for (i = 0; i < ELEMENTS; i++)
password_input_fields[i] = _(password_input_fields[i]);
#endif
t = g_strstrip (g_strdup (text));
empty = *t == '\0';
g_free (t);
t = g_strdup (empty ? "" : text);
if (in->history_name != NULL)
if (!empty && in->history_name != NULL && in->strip_password)
{
/* FIXME: It is the strange code. Rewrite is needed. */
const char *p = in->history_name + 3;
/*
We got string user:pass@host without any VFS prefixes
and vfs_path_to_str_flags (t, VPF_STRIP_PASSWORD) doesn't work.
Therefore we want to strip password in separate algorithm
*/
char *url_with_stripped_password;
for (i = 0; i < ELEMENTS; i++)
if (strcmp (p, password_input_fields[i]) == 0)
{
vfs_path_t *vpath;
vpath = vfs_path_from_str (t);
url_with_stripped_password = input_history_strip_password (t);
g_free (t);
t = vfs_path_to_str_flags (vpath, 0, VPF_STRIP_PASSWORD);
vfs_path_free (vpath);
break;
}
t = url_with_stripped_password;
}
if (in->history == NULL || in->history->data == NULL || strcmp (in->history->data, t) != 0 ||
@ -979,6 +991,7 @@ input_new (int y, int x, const int *input_colors, int width, const char *def_tex
in->need_push = TRUE;
in->is_password = FALSE;
in->charpoint = 0;
in->strip_password = FALSE;
/* in->buffer will be corrected in "history_load" event handler */
in->current_max_size = width + 1;

View File

@ -62,6 +62,7 @@ typedef struct
GList *history; /* the history */
gboolean history_changed; /* the history has changed */
gboolean need_push; /* need to push the current Input on hist? */
gboolean strip_password; /* need to strip password before placing string to history */
char **completions; /* possible completions array */
input_complete_t completion_flags;
char charbuf[MB_LEN_MAX]; /* buffer for multibytes characters */

View File

@ -109,6 +109,8 @@ quick_dialog_skip (QuickDialog * qd, int nskip)
in->is_password = (qw->u.input.flags == 1);
if ((qw->u.input.flags & 2) != 0)
in->completion_flags |= INPUT_COMPLETE_CD;
if ((qw->u.input.flags & 4) != 0)
in->strip_password = TRUE;
qw->widget = (Widget *) in;
*qw->u.input.result = NULL;
break;

View File

@ -186,6 +186,7 @@ typedef struct
int flags; /* 1 -- is_password, 2 -- INPUT_COMPLETE_CD */
const char *histname;
char **result;
gboolean strip_password;
} input;
struct

View File

@ -180,14 +180,14 @@ bg_message (int dummy, int *flags, char *title, const char *text)
*/
static char *
fg_input_dialog_help (const char *header, const char *text, const char *help,
const char *history_name, const char *def_text)
const char *history_name, const char *def_text, gboolean strip_password)
{
char *my_str;
int flags = (strip_password) ? 4 : 0;
QuickWidget quick_widgets[] = {
/* 0 */ QUICK_BUTTON (6, 64, 1, 0, N_("&Cancel"), B_CANCEL, NULL),
/* 1 */ QUICK_BUTTON (3, 64, 1, 0, N_("&OK"), B_ENTER, NULL),
/* 2 */ QUICK_INPUT (3, 64, 0, 0, def_text, 58, 0, NULL, &my_str),
/* 2 */ QUICK_INPUT (3, 64, 0, 0, def_text, 58, flags, NULL, &my_str),
/* 3 */ QUICK_LABEL (3, 64, 2, 0, ""),
QUICK_END
};
@ -474,7 +474,7 @@ message (int flags, const char *title, const char *text, ...)
char *
input_dialog_help (const char *header, const char *text, const char *help,
const char *history_name, const char *def_text)
const char *history_name, const char *def_text, gboolean strip_password)
{
#ifdef ENABLE_BACKGROUND
if (mc_global.we_are_background)
@ -482,18 +482,20 @@ input_dialog_help (const char *header, const char *text, const char *help,
union
{
void *p;
char *(*f) (const char *, const char *, const char *, const char *, const char *);
char *(*f) (const char *, const char *, const char *, const char *, const char *,
gboolean);
} func;
func.f = fg_input_dialog_help;
return wtools_parent_call_string (func.p, 5,
return wtools_parent_call_string (func.p, 6,
strlen (header), header, strlen (text),
text, strlen (help), help,
strlen (history_name), history_name,
strlen (def_text), def_text);
strlen (def_text), def_text,
sizeof (gboolean), strip_password);
}
else
#endif /* ENABLE_BACKGROUND */
return fg_input_dialog_help (header, text, help, history_name, def_text);
return fg_input_dialog_help (header, text, help, history_name, def_text, strip_password);
}
/* --------------------------------------------------------------------------------------------- */
@ -502,7 +504,7 @@ input_dialog_help (const char *header, const char *text, const char *help,
char *
input_dialog (const char *header, const char *text, const char *history_name, const char *def_text)
{
return input_dialog_help (header, text, "[Input Line Keys]", history_name, def_text);
return input_dialog_help (header, text, "[Input Line Keys]", history_name, def_text, FALSE);
}
/* --------------------------------------------------------------------------------------------- */

View File

@ -33,7 +33,7 @@ enum
char *input_dialog (const char *header, const char *text,
const char *history_name, const char *def_text);
char *input_dialog_help (const char *header, const char *text, const char *help,
const char *history_name, const char *def_text);
const char *history_name, const char *def_text, gboolean strip_password);
char *input_expand_dialog (const char *header, const char *text,
const char *history_name, const char *def_text);

View File

@ -234,7 +234,7 @@ set_panel_filter (WPanel * p)
reg_exp = input_dialog_help (_("Filter"),
_("Set expression for filtering filenames"),
"[Filter...]", MC_HISTORY_FM_PANEL_FILTER, x);
"[Filter...]", MC_HISTORY_FM_PANEL_FILTER, x, FALSE);
if (!reg_exp)
return;
set_panel_filter_to (p, reg_exp);
@ -539,7 +539,7 @@ transform_prefix (const char *prefix)
static void
nice_cd (const char *text, const char *xtext, const char *help,
const char *history_name, const char *prefix, int to_home)
const char *history_name, const char *prefix, int to_home, gboolean strip_password)
{
char *machine;
char *cd_path;
@ -547,7 +547,7 @@ nice_cd (const char *text, const char *xtext, const char *help,
if (!SELECTED_IS_PANEL)
return;
machine = input_dialog_help (text, xtext, help, history_name, "");
machine = input_dialog_help (text, xtext, help, history_name, "", strip_password);
if (!machine)
return;
@ -1537,7 +1537,7 @@ void
ftplink_cmd (void)
{
nice_cd (_("FTP to machine"), _(machine_str),
"[FTP File System]", ":ftplink_cmd: FTP to machine ", "/#ftp:", 1);
"[FTP File System]", ":ftplink_cmd: FTP to machine ", "/#ftp:", 1, TRUE);
}
#endif /* ENABLE_VFS_FTP */
@ -1549,7 +1549,7 @@ fishlink_cmd (void)
{
nice_cd (_("Shell link to machine"), _(machine_str),
"[FIle transfer over SHell filesystem]", ":fishlink_cmd: Shell link to machine ",
"/#sh:", 1);
"/#sh:", 1, TRUE);
}
#endif /* ENABLE_VFS_FISH */
@ -1560,7 +1560,7 @@ void
smblink_cmd (void)
{
nice_cd (_("SMB link to machine"), _(machine_str),
"[SMB File System]", ":smblink_cmd: SMB link to machine ", "/#smb:", 0);
"[SMB File System]", ":smblink_cmd: SMB link to machine ", "/#smb:", 0, TRUE);
}
#endif /* ENABLE_VFS_SMB */
#endif /* ENABLE_VFS_NET */
@ -1573,7 +1573,7 @@ undelete_cmd (void)
{
nice_cd (_("Undelete files on an ext2 file system"),
_("Enter device (without /dev/) to undelete\nfiles on: (F1 for details)"),
"[Undelete File System]", ":undelete_cmd: Undel on ext2 fs ", "/#undel:", 0);
"[Undelete File System]", ":undelete_cmd: Undel on ext2 fs ", "/#undel:", 0, FALSE);
}
#endif /* ENABLE_VFS_UNDELFS */

View File

@ -159,6 +159,11 @@ START_TEST(test_path_to_str_flags)
vfs_test_ops1.prefix = "test1";
vfs_register_class (&vfs_test_ops1);
vpath = vfs_path_from_str_flags ("test1://user:passwd@127.0.0.1", VPF_NO_CANON);
str_path = vfs_path_to_str_flags (vpath, 0, VPF_STRIP_PASSWORD);
fail_unless (strcmp ("test1://user@127.0.0.1/", str_path) == 0, "\nstr=%s\n", str_path);
g_free (str_path);
vfs_path_free (vpath);
vpath = vfs_path_from_str ("/test1://user:passwd@host.name/#enc:KOI8-R/тестовый/путь");
str_path = vfs_path_to_str_flags (vpath, 0, VPF_STRIP_PASSWORD);