Allow argv_split() to optionally terminate tokenisation when it
authordjm <djm@openbsd.org>
Tue, 8 Jun 2021 06:54:40 +0000 (06:54 +0000)
committerdjm <djm@openbsd.org>
Tue, 8 Jun 2021 06:54:40 +0000 (06:54 +0000)
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

usr.bin/ssh/auth2-pubkey.c
usr.bin/ssh/misc.c
usr.bin/ssh/misc.h
usr.bin/ssh/sshconnect.c

index b77d353..7c6fe33 100644 (file)
@@ -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.
  *
@@ -472,7 +472,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;
@@ -923,7 +924,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;
index 94a1ea8..ea45b00 100644 (file)
@@ -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.
@@ -71,6 +71,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)
@@ -1823,14 +1837,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;
@@ -1843,7 +1856,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;
 
@@ -1856,7 +1870,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 {
@@ -1950,6 +1965,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)
index eba125c..7c65d23 100644 (file)
@@ -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 <ylo@cs.hut.fi>
@@ -45,6 +45,7 @@ struct ForwardOptions {
 /* misc.c */
 
 char   *chop(char *);
+void    rtrim(char *);
 void   skip_space(char **);
 char   *strdelim(char **);
 char   *strdelimw(char **);
@@ -176,8 +177,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;
index 72fdad1..983c0f0 100644 (file)
@@ -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 <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -827,7 +827,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;