]> git.ipfire.org Git - thirdparty/openssh-portable.git/commitdiff
Revert "[auth.c] On Cygwin, refuse usernames that have differences in case"
authorCorinna Vinschen <vinschen@redhat.com>
Wed, 20 Feb 2019 12:41:24 +0000 (13:41 +0100)
committerDarren Tucker <dtucker@dtucker.net>
Fri, 22 Feb 2019 04:04:16 +0000 (15:04 +1100)
This reverts commit acc9b29486dfd649dfda474e5c1a03b317449f1c.

Signed-off-by: Corinna Vinschen <vinschen@redhat.com>
auth.c
groupaccess.c
match.c
openbsd-compat/bsd-cygwin_util.c
servconf.c

diff --git a/auth.c b/auth.c
index 62c58e72f01e6d94e9be9d22f8528c099511499e..332b6220cd21ed3c30febe9f3f4d7179e92a10b5 100644 (file)
--- a/auth.c
+++ b/auth.c
@@ -583,19 +583,6 @@ getpwnamallow(struct ssh *ssh, const char *user)
 
 #if defined(_AIX) && defined(HAVE_SETAUTHDB)
        aix_restoreauthdb();
-#endif
-#ifdef HAVE_CYGWIN
-       /*
-        * Windows usernames are case-insensitive.  To avoid later problems
-        * when trying to match the username, the user is only allowed to
-        * login if the username is given in the same case as stored in the
-        * user database.
-        */
-       if (pw != NULL && strcmp(user, pw->pw_name) != 0) {
-               logit("Login name %.100s does not match stored username %.100s",
-                   user, pw->pw_name);
-               pw = NULL;
-       }
 #endif
        if (pw == NULL) {
                logit("Invalid user %.100s from %.100s port %d",
index 9e4d25521647dab0020bddfc4a3dea59091e8770..43367990d8c31e360cde12e717103434362c77cd 100644 (file)
@@ -103,7 +103,11 @@ ga_match_pattern_list(const char *group_pattern)
        int i, found = 0;
 
        for (i = 0; i < ngroups; i++) {
+#ifndef HAVE_CYGWIN
                switch (match_pattern_list(groups_byname[i], group_pattern, 0)) {
+#else
+               switch (match_pattern_list(groups_byname[i], group_pattern, 1)) {
+#endif
                case -1:
                        return 0;       /* Negated match wins */
                case 0:
diff --git a/match.c b/match.c
index bb3e95f678caffa5bea87880c9e31ae8572c4ef9..b50ae4057391f74a5f835a8060000f6f752fdd85 100644 (file)
--- a/match.c
+++ b/match.c
@@ -111,6 +111,8 @@ match_pattern(const char *s, const char *pattern)
        /* NOTREACHED */
 }
 
+#ifndef HAVE_CYGWIN /* Cygwin version in openbsd-compat/bsd-cygwin_util.c */
+
 /*
  * Tries to match the string against the
  * comma-separated sequence of subpatterns (each possibly preceded by ! to
@@ -170,6 +172,8 @@ match_pattern_list(const char *string, const char *pattern, int dolower)
        return got_positive;
 }
 
+#endif
+
 /*
  * Tries to match the host name (which must be in all lowercase) against the
  * comma-separated sequence of subpatterns (each possibly preceded by ! to
index fb49e30f5981e752bb9e6afe99ffa24f4a9b0170..f721fca9d9987a16e98579324d6fdb6c4228ac54 100644 (file)
@@ -37,6 +37,8 @@
 #include <string.h>
 #include <unistd.h>
 #include <stdarg.h>
+#include <wchar.h>
+#include <wctype.h>
 
 #include "xmalloc.h"
 
@@ -117,4 +119,148 @@ free_windows_environment(char **p)
        free(p);
 }
 
+/*
+ * Returns true if the given string matches the pattern (which may contain ?
+ * and * as wildcards), and zero if it does not match.
+ *
+ * The Cygwin version of this function must be case-insensitive and take
+ * Unicode characters into account.
+ */
+
+static int
+__match_pattern (const wchar_t *s, const wchar_t *pattern, int caseinsensitive)
+{
+       for (;;) {
+               /* If at end of pattern, accept if also at end of string. */
+               if (!*pattern)
+                       return !*s;
+
+               if (*pattern == '*') {
+                       /* Skip the asterisk. */
+                       pattern++;
+
+                       /* If at end of pattern, accept immediately. */
+                       if (!*pattern)
+                               return 1;
+
+                       /* If next character in pattern is known, optimize. */
+                       if (*pattern != '?' && *pattern != '*') {
+                               /*
+                                * Look instances of the next character in
+                                * pattern, and try to match starting from
+                                * those.
+                                */
+                               for (; *s; s++)
+                                       if (*s == *pattern &&
+                                           __match_pattern(s + 1, pattern + 1,
+                                                           caseinsensitive))
+                                               return 1;
+                               /* Failed. */
+                               return 0;
+                       }
+                       /*
+                        * Move ahead one character at a time and try to
+                        * match at each position.
+                        */
+                       for (; *s; s++)
+                               if (__match_pattern(s, pattern, caseinsensitive))
+                                       return 1;
+                       /* Failed. */
+                       return 0;
+               }
+               /*
+                * There must be at least one more character in the string.
+                * If we are at the end, fail.
+                */
+               if (!*s)
+                       return 0;
+
+               /* Check if the next character of the string is acceptable. */
+               if (*pattern != '?' && (*pattern != *s &&
+                    (!caseinsensitive || towlower(*pattern) != towlower(*s))))
+                       return 0;
+
+               /* Move to the next character, both in string and in pattern. */
+               s++;
+               pattern++;
+       }
+       /* NOTREACHED */
+}
+
+static int
+_match_pattern(const char *s, const char *pattern, int caseinsensitive)
+{
+       wchar_t *ws;
+       wchar_t *wpattern;
+       size_t len;
+
+       if ((len = mbstowcs(NULL, s, 0)) < 0)
+               return 0;
+       ws = (wchar_t *) alloca((len + 1) * sizeof (wchar_t));
+       mbstowcs(ws, s, len + 1);
+       if ((len = mbstowcs(NULL, pattern, 0)) < 0)
+               return 0;
+       wpattern = (wchar_t *) alloca((len + 1) * sizeof (wchar_t));
+       mbstowcs(wpattern, pattern, len + 1);
+       return __match_pattern (ws, wpattern, caseinsensitive);
+}
+
+/*
+ * Tries to match the string against the
+ * comma-separated sequence of subpatterns (each possibly preceded by ! to
+ * indicate negation).  Returns -1 if negation matches, 1 if there is
+ * a positive match, 0 if there is no match at all.
+ */
+int
+match_pattern_list(const char *string, const char *pattern, int caseinsensitive)
+{
+       char sub[1024];
+       int negated;
+       int got_positive;
+       u_int i, subi, len = strlen(pattern);
+
+       got_positive = 0;
+       for (i = 0; i < len;) {
+               /* Check if the subpattern is negated. */
+               if (pattern[i] == '!') {
+                       negated = 1;
+                       i++;
+               } else
+                       negated = 0;
+
+               /*
+                * Extract the subpattern up to a comma or end.  Convert the
+                * subpattern to lowercase.
+                */
+               for (subi = 0;
+                   i < len && subi < sizeof(sub) - 1 && pattern[i] != ',';
+                   subi++, i++)
+                       sub[subi] = pattern[i];
+               /* If subpattern too long, return failure (no match). */
+               if (subi >= sizeof(sub) - 1)
+                       return 0;
+
+               /* If the subpattern was terminated by a comma, then skip it. */
+               if (i < len && pattern[i] == ',')
+                       i++;
+
+               /* Null-terminate the subpattern. */
+               sub[subi] = '\0';
+
+               /* Try to match the subpattern against the string. */
+               if (_match_pattern(string, sub, caseinsensitive)) {
+                       if (negated)
+                               return -1;              /* Negative */
+                       else
+                               got_positive = 1;       /* Positive */
+               }
+       }
+
+       /*
+        * Return success if got a positive match.  If there was a negative
+        * match, we have already returned -1 and never get here.
+        */
+       return got_positive;
+}
+
 #endif /* HAVE_CYGWIN */
index d9680aba11cad6aa43d40f494887ddb5a5c894c6..4fa896fd4576e7206c49b4bb6de7955f98f92f69 100644 (file)
@@ -1049,7 +1049,11 @@ match_cfg_line(char **condition, int line, struct connection_info *ci)
                        }
                        if (ci->user == NULL)
                                match_test_missing_fatal("User", "user");
+#ifndef HAVE_CYGWIN
                        if (match_pattern_list(ci->user, arg, 0) != 1)
+#else
+                       if (match_pattern_list(ci->user, arg, 1) != 1)
+#endif
                                result = 0;
                        else
                                debug("user %.100s matched 'User %.100s' at "