Skip to content

Commit

Permalink
lib/chkname.c, src/: Strictly disallow really bad names
Browse files Browse the repository at this point in the history
Some names are bad, and some names are really bad.  '--badname' should
only allow the mildly bad ones, which we can handle.  Some names are too
bad, and it's not possible to deal with them.  Reject them
unconditionally.

Acked-by: Chris Hofstaedtler <[email protected]>
Cc: Marc 'Zugschlus' Haber <[email protected]>
Cc: Iker Pedrosa <[email protected]>
Cc: Serge Hallyn <[email protected]>
Signed-off-by: Alejandro Colomar <[email protected]>
  • Loading branch information
alejandro-colomar committed Dec 23, 2024
1 parent dda02b8 commit 5c45a5a
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 22 deletions.
38 changes: 20 additions & 18 deletions lib/chkname.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/

Expand All @@ -33,7 +34,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"


int allow_bad_names = false;
Expand All @@ -56,6 +60,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;
}
Expand All @@ -66,26 +82,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') ||
Expand All @@ -96,15 +104,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;
Expand Down
2 changes: 1 addition & 1 deletion src/newusers.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/pwck.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion src/useradd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/usermod.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 5c45a5a

Please sign in to comment.