Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 25aea74

Browse files
alejandro-colomarhallyn
authored andcommitted
lib/chkname.c, src/: Strictly disallow really bad names
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. - A leading '-' is too dangerous. It breaks things like execve(2), and almost every command. - Spaces are used for delimiting lists of users and groups. - '"' is special in many languages, including the shell. Having it in user names would be unnecessarily dangerous. - '#' is used for delimiting comments in several of our config files. Having it in usernames could result in incorrect configuration files. - "'" is special in many languages, including the shell. Having it in user names would be unnecessarily dangerous. - ',' is used for delimiting lists of users and groups. - '/' is used for delimiting files, and thus could result in incorrect handling of users and groups. - ':' is the main delimiter in /etc/shadow and /etc/passwd. - ';' is special in many languages, including the shell. Having it in user names would be unnecessarily dangerous. There are other characters that we should disallow, but they need more research to make sure we don't introduce regressions. This set should be less problematic. Acked-by: Tobias Stoeckmann <[email protected]> Reviewed-by: Iker Pedrosa <[email protected]> Reviewed-by: Chris Hofstaedtler <[email protected]> Cc: Marc 'Zugschlus' Haber <[email protected]> Cc: Serge Hallyn <[email protected]> Signed-off-by: Alejandro Colomar <[email protected]>
1 parent 9f8cf33 commit 25aea74

5 files changed

Lines changed: 24 additions & 18 deletions

File tree

lib/chkname.c

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
* true - OK
1414
* false - bad name
1515
* errors:
16-
* EINVAL Invalid name characters or sequences
16+
* EINVAL Invalid name
17+
* EILSEQ Invalid name character sequence (acceptable with --badname)
1718
* EOVERFLOW Name longer than maximum size
1819
*/
1920

@@ -27,12 +28,15 @@
2728
#include <limits.h>
2829
#include <stdbool.h>
2930
#include <stddef.h>
31+
#include <string.h>
3032
#include <unistd.h>
3133

3234
#include "defines.h"
3335
#include "chkname.h"
36+
#include "string/ctype/strchrisascii/strchriscntrl.h"
3437
#include "string/ctype/strisascii/strisdigit.h"
3538
#include "string/strcmp/streq.h"
39+
#include "string/strcmp/strcaseeq.h"
3640

3741

3842
#ifndef LOGIN_NAME_MAX
@@ -59,6 +63,18 @@ login_name_max_size(void)
5963
static bool
6064
is_valid_name(const char *name)
6165
{
66+
if (streq(name, "")
67+
|| streq(name, ".")
68+
|| streq(name, "..")
69+
|| strspn(name, "-")
70+
|| strpbrk(name, " \"#',/:;")
71+
|| strchriscntrl(name)
72+
|| strisdigit(name))
73+
{
74+
errno = EINVAL;
75+
return false;
76+
}
77+
6278
if (allow_bad_names) {
6379
return true;
6480
}
@@ -69,25 +85,15 @@ is_valid_name(const char *name)
6985
*
7086
* as a non-POSIX, extension, allow "$" as the last char for
7187
* sake of Samba 3.x "add machine script"
72-
*
73-
* Also do not allow fully numeric names or just "." or "..".
7488
*/
7589

76-
if (strisdigit(name)) {
77-
errno = EINVAL;
78-
return false;
79-
}
80-
81-
if (streq(name, "") ||
82-
streq(name, ".") ||
83-
streq(name, "..") ||
84-
!((*name >= 'a' && *name <= 'z') ||
90+
if (!((*name >= 'a' && *name <= 'z') ||
8591
(*name >= 'A' && *name <= 'Z') ||
8692
(*name >= '0' && *name <= '9') ||
8793
*name == '_' ||
8894
*name == '.'))
8995
{
90-
errno = EINVAL;
96+
errno = EILSEQ;
9197
return false;
9298
}
9399

@@ -101,7 +107,7 @@ is_valid_name(const char *name)
101107
streq(name, "$")
102108
))
103109
{
104-
errno = EINVAL;
110+
errno = EILSEQ;
105111
return false;
106112
}
107113
}

src/newusers.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ static int add_user (const char *name, uid_t uid, gid_t gid)
398398

399399
/* Check if this is a valid user name */
400400
if (!is_valid_user_name(name)) {
401-
if (errno == EINVAL) {
401+
if (errno == EILSEQ) {
402402
fprintf(stderr,
403403
_("%s: invalid user name '%s': use --badname to ignore\n"),
404404
Prog, name);

src/pwck.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,7 @@ static void check_pw_file(bool *errors, bool *changed, const struct option_flags
492492
*/
493493

494494
if (!is_valid_user_name(pwd->pw_name)) {
495-
if (errno == EINVAL) {
495+
if (errno == EILSEQ) {
496496
printf(_("invalid user name '%s': use --badname to ignore\n"),
497497
pwd->pw_name);
498498
} else {

src/useradd.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1498,7 +1498,7 @@ static void process_flags (int argc, char **argv, struct option_flags *flags)
14981498

14991499
user_name = argv[optind];
15001500
if (!is_valid_user_name(user_name)) {
1501-
if (errno == EINVAL) {
1501+
if (errno == EILSEQ) {
15021502
fprintf(stderr,
15031503
_("%s: invalid user name '%s': use --badname to ignore\n"),
15041504
Prog, user_name);

src/usermod.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1137,7 +1137,7 @@ process_flags(int argc, char **argv, struct option_flags *flags)
11371137
/*@notreached@*/break;
11381138
case 'l':
11391139
if (!is_valid_user_name(optarg)) {
1140-
if (errno == EINVAL) {
1140+
if (errno == EILSEQ) {
11411141
fprintf(stderr,
11421142
_("%s: invalid user name '%s': use --badname to ignore\n"),
11431143
Prog, optarg);

0 commit comments

Comments
 (0)