Use flags to set which parts of a passwd entry are to be changed.
Before removing the home directory of a user check that + the user does not have uid 0 + the user is the owner of the directory. and remove the files using the effective user-id of the user. Show a warning if the directory is not removed. Use asprintf and fgetln for some string work to remove arbitary string length limitations. Fixes for PRs bin/11100 and bin/11103.
This commit is contained in:
parent
f9a49b32bf
commit
97c54a1bab
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: user.c,v 1.25 2000/10/11 20:23:58 is Exp $ */
|
||||
/* $NetBSD: user.c,v 1.26 2000/10/17 04:53:27 simonb Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1999 Alistair G. Crooks. All rights reserved.
|
||||
|
@ -33,10 +33,9 @@
|
|||
#include <sys/cdefs.h>
|
||||
|
||||
#ifndef lint
|
||||
__COPYRIGHT(
|
||||
"@(#) Copyright (c) 1999 \
|
||||
__COPYRIGHT("@(#) Copyright (c) 1999 \
|
||||
The NetBSD Foundation, Inc. All rights reserved.");
|
||||
__RCSID("$NetBSD: user.c,v 1.25 2000/10/11 20:23:58 is Exp $");
|
||||
__RCSID("$NetBSD: user.c,v 1.26 2000/10/17 04:53:27 simonb Exp $");
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
@ -61,6 +60,7 @@ __RCSID("$NetBSD: user.c,v 1.25 2000/10/11 20:23:58 is Exp $");
|
|||
#include "defs.h"
|
||||
#include "usermgmt.h"
|
||||
|
||||
|
||||
/* this struct describes a uid range */
|
||||
typedef struct range_t {
|
||||
int r_from; /* low uid */
|
||||
|
@ -69,10 +69,10 @@ typedef struct range_t {
|
|||
|
||||
/* this struct encapsulates the user information */
|
||||
typedef struct user_t {
|
||||
int u_flags; /* see below */
|
||||
int u_uid; /* uid of user */
|
||||
char *u_password; /* encrypted password */
|
||||
char *u_comment; /* comment field */
|
||||
int u_homeset; /* home dir has been set */
|
||||
char *u_home; /* home directory */
|
||||
char *u_primgrp; /* primary group */
|
||||
int u_groupc; /* # of secondary groups */
|
||||
|
@ -81,8 +81,6 @@ typedef struct user_t {
|
|||
char *u_basedir; /* base directory for home */
|
||||
char *u_expire; /* when password will expire */
|
||||
int u_inactive; /* inactive */
|
||||
int u_mkdir; /* make the home directory */
|
||||
int u_dupuid; /* duplicate uids are allowed */
|
||||
char *u_skeldir; /* directory for startup files */
|
||||
unsigned u_rsize; /* size of range array */
|
||||
unsigned u_rc; /* # of ranges */
|
||||
|
@ -91,6 +89,22 @@ typedef struct user_t {
|
|||
int u_preserve; /* preserve uids on deletion */
|
||||
} user_t;
|
||||
|
||||
/* flags for which fields of the user_t replace the passwd entry */
|
||||
enum {
|
||||
F_COMMENT = 0x0001,
|
||||
F_DUPUID = 0x0002,
|
||||
F_EXPIRE = 0x0004,
|
||||
F_GROUP = 0x0008,
|
||||
F_HOMEDIR = 0x0010,
|
||||
F_MKDIR = 0x0020,
|
||||
F_INACTIVE = 0x0040,
|
||||
F_PASSWORD = 0x0080,
|
||||
F_SECGROUP = 0x0100,
|
||||
F_SHELL = 0x0200,
|
||||
F_UID = 0x0400,
|
||||
F_USERNAME = 0x0800
|
||||
};
|
||||
|
||||
#define CONFFILE "/etc/usermgmt.conf"
|
||||
|
||||
#ifndef DEF_GROUP
|
||||
|
@ -198,6 +212,49 @@ asystem(const char *fmt, ...)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* remove a users home directory, returning 1 for success (ie, no problems encountered) */
|
||||
static int
|
||||
removehomedir(const char *user, int uid, const char *dir)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
/* userid not root? */
|
||||
if (uid == 0) {
|
||||
warnx("Not deleting home directory `%s'; userid is 0", dir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* directory exists (and is a directory!) */
|
||||
if (stat(dir, &st) < 0) {
|
||||
warnx("Home directory `%s' doesn't exist", dir);
|
||||
return 0;
|
||||
}
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
warnx("Home directory `%s' is not a directory", dir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* userid matches directory owner? */
|
||||
if (st.st_uid != uid) {
|
||||
warnx("User `%s' doesn't own directory `%s', not removed\n", user, dir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
(void) seteuid(uid);
|
||||
/* we add the "|| true" to keep asystem() quiet if there is a non-zero exit status. */
|
||||
#if 1
|
||||
printf("XXX: %s -rf %s > /dev/null 2>&1 || true", RM, dir);
|
||||
#else
|
||||
(void) asystem("%s -rf %s > /dev/null 2>&1 || true", RM, dir);
|
||||
(void) seteuid(0);
|
||||
if (rmdir(dir) < 0) {
|
||||
warnx("Unable to remove all files in `%s'\n", dir);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define NetBSD_1_4_K 104110000
|
||||
|
||||
#if defined(__NetBSD_Version__) && (__NetBSD_Version__ < NetBSD_1_4_K)
|
||||
|
@ -214,7 +271,75 @@ strlcpy(char *to, char *from, size_t tosize)
|
|||
to[n] = '\0';
|
||||
return fromsize;
|
||||
}
|
||||
#endif
|
||||
#endif /* NetBSD < 1.4K */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* research has shown that NetBSD 1.3H was the first version of -current
|
||||
* with asprintf in libc. agc
|
||||
*/
|
||||
#define NetBSD_1_3_H 103080000
|
||||
|
||||
#if defined(__NetBSD_Version__) && (__NetBSD_Version__ < NetBSD_1_3_H)
|
||||
|
||||
int
|
||||
asprintf(char **str, char const *fmt, ...)
|
||||
{
|
||||
int ret;
|
||||
va_list ap;
|
||||
FILE f;
|
||||
unsigned char *_base;
|
||||
|
||||
va_start(ap, fmt);
|
||||
f._flags = __SWR | __SSTR | __SALC;
|
||||
f._bf._base = f._p = (unsigned char *)malloc(128);
|
||||
if (f._bf._base == NULL)
|
||||
goto err;
|
||||
f._bf._size = f._w = 127; /* Leave room for the NUL */
|
||||
ret = vfprintf(&f, fmt, ap);
|
||||
if (ret == -1)
|
||||
goto err;
|
||||
*f._p = '\0';
|
||||
va_end(ap);
|
||||
_base = realloc(f._bf._base, (size_t)(ret + 1));
|
||||
if (_base == NULL)
|
||||
goto err;
|
||||
*str = (char *)_base;
|
||||
return (ret);
|
||||
|
||||
err:
|
||||
if (f._bf._base)
|
||||
free(f._bf._base);
|
||||
*str = NULL;
|
||||
return (-1);
|
||||
}
|
||||
#endif /* NetBSD < 1.3H */
|
||||
|
||||
/* return 1 if all of `s' is numeric */
|
||||
static int
|
||||
|
@ -464,8 +589,7 @@ append_group(char *user, int ngroups, char **groups)
|
|||
"%s%s\n",
|
||||
(buf[cc - 2] == ':') ? "" : ",",
|
||||
user)) < 0) {
|
||||
warnx(
|
||||
"Warning: group `%s' entry too long", groups[i]);
|
||||
warnx("Warning: group `%s' entry too long", groups[i]);
|
||||
}
|
||||
cc += nc - 1;
|
||||
}
|
||||
|
@ -767,7 +891,7 @@ adduser(char *login, user_t *up)
|
|||
}
|
||||
}
|
||||
/* check uid isn't already allocated */
|
||||
if (!up->u_dupuid && getpwuid((uid_t)(up->u_uid)) != NULL) {
|
||||
if (!(up->u_flags & F_DUPUID) && getpwuid((uid_t)(up->u_uid)) != NULL) {
|
||||
(void) close(ptmpfd);
|
||||
(void) pw_abort();
|
||||
errx(EXIT_FAILURE, "uid %d is already in use", up->u_uid);
|
||||
|
@ -791,12 +915,12 @@ adduser(char *login, user_t *up)
|
|||
errx(EXIT_FAILURE, "group %s not found", up->u_primgrp);
|
||||
}
|
||||
/* check name isn't already in use */
|
||||
if (!up->u_dupuid && getpwnam(login) != NULL) {
|
||||
if (!(up->u_flags & F_DUPUID) && getpwnam(login) != NULL) {
|
||||
(void) close(ptmpfd);
|
||||
(void) pw_abort();
|
||||
errx(EXIT_FAILURE, "already a `%s' user", login);
|
||||
}
|
||||
if (up->u_homeset) {
|
||||
if (up->u_flags & F_HOMEDIR) {
|
||||
(void) strlcpy(home, up->u_home, sizeof(home));
|
||||
} else {
|
||||
/* if home directory hasn't been given, make it up */
|
||||
|
@ -811,10 +935,9 @@ adduser(char *login, user_t *up)
|
|||
expire = mktime(&tm);
|
||||
}
|
||||
}
|
||||
if (lstat(home, &st) < 0 && !up->u_mkdir) {
|
||||
warnx(
|
||||
"Warning: home directory `%s' doesn't exist, and -m was not specified",
|
||||
home);
|
||||
if (lstat(home, &st) < 0 && !(up->u_flags & F_MKDIR)) {
|
||||
warnx("Warning: home directory `%s' doesn't exist, and -m was not specified",
|
||||
home);
|
||||
}
|
||||
password[PasswordLength] = '\0';
|
||||
if (up->u_password != NULL &&
|
||||
|
@ -842,7 +965,7 @@ adduser(char *login, user_t *up)
|
|||
(void) pw_abort();
|
||||
err(EXIT_FAILURE, "can't add `%s'", buf);
|
||||
}
|
||||
if (up->u_mkdir) {
|
||||
if (up->u_flags & F_MKDIR) {
|
||||
if (lstat(home, &st) < 0 && asystem("%s -p %s", MKDIR, home) != 0) {
|
||||
(void) close(ptmpfd);
|
||||
(void) pw_abort();
|
||||
|
@ -868,22 +991,14 @@ adduser(char *login, user_t *up)
|
|||
static int
|
||||
moduser(char *login, char *newlogin, user_t *up)
|
||||
{
|
||||
struct passwd *pwp;
|
||||
struct passwd *pwp, *newpwp;
|
||||
struct group *grp;
|
||||
struct tm tm;
|
||||
time_t expire;
|
||||
size_t loginc;
|
||||
size_t colonc;
|
||||
size_t colonc, len, loginc;
|
||||
FILE *master;
|
||||
char password[PasswordLength + 1];
|
||||
char oldhome[MaxFileNameLen];
|
||||
char home[MaxFileNameLen];
|
||||
char buf[MaxFileNameLen];
|
||||
char *colon;
|
||||
char *buf, *colon, *line;
|
||||
int masterfd;
|
||||
int ptmpfd;
|
||||
int gid;
|
||||
int cc;
|
||||
|
||||
if (!valid_login(newlogin)) {
|
||||
errx(EXIT_FAILURE, "`%s' is not a valid login name", login);
|
||||
|
@ -891,6 +1006,7 @@ moduser(char *login, char *newlogin, user_t *up)
|
|||
if ((pwp = getpwnam(login)) == NULL) {
|
||||
errx(EXIT_FAILURE, "No such user `%s'", login);
|
||||
}
|
||||
newpwp = pwp;
|
||||
if ((masterfd = open(_PATH_MASTERPASSWD, O_RDONLY)) < 0) {
|
||||
err(EXIT_FAILURE, "can't open `%s'", _PATH_MASTERPASSWD);
|
||||
}
|
||||
|
@ -909,112 +1025,112 @@ moduser(char *login, char *newlogin, user_t *up)
|
|||
err(EXIT_FAILURE, "can't fdopen fd for %s", _PATH_MASTERPASSWD);
|
||||
}
|
||||
if (up != NULL) {
|
||||
if (up->u_mkdir) {
|
||||
(void) strcpy(oldhome, pwp->pw_dir);
|
||||
}
|
||||
if (up->u_uid == -1) {
|
||||
up->u_uid = pwp->pw_uid;
|
||||
}
|
||||
/* if -g=uid was specified, check gid is unused */
|
||||
if (strcmp(up->u_primgrp, "=uid") == 0) {
|
||||
if (getgrgid((gid_t)(up->u_uid)) != NULL) {
|
||||
if (up->u_flags & F_USERNAME) {
|
||||
/* if changing name, check new name isn't already in use */
|
||||
if (strcmp(login, newlogin) != 0 && getpwnam(newlogin) != NULL) {
|
||||
(void) close(ptmpfd);
|
||||
(void) pw_abort();
|
||||
errx(EXIT_FAILURE, "gid %d is already in use", up->u_uid);
|
||||
errx(EXIT_FAILURE, "already a `%s' user", newlogin);
|
||||
}
|
||||
gid = up->u_uid;
|
||||
} else if ((grp = getgrnam(up->u_primgrp)) != NULL) {
|
||||
gid = grp->gr_gid;
|
||||
} else if (is_number(up->u_primgrp) &&
|
||||
(grp = getgrgid((gid_t)atoi(up->u_primgrp))) != NULL) {
|
||||
gid = grp->gr_gid;
|
||||
} else {
|
||||
(void) close(ptmpfd);
|
||||
(void) pw_abort();
|
||||
errx(EXIT_FAILURE, "group %s not found", up->u_primgrp);
|
||||
newpwp->pw_name = newlogin;
|
||||
}
|
||||
/* if changing name, check new name isn't already in use */
|
||||
if (strcmp(login, newlogin) != 0 && getpwnam(newlogin) != NULL) {
|
||||
(void) close(ptmpfd);
|
||||
(void) pw_abort();
|
||||
errx(EXIT_FAILURE, "already a `%s' user", newlogin);
|
||||
if (up->u_flags & F_PASSWORD) {
|
||||
if (up->u_password != NULL && strlen(up->u_password) == PasswordLength)
|
||||
newpwp->pw_passwd = up->u_password;
|
||||
}
|
||||
/* if home directory hasn't been given, use the old one */
|
||||
if (!up->u_homeset) {
|
||||
(void) strcpy(home, pwp->pw_dir);
|
||||
if (up->u_flags & F_UID) {
|
||||
/* check uid isn't already allocated */
|
||||
if (!(up->u_flags & F_DUPUID) && getpwuid((uid_t)(up->u_uid)) != NULL) {
|
||||
(void) close(ptmpfd);
|
||||
(void) pw_abort();
|
||||
errx(EXIT_FAILURE, "uid %d is already in use", up->u_uid);
|
||||
}
|
||||
newpwp->pw_uid = up->u_uid;
|
||||
}
|
||||
expire = 0;
|
||||
if (up->u_expire != NULL) {
|
||||
(void) memset(&tm, 0, sizeof(tm));
|
||||
if (strptime(up->u_expire, "%c", &tm) == NULL) {
|
||||
warnx("invalid time format `%s'", optarg);
|
||||
if (up->u_flags & F_GROUP) {
|
||||
/* if -g=uid was specified, check gid is unused */
|
||||
if (strcmp(up->u_primgrp, "=uid") == 0) {
|
||||
if (getgrgid((gid_t)(up->u_uid)) != NULL) {
|
||||
(void) close(ptmpfd);
|
||||
(void) pw_abort();
|
||||
errx(EXIT_FAILURE, "gid %d is already in use", up->u_uid);
|
||||
}
|
||||
newpwp->pw_gid = up->u_uid;
|
||||
} else if ((grp = getgrnam(up->u_primgrp)) != NULL) {
|
||||
newpwp->pw_gid = grp->gr_gid;
|
||||
} else if (is_number(up->u_primgrp) &&
|
||||
(grp = getgrgid((gid_t)atoi(up->u_primgrp))) != NULL) {
|
||||
newpwp->pw_gid = grp->gr_gid;
|
||||
} else {
|
||||
expire = mktime(&tm);
|
||||
(void) close(ptmpfd);
|
||||
(void) pw_abort();
|
||||
errx(EXIT_FAILURE, "group %s not found", up->u_primgrp);
|
||||
}
|
||||
}
|
||||
password[PasswordLength] = '\0';
|
||||
if (up->u_password != NULL &&
|
||||
strlen(up->u_password) == PasswordLength) {
|
||||
(void) memcpy(password, up->u_password, PasswordLength);
|
||||
} else {
|
||||
(void) memcpy(password, pwp->pw_passwd, PasswordLength);
|
||||
}
|
||||
if (strcmp(up->u_comment, DEF_COMMENT) == 0) {
|
||||
memsave(&up->u_comment, pwp->pw_gecos, strlen(pwp->pw_gecos));
|
||||
}
|
||||
if (strcmp(up->u_shell, DEF_SHELL) == 0 && strcmp(pwp->pw_shell, DEF_SHELL) != 0) {
|
||||
memsave(&up->u_shell, pwp->pw_shell, strlen(pwp->pw_shell));
|
||||
if (up->u_flags |= F_INACTIVE)
|
||||
newpwp->pw_change = up->u_inactive;
|
||||
if (up->u_flags & F_EXPIRE) {
|
||||
(void) memset(&tm, 0, sizeof(tm));
|
||||
if (strptime(up->u_expire, "%c", &tm) == NULL)
|
||||
warnx("invalid time format `%s'", optarg);
|
||||
else
|
||||
newpwp->pw_expire = mktime(&tm);
|
||||
}
|
||||
if (up->u_flags & F_COMMENT)
|
||||
newpwp->pw_gecos = up->u_comment;
|
||||
if (up->u_flags & F_HOMEDIR)
|
||||
newpwp->pw_dir = up->u_home;
|
||||
if (up->u_flags & F_SHELL)
|
||||
newpwp->pw_shell = up->u_shell;
|
||||
}
|
||||
loginc = strlen(login);
|
||||
while (fgets(buf, sizeof(buf), master) != NULL) {
|
||||
cc = strlen(buf);
|
||||
if ((colon = strchr(buf, ':')) == NULL) {
|
||||
warnx("Malformed entry `%s'. Skipping", buf);
|
||||
while ((line = fgetln(master, &len)) != NULL) {
|
||||
if ((colon = strchr(line, ':')) == NULL) {
|
||||
warnx("Malformed entry `%s'. Skipping", line);
|
||||
continue;
|
||||
}
|
||||
colonc = (size_t)(colon - buf);
|
||||
if (strncmp(login, buf, loginc) == 0 && loginc == colonc) {
|
||||
colonc = (size_t)(colon - line);
|
||||
if (strncmp(login, line, loginc) == 0 && loginc == colonc) {
|
||||
if (up != NULL) {
|
||||
cc = snprintf(buf, sizeof(buf), "%s:%s:%d:%d::%d:%ld:%s:%s:%s\n",
|
||||
len = (int)asprintf(&buf, "%s:%s:%d:%d::%d:%ld:%s:%s:%s\n",
|
||||
newlogin,
|
||||
password,
|
||||
up->u_uid,
|
||||
gid,
|
||||
up->u_inactive,
|
||||
(long) expire,
|
||||
up->u_comment,
|
||||
home,
|
||||
up->u_shell);
|
||||
if (write(ptmpfd, buf, (size_t) cc) != cc) {
|
||||
newpwp->pw_passwd,
|
||||
newpwp->pw_uid,
|
||||
newpwp->pw_gid,
|
||||
newpwp->pw_change,
|
||||
(long)newpwp->pw_expire,
|
||||
newpwp->pw_gecos,
|
||||
newpwp->pw_dir,
|
||||
newpwp->pw_shell);
|
||||
if (write(ptmpfd, buf, len) != len) {
|
||||
(void) close(ptmpfd);
|
||||
(void) pw_abort();
|
||||
err(EXIT_FAILURE, "can't add `%s'", buf);
|
||||
}
|
||||
}
|
||||
} else if (write(ptmpfd, buf, (size_t)(cc)) != cc) {
|
||||
/* } else if (write(ptmpfd, line, len) != len) { */
|
||||
} else if ((colonc = write(ptmpfd, line, len)) != len) {
|
||||
(void) close(masterfd);
|
||||
(void) close(ptmpfd);
|
||||
(void) pw_abort();
|
||||
err(EXIT_FAILURE,
|
||||
"short write to /etc/ptmp (not %d chars)",
|
||||
cc);
|
||||
err(EXIT_FAILURE, "short write to /etc/ptmp (%lld not %lld chars)",
|
||||
(long long)colonc,
|
||||
(long long)len);
|
||||
}
|
||||
}
|
||||
if (up != NULL) {
|
||||
if (up->u_mkdir &&
|
||||
asystem("%s %s %s", MV, oldhome, home) != 0) {
|
||||
if ((up->u_flags & F_MKDIR) &&
|
||||
asystem("%s %s %s", MV, pwp->pw_dir, newpwp->pw_dir) != 0) {
|
||||
(void) close(ptmpfd);
|
||||
(void) pw_abort();
|
||||
err(EXIT_FAILURE, "can't move `%s' to `%s'",
|
||||
oldhome, home);
|
||||
pwp->pw_dir, newpwp->pw_dir);
|
||||
}
|
||||
if (up->u_groupc > 0 &&
|
||||
!append_group(newlogin, up->u_groupc, up->u_groupv)) {
|
||||
(void) close(ptmpfd);
|
||||
(void) pw_abort();
|
||||
errx(EXIT_FAILURE,
|
||||
"can't append `%s' to new groups",
|
||||
errx(EXIT_FAILURE, "can't append `%s' to new groups",
|
||||
newlogin);
|
||||
}
|
||||
}
|
||||
|
@ -1150,8 +1266,8 @@ useradd(int argc, char **argv)
|
|||
memsave(&u.u_comment, optarg, strlen(optarg));
|
||||
break;
|
||||
case 'd':
|
||||
u.u_homeset = 1;
|
||||
memsave(&u.u_home, optarg, strlen(optarg));
|
||||
u.u_flags |= (F_MKDIR | F_HOMEDIR);
|
||||
break;
|
||||
case 'e':
|
||||
defaultfield = 1;
|
||||
|
@ -1169,10 +1285,10 @@ useradd(int argc, char **argv)
|
|||
memsave(&u.u_skeldir, optarg, strlen(optarg));
|
||||
break;
|
||||
case 'm':
|
||||
u.u_mkdir = 1;
|
||||
u.u_flags |= F_MKDIR;
|
||||
break;
|
||||
case 'o':
|
||||
u.u_dupuid = 1;
|
||||
u.u_flags |= F_DUPUID;
|
||||
break;
|
||||
#ifdef EXTENSIONS
|
||||
case 'p':
|
||||
|
@ -1238,13 +1354,11 @@ usermod(int argc, char **argv)
|
|||
{
|
||||
user_t u;
|
||||
char newuser[MaxUserNameLen + 1];
|
||||
int have_new_user;
|
||||
int c;
|
||||
int c, have_new_user;
|
||||
|
||||
(void) memset(&u, 0, sizeof(u));
|
||||
(void) memset(newuser, 0, sizeof(newuser));
|
||||
read_defaults(&u);
|
||||
u.u_uid = -1;
|
||||
have_new_user = 0;
|
||||
while ((c = getopt(argc, argv, "G:c:d:e:f:g:l:mos:u:" MOD_OPT_EXTENSIONS)) != -1) {
|
||||
switch(c) {
|
||||
|
@ -1258,46 +1372,55 @@ usermod(int argc, char **argv)
|
|||
if (optarg != NULL) {
|
||||
warnx("Truncated list of secondary groups to %d entries", NGROUPS_MAX);
|
||||
}
|
||||
u.u_flags |= F_SECGROUP;
|
||||
break;
|
||||
case 'c':
|
||||
memsave(&u.u_comment, optarg, strlen(optarg));
|
||||
u.u_flags |= F_COMMENT;
|
||||
break;
|
||||
case 'd':
|
||||
u.u_homeset = 1;
|
||||
memsave(&u.u_home, optarg, strlen(optarg));
|
||||
u.u_flags |= (F_MKDIR | F_HOMEDIR);
|
||||
break;
|
||||
case 'e':
|
||||
memsave(&u.u_expire, optarg, strlen(optarg));
|
||||
u.u_flags |= F_EXPIRE;
|
||||
break;
|
||||
case 'f':
|
||||
u.u_inactive = atoi(optarg);
|
||||
u.u_flags |= F_INACTIVE;
|
||||
break;
|
||||
case 'g':
|
||||
memsave(&u.u_primgrp, optarg, strlen(optarg));
|
||||
u.u_flags |= F_GROUP;
|
||||
break;
|
||||
case 'l':
|
||||
have_new_user = 1;
|
||||
(void) strlcpy(newuser, optarg, sizeof(newuser));
|
||||
have_new_user = 1;
|
||||
u.u_flags |= F_USERNAME;
|
||||
break;
|
||||
case 'm':
|
||||
u.u_mkdir = 1;
|
||||
u.u_flags |= F_MKDIR;
|
||||
break;
|
||||
case 'o':
|
||||
u.u_dupuid = 1;
|
||||
u.u_flags |= F_DUPUID;
|
||||
break;
|
||||
#ifdef EXTENSIONS
|
||||
case 'p':
|
||||
memsave(&u.u_password, optarg, strlen(optarg));
|
||||
u.u_flags |= F_PASSWORD;
|
||||
break;
|
||||
#endif
|
||||
case 's':
|
||||
memsave(&u.u_shell, optarg, strlen(optarg));
|
||||
u.u_flags |= F_SHELL;
|
||||
break;
|
||||
case 'u':
|
||||
if (!is_number(optarg)) {
|
||||
errx(EXIT_FAILURE, "When using [-u uid], the uid must be numeric");
|
||||
}
|
||||
u.u_uid = atoi(optarg);
|
||||
u.u_flags |= F_UID;
|
||||
break;
|
||||
#ifdef EXTENSIONS
|
||||
case 'v':
|
||||
|
@ -1323,7 +1446,6 @@ int
|
|||
userdel(int argc, char **argv)
|
||||
{
|
||||
struct passwd *pwp;
|
||||
struct stat st;
|
||||
user_t u;
|
||||
char password[PasswordLength + 1];
|
||||
int defaultfield;
|
||||
|
@ -1377,18 +1499,14 @@ userdel(int argc, char **argv)
|
|||
warnx("No such user `%s'", argv[optind]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (rmhome) {
|
||||
if (stat(pwp->pw_dir, &st) < 0) {
|
||||
warn("Home directory `%s' does not exist", pwp->pw_dir);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
(void) asystem("%s -rf %s", RM, pwp->pw_dir);
|
||||
}
|
||||
if (rmhome)
|
||||
(void)removehomedir(pwp->pw_name, pwp->pw_uid, pwp->pw_dir);
|
||||
if (u.u_preserve) {
|
||||
memsave(&u.u_shell, NOLOGIN, strlen(NOLOGIN));
|
||||
(void) memset(password, '*', PasswordLength);
|
||||
password[PasswordLength] = '\0';
|
||||
memsave(&u.u_password, password, PasswordLength);
|
||||
u.u_flags |= F_PASSWORD;
|
||||
return moduser(argv[optind], argv[optind], &u) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
return moduser(argv[optind], argv[optind], NULL) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
|
|
Loading…
Reference in New Issue