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");
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 */
|| *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);
}
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;
3) enforce minimum length of 1 char (or at least 2 chars if '$' is used as last char);
4) enforce maximum length of LOGIN_NAME_MAX (including null termination);
5) don't use goto to jump into the loop (requested by Matthias Andree);
6) don't allow '$', '.', '@' and '-' as first char;
7) allow '$' only as last char;
8) don't print the illegal char in error message as if it is a wide char it will be unreadable
print its position instead.
Signed-off-by: Tito Ragusa <[email protected]>
--- libbb/die_if_bad_username.c.orig 2011-02-03 21:30:50.000000000 +0100
+++ libbb/die_if_bad_username.c 2011-08-02 21:43:13.000000000 +0200
@@ -8,33 +8,53 @@
*/
#include "libbb.h"
+#include <assert.h>
-/* To avoid problems, the username should consist only of
- * letters, digits, underscores, periods, at signs and dashes,
- * and not start with a dash (as defined by IEEE Std 1003.1-2001).
- * For compatibility with Samba machine accounts $ is also supported
- * at the end of the username.
+/* The username to "(...) be portable across systems conforming to IEEE Std
+ * 1003.1-2001, (...) is composed of characters from the portable
+ * filename character set. The hyphen should not be used as the first character
+ * of a portable username" (SUSv3). The Portable Filename Character Set is:
+ * A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
+ * a b c d e f g h i j k l m n o p q r s t u v w x y z
+ * 0 1 2 3 4 5 6 7 8 9 . _ -
+ * We allow also the '@' and the '$' sign, but to avoid problems, '@','$' and '.'
+ * are not permitted at the beginning of the username (for example, a name
+ * like ".." can make adduser chown "/home/..).
+ * For compatibility with Samba machine accounts '$' is supported
+ * (only) at the end of the username. Be aware that it might be necessary
+ * to quote or escape the '$' sign to avoid that the shell mangles it.
+ * On Debian the default is more conservative as defined by the regular
+ * expression /^[a-z][-a-z0-9]*$/.
*/
void FAST_FUNC die_if_bad_username(const char *name)
{
- /* 1st char being dash or dot isn't valid: */
- goto skip;
- /* For example, name like ".." can make adduser
- * chown "/home/.." recursively - NOT GOOD
- */
+ 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");
+
do {
- if (*name == '-' || *name == '.')
- continue;
- skip:
- if (isalnum(*name)
+ /* 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 */
|| *name == '_'
- || *name == '@'
- || (*name == '$' && !name[1])
+ || (*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 '%c'", *name);
+ bb_error_msg_and_die("illegal character at position '%d'", name - s);
} while (*++name);
}
+
_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox