[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Bug-wget] [PATCH] wget: Add --ssh-askpass support
From: |
Tim Rühsen |
Subject: |
Re: [Bug-wget] [PATCH] wget: Add --ssh-askpass support |
Date: |
Sun, 24 Jul 2016 11:19:17 +0200 |
User-agent: |
KMail/5.2.3 (Linux/4.6.0-1-amd64; KDE/5.23.0; x86_64; ; ) |
Thanks for your contribution, Liam.
I think it is a good feature.
A few questions, some have already been mentioned by Eli and Jeremie.
* what about posix_spawn instead of fork ? It is covered by gnulib...
* the 'strace' is left over from your tests !?
* could you attach your patch as a file, best generated with 'git format-patch
-1' ?
* Did you already signed the FSF copyright assignment ? The patch is
considered 'non-trivial'.
Regards, Tim
On Freitag, 22. Juli 2016 20:24:05 CEST Liam R. Howlett wrote:
> This adds the --ssh-askpass option which is disabled by default.
>
> --ssh-askpass will request the username and password for a given URL by
> executing the external program pointed to by the environment variable
> SSH_ASKPASS. If the environment variable is not set, an error is
> returned. If an error occurs requesting the username or password, wget
> will exit.
>
> Signed-off-by: Liam R. Howlett <address@hidden>
> ---
> src/init.c | 3 ++
> src/main.c | 92
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/options.h |
> 2 ++
> src/url.c | 6 ++++
> src/url.h | 1 +
> 5 files changed, 104 insertions(+)
>
> diff --git a/src/init.c b/src/init.c
> index d043d83..886d701 100644
> --- a/src/init.c
> +++ b/src/init.c
> @@ -322,6 +322,7 @@ static const struct {
> { "user", &opt.user, cmd_string },
> { "useragent", NULL, cmd_spec_useragent },
> { "useservertimestamps", &opt.useservertimestamps, cmd_boolean },
> + { "usesshaskpass", &opt.use_ssh_askpass, cmd_boolean},
> { "verbose", NULL, cmd_spec_verbose },
> { "wait", &opt.wait, cmd_time },
> { "waitretry", &opt.waitretry, cmd_time },
> @@ -392,6 +393,8 @@ defaults (void)
> tmp = getenv ("no_proxy");
> if (tmp)
> opt.no_proxy = sepstring (tmp);
> + opt.use_ssh_askpass = false;
> + opt.ssh_askpass = getenv ("SSH_ASKPASS");
> opt.prefer_family = prefer_none;
> opt.allow_cache = true;
> opt.if_modified_since = true;
> diff --git a/src/main.c b/src/main.c
> index e7d5c66..cf82d3c 100644
> --- a/src/main.c
> +++ b/src/main.c
> @@ -415,6 +415,7 @@ static struct cmdline_option option_data[] =
> { "unlink", 0, OPT_BOOLEAN, "unlink", -1 },
> { "trust-server-names", 0, OPT_BOOLEAN, "trustservernames", -1 },
> { "use-server-timestamps", 0, OPT_BOOLEAN, "useservertimestamps", -1 },
> + { "ssh-askpass", 0, OPT_BOOLEAN, "usesshaskpass", -1 },
> { "user", 0, OPT_VALUE, "user", -1 },
> { "user-agent", 'U', OPT_VALUE, "useragent", -1 },
> { "verbose", 'v', OPT_BOOLEAN, "verbose", -1 },
> @@ -691,6 +692,8 @@ Download:\n"),
> N_("\
> --ask-password prompt for passwords\n"),
> N_("\
> + --ssh-askpass Use SSH_ASKPASS for credential
> requests\n"), + N_("\
> --no-iri turn off IRI support\n"),
> N_("\
> --local-encoding=ENC use ENC as the local encoding for
> IRIs\n"), @@ -1019,6 +1022,81 @@ prompt_for_password (void)
> return getpass("");
> }
>
> +
> +/* Execute external application SSH_ASKPASS which is stored in
> opt.ssh_askpass + */
> +void
> +run_ssh_askpass(const char *question, char **answer)
> +{
> + char tmp[1024];
> + pid_t pid;
> + int com[2];
> +
> + if (pipe(com) == -1)
> + {
> + fprintf(stderr, _("Cannot create pipe"));
> + exit (WGET_EXIT_GENERIC_ERROR);
> + }
> +
> + pid = fork();
> + if (pid == -1)
> + {
> + fprintf(stderr, "Error forking SSH_ASKPASS");
> + exit (WGET_EXIT_GENERIC_ERROR);
> + }
> + else if (pid == 0)
> + {
> + /* Child */
> + dup2(com[1], STDOUT_FILENO);
> + close(com[0]);
> + close(com[1]);
> + fprintf(stdout, "test");
> + execlp("/usr/bin/strace", "-s256", "-otest.out", opt.ssh_askpass,
> question, (char*)NULL); + assert("Execlp failed!");
> + }
> + else
> + {
> + close(com[1]);
> + unsigned int bytes = read(com[0], tmp, sizeof(tmp));
> + if (!bytes)
> + {
> + fprintf(stderr,
> + _("Error reading response from SSH_ASKPASS %s %s\n"),
> + opt.ssh_askpass, question);
> + exit (WGET_EXIT_GENERIC_ERROR);
> + }
> + else if (bytes > 1)
> + *answer = strndup(tmp, bytes-1);
> + }
> +}
> +
> +/* set the user name and password*/
> +void
> +ssh_askpass (struct url *u)
> +{
> + static char question[1024];
> +
> + if (u->user == NULL || u->user[0] == '\0')
> + {
> + sprintf(question, "Username for '%s%s': ",
> + scheme_leading_string(u->scheme), u->host);
> + /* Prompt for username */
> + run_ssh_askpass(question, &u->user);
> + if (opt.recursive)
> + opt.user = strdup(u->user);
> + }
> +
> + if (u->passwd == NULL || u->passwd[0] == '\0')
> + {
> + sprintf(question, "Password for 'address@hidden': ",
> + scheme_leading_string(u->scheme), u->user,
> + u->host);
> + /* Prompt for password */
> + run_ssh_askpass(question, &u->passwd);
> + if (opt.recursive)
> + opt.passwd = strdup(u->passwd);
> + }
> +}
> /* Function that prints the line argument while limiting it
> to at most line_length. prefix is printed on the first line
> and an appropriate number of spaces are added on subsequent
> @@ -1702,6 +1780,16 @@ for details.\n\n"));
> exit (WGET_EXIT_GENERIC_ERROR);
> }
>
> + if (opt.use_ssh_askpass)
> + {
> + /* can't request credentials until the URL is known. */
> + if (opt.ssh_askpass == NULL || opt.ssh_askpass[0] == '\0')
> + {
> + fprintf(stderr, _("--ssh-askpass requires environment variable
> SSH_ASKPASS to be set.\n")); + exit(WGET_EXIT_GENERIC_ERROR);
> + }
> + }
> +
> #ifdef USE_WATT32
> if (opt.wdebug)
> dbug_init();
> @@ -1920,6 +2008,10 @@ only if outputting to a regular file.\n"));
> }
> else
> {
> + if (opt.use_ssh_askpass)
> + {
> + ssh_askpass(url_parsed);
> + }
> if ((opt.recursive || opt.page_requisites)
> && ((url_scheme (*t) != SCHEME_FTP
> #ifdef HAVE_SSL
> diff --git a/src/options.h b/src/options.h
> index a8c494b..977c150 100644
> --- a/src/options.h
> +++ b/src/options.h
> @@ -130,6 +130,8 @@ struct options
> char *user; /* Generic username */
> char *passwd; /* Generic password */
> bool ask_passwd; /* Ask for password? */
> + bool use_ssh_askpass; /* Use SSH_ASKPASS infrastructure */
> + char *ssh_askpass; /* value of SSH_ASKPASS */
>
> bool always_rest; /* Always use REST. */
> wgint start_pos; /* Start position of a download. */
> diff --git a/src/url.c b/src/url.c
> index ec38d6f..c133d91 100644
> --- a/src/url.c
> +++ b/src/url.c
> @@ -512,6 +512,12 @@ scheme_disable (enum url_scheme scheme)
> supported_schemes[scheme].flags |= scm_disabled;
> }
>
> +const char *
> +scheme_leading_string (enum url_scheme scheme)
> +{
> + return supported_schemes[scheme].leading_string;
> +}
> +
> /* Skip the username and password, if present in the URL. The
> function should *not* be called with the complete URL, but with the
> portion after the scheme.
> diff --git a/src/url.h b/src/url.h
> index 7c77737..bf2e3f7 100644
> --- a/src/url.h
> +++ b/src/url.h
> @@ -124,6 +124,7 @@ bool url_has_scheme (const char *);
> bool url_valid_scheme (const char *);
> int scheme_default_port (enum url_scheme);
> void scheme_disable (enum url_scheme);
> +const char *scheme_leading_string(enum url_scheme);
>
> char *url_string (const struct url *, enum url_auth_mode);
> char *url_file_name (const struct url *, char *);
signature.asc
Description: This is a digitally signed message part.