From aae4b4d3585b9f944d7dbd3c9e5ba0006c55e457 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Tue, 8 Jun 2021 06:54:40 +0000 Subject: [PATCH] upstream: Allow argv_split() to optionally terminate tokenisation when it encounters an unquoted comment. Add some additional utility function for working with argument vectors, since we'll be switching to using them to parse ssh/sshd_config shortly. ok markus@ as part of a larger diff; tested in snaps OpenBSD-Commit-ID: fd9c108cef2f713f24e3bc5848861d221bb3a1ac --- auth2-pubkey.c | 7 ++++--- misc.c | 55 +++++++++++++++++++++++++++++++++++++++++++++----- misc.h | 9 +++++++-- sshconnect.c | 4 ++-- 4 files changed, 63 insertions(+), 12 deletions(-) diff --git a/auth2-pubkey.c b/auth2-pubkey.c index 721c1d9bd..d288d110b 100644 --- a/auth2-pubkey.c +++ b/auth2-pubkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-pubkey.c,v 1.107 2021/04/03 06:18:40 djm Exp $ */ +/* $OpenBSD: auth2-pubkey.c,v 1.108 2021/06/08 06:54:40 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -475,7 +475,8 @@ match_principals_command(struct ssh *ssh, struct passwd *user_pw, } /* Turn the command into an argument vector */ - if (argv_split(options.authorized_principals_command, &ac, &av) != 0) { + if (argv_split(options.authorized_principals_command, + &ac, &av, 0) != 0) { error("AuthorizedPrincipalsCommand \"%s\" contains " "invalid quotes", options.authorized_principals_command); goto out; @@ -926,7 +927,7 @@ user_key_command_allowed2(struct ssh *ssh, struct passwd *user_pw, } /* Turn the command into an argument vector */ - if (argv_split(options.authorized_keys_command, &ac, &av) != 0) { + if (argv_split(options.authorized_keys_command, &ac, &av, 0) != 0) { error("AuthorizedKeysCommand \"%s\" contains invalid quotes", options.authorized_keys_command); goto out; diff --git a/misc.c b/misc.c index 78fb1e000..3c9ea067f 100644 --- a/misc.c +++ b/misc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.c,v 1.165 2021/06/04 05:02:40 djm Exp $ */ +/* $OpenBSD: misc.c,v 1.166 2021/06/08 06:54:40 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2005-2020 Damien Miller. All rights reserved. @@ -85,6 +85,20 @@ chop(char *s) } +/* remove whitespace from end of string */ +void +rtrim(char *s) +{ + size_t i; + + if ((i = strlen(s)) == 0) + return; + for (i--; i > 0; i--) { + if (isspace((int)s[i])) + s[i] = '\0'; + } +} + /* set/unset filedescriptor to non-blocking */ int set_nonblock(int fd) @@ -1912,14 +1926,13 @@ daemonized(void) return 1; } - /* * Splits 's' into an argument vector. Handles quoted string and basic * escape characters (\\, \", \'). Caller must free the argument vector * and its members. */ int -argv_split(const char *s, int *argcp, char ***argvp) +argv_split(const char *s, int *argcp, char ***argvp, int terminate_on_comment) { int r = SSH_ERR_INTERNAL_ERROR; int argc = 0, quote, i, j; @@ -1932,7 +1945,8 @@ argv_split(const char *s, int *argcp, char ***argvp) /* Skip leading whitespace */ if (s[i] == ' ' || s[i] == '\t') continue; - + if (terminate_on_comment && s[i] == '#') + break; /* Start of a token */ quote = 0; @@ -1945,7 +1959,8 @@ argv_split(const char *s, int *argcp, char ***argvp) if (s[i] == '\\') { if (s[i + 1] == '\'' || s[i + 1] == '\"' || - s[i + 1] == '\\') { + s[i + 1] == '\\' || + (quote == 0 && s[i + 1] == ' ')) { i++; /* Skip '\' */ arg[j++] = s[i]; } else { @@ -2039,6 +2054,36 @@ argv_assemble(int argc, char **argv) return ret; } +char * +argv_next(int *argcp, char ***argvp) +{ + char *ret = (*argvp)[0]; + + if (*argcp > 0 && ret != NULL) { + (*argcp)--; + (*argvp)++; + } + return ret; +} + +void +argv_consume(int *argcp) +{ + *argcp = 0; +} + +void +argv_free(char **av, int ac) +{ + int i; + + if (av == NULL) + return; + for (i = 0; i < ac; i++) + free(av[i]); + free(av); +} + /* Returns 0 if pid exited cleanly, non-zero otherwise */ int exited_cleanly(pid_t pid, const char *tag, const char *cmd, int quiet) diff --git a/misc.h b/misc.h index 6c765e918..dd899a32a 100644 --- a/misc.h +++ b/misc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.h,v 1.96 2021/06/04 05:02:40 djm Exp $ */ +/* $OpenBSD: misc.h,v 1.97 2021/06/08 06:54:40 djm Exp $ */ /* * Author: Tatu Ylonen @@ -45,6 +45,7 @@ struct ForwardOptions { /* misc.c */ char *chop(char *); +void rtrim(char *); void skip_space(char **); char *strdelim(char **); char *strdelimw(char **); @@ -178,8 +179,12 @@ void child_set_env(char ***envp, u_int *envsizep, const char *name, const char *lookup_env_in_list(const char *env, char * const *envs, size_t nenvs); -int argv_split(const char *, int *, char ***); +int argv_split(const char *, int *, char ***, int); char *argv_assemble(int, char **argv); +char *argv_next(int *, char ***); +void argv_consume(int *); +void argv_free(char **, int); + int exited_cleanly(pid_t, const char *, const char *, int); struct stat; diff --git a/sshconnect.c b/sshconnect.c index 47f0b1c93..107e42097 100644 --- a/sshconnect.c +++ b/sshconnect.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect.c,v 1.352 2021/04/03 06:18:41 djm Exp $ */ +/* $OpenBSD: sshconnect.c,v 1.353 2021/06/08 06:54:40 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -865,7 +865,7 @@ load_hostkeys_command(struct hostkeys *hostkeys, const char *command_template, osigchld = ssh_signal(SIGCHLD, SIG_DFL); /* Turn the command into an argument vector */ - if (argv_split(command_template, &ac, &av) != 0) { + if (argv_split(command_template, &ac, &av, 0) != 0) { error("%s \"%s\" contains invalid quotes", tag, command_template); goto out;