Discussion:
case sensitivity, "Match User" and "AllowUsers"
(too old to reply)
Hu, Eric
2010-02-01 19:18:08 UTC
Permalink
Hello,

I sent this last week before signing up for the list, but haven't seen it in the archives, so I'm guessing it got discarded either as spam or HTML (sorry about that). In any case, the following was sent to comp.security.ssh early last week and I have gotten no response there. Can anyone here shed some light?

Thanks,
Eric

------------------------------------------

Hello,

I'm running an SSH daemon on Cygwin on Windows Server 2003.  SSH version is 5.1.  cygrunsrv version is 1.34.
I have the following in my sshd_config file.

Match User user
    ForceCommand start.sh

What some users have discovered is that they can log in with arbitrarily mixed case user names.  For instance, logging in as "usEr" is exactly the same as logging in with "USer" as well as the other fourteen possible combinations for a four-letter username.  Further, only the all-lowercase version invokes "start.sh." I thought I might be able to solve this with the following.

AllowUsers user

I thought this would force sshd to only let one case combination through.  However, all case combinations can still log in and "start.sh" is not getting executed.  In other words, there is a discrepancy between "Match User" and "AllowUsers" in this regard. Does anyone have any idea how to get around this?  I don't want to add 2^(length of user name) "Match User" entries to the sshd_config file for every user, which is the only remedy at the moment.

Thanks
Damien Miller
2010-02-02 00:25:44 UTC
Permalink
[+Corinna Vinschen]

It looks like Windows is matching users case-insensitively. OpenSSH
always performs case-sensitive matching (following Unix). If this is
the case, then perhaps we should tolower() all usernames on Windows?

-d
Post by Hu, Eric
Hello,
I sent this last week before signing up for the list, but haven't seen
it in the archives, so I'm guessing it got discarded either as spam
or HTML (sorry about that). In any case, the following was sent to
comp.security.ssh early last week and I have gotten no response there.
Can anyone here shed some light?
------------------------------------------
Hello,
I'm running an SSH daemon on Cygwin on Windows Server 2003. SSH
version is 5.1. cygrunsrv version is 1.34. I have the following in my
sshd_config file.
Match User user
ForceCommand start.sh
What some users have discovered is that they can log in with
arbitrarily mixed case user names. For instance, logging in as "usEr"
is exactly the same as logging in with "USer" as well as the other
fourteen possible combinations for a four-letter username. Further,
only the all-lowercase version invokes "start.sh." I thought I might
be able to solve this with the following.
AllowUsers user
I thought this would force sshd to only let one case combination
through. However, all case combinations can still log in and
"start.sh" is not getting executed. In other words, there is a
discrepancy between "Match User" and "AllowUsers" in this regard.
Does anyone have any idea how to get around this? I don't want to add
2^(length of user name) "Match User" entries to the sshd_config file
for every user, which is the only remedy at the moment.
Hu, Eric
2010-02-02 00:52:27 UTC
Permalink
Does that mean "AllowUsers" is going through Windows and "Match User" is going through the OpenSSH machinery (sorry, I've read the docs reasonably well, but haven't looked at the code at all)?

Not being very familiar with the code, it's hard for me to recommend a solution. Had I not discovered this oddity, I would've guessed the order of events is something like

1) OpenSSH gets authentication information including user name
2) OpenSSH checks Allow/Deny directives in sshd_config
3) If user passes in step 2, send info to Windows
4) If Windows says authentication passes, OpenSSH runs through Match clauses

Using tolower() at step 4 (ie, before running Match clauses) would probably work. Not knowing the broader implications, it makes more sense to me for OpenSSH to report a failure at step 2.

-----Original Message-----
From: Damien Miller [mailto:***@mindrot.org]
Sent: Monday, February 01, 2010 4:26 PM
To: Hu, Eric
Cc: openssh-unix-***@mindrot.org; Corinna Vinschen
Subject: Re: case sensitivity, "Match User" and "AllowUsers"

[+Corinna Vinschen]

It looks like Windows is matching users case-insensitively. OpenSSH
always performs case-sensitive matching (following Unix). If this is
the case, then perhaps we should tolower() all usernames on Windows?

-d
Post by Hu, Eric
Hello,
I sent this last week before signing up for the list, but haven't seen
it in the archives, so I'm guessing it got discarded either as spam
or HTML (sorry about that). In any case, the following was sent to
comp.security.ssh early last week and I have gotten no response there.
Can anyone here shed some light?
------------------------------------------
Hello,
I'm running an SSH daemon on Cygwin on Windows Server 2003. SSH
version is 5.1. cygrunsrv version is 1.34. I have the following in my
sshd_config file.
Match User user
ForceCommand start.sh
What some users have discovered is that they can log in with
arbitrarily mixed case user names. For instance, logging in as "usEr"
is exactly the same as logging in with "USer" as well as the other
fourteen possible combinations for a four-letter username. Further,
only the all-lowercase version invokes "start.sh." I thought I might
be able to solve this with the following.
AllowUsers user
I thought this would force sshd to only let one case combination
through. However, all case combinations can still log in and
"start.sh" is not getting executed. In other words, there is a
discrepancy between "Match User" and "AllowUsers" in this regard.
Does anyone have any idea how to get around this? I don't want to add
2^(length of user name) "Match User" entries to the sshd_config file
for every user, which is the only remedy at the moment.
Corinna Vinschen
2010-02-02 10:53:56 UTC
Permalink
Post by Damien Miller
[+Corinna Vinschen]
Thanks, but not necessary, I'm subscribed to this list anyway.
Post by Damien Miller
It looks like Windows is matching users case-insensitively. OpenSSH
always performs case-sensitive matching (following Unix). If this is
the case, then perhaps we should tolower() all usernames on Windows?
That might be a good idea. I was surprised to read what Eric wrote, but
it turned out that this is just a result of how getpwnam is implemented
in Cygwin. Given Windows' underlying case-insensitivity in terms of
user and group names, the getpwnam function checks the user name using
strcasecmp. The returned struct passwd contain the name in the original
case, though, and that in turn is used in match_user() to check the user
name.

The most simple patch would be

Index: match.c
===================================================================
RCS file: /cvs/openssh/match.c,v
retrieving revision 1.26
diff -u -p -r1.26 match.c
--- match.c 10 Jun 2008 23:34:46 -0000 1.26
+++ match.c 2 Feb 2010 10:40:26 -0000
@@ -98,7 +98,7 @@ match_pattern(const char *s, const char
return 0;

/* Check if the next character of the string is acceptable. */
- if (*pattern != '?' && *pattern != *s)
+ if (*pattern != '?' && tolower (*pattern) != tolower (*s))
return 0;

/* Move to the next character, both in string and in pattern. */

Wouldn't that be acceptable for Unix as well, given that the username is
supposed not to contain capital letters anyway? This function is also
used to compare hostnames, and hostnames are usually case-insensitive as
well, so this would be the right thing to do to allow arbitrary host
strings. Is there any advantage to do the pattern matching case-sensitive?

Alternatively, wouldn't it make sense to add a parameter to
match_pattern and match_pattern_list to control case-sensitivity when
calling these functions?


Corinna
--
Corinna Vinschen
Cygwin Project Co-Leader
Red Hat
Corinna Vinschen
2010-02-02 11:39:02 UTC
Permalink
Post by Corinna Vinschen
Post by Damien Miller
[+Corinna Vinschen]
Thanks, but not necessary, I'm subscribed to this list anyway.
Post by Damien Miller
It looks like Windows is matching users case-insensitively. OpenSSH
always performs case-sensitive matching (following Unix). If this is
the case, then perhaps we should tolower() all usernames on Windows?
That might be a good idea. I was surprised to read what Eric wrote, but
it turned out that this is just a result of how getpwnam is implemented
in Cygwin. Given Windows' underlying case-insensitivity in terms of
user and group names, the getpwnam function checks the user name using
strcasecmp. The returned struct passwd contain the name in the original
case, though, and that in turn is used in match_user() to check the user
name.
The most simple patch would be
Index: match.c
===================================================================
RCS file: /cvs/openssh/match.c,v
retrieving revision 1.26
diff -u -p -r1.26 match.c
--- match.c 10 Jun 2008 23:34:46 -0000 1.26
+++ match.c 2 Feb 2010 10:40:26 -0000
@@ -98,7 +98,7 @@ match_pattern(const char *s, const char
return 0;
/* Check if the next character of the string is acceptable. */
- if (*pattern != '?' && *pattern != *s)
+ if (*pattern != '?' && tolower (*pattern) != tolower (*s))
return 0;
/* Move to the next character, both in string and in pattern. */
Wouldn't that be acceptable for Unix as well, given that the username is
supposed not to contain capital letters anyway? This function is also
used to compare hostnames, and hostnames are usually case-insensitive as
well, so this would be the right thing to do to allow arbitrary host
strings. Is there any advantage to do the pattern matching case-sensitive?
Alternatively, wouldn't it make sense to add a parameter to
match_pattern and match_pattern_list to control case-sensitivity when
calling these functions?
Of course, using tolower has an obvious disadvantage. It doesn't work
for multibyte codesets, like UTF-8. Usernames are stored in UTF-16 in
Windows and consequentially they can contain any character from the
entire Unicode range. So, after all, it might be more feasible to
convert the string and the pattern to wide char, call towlower on the
string, and convert back to multibyte, before calling match_pattern.


Corinna
--
Corinna Vinschen
Cygwin Project Co-Leader
Red Hat
Robert Dahlem
2010-02-03 12:37:14 UTC
Permalink
Hi,
Post by Corinna Vinschen
- if (*pattern != '?' && *pattern != *s)
+ if (*pattern != '?' && tolower (*pattern) != tolower (*s))
Wouldn't that be acceptable for Unix as well, given that the username is
supposed not to contain capital letters anyway?
I wouldn't consider this acceptable. Corinna is someone else in Unix
than corinna.

Regards,
Robert
Hu, Eric
2010-02-06 00:38:25 UTC
Permalink
From the below code (lines 191-203 of auth.c in allowed_user, called from getpwnamallow), the logic for "AllowUsers" calls match_user with the passwd struct's name (line 194). This should fail if the wrong case combination is given, should it not?
/* Return false if AllowUsers isn't empty and user isn't listed there */
if (options.num_allow_users > 0) {
for (i = 0; i < options.num_allow_users; i++)
if (match_user(pw->pw_name, hostname, ipaddr,
options.allow_users[i]))
break;
/* i < options.num_allow_users iff we break for loop */
if (i >= options.num_allow_users) {
logit("User %.100s from %.100s not allowed because "
"not listed in AllowUsers", pw->pw_name, hostname);
return 0;
}
}

The only thing consistent with what I originally saw and the above is if getpwnam (where pw in the above code comes from) returns the all-lowercase version of the name in the passwd struct. I think the problem might be in auth2.c. Lines 234-236 are shown below.

/* setup auth context */
authctxt->pw = PRIVSEP(getpwnamallow(user));
authctxt->user = xstrdup(user);
From this, it is possible for authctxt->user to hold a different string than authctxt->pw->pw_name. Perhaps the patch is simply changing line 236 to the following?
authctxt->user = xstrdup(authctxt->pw->pw_name);

I'm not familiar enough with the code to track down what happens to the lines under "Match User" in the configuration file.

-----Original Message-----
From: openssh-unix-dev-bounces+eric.hu=***@mindrot.org [mailto:openssh-unix-dev-bounces+eric.hu=***@mindrot.org] On Behalf Of Corinna Vinschen
Sent: Tuesday, February 02, 2010 3:39 AM
To: openssh-unix-***@mindrot.org
Subject: Re: case sensitivity, "Match User" and "AllowUsers"
Post by Damien Miller
[+Corinna Vinschen]
Thanks, but not necessary, I'm subscribed to this list anyway.
Post by Damien Miller
It looks like Windows is matching users case-insensitively. OpenSSH
always performs case-sensitive matching (following Unix). If this is
the case, then perhaps we should tolower() all usernames on Windows?
That might be a good idea. I was surprised to read what Eric wrote, but
it turned out that this is just a result of how getpwnam is implemented
in Cygwin. Given Windows' underlying case-insensitivity in terms of
user and group names, the getpwnam function checks the user name using
strcasecmp. The returned struct passwd contain the name in the original
case, though, and that in turn is used in match_user() to check the user
name.
The most simple patch would be
Index: match.c
===================================================================
RCS file: /cvs/openssh/match.c,v
retrieving revision 1.26
diff -u -p -r1.26 match.c
--- match.c 10 Jun 2008 23:34:46 -0000 1.26
+++ match.c 2 Feb 2010 10:40:26 -0000
@@ -98,7 +98,7 @@ match_pattern(const char *s, const char
return 0;
/* Check if the next character of the string is acceptable. */
- if (*pattern != '?' && *pattern != *s)
+ if (*pattern != '?' && tolower (*pattern) != tolower (*s))
return 0;
/* Move to the next character, both in string and in pattern. */
Wouldn't that be acceptable for Unix as well, given that the username is
supposed not to contain capital letters anyway? This function is also
used to compare hostnames, and hostnames are usually case-insensitive as
well, so this would be the right thing to do to allow arbitrary host
strings. Is there any advantage to do the pattern matching case-sensitive?
Alternatively, wouldn't it make sense to add a parameter to
match_pattern and match_pattern_list to control case-sensitivity when
calling these functions?
Of course, using tolower has an obvious disadvantage. It doesn't work
for multibyte codesets, like UTF-8. Usernames are stored in UTF-16 in
Windows and consequentially they can contain any character from the
entire Unicode range. So, after all, it might be more feasible to
convert the string and the pattern to wide char, call towlower on the
string, and convert back to multibyte, before calling match_pattern.


Corinna
--
Corinna Vinschen
Cygwin Project Co-Leader
Red Hat
Loading...