diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2011-08-09 04:05:13 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2011-08-09 04:05:13 +0200 |
commit | 7485086f1eca78998d6cd31b0ce18a8a8ea3fc35 (patch) | |
tree | ad3a754a07e29b0c86514bdac98c63618628b37d | |
parent | 6e42b89b8d136316e1b97b56cf885e8ef9d64caf (diff) | |
download | busybox-w32-7485086f1eca78998d6cd31b0ce18a8a8ea3fc35.tar.gz busybox-w32-7485086f1eca78998d6cd31b0ce18a8a8ea3fc35.tar.bz2 busybox-w32-7485086f1eca78998d6cd31b0ce18a8a8ea3fc35.zip |
die_if_bad_username: tighten up a bit
function old new delta
die_if_bad_username 77 97 +20
Based on patches from Tito.
The changes are:
better comments
we disallow '@' now - in practice such usernames will be unusable
use of the portable filename character set plus '$'
don't use isalnum as it allows non-ASCII letters in legacy 8-bit locales (pointed out by Rich Felker)
enforce maximum length of LOGIN_NAME_MAX (including NUL)
don't allow '$', '.', and '-' as first char
don't print the illegal char in error message as if it is a wide char it will be unreadable
print the position of the illegal character
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | libbb/die_if_bad_username.c | 42 |
1 files changed, 32 insertions, 10 deletions
diff --git a/libbb/die_if_bad_username.c b/libbb/die_if_bad_username.c index 9946e3a1d..cf1297bd6 100644 --- a/libbb/die_if_bad_username.c +++ b/libbb/die_if_bad_username.c | |||
@@ -18,23 +18,45 @@ | |||
18 | 18 | ||
19 | void FAST_FUNC die_if_bad_username(const char *name) | 19 | void FAST_FUNC die_if_bad_username(const char *name) |
20 | { | 20 | { |
21 | /* 1st char being dash or dot isn't valid: */ | 21 | const char *start = name; |
22 | goto skip; | 22 | |
23 | /* For example, name like ".." can make adduser | 23 | /* 1st char being dash or dot isn't valid: |
24 | * chown "/home/.." recursively - NOT GOOD | 24 | * for example, name like ".." can make adduser |
25 | * chown "/home/.." recursively - NOT GOOD. | ||
26 | * Name of just a single "$" is also rejected. | ||
25 | */ | 27 | */ |
28 | goto skip; | ||
26 | 29 | ||
27 | do { | 30 | do { |
28 | if (*name == '-' || *name == '.') | 31 | unsigned char ch; |
32 | |||
33 | /* These chars are valid unless they are at the 1st pos: */ | ||
34 | if (*name == '-' | ||
35 | || *name == '.' | ||
36 | /* $ is allowed if it's the last char: */ | ||
37 | || (*name == '$' && !name[1]) | ||
38 | ) { | ||
29 | continue; | 39 | continue; |
40 | } | ||
30 | skip: | 41 | skip: |
31 | if (isalnum(*name) | 42 | ch = *name; |
32 | || *name == '_' | 43 | if (ch == '_' |
33 | || *name == '@' | 44 | /* || ch == '@' -- we disallow this too. Think about "user@host" */ |
34 | || (*name == '$' && !name[1]) | 45 | /* open-coded isalnum: */ |
46 | || (ch >= '0' && ch <= '9') | ||
47 | || ((ch|0x20) >= 'a' && (ch|0x20) <= 'z') | ||
35 | ) { | 48 | ) { |
36 | continue; | 49 | continue; |
37 | } | 50 | } |
38 | bb_error_msg_and_die("illegal character '%c'", *name); | 51 | bb_error_msg_and_die("illegal character with code %u at position %u", |
52 | (unsigned)ch, (unsigned)(name - start)); | ||
39 | } while (*++name); | 53 | } while (*++name); |
54 | |||
55 | /* The minimum size of the login name is one char or two if | ||
56 | * last char is the '$'. Violations of this are caught above. | ||
57 | * The maximum size of the login name is LOGIN_NAME_MAX | ||
58 | * including the terminating null byte. | ||
59 | */ | ||
60 | if (name - start >= LOGIN_NAME_MAX) | ||
61 | bb_error_msg_and_die("name is too long"); | ||
40 | } | 62 | } |