diff --git a/lib/chkname.c b/lib/chkname.c index b2fc0b88a..b42b49bb4 100644 --- a/lib/chkname.c +++ b/lib/chkname.c @@ -13,7 +13,8 @@ * true - OK * false - bad name * errors: - * EINVAL Invalid name characters or sequences + * EINVAL Invalid name + * EILSEQ Invalid name character sequence (acceptable with --badname) * EOVERFLOW Name longer than maximum size */ @@ -31,7 +32,10 @@ #include "defines.h" #include "chkname.h" +#include "string/ctype/strchrisascii/strchriscntrl.h" +#include "string/ctype/strisascii/strisdigit.h" #include "string/strcmp/streq.h" +#include "string/strcmp/strprefix.h" #ifndef LOGIN_NAME_MAX @@ -58,6 +62,18 @@ login_name_max_size(void) static bool is_valid_name(const char *name) { + if (streq(name, "") + || streq(name, ".") + || streq(name, "..") + || strpbrk(name, ",: /") + || strprefix(name, "-") + || strchriscntrl(name) + || strisdigit(name)) + { + errno = EINVAL; + return false; + } + if (allow_bad_names) { return true; } @@ -68,26 +84,18 @@ is_valid_name(const char *name) * * as a non-POSIX, extension, allow "$" as the last char for * sake of Samba 3.x "add machine script" - * - * Also do not allow fully numeric names or just "." or "..". */ - int numeric; - if (streq(name, "") || - streq(name, ".") || - streq(name, "..") || - !((*name >= 'a' && *name <= 'z') || + if (!((*name >= 'a' && *name <= 'z') || (*name >= 'A' && *name <= 'Z') || (*name >= '0' && *name <= '9') || *name == '_' || *name == '.')) { - errno = EINVAL; + errno = EILSEQ; return false; } - numeric = isdigit(*name); - while (!streq(++name, "")) { if (!((*name >= 'a' && *name <= 'z') || (*name >= 'A' && *name <= 'Z') || @@ -98,15 +106,9 @@ is_valid_name(const char *name) streq(name, "$") )) { - errno = EINVAL; + errno = EILSEQ; return false; } - numeric &= isdigit(*name); - } - - if (numeric) { - errno = EINVAL; - return false; } return true; diff --git a/src/newusers.c b/src/newusers.c index 5e78dd976..18748268e 100644 --- a/src/newusers.c +++ b/src/newusers.c @@ -388,7 +388,7 @@ static int add_user (const char *name, uid_t uid, gid_t gid) /* Check if this is a valid user name */ if (!is_valid_user_name(name)) { - if (errno == EINVAL) { + if (errno == EILSEQ) { fprintf(stderr, _("%s: invalid user name '%s': use --badname to ignore\n"), Prog, name); diff --git a/src/pwck.c b/src/pwck.c index ae7ddaddf..8594e2e59 100644 --- a/src/pwck.c +++ b/src/pwck.c @@ -475,7 +475,7 @@ static void check_pw_file (int *errors, bool *changed) */ if (!is_valid_user_name(pwd->pw_name)) { - if (errno == EINVAL) { + if (errno == EILSEQ) { printf(_("invalid user name '%s': use --badname to ignore\n"), pwd->pw_name); } else { diff --git a/src/useradd.c b/src/useradd.c index 4275794a7..67b2f3e18 100644 --- a/src/useradd.c +++ b/src/useradd.c @@ -1534,7 +1534,7 @@ static void process_flags (int argc, char **argv) user_name = argv[optind]; if (!is_valid_user_name(user_name)) { - if (errno == EINVAL) { + if (errno == EILSEQ) { fprintf(stderr, _("%s: invalid user name '%s': use --badname to ignore\n"), Prog, user_name); diff --git a/src/usermod.c b/src/usermod.c index 24c5a4d23..ca4860f93 100644 --- a/src/usermod.c +++ b/src/usermod.c @@ -1118,7 +1118,7 @@ process_flags(int argc, char **argv) /*@notreached@*/break; case 'l': if (!is_valid_user_name(optarg)) { - if (errno == EINVAL) { + if (errno == EILSEQ) { fprintf(stderr, _("%s: invalid user name '%s': use --badname to ignore\n"), Prog, optarg);