group IDs.
* NEWS, src/grpck.c, src/pwck.c: Issue a warning if an ID is set
to -1.
+ * NEWS, src/newusers.c, src/usermod.c, src/useradd.c,
+ src/groupmod.c, src/groupadd.c: Make sure no user or group are
+ created with an ID set to -1.
2009-03-07 Nicolas François <nicolas.francois@centraliens.net>
* Copyright (c) 1991 - 1993, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2000 - 2006, Tomasz Kłoczko
- * Copyright (c) 2007 - 2008, Nicolas François
+ * Copyright (c) 2007 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
static void check_new_name (void);
static void close_files (void);
static void open_files (void);
-static gid_t get_gid (const char *gidstr);
static void process_flags (int argc, char **argv);
static void check_flags (void);
static void check_perms (void);
#endif /* SHADOWGRP */
}
-/*
- * get_id - validate and get group ID
- */
-static gid_t get_gid (const char *gidstr)
-{
- long val;
- char *errptr;
-
- val = strtol (gidstr, &errptr, 10);
- if (('\0' != *errptr) || (errno == ERANGE) || (val < 0)) {
- fprintf (stderr, _("%s: invalid numeric argument '%s'\n"),
- Prog, gidstr);
- exit (E_BAD_ARG);
- }
- return (gid_t) val;
-}
-
/*
* process_flags - parse the command line options
*
break;
case 'g':
gflg = true;
- group_id = get_gid (optarg);
+ if ( (get_gid (optarg, &group_id) == 0)
+ || (group_id == (gid_t)-1)) {
+ fprintf (stderr,
+ _("%s: invalid group ID '%s'\n"),
+ Prog, optarg);
+ exit (E_BAD_ARG);
+ }
break;
case 'h':
usage ();
* Copyright (c) 1991 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2000 - 2006, Tomasz Kłoczko
- * Copyright (c) 2007 - 2008, Nicolas François
+ * Copyright (c) 2007 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
static void prepare_failure_reports (void);
static void open_files (void);
static void close_files (void);
-static gid_t get_gid (const char *gidstr);
static void update_primary_groups (gid_t ogid, gid_t ngid);
/*
exit (E_BAD_ARG);
}
-/*
- * get_id - validate and get group ID
- */
-static gid_t get_gid (const char *gidstr)
-{
- long val;
- char *errptr;
-
- val = strtol (gidstr, &errptr, 10); /* FIXME: Should be strtoul ? */
- if (('\0' != *errptr) || (ERANGE == errno) || (val < 0)) {
- fprintf (stderr,
- _("%s: invalid numeric argument '%s'\n"),
- Prog, gidstr);
- exit (E_BAD_ARG);
- }
- return (gid_t) val;
-}
-
/*
* process_flags - perform command line argument setting
*
switch (c) {
case 'g':
gflg = true;
- group_newid = get_gid (optarg);
+ if ( (get_gid (optarg, &group_newid) == 0)
+ || (group_newid == (gid_t)-1)) {
+ fprintf (stderr,
+ _("%s: invalid group ID '%s'\n"),
+ Prog, optarg);
+ exit (E_BAD_ARG);
+ }
break;
case 'n':
nflg = true;
* Copyright (c) 1990 - 1993, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2000 - 2006, Tomasz Kłoczko
- * Copyright (c) 2007 - 2008, Nicolas François
+ * Copyright (c) 2007 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
static void usage (void);
static void fail_exit (int);
static int add_group (const char *, const char *, gid_t *, gid_t);
-static int get_uid (const char *, uid_t *);
+static int get_user_id (const char *, uid_t *);
static int add_user (const char *, uid_t, gid_t);
static void update_passwd (struct passwd *, const char *);
static int add_passwd (struct passwd *, const char *);
* The GID is a number, which means either this is a brand
* new group, or an existing group.
*/
- char *endptr;
- unsigned long int i = strtoul (gid, &endptr, 10);
- if ((*endptr != '\0') || (ERANGE == errno)) {
+
+ if (get_gid (gid, &grent.gr_gid) == 0) {
fprintf (stderr,
- _("%s: group ID '%s' is not valid\n"),
+ _("%s: invalid group ID '%s'\n"),
Prog, gid);
return -1;
}
+
/* Look in both the system database (getgrgid) and in the
* internal database (gr_locate_gid), which may contain
* uncommitted changes */
- if ( (getgrgid ((gid_t) i) != NULL)
- || (gr_locate_gid ((gid_t) i) != NULL)) {
+ if ( (getgrgid ((gid_t) grent.gr_gid) != NULL)
+ || (gr_locate_gid ((gid_t) grent.gr_gid) != NULL)) {
/* The user will use this ID for her
* primary group */
- *ngid = (gid_t) i;
+ *ngid = (gid_t) grent.gr_gid;
return 0;
}
- grent.gr_gid = (gid_t) i;
+
+ /* Do not create groups with GID == (gid_t)-1 */
+ if (grent.gr_gid == (gid_t)-1) {
+ fprintf (stderr,
+ _("%s: invalid group ID '%s'\n"),
+ Prog, gid);
+ return -1;
+ }
} else {
/* The gid parameter can be "" or a name which is not
* already the name of an existing group.
return 0;
}
-static int get_uid (const char *uid, uid_t *nuid) {
+static int get_user_id (const char *uid, uid_t *nuid) {
/*
* The first guess for the UID is either the numerical UID that the
* caller provided, or the next available UID.
*/
if (isdigit (uid[0])) {
- char *endptr;
- unsigned long int i = strtoul (uid, &endptr, 10);
- if (('\0' != *endptr) || (ERANGE == errno)) {
+ if ((get_uid (uid, nuid) == 0) || (*nuid == (uid_t)-1)) {
fprintf (stderr,
- _("%s: user ID '%s' is not valid\n"),
+ _("%s: invalid user ID '%s'\n"),
Prog, uid);
return -1;
}
- *nuid = (uid_t) i;
} else {
if ('\0' != uid[0]) {
const struct passwd *pwd;
}
if ( (NULL == pw)
- && (get_uid (fields[2], &uid) != 0)) {
+ && (get_user_id (fields[2], &uid) != 0)) {
fprintf (stderr,
_("%s: line %d: can't create user\n"),
Prog, line);
* Copyright (c) 1991 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2000 - 2006, Tomasz Kłoczko
- * Copyright (c) 2007 - 2008, Nicolas François
+ * Copyright (c) 2007 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
static void fail_exit (int);
static struct group *getgr_nam_gid (const char *);
static long get_number (const char *);
-static uid_t get_uid (const char *);
static void get_defaults (void);
static void show_defaults (void);
static int set_defaults (void);
static struct group *getgr_nam_gid (const char *grname)
{
- long gid;
- char *errptr;
-
- gid = strtol (grname, &errptr, 10);
- if (*grname != '\0' && *errptr == '\0' && errno != ERANGE && gid >= 0) {
+ long long int gid;
+ char *endptr;
+
+ errno = 0;
+ gid = strtoll (grname, &errptr, 10);
+ if ( ('\0' != *grname)
+ && ('\0' == *endptr)
+ && (ERANGE != errno)
+ && (gid == (gid_t)gid)) {
return xgetgrgid ((gid_t) gid);
}
return xgetgrnam (grname);
char *errptr;
val = strtol (numstr, &errptr, 10);
- if (('\0' != *errptr) || (ERANGE == errno)) {
- fprintf (stderr, _("%s: invalid numeric argument '%s'\n"), Prog,
- numstr);
- exit (E_BAD_ARG);
- }
- return val;
-}
-
-static uid_t get_uid (const char *uidstr)
-{
- long val;
- char *errptr;
-
- val = strtol (uidstr, &errptr, 10);
- if (('\0' != *errptr) || (ERANGE == errno) || (val < 0)) {
+ if (('\0' == *numstr) || ('\0' != *errptr) || (ERANGE == errno)) {
fprintf (stderr,
- _("%s: invalid numeric argument '%s'\n"), Prog,
- uidstr);
+ _("%s: invalid numeric argument '%s'\n"),
+ Prog, numstr);
exit (E_BAD_ARG);
}
- return (uid_t) val;
+ return val;
}
#define MATCH(x,y) (strncmp((x),(y),strlen(y)) == 0)
* Primary GROUP identifier
*/
if (MATCH (buf, DGROUP)) {
- unsigned int val = (unsigned int) strtoul (cp, &ep, 10);
- const struct group *grp;
-
- if (*cp != '\0' && *ep == '\0') { /* valid number */
- def_group = val;
- /* local, no need for xgetgrgid */
- grp = getgrgid (def_group);
- if (NULL != grp) {
- def_gname = xstrdup (grp->gr_name);
- } else {
- fprintf (stderr,
- _("%s: GID '%s' does not exist\n"),
- Prog, cp);
- }
- /* local, no need for xgetgrnam */
- } else if ((grp = getgrnam (cp)) != NULL) {
- def_group = grp->gr_gid;
- def_gname = xstrdup (cp);
- } else {
+ const struct group *grp = getgr_nam_gid (cp);
+ if (NULL == grp) {
fprintf (stderr,
- _("%s: group '%s' does not exist\n"), Prog, cp);
+ _("%s: group '%s' does not exist\n"),
+ Prog, cp);
+ } else {
+ def_group = grp->gr_gid;
+ def_gname = xstrdup (grp->gr_name);
}
}
else if (MATCH (buf, INACT)) {
long val = strtol (cp, &ep, 10);
- if (('\0' != *cp) || (ERANGE == errno)) {
+ if ( ('\0' != *cp)
+ && ('\0' == *ep)
+ && (ERANGE != errno)
+ && (val >= 0)) {
def_inactive = val;
} else {
def_inactive = -1;
sflg = true;
break;
case 'u':
- user_id = get_uid (optarg);
+ if ( (get_uid (optarg, &user_id) == 0)
+ || (user_id == (gid_t)-1)) {
+ fprintf (stderr,
+ _("%s: invalid user ID '%s'\n"),
+ Prog, optarg);
+ exit (E_BAD_ARG);
+ }
uflg = true;
break;
case 'U':
* Copyright (c) 1991 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2000 - 2006, Tomasz Kłoczko
- * Copyright (c) 2007 - 2008, Nicolas François
+ * Copyright (c) 2007 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
static void grp_update (void);
static long get_number (const char *);
-static uid_t get_id (const char *);
static void process_flags (int, char **);
static void close_files (void);
static void open_files (void);
*/
static struct group *getgr_nam_gid (const char *grname)
{
- long val;
- char *errptr;
-
- val = strtol (grname, &errptr, 10);
- if (*grname != '\0' && *errptr == '\0' && errno != ERANGE && val >= 0) {
+ long long int val;
+ char *endptr;
+
+ errno = 0;
+ val = strtoll (grname, &errptr, 10);
+ if ( ('\0' != *grname)
+ && ('\0' == *endptr)
+ && (ERANGE != errno)
+ && (val == (gid_t)val)) {
return xgetgrgid ((gid_t) val);
}
return xgetgrnam (grname);
return val;
}
-static uid_t get_id (const char *uidstr)
-{
- long val;
- char *errptr;
-
- val = strtol (uidstr, &errptr, 10);
- if (('\0' != *errptr) || (ERANGE == errno) || (val < 0)) {
- fprintf (stderr, _("%s: invalid numeric argument '%s'\n"), Prog,
- uidstr);
- exit (E_BAD_ARG);
- }
- return (uid_t) val;
-}
-
/*
* process_flags - perform command line argument setting
*
sflg = true;
break;
case 'u':
- user_newid = get_id (optarg);
+ if ( (get_uid (optarg, &user_newid) ==0)
+ || (user_newid == (uid_t)-1)) {
+ fprintf (stderr,
+ _("%s: invalid user ID '%s'\n"),
+ Prog, optarg);
+ exit (E_BAD_ARG);
+ }
uflg = true;
break;
case 'U':