[PATCH 00/16] Improvements, mainly to user name handling and scp.
Michael Witten
mfwitten at gmail.com
Tue Dec 8 06:42:59 AWST 2015
User names have hitherto been handled neither consistently nor well; this
series alleviates at least some of the issues.
Fear not the long patch series!
Most commits involve a fairly small number of changes; while I could have
consolidated these changes into fewer commits, I think the series as a whole
provides a better narration for what's going.
Besides a few small improvements along the way, the main thrust is:
* Removing user-name handling from `scp' (in favor of using the
handling that is already present in `dropbear'/`dbclient').
* Lazily looking up the current user's name.
* Removing unused code.
Overall, 7 files were changed, with 37 insertions(+) and 158 deletions(-):
cli-main.c | 2 +-
cli-runopts.c | 32 ++++++--------
common-session.c | 1 +
runopts.h | 2 +-
scp.c | 125 ++++++++++---------------------------------------------
scpmisc.c | 31 +-------------
scpmisc.h | 2 -
This is the series:
[01] scp: Insert comma into stderr message
[02] scp: Have `fatal()' append a newline to the message
[03] scp: only pass `-v' when DEBUG_TRACE is set
[04] scp: `-l%s' -> `-l %s'
[05] scp: const/static correctness improvements
[06] scp: Introduce `get_user_name()'
[07] scp: Use "unknown" when the user name cannot be retrieved
[08] scp: style: simplify code by using a tertiary operator
[09] scp: Use `get_user_name()' more often
[10] scp: Simplify code now that the user name is never `NULL'
[11] scp: Remove parsing of `[user@]host'
[12] scp: Remove unused functions
[13] scp: Remove `replacearg()'
[14] runopts: Mark `*cli_runopts.own_user' as `const'
[15] runopts: There's no reason to make a duplicate of "unknown"
[16] runopts: Re-introduce the `get_user_name()' function from `scp' development
Lastly, for convenience in reviewing the changes, here is the overall patch:
--- a/cli-main.c
+++ b/cli-main.c
@@ -135,7 +135,7 @@
static void cli_proxy_cmd(int *sock_in, int *sock_out) {
int ret;
- fill_passwd(cli_opts.own_user);
+ fill_passwd(get_user_name());
ret = spawn_command(exec_proxy_cmd, cli_opts.proxycmd,
sock_out, sock_in, NULL, NULL);
--- a/cli-runopts.c
+++ b/cli-runopts.c
@@ -36,7 +36,6 @@
static void printhelp();
static void parse_hostname(const char* orighostarg);
static void parse_multihop_hostname(const char* orighostarg, const char* argv0);
-static void fill_own_user();
#ifdef ENABLE_CLI_PUBKEY_AUTH
static void loadidentityfile(const char* filename, int warnfail);
#endif
@@ -102,6 +101,17 @@
}
+const char *get_user_name() {
+ static const char *user_name = NULL;
+
+ if (user_name == NULL) {
+ struct passwd *pwd = getpwuid(getuid());
+ user_name = pwd ? m_strdup(pwd->pw_name) : "unknown";
+ }
+
+ return user_name;
+}
+
void cli_getopts(int argc, char ** argv) {
unsigned int i, j;
char ** next = 0;
@@ -175,8 +185,6 @@
opts.keepalive_secs = DEFAULT_KEEPALIVE;
opts.idle_timeout_secs = DEFAULT_IDLE_TIMEOUT;
- fill_own_user();
-
for (i = 1; i < (unsigned int)argc; i++) {
/* Handle non-flag arguments such as hostname or commands for the remote host */
if (argv[i][0] != '-')
@@ -640,7 +648,7 @@
}
if (cli_opts.username == NULL) {
- cli_opts.username = m_strdup(cli_opts.own_user);
+ cli_opts.username = m_strdup(get_user_name());
}
port = strchr(cli_opts.remotehost, '^');
@@ -695,22 +703,6 @@
}
#endif
-static void fill_own_user() {
- uid_t uid;
- struct passwd *pw = NULL;
-
- uid = getuid();
-
- pw = getpwuid(uid);
- if (pw && pw->pw_name != NULL) {
- cli_opts.own_user = m_strdup(pw->pw_name);
- } else {
- dropbear_log(LOG_INFO, "Warning: failed to identify current user. Trying anyway.");
- cli_opts.own_user = m_strdup("unknown");
- }
-
-}
-
#ifdef ENABLE_CLI_ANYTCPFWD
/* Turn a "[listenaddr:]listenport:remoteaddr:remoteport" string into into a forwarding
* set, and add it to the forwarding list */
--- a/common-session.c
+++ b/common-session.c
@@ -581,6 +581,7 @@
return ses.authstate.pw_shell;
}
}
+
void fill_passwd(const char* username) {
struct passwd *pw = NULL;
if (ses.authstate.pw_name)
--- a/runopts.h
+++ b/runopts.h
@@ -127,7 +127,6 @@
char *remotehost;
char *remoteport;
- char *own_user;
char *username;
char *cmd;
@@ -165,6 +164,7 @@
extern cli_runopts cli_opts;
void cli_getopts(int argc, char ** argv);
+const char *get_user_name();
#ifdef ENABLE_USER_ALGO_LIST
void parse_ciphers_macs();
--- a/scp.c
+++ b/scp.c
@@ -172,25 +172,21 @@
*/
static void
-arg_setup(char *host, char *remuser, char *cmd)
+arg_setup(const char *user_at_host, const char *cmd)
{
- replacearg(&args, 0, "%s", ssh_program);
- if (remuser != NULL)
- addargs(&args, "-l%s", remuser);
- addargs(&args, "%s", host);
+ addargs(&args, "%s", user_at_host);
addargs(&args, "%s", cmd);
}
int
-do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc)
+do_cmd(const char *user_at_host, const char *cmd, int *fdin, int *fdout, int argc)
{
int pin[2], pout[2], reserved[2];
if (verbose_mode)
fprintf(stderr,
- "Executing: program %s host %s, user %s, command %s\n",
- ssh_program, host,
- remuser ? remuser : "(unspecified)", cmd);
+ "Executing: program %s, login %s, command %s\n",
+ ssh_program, user_at_host, cmd);
/*
* Reserve two descriptors so that the real pipes won't get
@@ -211,7 +207,7 @@
/* uClinux needs to build the args here before vforking,
otherwise we do it later on. */
#ifdef USE_VFORK
- arg_setup(host, remuser, cmd);
+ arg_setup(user_at_host, cmd);
#endif
/* Fork a child to execute the command on the remote host using ssh. */
@@ -231,7 +227,7 @@
close(pout[1]);
#ifndef USE_VFORK
- arg_setup(host, remuser, cmd);
+ arg_setup(user_at_host, cmd);
#endif
execvp(ssh_program, args.list);
@@ -251,16 +247,10 @@
xfree(args.list[args.num-1]);
args.list[args.num-1]=NULL;
args.num--;
- /* pop host */
+ /* pop user_at_host */
xfree(args.list[args.num-1]);
args.list[args.num-1]=NULL;
args.num--;
- /* pop user */
- if (remuser != NULL) {
- xfree(args.list[args.num-1]);
- args.list[args.num-1]=NULL;
- args.num--;
- }
#endif
/* Parent. Close the other side, and return the local side. */
@@ -282,12 +272,9 @@
BUF *allocbuf(BUF *, int, int);
void lostconn(int);
void nospace(void);
-int okname(char *);
void run_err(const char *,...);
void verifydir(char *);
-struct passwd *pwd;
-uid_t userid;
int errs, remin, remout;
int pflag, iamremote, iamrecursive, targetshouldbedirectory;
@@ -362,7 +349,9 @@
ssh_program = xstrdup(optarg);
break;
case 'v':
+#ifdef DEBUG_TRACE
addargs(&args, "-v");
+#endif
verbose_mode = 1;
break;
case 'q':
@@ -393,9 +382,6 @@
argc -= optind;
argv += optind;
- if ((pwd = getpwuid(userid = getuid())) == NULL)
- fatal("unknown user %u", (u_int) userid);
-
if (!isatty(STDERR_FILENO))
showprogress = 0;
@@ -459,7 +445,8 @@
toremote(char *targ, int argc, char **argv)
{
int i, len;
- char *bp, *host, *src, *suser, *thost, *tuser, *arg;
+ const char *targ_user_at_host;
+ char *bp, *src;
arglist alist;
memset(&alist, '\0', sizeof(alist));
@@ -469,30 +456,17 @@
if (*targ == 0)
targ = ".";
- arg = xstrdup(argv[argc - 1]);
- if ((thost = strrchr(arg, '@'))) {
- /* user at host */
- *thost++ = 0;
- tuser = arg;
- if (*tuser == '\0')
- tuser = NULL;
- } else {
- thost = arg;
- tuser = NULL;
- }
-
- if (tuser != NULL && !okname(tuser)) {
- xfree(arg);
- return;
- }
+ targ_user_at_host = argv[argc - 1];
for (i = 0; i < argc - 1; i++) {
src = colon(argv[i]);
if (src) { /* remote to remote */
freeargs(&alist);
addargs(&alist, "%s", ssh_program);
+#ifdef DEBUG_TRACE
if (verbose_mode)
addargs(&alist, "-v");
+#endif
#if 0
/* Disabled since dbclient won't understand them
and scp works fine without them. */
@@ -504,27 +478,11 @@
*src++ = 0;
if (*src == 0)
src = ".";
- host = strrchr(argv[i], '@');
-
- if (host) {
- *host++ = 0;
- host = cleanhostname(host);
- suser = argv[i];
- if (*suser == '\0')
- suser = pwd->pw_name;
- else if (!okname(suser))
- continue;
- addargs(&alist, "-l");
- addargs(&alist, "%s", suser);
- } else {
- host = cleanhostname(argv[i]);
- }
- addargs(&alist, "%s", host);
+
+ addargs(&alist, "%s", argv[i]); /* [user@]host */
addargs(&alist, "%s", cmd);
addargs(&alist, "%s", src);
- addargs(&alist, "%s%s%s:%s",
- tuser ? tuser : "", tuser ? "@" : "",
- thost, targ);
+ addargs(&alist, "%s:%s", targ_user_at_host, targ);
if (do_local_cmd(&alist) != 0)
errs = 1;
} else { /* local to remote */
@@ -532,8 +490,7 @@
len = strlen(targ) + CMDNEEDS + 20;
bp = xmalloc(len);
(void) snprintf(bp, len, "%s -t %s", cmd, targ);
- host = cleanhostname(thost);
- if (do_cmd(host, tuser, bp, &remin,
+ if (do_cmd(targ_user_at_host, bp, &remin,
&remout, argc) < 0)
exit(1);
if (response() < 0)
@@ -549,7 +506,7 @@
tolocal(int argc, char **argv)
{
int i, len;
- char *bp, *host, *src, *suser;
+ char *bp, *src;
arglist alist;
memset(&alist, '\0', sizeof(alist));
@@ -572,20 +529,10 @@
*src++ = 0;
if (*src == 0)
src = ".";
- if ((host = strrchr(argv[i], '@')) == NULL) {
- host = argv[i];
- suser = NULL;
- } else {
- *host++ = 0;
- suser = argv[i];
- if (*suser == '\0')
- suser = pwd->pw_name;
- }
- host = cleanhostname(host);
len = strlen(src) + CMDNEEDS + 20;
bp = xmalloc(len);
(void) snprintf(bp, len, "%s -f %s", cmd, src);
- if (do_cmd(host, suser, bp, &remin, &remout, argc) < 0) {
+ if (do_cmd(argv[i], bp, &remin, &remout, argc) < 0) {
(void) xfree(bp);
++errs;
continue;
@@ -1190,36 +1137,6 @@
killchild(0);
}
-int
-okname(char *cp0)
-{
- int c;
- char *cp;
-
- cp = cp0;
- do {
- c = (int)*cp;
- if (c & 0200)
- goto bad;
- if (!isalpha(c) && !isdigit(c)) {
- switch (c) {
- case '\'':
- case '"':
- case '`':
- case ' ':
- case '#':
- goto bad;
- default:
- break;
- }
- }
- } while (*++cp);
- return (1);
-
-bad: fprintf(stderr, "%s: invalid user name\n", cp0);
- return (0);
-}
-
BUF *
allocbuf(BUF *bp, int fd, int blksize)
{
--- a/scpmisc.c
+++ b/scpmisc.c
@@ -104,16 +104,6 @@
}
char *
-cleanhostname(char *host)
-{
- if (*host == '[' && host[strlen(host) - 1] == ']') {
- host[strlen(host) - 1] = '\0';
- return (host + 1);
- } else
- return host;
-}
-
-char *
colon(char *cp)
{
int flag = 0;
@@ -165,26 +155,6 @@
}
void
-replacearg(arglist *args, u_int which, char *fmt, ...)
-{
- va_list ap;
- char *cp;
- int r;
-
- va_start(ap, fmt);
- r = vasprintf(&cp, fmt, ap);
- va_end(ap);
- if (r == -1)
- fatal("replacearg: argument too long");
-
- if (which >= args->num)
- fatal("replacearg: tried to replace invalid arg %d >= %d",
- which, args->num);
- xfree(args->list[which]);
- args->list[which] = cp;
-}
-
-void
freeargs(arglist *args)
{
u_int i;
@@ -223,6 +193,7 @@
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
+ fputc('\n', stderr);
exit(255);
}
--- a/scpmisc.h
+++ b/scpmisc.h
@@ -21,7 +21,6 @@
void unset_nonblock(int);
void set_nodelay(int);
int a2port(const char *);
-char *cleanhostname(char *);
char *colon(char *);
long convtime(const char *);
@@ -34,7 +33,6 @@
int nalloc;
};
void addargs(arglist *, char *, ...);
-void replacearg(arglist *, u_int, char *, ...);
void freeargs(arglist *);
/* from xmalloc.h */
More information about the Dropbear
mailing list