]> git.ipfire.org Git - thirdparty/openssh-portable.git/commitdiff
upstream: fix regression introduced when I switched the "Match"
authordjm@openbsd.org <djm@openbsd.org>
Wed, 25 Sep 2024 01:24:04 +0000 (01:24 +0000)
committerDamien Miller <djm@mindrot.org>
Wed, 25 Sep 2024 01:33:51 +0000 (11:33 +1000)
criteria tokeniser to a more shell-like one. Apparently the old tokeniser
(accidentally?) allowed "Match criteria=argument" as well as the "Match
criteria argument" syntax that we tested for.

People were using this syntax so this adds back support for
"Match criteria=argument"

bz3739 ok dtucker

OpenBSD-Commit-ID: d1eebedb8c902002b75b75debfe1eeea1801f58a

misc.c
misc.h
readconf.c
servconf.c

diff --git a/misc.c b/misc.c
index afdf5142ec0d62a645ddb1ce2b18be91ab288aed..1b4b55c5034dd949f752858477f564738f8672e5 100644 (file)
--- a/misc.c
+++ b/misc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: misc.c,v 1.196 2024/06/06 17:15:25 djm Exp $ */
+/* $OpenBSD: misc.c,v 1.197 2024/09/25 01:24:04 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  * Copyright (c) 2005-2020 Damien Miller.  All rights reserved.
@@ -107,6 +107,27 @@ rtrim(char *s)
        }
 }
 
+/*
+ * returns pointer to character after 'prefix' in 's' or otherwise NULL
+ * if the prefix is not present.
+ */
+const char *
+strprefix(const char *s, const char *prefix, int ignorecase)
+{
+       size_t prefixlen;
+
+       if ((prefixlen = strlen(prefix)) == 0)
+               return s;
+       if (ignorecase) {
+               if (strncasecmp(s, prefix, prefixlen) != 0)
+                       return NULL;
+       } else {
+               if (strncmp(s, prefix, prefixlen) != 0)
+                       return NULL;
+       }
+       return s + prefixlen;
+}
+
 /* set/unset filedescriptor to non-blocking */
 int
 set_nonblock(int fd)
diff --git a/misc.h b/misc.h
index 113403896d8a510f36c5d1be4ba01f9ad0ae8148..efecdf1ad6f93cc89b7ace84ac7a7069c7a54493 100644 (file)
--- a/misc.h
+++ b/misc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: misc.h,v 1.109 2024/06/06 17:15:25 djm Exp $ */
+/* $OpenBSD: misc.h,v 1.110 2024/09/25 01:24:04 djm Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -56,6 +56,7 @@ struct ForwardOptions {
 char   *chop(char *);
 void    rtrim(char *);
 void   skip_space(char **);
+const char *strprefix(const char *, const char *, int);
 char   *strdelim(char **);
 char   *strdelimw(char **);
 int     set_nonblock(int);
index 3d9cc6dbbe4a6ceb8b74e7ed74900f7aadc11dd8..de42fb6ff14fef8b5ece08d7a15c6a39d943c163 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.c,v 1.390 2024/09/15 00:57:36 djm Exp $ */
+/* $OpenBSD: readconf.c,v 1.391 2024/09/25 01:24:04 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -710,7 +710,7 @@ match_cfg_line(Options *options, const char *full_line, int *acp, char ***avp,
     struct passwd *pw, const char *host_arg, const char *original_host,
     int final_pass, int *want_final_pass, const char *filename, int linenum)
 {
-       char *arg, *oattrib, *attrib, *cmd, *host, *criteria;
+       char *arg, *oattrib, *attrib = NULL, *cmd, *host, *criteria;
        const char *ruser;
        int r, this_result, result = 1, attributes = 0, negate;
 
@@ -731,7 +731,8 @@ match_cfg_line(Options *options, const char *full_line, int *acp, char ***avp,
 
        debug2("checking match for '%s' host %s originally %s",
            full_line, host, original_host);
-       while ((oattrib = attrib = argv_next(acp, avp)) != NULL) {
+       while ((oattrib = argv_next(acp, avp)) != NULL) {
+               attrib = xstrdup(oattrib);
                /* Terminate on comment */
                if (*attrib == '#') {
                        argv_consume(acp);
@@ -777,9 +778,23 @@ match_cfg_line(Options *options, const char *full_line, int *acp, char ***avp,
                            this_result ? "" : "not ", oattrib);
                        continue;
                }
+
+               /* Keep this list in sync with below */
+               if (strprefix(attrib, "host=", 1)  != NULL ||
+                   strprefix(attrib, "originalhost=", 1) != NULL ||
+                   strprefix(attrib, "user=", 1) != NULL ||
+                   strprefix(attrib, "localuser=", 1) != NULL ||
+                   strprefix(attrib, "localnetwork=", 1) != NULL ||
+                   strprefix(attrib, "tagged=", 1) != NULL ||
+                   strprefix(attrib, "exec=", 1) != NULL) {
+                       arg = strchr(attrib, '=');
+                       *(arg++) = '\0';
+               } else {
+                       arg = argv_next(acp, avp);
+               }
+
                /* All other criteria require an argument */
-               if ((arg = argv_next(acp, avp)) == NULL ||
-                   *arg == '\0' || *arg == '#') {
+               if (arg == NULL || *arg == '\0' || *arg == '#') {
                        error("Missing Match criteria for %s", attrib);
                        result = -1;
                        goto out;
@@ -856,6 +871,8 @@ match_cfg_line(Options *options, const char *full_line, int *acp, char ***avp,
                    criteria == NULL ? "" : criteria,
                    criteria == NULL ? "" : "\"");
                free(criteria);
+               free(attrib);
+               attrib = NULL;
        }
        if (attributes == 0) {
                error("One or more attributes required for Match");
@@ -865,6 +882,7 @@ match_cfg_line(Options *options, const char *full_line, int *acp, char ***avp,
  out:
        if (result != -1)
                debug2("match %sfound", result ? "" : "not ");
+       free(attrib);
        free(host);
        return result;
 }
index 89b8413e87d797acc25c7aa71bf29cd0858b9f43..dd774f46817c911a4bf6fe0b6cfb358f2167e9f6 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: servconf.c,v 1.418 2024/09/15 03:09:44 djm Exp $ */
+/* $OpenBSD: servconf.c,v 1.419 2024/09/25 01:24:04 djm Exp $ */
 /*
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
  *                    All rights reserved
@@ -1033,7 +1033,7 @@ match_cfg_line(const char *full_line, int *acp, char ***avp,
     int line, struct connection_info *ci)
 {
        int result = 1, attributes = 0, port;
-       char *arg, *attrib;
+       char *arg, *attrib = NULL, *oattrib;
 
        if (ci == NULL)
                debug3("checking syntax for 'Match %s'", full_line);
@@ -1047,7 +1047,8 @@ match_cfg_line(const char *full_line, int *acp, char ***avp,
                    ci->laddress ? ci->laddress : "(null)", ci->lport);
        }
 
-       while ((attrib = argv_next(acp, avp)) != NULL) {
+       while ((oattrib = argv_next(acp, avp)) != NULL) {
+               attrib = xstrdup(oattrib);
                /* Terminate on comment */
                if (*attrib == '#') {
                        argv_consume(acp); /* mark all arguments consumed */
@@ -1062,11 +1063,13 @@ match_cfg_line(const char *full_line, int *acp, char ***avp,
                            *arg != '\0' && *arg != '#')) {
                                error("'all' cannot be combined with other "
                                    "Match attributes");
-                               return -1;
+                               result = -1;
+                               goto out;
                        }
                        if (arg != NULL && *arg == '#')
                                argv_consume(acp); /* consume remaining args */
-                       return 1;
+                       result = 1;
+                       goto out;
                }
                /* Criterion "invalid-user" also has no argument */
                if (strcasecmp(attrib, "invalid-user") == 0) {
@@ -1078,11 +1081,26 @@ match_cfg_line(const char *full_line, int *acp, char ***avp,
                                debug("matched invalid-user at line %d", line);
                        continue;
                }
+
+               /* Keep this list in sync with below */
+               if (strprefix(attrib, "user=", 1) != NULL ||
+                   strprefix(attrib, "group=", 1) != NULL ||
+                   strprefix(attrib, "host=", 1) != NULL ||
+                   strprefix(attrib, "address=", 1) != NULL ||
+                   strprefix(attrib, "localaddress=", 1) != NULL ||
+                   strprefix(attrib, "localport=", 1) != NULL ||
+                   strprefix(attrib, "rdomain=", 1) != NULL) {
+                       arg = strchr(attrib, '=');
+                       *(arg++) = '\0';
+               } else {
+                       arg = argv_next(acp, avp);
+               }
+
                /* All other criteria require an argument */
-               if ((arg = argv_next(acp, avp)) == NULL ||
-                   *arg == '\0' || *arg == '#') {
+               if (arg == NULL || *arg == '\0' || *arg == '#') {
                        error("Missing Match criteria for %s", attrib);
-                       return -1;
+                       result = -1;
+                       goto out;
                }
                if (strcasecmp(attrib, "user") == 0) {
                        if (ci == NULL || (ci->test && ci->user == NULL)) {
@@ -1105,7 +1123,8 @@ match_cfg_line(const char *full_line, int *acp, char ***avp,
                                match_test_missing_fatal("Group", "user");
                        switch (match_cfg_line_group(arg, line, ci->user)) {
                        case -1:
-                               return -1;
+                               result = -1;
+                               goto out;
                        case 0:
                                result = 0;
                        }
@@ -1141,7 +1160,8 @@ match_cfg_line(const char *full_line, int *acp, char ***avp,
                                result = 0;
                                break;
                        case -2:
-                               return -1;
+                               result = -1;
+                               goto out;
                        }
                } else if (strcasecmp(attrib, "localaddress") == 0){
                        if (ci == NULL || (ci->test && ci->laddress == NULL)) {
@@ -1166,13 +1186,15 @@ match_cfg_line(const char *full_line, int *acp, char ***avp,
                                result = 0;
                                break;
                        case -2:
-                               return -1;
+                               result = -1;
+                               goto out;
                        }
                } else if (strcasecmp(attrib, "localport") == 0) {
                        if ((port = a2port(arg)) == -1) {
                                error("Invalid LocalPort '%s' on Match line",
                                    arg);
-                               return -1;
+                               result = -1;
+                               goto out;
                        }
                        if (ci == NULL || (ci->test && ci->lport == -1)) {
                                result = 0;
@@ -1200,16 +1222,21 @@ match_cfg_line(const char *full_line, int *acp, char ***avp,
                                debug("user %.100s matched 'RDomain %.100s' at "
                                    "line %d", ci->rdomain, arg, line);
                } else {
-                       error("Unsupported Match attribute %s", attrib);
-                       return -1;
+                       error("Unsupported Match attribute %s", oattrib);
+                       result = -1;
+                       goto out;
                }
+               free(attrib);
+               attrib = NULL;
        }
        if (attributes == 0) {
                error("One or more attributes required for Match");
                return -1;
        }
-       if (ci != NULL)
+ out:
+       if (ci != NULL && result != -1)
                debug3("match %sfound", result ? "" : "not ");
+       free(attrib);
        return result;
 }