diff --git a/libmisc/chkname.c b/libmisc/chkname.c
index 64f5580c..bdd1e72a 100644
--- a/libmisc/chkname.c
+++ b/libmisc/chkname.c
@@ -46,11 +46,18 @@
#include "defines.h"
#include "chkname.h"
+int allow_bad_names = false;
+
static bool is_valid_name (const char *name)
{
+ if (allow_bad_names) {
+ return true;
+ }
+
/*
* User/group names must match [a-z_][a-z0-9_-]*[$]
*/
+
if (('\0' == *name) ||
!((('a' <= *name) && ('z' >= *name)) || ('_' == *name))) {
return false;
diff --git a/man/newusers.8.xml b/man/newusers.8.xml
index ff6dc1c3..a1029a27 100644
--- a/man/newusers.8.xml
+++ b/man/newusers.8.xml
@@ -266,6 +266,18 @@
The options which apply to the newusers command are:
+
+
+
+
+
+
+
+ Allow names that do not conform to standards.
+
+
+
+
,
diff --git a/man/pwck.8.xml b/man/pwck.8.xml
index 25952df5..bc99605f 100644
--- a/man/pwck.8.xml
+++ b/man/pwck.8.xml
@@ -182,6 +182,16 @@
The options which apply to the pwck command are:
+
+
+
+
+
+
+ Allow names that do not conform to standards.
+
+
+
,
diff --git a/man/useradd.8.xml b/man/useradd.8.xml
index 59e53c1f..a16d7307 100644
--- a/man/useradd.8.xml
+++ b/man/useradd.8.xml
@@ -126,6 +126,16 @@
The options which apply to the useradd command are:
+
+
+
+
+
+
+ Allow names that do not conform to standards.
+
+
+
, BASE_DIR
diff --git a/man/usermod.8.xml b/man/usermod.8.xml
index bb8312db..81a99592 100644
--- a/man/usermod.8.xml
+++ b/man/usermod.8.xml
@@ -108,6 +108,26 @@
+
+
+ ,
+
+
+
+ Allow names that do not conform to standards.
+
+
+
+
+
+ ,
+
+
+
+ Allow names that do not conform to standards.
+
+
+
, COMMENT
diff --git a/src/newusers.c b/src/newusers.c
index 7c3bb1c2..bf63f4b5 100644
--- a/src/newusers.c
+++ b/src/newusers.c
@@ -117,6 +117,8 @@ static void check_perms (void);
static void open_files (void);
static void close_files (void);
+extern int allow_bad_names;
+
/*
* usage - display usage message and exit
*/
@@ -128,6 +130,7 @@ static void usage (int status)
"\n"
"Options:\n"),
Prog);
+ (void) fputs (_(" -b, --badnames allow bad names\n"), usageout);
#ifndef USE_PAM
(void) fprintf (usageout,
_(" -c, --crypt-method METHOD the crypt method (one of %s)\n"),
@@ -580,6 +583,7 @@ static void process_flags (int argc, char **argv)
{
int c;
static struct option long_options[] = {
+ {"badnames", no_argument, NULL, 'b'},
#ifndef USE_PAM
{"crypt-method", required_argument, NULL, 'c'},
#endif /* !USE_PAM */
@@ -597,15 +601,18 @@ static void process_flags (int argc, char **argv)
while ((c = getopt_long (argc, argv,
#ifndef USE_PAM
#ifdef USE_SHA_CRYPT
- "c:hrs:",
+ "c:bhrs:",
#else /* !USE_SHA_CRYPT */
- "c:hr",
+ "c:bhr",
#endif /* !USE_SHA_CRYPT */
#else /* USE_PAM */
- "hr",
+ "bhr",
#endif
long_options, NULL)) != -1) {
switch (c) {
+ case 'b':
+ allow_bad_names = true;
+ break;
#ifndef USE_PAM
case 'c':
crypt_method = optarg;
diff --git a/src/pwck.c b/src/pwck.c
index f022e473..c24524ce 100644
--- a/src/pwck.c
+++ b/src/pwck.c
@@ -95,6 +95,8 @@ static void close_files (bool changed);
static void check_pw_file (int *errors, bool *changed);
static void check_spw_file (int *errors, bool *changed);
+extern int allow_bad_names;
+
/*
* fail_exit - do some cleanup and exit with the given error code
*/
@@ -148,6 +150,7 @@ static /*@noreturn@*/void usage (int status)
"Options:\n"),
Prog);
}
+ (void) fputs (_(" -b, --badnames allow bad names\n"), usageout);
(void) fputs (_(" -h, --help display this help message and exit\n"), usageout);
(void) fputs (_(" -q, --quiet report errors only\n"), usageout);
(void) fputs (_(" -r, --read-only display errors and warnings\n"
@@ -172,6 +175,7 @@ static void process_flags (int argc, char **argv)
{
int c;
static struct option long_options[] = {
+ {"badnames", no_argument, NULL, 'b'},
{"help", no_argument, NULL, 'h'},
{"quiet", no_argument, NULL, 'q'},
{"read-only", no_argument, NULL, 'r'},
@@ -183,9 +187,12 @@ static void process_flags (int argc, char **argv)
/*
* Parse the command line arguments
*/
- while ((c = getopt_long (argc, argv, "ehqrR:s",
+ while ((c = getopt_long (argc, argv, "behqrR:s",
long_options, NULL)) != -1) {
switch (c) {
+ case 'b':
+ allow_bad_names = true;
+ break;
case 'h':
usage (E_SUCCESS);
/*@notreached@*/break;
@@ -481,6 +488,7 @@ static void check_pw_file (int *errors, bool *changed)
/*
* Check for invalid usernames. --marekm
*/
+
if (!is_valid_user_name (pwd->pw_name)) {
printf (_("invalid user name '%s'\n"), pwd->pw_name);
*errors += 1;
diff --git a/src/useradd.c b/src/useradd.c
index 94835e93..3e22dbf7 100644
--- a/src/useradd.c
+++ b/src/useradd.c
@@ -148,6 +148,8 @@ static char **user_groups; /* NULL-terminated list */
static long sys_ngroups;
static bool do_grp_update = false; /* group files need to be updated */
+extern int allow_bad_names;
+
static bool
bflg = false, /* new default root of home directory */
cflg = false, /* comment (GECOS) field for new account */
@@ -821,6 +823,7 @@ static void usage (int status)
"\n"
"Options:\n"),
Prog, Prog, Prog);
+ (void) fputs (_(" --badnames do not check for bad names\n"), usageout);
(void) fputs (_(" -b, --base-dir BASE_DIR base directory for the home directory of the\n"
" new account\n"), usageout);
#ifdef WITH_BTRFS
@@ -1109,6 +1112,7 @@ static void process_flags (int argc, char **argv)
#ifdef WITH_BTRFS
{"btrfs-subvolume-home", no_argument, NULL, 200},
#endif
+ {"badnames", no_argument, NULL, 201},
{"comment", required_argument, NULL, 'c'},
{"home-dir", required_argument, NULL, 'd'},
{"defaults", no_argument, NULL, 'D'},
@@ -1158,6 +1162,9 @@ static void process_flags (int argc, char **argv)
case 200:
subvolflg = true;
break;
+ case 201:
+ allow_bad_names = true;
+ break;
case 'c':
if (!VALID (optarg)) {
fprintf (stderr,
diff --git a/src/usermod.c b/src/usermod.c
index 0ae50e34..05b98715 100644
--- a/src/usermod.c
+++ b/src/usermod.c
@@ -206,6 +206,8 @@ static void update_faillog (void);
static void move_mailbox (void);
#endif
+extern int allow_bad_names;
+
static void date_to_str (/*@unique@*//*@out@*/char *buf, size_t maxsize,
long int date)
{
@@ -408,6 +410,7 @@ static /*@noreturn@*/void usage (int status)
"\n"
"Options:\n"),
Prog);
+ (void) fputs (_(" -b, --badnames allow bad names\n"), usageout);
(void) fputs (_(" -c, --comment COMMENT new value of the GECOS field\n"), usageout);
(void) fputs (_(" -d, --home HOME_DIR new home directory for the user account\n"), usageout);
(void) fputs (_(" -e, --expiredate EXPIRE_DATE set account expiration date to EXPIRE_DATE\n"), usageout);
@@ -991,6 +994,7 @@ static void process_flags (int argc, char **argv)
int c;
static struct option long_options[] = {
{"append", no_argument, NULL, 'a'},
+ {"badnames", no_argument, NULL, 'b'},
{"comment", required_argument, NULL, 'c'},
{"home", required_argument, NULL, 'd'},
{"expiredate", required_argument, NULL, 'e'},
@@ -1020,7 +1024,7 @@ static void process_flags (int argc, char **argv)
{NULL, 0, NULL, '\0'}
};
while ((c = getopt_long (argc, argv,
- "ac:d:e:f:g:G:hl:Lmop:R:s:u:UP:"
+ "abc:d:e:f:g:G:hl:Lmop:R:s:u:UP:"
#ifdef ENABLE_SUBIDS
"v:w:V:W:"
#endif /* ENABLE_SUBIDS */
@@ -1032,6 +1036,9 @@ static void process_flags (int argc, char **argv)
case 'a':
aflg = true;
break;
+ case 'b':
+ allow_bad_names = true;
+ break;
case 'c':
if (!VALID (optarg)) {
fprintf (stderr,