mirror of
https://github.com/mirror/wget.git
synced 2025-04-24 12:10:16 +08:00
Add --use-askpass=COMMAND support
* doc/wget.texi: Add --use-askpass to documentation. * src/init.c: Add cmd_use_askpasss to set opt.use_askpass based on argument, WGET_ASKPASS, and SSH_ASKPASS environment variables. opt.wget-askpass is freed in cleanup () * src/main.c: Update options & add spawn process of opt.use_askpass command. * src/options.h: Addition of string use_askpass. * src/url.c: Function scheme_leading_string to access the leading string of a parsed url. * src/url.h: Prototype for scheme_leading_string for returning the leading string. * bootstrap.conf: Add posix_spawn to gnulib_modules This adds the --use-askpass option which is disabled by default. --use-askpass=COMMAND will request the username and password for a given URL by executing the external program COMMAND. If COMMAND is left blank, then the external program in the environment variable WGET_ASKPASS will be used. If WGET_ASKPASS is not set then the environment variable SSH_ASKPASS is used. If there is no value set, an error is returned. If an error occurs requesting the username or password, wget will exit. Signed-off-by: Liam R. Howlett <Liam.Howlett@WindRiver.com>
This commit is contained in:
parent
796e30dcea
commit
21e1725e12
@ -73,6 +73,7 @@ crypto/sha1
|
||||
crypto/sha256
|
||||
crypto/sha512
|
||||
open
|
||||
posix_spawn
|
||||
quote
|
||||
quotearg
|
||||
recv
|
||||
|
@ -1160,6 +1160,15 @@ options for @sc{http} connections.
|
||||
Prompt for a password for each connection established. Cannot be specified
|
||||
when @samp{--password} is being used, because they are mutually exclusive.
|
||||
|
||||
@item --use-askpass=@var{command}
|
||||
Prompt for a user and password using the specified command. If no command is
|
||||
specified then the command in the environment variable WGET_ASKPASS is used.
|
||||
If WGET_ASKPASS is not set then the command in the environment variable
|
||||
SSH_ASKPASS is used.
|
||||
|
||||
You can set the default command for use-askpass in the @file{.wgetrc}. That
|
||||
setting may be overridden from the command line.
|
||||
|
||||
@cindex iri support
|
||||
@cindex idn support
|
||||
@item --no-iri
|
||||
@ -1333,10 +1342,10 @@ the @code{digest}, or the Windows @code{NTLM} authentication scheme.
|
||||
Another way to specify username and password is in the @sc{url} itself
|
||||
(@pxref{URL Format}). Either method reveals your password to anyone who
|
||||
bothers to run @code{ps}. To prevent the passwords from being seen,
|
||||
store them in @file{.wgetrc} or @file{.netrc}, and make sure to protect
|
||||
those files from other users with @code{chmod}. If the passwords are
|
||||
really important, do not leave them lying in those files either---edit
|
||||
the files and delete them after Wget has started the download.
|
||||
use the @samp{--use-askpass} or store them in @file{.wgetrc} or @file{.netrc},
|
||||
and make sure to protect those files from other users with @code{chmod}. If
|
||||
the passwords are really important, do not leave them lying in those files
|
||||
either---edit the files and delete them after Wget has started the download.
|
||||
|
||||
@iftex
|
||||
@xref{Security Considerations}, for more information about security
|
||||
|
44
src/init.c
44
src/init.c
@ -97,6 +97,8 @@ CMD_DECLARE (cmd_directory);
|
||||
CMD_DECLARE (cmd_time);
|
||||
CMD_DECLARE (cmd_vector);
|
||||
|
||||
CMD_DECLARE (cmd_use_askpass);
|
||||
|
||||
CMD_DECLARE (cmd_spec_dirstruct);
|
||||
CMD_DECLARE (cmd_spec_header);
|
||||
CMD_DECLARE (cmd_spec_warc_header);
|
||||
@ -319,6 +321,7 @@ static const struct {
|
||||
{ "tries", &opt.ntry, cmd_number_inf },
|
||||
{ "trustservernames", &opt.trustservernames, cmd_boolean },
|
||||
{ "unlink", &opt.unlink, cmd_boolean },
|
||||
{ "useaskpass" , &opt.use_askpass, cmd_use_askpass },
|
||||
{ "useproxy", &opt.use_proxy, cmd_boolean },
|
||||
{ "user", &opt.user, cmd_string },
|
||||
{ "useragent", NULL, cmd_spec_useragent },
|
||||
@ -1381,6 +1384,46 @@ cmd_time (const char *com, const char *val, void *place)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
cmd_use_askpass (const char *com _GL_UNUSED, const char *val, void *place)
|
||||
{
|
||||
char *env_name = "WGET_ASKPASS";
|
||||
char *env;
|
||||
|
||||
if (val && *val)
|
||||
{
|
||||
if (!file_exists_p (val))
|
||||
{
|
||||
fprintf (stderr, _("%s does not exist.\n"), val);
|
||||
exit (WGET_EXIT_GENERIC_ERROR);
|
||||
}
|
||||
return cmd_string (com, val, place);
|
||||
}
|
||||
|
||||
env = getenv (env_name);
|
||||
if (!(env && *env))
|
||||
{
|
||||
env_name = "SSH_ASKPASS";
|
||||
env = getenv (env_name);
|
||||
}
|
||||
|
||||
if (!(env && *env))
|
||||
{
|
||||
fprintf (stderr, _("use-askpass requires a string or either environment variable WGET_ASKPASS or SSH_ASKPASS to be set.\n"));
|
||||
exit (WGET_EXIT_GENERIC_ERROR);
|
||||
}
|
||||
|
||||
if (!file_exists_p (env))
|
||||
{
|
||||
fprintf (stderr, _("%s points to %s, which does not exist.\n"),
|
||||
env_name, env);
|
||||
exit (WGET_EXIT_GENERIC_ERROR);
|
||||
}
|
||||
|
||||
return cmd_string (com, env, place);
|
||||
}
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
static bool
|
||||
cmd_cert_type (const char *com, const char *val, void *place)
|
||||
@ -1940,6 +1983,7 @@ cleanup (void)
|
||||
xfree (opt.body_data);
|
||||
xfree (opt.body_file);
|
||||
xfree (opt.rejected_log);
|
||||
xfree (opt.use_askpass);
|
||||
|
||||
#ifdef HAVE_LIBCARES
|
||||
#include <ares.h>
|
||||
|
112
src/main.c
112
src/main.c
@ -36,6 +36,7 @@ as that of the covered work. */
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <spawn.h>
|
||||
#ifdef ENABLE_NLS
|
||||
# include <locale.h>
|
||||
#endif
|
||||
@ -415,6 +416,7 @@ static struct cmdline_option option_data[] =
|
||||
{ "tries", 't', OPT_VALUE, "tries", -1 },
|
||||
{ "unlink", 0, OPT_BOOLEAN, "unlink", -1 },
|
||||
{ "trust-server-names", 0, OPT_BOOLEAN, "trustservernames", -1 },
|
||||
{ "use-askpass", 0, OPT_VALUE, "useaskpass", -1},
|
||||
{ "use-server-timestamps", 0, OPT_BOOLEAN, "useservertimestamps", -1 },
|
||||
{ "user", 0, OPT_VALUE, "user", -1 },
|
||||
{ "user-agent", 'U', OPT_VALUE, "useragent", -1 },
|
||||
@ -694,6 +696,11 @@ Download:\n"),
|
||||
--password=PASS set both ftp and http password to PASS\n"),
|
||||
N_("\
|
||||
--ask-password prompt for passwords\n"),
|
||||
N_("\
|
||||
--use-askpass=COMMAND specify credential handler for requesting \n\
|
||||
username and password. If no COMMAND is \n\
|
||||
specified the WGET_ASKPASS or the SSH_ASKPASS \n\
|
||||
environment variable is used.\n"),
|
||||
N_("\
|
||||
--no-iri turn off IRI support\n"),
|
||||
N_("\
|
||||
@ -1029,6 +1036,97 @@ prompt_for_password (void)
|
||||
return getpass("");
|
||||
}
|
||||
|
||||
|
||||
/* Execute external application opt.use_askpass */
|
||||
void
|
||||
run_use_askpass (char *question, char **answer)
|
||||
{
|
||||
char tmp[1024];
|
||||
pid_t pid;
|
||||
int status;
|
||||
int com[2];
|
||||
ssize_t bytes = 0;
|
||||
char * const argv[] = { opt.use_askpass, question, NULL };
|
||||
posix_spawn_file_actions_t fa;
|
||||
|
||||
if (pipe (com) == -1)
|
||||
{
|
||||
fprintf (stderr, _("Cannot create pipe"));
|
||||
exit (WGET_EXIT_GENERIC_ERROR);
|
||||
}
|
||||
|
||||
status = posix_spawn_file_actions_init (&fa);
|
||||
if (status)
|
||||
{
|
||||
fprintf (stderr,
|
||||
_("Error initializing spawn file actions for use-askpass: %d"),
|
||||
status);
|
||||
exit (WGET_EXIT_GENERIC_ERROR);
|
||||
}
|
||||
|
||||
status = posix_spawn_file_actions_adddup2 (&fa, com[1], STDOUT_FILENO);
|
||||
if (status)
|
||||
{
|
||||
fprintf (stderr,
|
||||
_("Error setting spawn file actions for use-askpass: %d"),
|
||||
status);
|
||||
exit (WGET_EXIT_GENERIC_ERROR);
|
||||
}
|
||||
|
||||
status = posix_spawnp (&pid, opt.use_askpass, &fa, NULL, argv, environ);
|
||||
if (status)
|
||||
{
|
||||
fprintf (stderr, "Error spawning %s: %d", opt.use_askpass, status);
|
||||
exit (WGET_EXIT_GENERIC_ERROR);
|
||||
}
|
||||
|
||||
/* Parent process reads from child. */
|
||||
close (com[1]);
|
||||
bytes = read (com[0], tmp, sizeof (tmp) - 1);
|
||||
if (bytes <= 0)
|
||||
{
|
||||
fprintf (stderr,
|
||||
_("Error reading response from command \"%s %s\": %s\n"),
|
||||
opt.use_askpass, question, strerror (errno));
|
||||
exit (WGET_EXIT_GENERIC_ERROR);
|
||||
}
|
||||
/* Set the end byte to \0, and decrement bytes */
|
||||
tmp[bytes--] = '\0';
|
||||
|
||||
/* Remove a possible new line */
|
||||
while (bytes >= 0 &&
|
||||
(tmp[bytes] == '\0' || tmp[bytes] == '\n' || tmp[bytes] == '\r'))
|
||||
tmp[bytes--] = '\0';
|
||||
|
||||
*answer = xmemdup (tmp, bytes + 2);
|
||||
}
|
||||
|
||||
/* set the user name and password*/
|
||||
void
|
||||
use_askpass (struct url *u)
|
||||
{
|
||||
static char question[1024];
|
||||
|
||||
if (u->user == NULL || u->user[0] == '\0')
|
||||
{
|
||||
snprintf (question, sizeof (question), _("Username for '%s%s': "),
|
||||
scheme_leading_string(u->scheme), u->host);
|
||||
/* Prompt for username */
|
||||
run_use_askpass (question, &u->user);
|
||||
if (opt.recursive)
|
||||
opt.user = xstrdup (u->user);
|
||||
}
|
||||
|
||||
if (u->passwd == NULL || u->passwd[0] == '\0')
|
||||
{
|
||||
snprintf(question, sizeof (question), _("Password for '%s%s@%s': "),
|
||||
scheme_leading_string (u->scheme), u->user, u->host);
|
||||
/* Prompt for password */
|
||||
run_use_askpass (question, &u->passwd);
|
||||
if (opt.recursive)
|
||||
opt.passwd = xstrdup (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
|
||||
@ -1712,6 +1810,16 @@ for details.\n\n"));
|
||||
exit (WGET_EXIT_GENERIC_ERROR);
|
||||
}
|
||||
|
||||
if (opt.use_askpass)
|
||||
{
|
||||
if (opt.use_askpass[0] == '\0')
|
||||
{
|
||||
fprintf (stderr,
|
||||
_("use-askpass requires a string or either environment variable WGET_ASKPASS or SSH_ASKPASS to be set.\n"));
|
||||
exit (WGET_EXIT_GENERIC_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_WATT32
|
||||
if (opt.wdebug)
|
||||
dbug_init();
|
||||
@ -1930,6 +2038,10 @@ only if outputting to a regular file.\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Request credentials if use_askpass is set. */
|
||||
if (opt.use_askpass)
|
||||
use_askpass (url_parsed);
|
||||
|
||||
if ((opt.recursive || opt.page_requisites)
|
||||
&& ((url_scheme (*t) != SCHEME_FTP
|
||||
#ifdef HAVE_SSL
|
||||
|
@ -132,6 +132,7 @@ struct options
|
||||
char *user; /* Generic username */
|
||||
char *passwd; /* Generic password */
|
||||
bool ask_passwd; /* Ask for password? */
|
||||
char *use_askpass; /* value to use for use-askpass if WGET_ASKPASS is not set */
|
||||
|
||||
bool always_rest; /* Always use REST. */
|
||||
wgint start_pos; /* Start position of a download. */
|
||||
|
@ -510,6 +510,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.
|
||||
|
@ -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 *);
|
||||
|
Loading…
Reference in New Issue
Block a user