On Monday 01 August 2011 22:01, Tito wrote:
> Hi,
> this patch improves the checks performed on usernames
> with the die_if_bad_username() function by adduser and addgroup.
> The changes are:
> 1) better comments;
> 2) use of the portable filename character set plus '@' and '$';
> 3) don't use isalnum as it will allow non-ASCII letters in legacy 8-bit
> locales as pointed out by Rich Felker;
We use ASCII-only isalnum throughout bbox anyway. But ok.
> 3) enforce minimum length of 1 char (or at least 2 chars if '$' is used as
> last char);
This was already the case, I think.
> 4) enforce maximum length of LOGIN_NAME_MAX (including null termination);
Ok.
> 5) don't use goto to jump into the loop (requested by Matthias Andree);
Don't see why. It's efficient.
> 6) don't allow '$', '.', '@' and '-' as first char;
> 7) allow '$' only as last char.
Ok.
> 8) don't print the illegal char in error message as if it is a wide char it
> will be unreadable.
Ok.
On Tuesday 02 August 2011 21:57, Tito wrote:
> Hi,
> minor improvements vs. v2 patch:
> 1) some more comments added.
> 2) we now print the position of the illegal character.
>
> Hints, critics, improvements are welcome.
> Thanks to all who helped.
>
> Ciao,
> Tito
>
> void FAST_FUNC die_if_bad_username(const char *name)
> {
> const char *s = name;
>
> assert(name != NULL);
>
> /* The minimum size of the login name is one char or two if
> * last char is the '$', this exception is catched later
> * as the dollar sign could not be the first char.
> * The maximum size of the login name is LOGIN_NAME_MAX
> * including the terminating null byte.
> */
> if (!*name || strlen(name) + 1 > LOGIN_NAME_MAX)
> bb_error_msg_and_die("illegal name length");
We can check length at the end by calcualting (name - s).
This way, we don't need strlen call.
Zero-length check is not necessary as this case is already caught
by the checking loop.
> do {
> /* We don't use isalnum as it will allow locale-specific
> non-ASCII */
> /* letters in legacy 8-bit locales. */
> if (((*name == '-' || *name == '.' || *name == '@') && name !=
> s) /* not as first char */
> || (*name == '$' && (!name[1] && name != s)) /* not as first,
> only as last char */
Come to think about it, '@' can't be used in usernames:
@ is used to delimit username from hostname:
user@host
> || *name == '_'
> || (*name >= 48 && *name <= 57) /* 0-9 */
> || (*name >= 65 && *name <= 90) /* A-Z */
> || (*name >= 97 && *name <= 122) /* a-z */
> ) {
> continue;
> }
> bb_error_msg_and_die("illegal character at position '%d'", name
> - s);
> } while (*++name);
> }
How about this?
void FAST_FUNC die_if_bad_username(const char *name)
{
const char *start = name;
/* 1st char being dash or dot isn't valid:
* for example, name like ".." can make adduser
* chown "/home/.." recursively - NOT GOOD.
* Name of just a single "$" is also rejected.
*/
goto skip;
do {
unsigned char ch;
/* These chars are valid unless they are at the 1st pos: */
if (*name == '-'
|| *name == '.'
/* $ is allowed if it's the last char: */
|| (*name == '$' && !name[1])
) {
continue;
}
skip:
ch = *name;
if (ch == '_'
/* || ch == '@' -- we disallow this too. Think about
"user@host" */
/* open-coded isalnum: */
|| (ch >= '0' && ch <= '9')
|| ((ch|0x20) >= 'a' && (ch|0x20) <= 'z')
) {
continue;
}
bb_error_msg_and_die("illegal character with code %u at
position %u",
(unsigned)ch, (unsigned)(name - start));
} while (*++name);
/* The minimum size of the login name is one char or two if
* last char is the '$'. Violations of this are caught above.
* The maximum size of the login name is LOGIN_NAME_MAX
* including the terminating null byte.
*/
if (name - start >= LOGIN_NAME_MAX)
bb_error_msg_and_die("name is too long");
}
function old new delta
die_if_bad_username 77 97 +20
--
vda
_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox