diff --git a/lib/chkname.c b/lib/chkname.c index 6abd34fffa..0abee4d294 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 */ @@ -27,12 +28,15 @@ #include #include #include +#include #include #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/strcaseeq.h" #ifndef LOGIN_NAME_MAX @@ -59,6 +63,18 @@ login_name_max_size(void) static bool is_valid_name(const char *name) { + if (streq(name, "") + || streq(name, ".") + || streq(name, "..") + || strspn(name, "-") + || strpbrk(name, " \"#',/:;") + || strchriscntrl(name) + || strisdigit(name)) + { + errno = EINVAL; + return false; + } + if (allow_bad_names) { return true; } @@ -69,25 +85,15 @@ 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 "..". */ - if (strisdigit(name)) { - errno = EINVAL; - return false; - } - - 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; } @@ -101,7 +107,7 @@ is_valid_name(const char *name) streq(name, "$") )) { - errno = EINVAL; + errno = EILSEQ; return false; } } diff --git a/src/newusers.c b/src/newusers.c index 8af65b7a2b..e9353fdc0a 100644 --- a/src/newusers.c +++ b/src/newusers.c @@ -398,7 +398,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 0e7dfe7c9a..c35f03e695 100644 --- a/src/pwck.c +++ b/src/pwck.c @@ -492,7 +492,7 @@ static void check_pw_file(bool *errors, bool *changed, const struct option_flags */ 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 a71a049dae..899efe3c84 100644 --- a/src/useradd.c +++ b/src/useradd.c @@ -1498,7 +1498,7 @@ static void process_flags (int argc, char **argv, struct option_flags *flags) 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 2418514dd3..e8c9da6687 100644 --- a/src/usermod.c +++ b/src/usermod.c @@ -1137,7 +1137,7 @@ process_flags(int argc, char **argv, struct option_flags *flags) /*@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);