From 7fc68ddf208200ddeef6f09e60ab0fbf0e919fea Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Fri, 18 Sep 2015 17:38:27 +0300 Subject: [PATCH] 293 useradd/del/mod should be ZFS-aware Portions contributed by: Alexander Pyhalov Reviewed by: Toomas Soome Reviewed by: Peter Tribble Approved by: Dan McDonald --- usr/src/cmd/oamuser/user/Makefile | 10 +- usr/src/cmd/oamuser/user/funcs.h | 6 +- usr/src/cmd/oamuser/user/homedir.c | 294 ++++++++++++++++++++++++++++++----- usr/src/cmd/oamuser/user/messages.c | 7 +- usr/src/cmd/oamuser/user/messages.h | 7 + usr/src/cmd/oamuser/user/movedir.c | 7 +- usr/src/cmd/oamuser/user/rmfiles.c | 57 ------- usr/src/cmd/oamuser/user/useradd.c | 42 ++++- usr/src/cmd/oamuser/user/useradd.dfl | 5 + usr/src/cmd/oamuser/user/userdel.c | 116 +++++++------- usr/src/cmd/oamuser/user/usermod.c | 39 ++++- usr/src/man/man1m/useradd.1m | 23 +-- usr/src/man/man1m/userdel.1m | 20 ++- usr/src/man/man1m/usermod.1m | 36 +++-- 14 files changed, 465 insertions(+), 204 deletions(-) delete mode 100644 usr/src/cmd/oamuser/user/rmfiles.c diff --git a/usr/src/cmd/oamuser/user/Makefile b/usr/src/cmd/oamuser/user/Makefile index 61886b168b..a8feed2b6d 100644 --- a/usr/src/cmd/oamuser/user/Makefile +++ b/usr/src/cmd/oamuser/user/Makefile @@ -50,11 +50,11 @@ ADD_OBJ= useradd.o homedir.o groups.o call_pass.o \ userdefs.o messages.o val_lgrp.o funcs.o \ val_lprj.o proj.o -DEL_OBJ= userdel.o call_pass.o rmfiles.o isbusy.o \ +DEL_OBJ= userdel.o call_pass.o homedir.o isbusy.o \ groups.o messages.o funcs.o proj.o -MOD_OBJ= usermod.o movedir.o groups.o rmfiles.o \ - call_pass.o isbusy.o homedir.o userdefs.o \ +MOD_OBJ= usermod.o movedir.o groups.o homedir.o \ + call_pass.o isbusy.o userdefs.o \ messages.o val_lgrp.o funcs.o val_lprj.o \ proj.o @@ -90,11 +90,11 @@ $(USERDEL) := LIBS = $(LIBUSRGRP) $(USERMOD) := OBJS = $(MOD_OBJ) $(USERMOD) := LIBS = $(LIBUSRGRP) -LDLIBS += -lbsm -lnsl -lsecdb -lproject -ltsol +LDLIBS += -lbsm -lnsl -lsecdb -lproject -lzfs -ltsol .PARALLEL: $(OBJECTS) -all: $(PRODUCT) +all: $(PRODUCT) $(PROG): $$(OBJS) $$(LIBS) $(LINK.c) $(OBJS) -o $@ $(LIBS) $(LDLIBS) diff --git a/usr/src/cmd/oamuser/user/funcs.h b/usr/src/cmd/oamuser/user/funcs.h index a8d7a200e2..9437767ac4 100644 --- a/usr/src/cmd/oamuser/user/funcs.h +++ b/usr/src/cmd/oamuser/user/funcs.h @@ -24,8 +24,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #ifndef _FUNCS_H #define _FUNCS_H @@ -51,6 +49,10 @@ char *getsetdefval(const char *, char *); extern int nkeys; +/* create_home() or rm_files() flags */ +#define MANAGE_ZFS_OPT "MANAGE_ZFS=" +#define MANAGE_ZFS 1 + #ifdef __cplusplus } #endif diff --git a/usr/src/cmd/oamuser/user/homedir.c b/usr/src/cmd/oamuser/user/homedir.c index 1551c60125..a31ae0b9a2 100644 --- a/usr/src/cmd/oamuser/user/homedir.c +++ b/usr/src/cmd/oamuser/user/homedir.c @@ -29,84 +29,300 @@ /* All Rights Reserved */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include +#include #include #include #include #include +#include +#include +#include +#include +#include +#include +#include + +#include "funcs.h" #include "messages.h" -#define SBUFSZ 256 +#define SBUFSZ 256 + +#define DEFAULT_USERADD "/etc/default/useradd" -extern int rm_homedir(); +static int rm_homedir(); +static char *get_mnt_special(); static char cmdbuf[ SBUFSZ ]; /* buffer for system call */ +static char dhome[ PATH_MAX + 1 ]; /* buffer for dirname */ +static char bhome[ PATH_MAX + 1 ]; /* buffer for basename */ +static char pdir[ PATH_MAX + 1 ]; /* parent directory */ +static libzfs_handle_t *g_zfs = NULL; /* - Create a home directory and populate with files from skeleton - directory. -*/ + * Create a home directory and populate with files from skeleton + * directory. + */ int -create_home(char *homedir, char *skeldir, uid_t uid, gid_t gid) +create_home(char *homedir, char *skeldir, uid_t uid, gid_t gid, int flags) /* home directory to create */ /* skel directory to copy if indicated */ /* uid of new user */ /* group id of new user */ + /* miscellaneous flags */ { - if( mkdir(homedir, 0775) != 0 ) { - errmsg(M_OOPS, "create the home directory", strerror(errno)); - return( EX_HOMEDIR ); + struct stat stbuf; + char *dataset; + char *dname, *bname, *rp; + int created_fs = 0; + + rp = realpath(homedir, NULL); + if (rp && (strcmp(rp, "/") == 0)) { + return (EX_HOMEDIR); } - if( chown(homedir, uid, gid) != 0 ) { - errmsg(M_OOPS, "change ownership of home directory", + (void) strcpy(dhome, homedir); + (void) strcpy(bhome, homedir); + dname = dirname(dhome); + bname = basename(bhome); + (void) strcpy(pdir, dname); + + if ((stat(pdir, &stbuf) != 0) || !S_ISDIR(stbuf.st_mode)) { + errmsg(M_OOPS, "access the parent directory", strerror(errno)); + return (EX_HOMEDIR); + } + + if ((strcmp(stbuf.st_fstype, MNTTYPE_ZFS) == 0) && + (flags & MANAGE_ZFS)) { + if (g_zfs == NULL) + g_zfs = libzfs_init(); + if (g_zfs == NULL) { + errmsg(M_OOPS, "libzfs_init failure", strerror(errno)); + return (EX_HOMEDIR); + } + if ((dataset = get_mnt_special(pdir, stbuf.st_fstype)) + != NULL) { + char nm[ZFS_MAXNAMELEN]; + zfs_handle_t *zhp; + + (void) snprintf(nm, ZFS_MAXNAMELEN, "%s/%s", + dataset, bname); + + if ((zfs_create(g_zfs, nm, ZFS_TYPE_FILESYSTEM, NULL) + != 0) || + ((zhp = zfs_open(g_zfs, nm, ZFS_TYPE_FILESYSTEM)) == + NULL)) { + errmsg(M_OOPS, "create the home directory", + libzfs_error_description(g_zfs)); + libzfs_fini(g_zfs); + g_zfs = NULL; + return (EX_HOMEDIR); + } + + if (zfs_mount(zhp, NULL, 0) != 0) { + errmsg(M_OOPS, "mount the home directory", + libzfs_error_description(g_zfs)); + (void) zfs_destroy(zhp, B_FALSE); + zfs_close(zhp); + libzfs_fini(g_zfs); + g_zfs = NULL; + return (EX_HOMEDIR); + } + + zfs_close(zhp); + + if (chmod(homedir, + S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) != 0) { + errmsg(M_OOPS, + "change permissions of home directory", + strerror(errno)); + libzfs_fini(g_zfs); + g_zfs = NULL; + return (EX_HOMEDIR); + } + + created_fs = 1; + } else { + errmsg(M_NO_ZFS_MOUNTPOINT, pdir); + } + } + + if (!created_fs) { + if (mkdir(homedir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) + != 0) { + errmsg(M_OOPS, "create the home directory", + strerror(errno)); + if (g_zfs != NULL) { + libzfs_fini(g_zfs); + g_zfs = NULL; + } + return (EX_HOMEDIR); + } + } + + if (chown(homedir, uid, gid) != 0) { + errmsg(M_OOPS, "change ownership of home directory", strerror(errno)); - return( EX_HOMEDIR ); + if (g_zfs != NULL) { + libzfs_fini(g_zfs); + g_zfs = NULL; + } + return (EX_HOMEDIR); } - if(skeldir) { + if (skeldir != NULL) { /* copy the skel_dir into the home directory */ - (void) sprintf( cmdbuf, "cd %s && find . -print | cpio -pd %s", + (void) sprintf(cmdbuf, "cd %s && find . -print | cpio -pd %s", skeldir, homedir); - if( system( cmdbuf ) != 0 ) { + if (system(cmdbuf) != 0) { errmsg(M_OOPS, "copy skeleton directory into home " "directory", strerror(errno)); - (void) rm_homedir( homedir ); - return( EX_HOMEDIR ); + (void) rm_homedir(homedir, flags); + if (g_zfs != NULL) { + libzfs_fini(g_zfs); + g_zfs = NULL; + } + return (EX_HOMEDIR); } /* make sure contents in the home dirctory have correct owner */ - (void) sprintf( cmdbuf,"cd %s && find . -exec chown %ld {} \\;", - homedir, uid ); - if( system( cmdbuf ) != 0) { - errmsg(M_OOPS, "change owner of files home directory", + (void) sprintf(cmdbuf, + "cd %s && find . -exec chown %ld:%ld {} \\;", + homedir, uid, gid); + if (system(cmdbuf) != 0) { + errmsg(M_OOPS, + "change owner and group of files home directory", strerror(errno)); + (void) rm_homedir(homedir, flags); + if (g_zfs != NULL) { + libzfs_fini(g_zfs); + g_zfs = NULL; + } + return (EX_HOMEDIR); + } + + } + if (g_zfs != NULL) { + libzfs_fini(g_zfs); + g_zfs = NULL; + } + return (EX_SUCCESS); +} + +/* Remove a home directory structure */ +int +rm_homedir(char *dir, int flags) +{ + struct stat stbuf; + char *nm, *rp; - (void) rm_homedir( homedir ); - return( EX_HOMEDIR ); + rp = realpath(dir, NULL); + if (rp && (strcmp(rp, "/") == 0)) { + return (0); + } + + if ((stat(dir, &stbuf) != 0) || !S_ISDIR(stbuf.st_mode)) + return (0); + + if ((strcmp(stbuf.st_fstype, MNTTYPE_ZFS) == 0) && + (flags & MANAGE_ZFS)) { + if (g_zfs == NULL) + g_zfs = libzfs_init(); + + if (g_zfs == NULL) { + errmsg(M_OOPS, "libzfs_init failure", strerror(errno)); + return (EX_HOMEDIR); } - /* and group....... */ - (void) sprintf( cmdbuf, "cd %s && find . -exec chgrp %ld {} \\;", - homedir, gid ); - if( system( cmdbuf ) != 0) { - errmsg(M_OOPS, "change group of files home directory", - strerror(errno)); - (void) rm_homedir( homedir ); - return( EX_HOMEDIR ); + if ((nm = get_mnt_special(dir, stbuf.st_fstype)) != NULL) { + zfs_handle_t *zhp; + + if ((zhp = zfs_open(g_zfs, nm, ZFS_TYPE_FILESYSTEM)) + != NULL) { + if ((zfs_unmount(zhp, NULL, 0) == 0) && + (zfs_destroy(zhp, B_FALSE) == 0)) { + zfs_close(zhp); + libzfs_fini(g_zfs); + g_zfs = NULL; + return (0); + } + + errmsg(M_OOPS, "destroy the home directory", + libzfs_error_description(g_zfs)); + + (void) zfs_mount(zhp, NULL, 0); + zfs_close(zhp); + + libzfs_fini(g_zfs); + g_zfs = NULL; + return (EX_HOMEDIR); + } } } - return( EX_SUCCESS ); + + (void) sprintf(cmdbuf, "rm -rf %s", dir); + + if (g_zfs != NULL) { + libzfs_fini(g_zfs); + g_zfs = NULL; + } + + return (system(cmdbuf)); +} + +int +rm_files(char *homedir, char *user, int flags) +{ + if (rm_homedir(homedir, flags) != 0) { + errmsg(M_RMFILES); + return (EX_HOMEDIR); + } + + return (EX_SUCCESS); } -/* Remove a home directory structure */ int -rm_homedir(char *dir) +get_default_zfs_flags() +{ + int flags = 0; + + if (defopen(DEFAULT_USERADD) == 0) { + char *defptr; + + if ((defptr = defread(MANAGE_ZFS_OPT)) != NULL) { + char let = tolower(*defptr); + + switch (let) { + case 'y': /* yes */ + flags |= MANAGE_ZFS; + case 'n': /* no */ + break; + } + } + (void) defopen((char *)NULL); + } + return (flags); +} + +/* Get the name of a mounted filesytem */ +char * +get_mnt_special(char *mountp, char *fstype) { - (void) sprintf( cmdbuf, "rm -rf %s", dir ); - - return( system( cmdbuf ) ); + struct mnttab entry, search; + char *special = NULL; + FILE *fp; + + search.mnt_special = search.mnt_mntopts = search.mnt_time = NULL; + search.mnt_mountp = mountp; + search.mnt_fstype = fstype; + + if ((fp = fopen(MNTTAB, "r")) != NULL) { + if (getmntany(fp, &entry, &search) == 0) + special = entry.mnt_special; + + (void) fclose(fp); + } + + return (special); } diff --git a/usr/src/cmd/oamuser/user/messages.c b/usr/src/cmd/oamuser/user/messages.c index 512b123323..a0e0661a03 100644 --- a/usr/src/cmd/oamuser/user/messages.c +++ b/usr/src/cmd/oamuser/user/messages.c @@ -35,7 +35,8 @@ char *errmsgs[] = { "ERROR: invalid syntax.\n" "usage: useradd [-u uid [-o] | -g group | -G group[[,group]...] |" "-d dir | -b base_dir |\n" - "\t\t-s shell | -c comment | -m [-k skel_dir] | -f inactive |\n" + "\t\t-s shell | -c comment | -m [-z|Z] [-k skel_dir] |" + "-f inactive |\n" "\t\t-e expire | -A authorization [, authorization ...] |\n" "\t\t-P profile [, profile ...] | -R role [, role ...] |\n" "\t\t-K key=value | -p project [, project ...]] login\n" @@ -46,7 +47,7 @@ char *errmsgs[] = { "ERROR: Invalid syntax.\nusage: userdel [-r] login\n", "ERROR: Invalid syntax.\n" "usage: usermod -u uid [-o] | -g group | -G group[[,group]...] |\n" - "\t\t-d dir [-m] | -s shell | -c comment |\n" + "\t\t-d dir [-m [-z|Z]] | -s shell | -c comment |\n" "\t\t-l new_logname | -f inactive | -e expire |\n" "\t\t-A authorization [, authorization ...] | -K key=value ... |\n" "\t\t-P profile [, profile ...] | -R role [, role ...] login\n", @@ -100,6 +101,8 @@ char *errmsgs[] = { "ERROR: Failed to read /etc/group file due to invalid entry or" " read error.\n", "ERROR: %s is too long. Choose another.\n", + "WARNING: Avoided creating ZFS filesystem as parent directory %s is not" + " a ZFS mount point.\n", }; int lasterrmsg = sizeof (errmsgs) / sizeof (char *); diff --git a/usr/src/cmd/oamuser/user/messages.h b/usr/src/cmd/oamuser/user/messages.h index 0655e9c402..5e208574f2 100644 --- a/usr/src/cmd/oamuser/user/messages.h +++ b/usr/src/cmd/oamuser/user/messages.h @@ -152,4 +152,11 @@ extern void errmsg(int, ...); /* ERROR: %s is too long. Choose another. */ #define M_TOO_LONG 38 +/* + * WARNING: Avoided creating ZFS filesystem as parent directory + * %s is not a ZFS mount point. + */ +#define M_NO_ZFS_MOUNTPOINT 39 + + #endif /* _MESSAGES_H */ diff --git a/usr/src/cmd/oamuser/user/movedir.c b/usr/src/cmd/oamuser/user/movedir.c index b5355c37ac..bad7a398ac 100644 --- a/usr/src/cmd/oamuser/user/movedir.c +++ b/usr/src/cmd/oamuser/user/movedir.c @@ -29,8 +29,6 @@ /* All Rights Reserved */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include #include #include @@ -49,10 +47,11 @@ static char cmdbuf[SBUFSZ]; /* buffer for system call */ * Move directory contents from one place to another */ int -move_dir(char *from, char *to, char *login) +move_dir(char *from, char *to, char *login, int flags) /* directory to move files from */ /* dirctory to move files to */ /* login id of owner */ + /* miscellaneous flags */ { size_t len = 0; int rc = EX_SUCCESS; @@ -92,7 +91,7 @@ move_dir(char *from, char *to, char *login) } /* Remove the files in the old place */ - rc = rm_files(from, login); + rc = rm_files(from, login, flags); } diff --git a/usr/src/cmd/oamuser/user/rmfiles.c b/usr/src/cmd/oamuser/user/rmfiles.c deleted file mode 100644 index b74af672ba..0000000000 --- a/usr/src/cmd/oamuser/user/rmfiles.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ -/* All Rights Reserved */ - - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include -#include -#include -#include -#include "messages.h" - -#define SBUFSZ 256 - -static char sptr[SBUFSZ]; /* buffer for system call */ - -int -rm_files(homedir, user) -char *homedir; /* home directory to remove */ -char *user; -{ - /* delete all files belonging to owner */ - (void) sprintf( sptr,"rm -rf %s", homedir ); - if( system(sptr) != 0 ) { - errmsg( M_RMFILES ); - return( EX_HOMEDIR ); - } - - return( EX_SUCCESS ); -} - diff --git a/usr/src/cmd/oamuser/user/useradd.c b/usr/src/cmd/oamuser/user/useradd.c index f04c3d48e9..de4f97e953 100644 --- a/usr/src/cmd/oamuser/user/useradd.c +++ b/usr/src/cmd/oamuser/user/useradd.c @@ -52,7 +52,8 @@ #include "funcs.h" /* - * useradd [-u uid [-o] | -g group | -G group [[, group]...] | -d dir [-m] + * useradd [-u uid [-o] | -g group | -G group [[, group]...] + * | -d dir [-m [-z|Z]] * | -s shell | -c comment | -k skel_dir | -b base_dir] ] * [ -A authorization [, authorization ...]] * [ -P profile [, profile ...]] @@ -96,6 +97,7 @@ extern int **valid_lgroup(); extern projid_t **valid_lproject(); extern void update_def(struct userdefs *); extern void import_def(struct userdefs *); +extern int get_default_zfs_flags(); static uid_t uid; /* new uid */ static char *logname; /* login name to add */ @@ -137,7 +139,8 @@ main(argc, argv) int argc; char *argv[]; { - int ch, ret, mflag = 0, oflag = 0, Dflag = 0, **gidlist = NULL; + int ch, ret, mflag = 0, oflag = 0, Dflag = 0; + int zflag = 0, Zflag = 0, **gidlist = NULL; projid_t **projlist = NULL; char *ptr; /* loc in a str, may be set by strtol */ struct group *g_ptr; @@ -148,6 +151,7 @@ char *argv[]; int busy = 0; char **nargv; /* arguments for execvp of passmgmt */ int argindex; /* argument index into nargv */ + int zfs_flags = 0; /* create_home flags */ cmdname = argv[0]; @@ -162,7 +166,7 @@ char *argv[]; change_key(USERATTR_TYPE_KW, usertype); while ((ch = getopt(argc, argv, - "b:c:Dd:e:f:G:g:k:mop:s:u:A:P:R:K:")) != EOF) + "b:c:Dd:e:f:G:g:k:mzZop:s:u:A:P:R:K:")) != EOF) switch (ch) { case 'b': base_dir = optarg; @@ -220,6 +224,14 @@ char *argv[]; uidstr = optarg; break; + case 'Z': + Zflag++; + break; + + case 'z': + zflag++; + break; + case 'A': change_key(USERATTR_AUTHS_KW, optarg); break; @@ -249,6 +261,16 @@ char *argv[]; exit(EX_SYNTAX); } + if (((!mflag) && (zflag || Zflag)) || (zflag && Zflag) || + (mflag > 1 && (zflag || Zflag))) { + if (is_role(usertype)) + errmsg(M_ARUSAGE); + else + errmsg(M_AUSAGE); + exit(EX_SYNTAX); + } + + /* get defaults for adding new users */ usrdefs = getusrdef(usertype); @@ -686,8 +708,18 @@ char *argv[]; } /* create home directory */ - if (mflag && - (create_home(homedir, skel_dir, uid, gid) != EX_SUCCESS)) { + if (mflag) { + zfs_flags = get_default_zfs_flags(); + + if (zflag || mflag > 1) + zfs_flags |= MANAGE_ZFS; + else if (Zflag) + zfs_flags &= ~MANAGE_ZFS; + ret = create_home(homedir, skel_dir, uid, gid, zfs_flags); + } + if (ret != EX_SUCCESS) { + (void) edit_project(logname, (char *)NULL, (projid_t **)NULL, + 0); (void) edit_group(logname, (char *)0, (int **)0, 1); cleanup(logname); exit(EX_HOMEDIR); diff --git a/usr/src/cmd/oamuser/user/useradd.dfl b/usr/src/cmd/oamuser/user/useradd.dfl index 492c3905cb..5611073947 100644 --- a/usr/src/cmd/oamuser/user/useradd.dfl +++ b/usr/src/cmd/oamuser/user/useradd.dfl @@ -31,3 +31,8 @@ EXCEED_TRAD=warning #EXCEED_TRAD=error #EXCEED_TRAD=silent +# The MANAGE_ZFS indicates if ZFS create/destroy operations +# should be performed by default when user passes -m flag to +# userdel/usermod or -r flag to userdel +MANAGE_ZFS=NO +#MANAGE_ZFS=YES diff --git a/usr/src/cmd/oamuser/user/userdel.c b/usr/src/cmd/oamuser/user/userdel.c index 1041583e61..ef34e4f936 100644 --- a/usr/src/cmd/oamuser/user/userdel.c +++ b/usr/src/cmd/oamuser/user/userdel.c @@ -46,17 +46,17 @@ #include "messages.h" #include "funcs.h" -/******************************************************************************* - * userdel [-r] login +/* + * userdel [-r ] login * * This command deletes user logins. Arguments are: * * -r - when given, this option removes home directory & its contents * * login - a string of printable chars except colon (:) - ******************************************************************************/ + */ -extern int check_perm(), isbusy(); +extern int check_perm(), isbusy(), get_default_zfs_flags(); extern int rm_files(), call_passmgmt(), edit_group(); static char *logname; /* login name to delete */ @@ -67,7 +67,8 @@ char *cmdname; int main(int argc, char **argv) { - int ch, ret = 0, rflag = 0, argindex, tries; + int ch, ret = 0, rflag = 0; + int zfs_flags = 0, argindex, tries; struct passwd *pstruct; struct stat statbuf; #ifndef att @@ -78,34 +79,34 @@ main(int argc, char **argv) cmdname = argv[0]; - if( geteuid() != 0 ) { - errmsg( M_PERM_DENIED ); - exit( EX_NO_PERM ); + if (geteuid() != 0) { + errmsg(M_PERM_DENIED); + exit(EX_NO_PERM); } opterr = 0; /* no print errors from getopt */ usertype = getusertype(argv[0]); - - while( (ch = getopt(argc, argv, "r")) != EOF ) { - switch(ch) { + + while ((ch = getopt(argc, argv, "r")) != EOF) { + switch (ch) { case 'r': rflag++; break; case '?': if (is_role(usertype)) - errmsg( M_DRUSAGE ); + errmsg(M_DRUSAGE); else - errmsg( M_DUSAGE ); - exit( EX_SYNTAX ); + errmsg(M_DUSAGE); + exit(EX_SYNTAX); } } - if( optind != argc - 1 ) { + if (optind != argc - 1) { if (is_role(usertype)) - errmsg( M_DRUSAGE ); + errmsg(M_DRUSAGE); else - errmsg( M_DUSAGE ); - exit( EX_SYNTAX ); + errmsg(M_DUSAGE); + exit(EX_SYNTAX); } logname = argv[optind]; @@ -118,7 +119,7 @@ main(int argc, char **argv) * system (since passmgmt only works on local system). */ if ((pwf = fopen("/etc/passwd", "r")) == NULL) { - errmsg( M_OOPS, "open", "/etc/passwd"); + errmsg(M_OOPS, "open", "/etc/passwd"); exit(EX_FAILURE); } while ((pstruct = fgetpwent(pwf)) != NULL) @@ -129,13 +130,13 @@ main(int argc, char **argv) #endif if (pstruct == NULL) { - errmsg( M_EXIST, logname ); - exit( EX_NAME_NOT_EXIST ); + errmsg(M_EXIST, logname); + exit(EX_NAME_NOT_EXIST); } - if( isbusy(logname) ) { - errmsg( M_BUSY, logname, "remove" ); - exit( EX_BUSY ); + if (isbusy(logname)) { + errmsg(M_BUSY, logname, "remove"); + exit(EX_BUSY); } /* that's it for validations - now do the work */ @@ -151,72 +152,75 @@ main(int argc, char **argv) nargv[argindex++] = NULL; /* remove home directory */ - if( rflag ) { + if (rflag) { /* Check Permissions */ - if( stat( pstruct->pw_dir, &statbuf ) ) { - errmsg(M_OOPS, "find status about home directory", + if (stat(pstruct->pw_dir, &statbuf)) { + errmsg(M_OOPS, "find status about home directory", strerror(errno)); - exit( EX_HOMEDIR ); + exit(EX_HOMEDIR); } - - if( check_perm( statbuf, pstruct->pw_uid, pstruct->pw_gid, - S_IWOTH|S_IXOTH ) != 0 ) { - errmsg( M_NO_PERM, logname, pstruct->pw_dir ); - exit( EX_HOMEDIR ); + + if (check_perm(statbuf, pstruct->pw_uid, pstruct->pw_gid, + S_IWOTH|S_IXOTH) != 0) { + errmsg(M_NO_PERM, logname, pstruct->pw_dir); + exit(EX_HOMEDIR); } + zfs_flags = get_default_zfs_flags(); - if( rm_files(pstruct->pw_dir, logname) != EX_SUCCESS ) - exit( EX_HOMEDIR ); + if (rm_files(pstruct->pw_dir, logname, zfs_flags) != EX_SUCCESS) + exit(EX_HOMEDIR); } /* now call passmgmt */ ret = PEX_FAILED; - for( tries = 3; ret != PEX_SUCCESS && tries--; ) { - switch( ret = call_passmgmt( nargv ) ) { + for (tries = 3; ret != PEX_SUCCESS && tries--; ) { + switch (ret = call_passmgmt(nargv)) { case PEX_SUCCESS: - ret = edit_group( logname, (char *)0, (int **)0, 1 ); - if( ret != EX_SUCCESS ) - errmsg( M_UPDATE, "deleted" ); + ret = edit_group(logname, (char *)0, (int **)0, 1); + if (ret != EX_SUCCESS) + errmsg(M_UPDATE, "deleted"); break; case PEX_BUSY: break; case PEX_HOSED_FILES: - errmsg( M_HOSED_FILES ); - exit( EX_INCONSISTENT ); + errmsg(M_HOSED_FILES); + exit(EX_INCONSISTENT); break; case PEX_SYNTAX: case PEX_BADARG: /* should NEVER occur that passmgmt usage is wrong */ if (is_role(usertype)) - errmsg( M_DRUSAGE ); + errmsg(M_DRUSAGE); else - errmsg( M_DUSAGE ); - exit( EX_SYNTAX ); + errmsg(M_DUSAGE); + exit(EX_SYNTAX); break; case PEX_BADUID: - /* uid is used - shouldn't happen but print message anyway */ - errmsg( M_UID_USED, pstruct->pw_uid ); - exit( EX_ID_EXISTS ); + /* + * uid is used - shouldn't happen but print message anyway + */ + errmsg(M_UID_USED, pstruct->pw_uid); + exit(EX_ID_EXISTS); break; case PEX_BADNAME: /* invalid loname */ - errmsg( M_USED, logname); - exit( EX_NAME_EXISTS ); + errmsg(M_USED, logname); + exit(EX_NAME_EXISTS); break; default: - errmsg( M_UPDATE, "deleted" ); - exit( ret ); + errmsg(M_UPDATE, "deleted"); + exit(ret); break; } } - if( tries == 0 ) - errmsg( M_UPDATE, "deleted" ); + if (tries == 0) + errmsg(M_UPDATE, "deleted"); /* * Now, remove this user from all project entries @@ -227,7 +231,7 @@ main(int argc, char **argv) errmsg(M_UPDATE, "modified"); exit(rc); } - - exit( ret ); + + exit(ret); /*NOTREACHED*/ } diff --git a/usr/src/cmd/oamuser/user/usermod.c b/usr/src/cmd/oamuser/user/usermod.c index fa2c018367..0264660fe3 100644 --- a/usr/src/cmd/oamuser/user/usermod.c +++ b/usr/src/cmd/oamuser/user/usermod.c @@ -50,7 +50,8 @@ #include "funcs.h" /* - * usermod [-u uid [-o] | -g group | -G group [[,group]...] | -d dir [-m] + * usermod [-u uid [-o] | -g group | -G group [[,group]...] + * | -d dir [-m [-z|Z]] * | -s shell | -c comment | -l new_logname] * | -f inactive | -e expire ] * [ -A authorization [, authorization ...]] @@ -82,7 +83,7 @@ * */ -extern int **valid_lgroup(), isbusy(); +extern int **valid_lgroup(), isbusy(), get_default_zfs_flags(); extern int valid_uid(), check_perm(), create_home(), move_dir(); extern int valid_expire(), edit_group(), call_passmgmt(); extern projid_t **valid_lproject(); @@ -145,8 +146,8 @@ main(argc, argv) int argc; char **argv; { - int ch, ret = EX_SUCCESS, call_pass = 0, oflag = 0; - int tries, mflag = 0, inact, **gidlist, flag = 0; + int ch, ret = EX_SUCCESS, call_pass = 0, oflag = 0, zfs_flags = 0; + int tries, mflag = 0, inact, **gidlist, flag = 0, zflag = 0, Zflag = 0; boolean_t fail_if_busy = B_FALSE; char *ptr; struct passwd *pstruct; /* password struct for login */ @@ -176,7 +177,7 @@ char **argv; usertype = getusertype(argv[0]); while ((ch = getopt(argc, argv, - "c:d:e:f:G:g:l:mop:s:u:A:P:R:K:")) != EOF) + "c:d:e:f:G:g:l:mzZop:s:u:A:P:R:K:")) != EOF) switch (ch) { case 'c': comment = optarg; @@ -232,6 +233,12 @@ char **argv; flag++; fail_if_busy = B_TRUE; break; + case 'Z': + Zflag++; + break; + case 'z': + zflag++; + break; case 'A': change_key(USERATTR_AUTHS_KW, optarg); flag++; @@ -257,6 +264,16 @@ char **argv; exit(EX_SYNTAX); } + if (((!mflag) && (zflag || Zflag)) || (zflag && Zflag) || + (mflag > 1 && (zflag || Zflag))) { + if (is_role(usertype)) + errmsg(M_ARUSAGE); + else + errmsg(M_AUSAGE); + exit(EX_SYNTAX); + } + + if (optind != argc - 1 || flag == 0) { if (is_role(usertype)) errmsg(M_MRUSAGE); @@ -490,10 +507,18 @@ char **argv; exit(EX_NO_PERM); } - } else ret = create_home(dir, NULL, uid, gid); + } else { + zfs_flags = get_default_zfs_flags(); + if (zflag || mflag > 1) + zfs_flags |= MANAGE_ZFS; + else if (Zflag) + zfs_flags &= ~MANAGE_ZFS; + ret = create_home(dir, NULL, uid, gid, zfs_flags); + } if (ret == EX_SUCCESS) - ret = move_dir(pstruct->pw_dir, dir, logname); + ret = move_dir(pstruct->pw_dir, dir, + logname, zfs_flags); if (ret != EX_SUCCESS) exit(ret); diff --git a/usr/src/man/man1m/useradd.1m b/usr/src/man/man1m/useradd.1m index 9e0fe52d07..f87c545a12 100644 --- a/usr/src/man/man1m/useradd.1m +++ b/usr/src/man/man1m/useradd.1m @@ -14,7 +14,7 @@ useradd \- administer a new user login on the system \fBuseradd\fR [\fB-A\fR \fIauthorization\fR [,\fIauthorization...\fR]] [\fB-b\fR \fIbase_dir\fR] [\fB-c\fR \fIcomment\fR] [\fB-d\fR \fIdir\fR] [\fB-e\fR \fIexpire\fR] [\fB-f\fR \fIinactive\fR] [\fB-g\fR \fIgroup\fR] [\fB-G\fR \fIgroup\fR [,\fIgroup\fR]...] - [\fB-K\fR \fIkey=value\fR] [\fB-m\fR [\fB-k\fR \fIskel_dir\fR]] [\fB-p\fR \fIprojname\fR] + [\fB-K\fR \fIkey=value\fR] [\fB-m\fR [\fB-z|-Z\fR] [\fB-k\fR \fIskel_dir\fR]] [\fB-p\fR \fIprojname\fR] [\fB-P\fR \fIprofile\fR [,\fIprofile...\fR]] [\fB-R\fR \fIrole\fR [,\fIrole...\fR]] [\fB-s\fR \fIshell\fR] [\fB-u\fR \fIuid\fR [\fB-o\fR]] \fIlogin\fR .fi @@ -28,7 +28,6 @@ useradd \- administer a new user login on the system .fi .SH DESCRIPTION -.sp .LP \fBuseradd\fR adds a new user to the \fB/etc/passwd\fR and \fB/etc/shadow\fR and \fB/etc/user_attr\fR files. The \fB-A\fR and \fB-P\fR options respectively @@ -66,7 +65,6 @@ length limit of eight characters is exceeded, edit the file \fB/etc/default/useradd\fR by removing the \fB#\fR (pound sign) before the appropriate \fBEXCEED_TRAD=\fR entry, and adding it before the others. .SH OPTIONS -.sp .LP The following options are supported: .sp @@ -341,13 +339,23 @@ this purpose. .sp .ne 2 .na -\fB\fB-m\fR\fR +\fB\fB-m\fR\fR [\fB-z|-Z\fR] .ad .sp .6 .RS 4n Create the new user's home directory if it does not already exist. If the directory already exists, it must have read, write, and execute permissions by \fIgroup\fR, where \fIgroup\fR is the user's primary group. +.sp +If the parent directory of the user's home directory is located on a separate +\fBZFS\fR file system and the \fB/etc/default/useradd\fR file contains the +parameter \fBMANAGE_ZFS\fR set to the value \fBYES\fR, a new \fBZFS\fR +file system will be created for the user. +.sp +If the \fB-z\fR option is specified, \fBuseradd\fR will always try to create +a new file system for the home directory. +.sp +If the \fB-Z\fR option is specified, a new file system will never be created. .RE .sp @@ -420,7 +428,6 @@ reserved for allocation by the Solaris Operating System. .RE .SH FILES -.sp .LP \fB/etc/default/useradd\fR .sp @@ -445,7 +452,6 @@ reserved for allocation by the Solaris Operating System. .LP \fB/etc/user_attr\fR .SH ATTRIBUTES -.sp .LP See \fBattributes\fR(5) for descriptions of the following attributes: .sp @@ -461,15 +467,13 @@ Interface Stability Committed .TE .SH SEE ALSO -.sp .LP \fBpasswd\fR(1), \fBprofiles\fR(1), \fBroles\fR(1), \fBusers\fR(1B), \fBgroupadd\fR(1M), \fBgroupdel\fR(1M), \fBgroupmod\fR(1M), \fBgrpck\fR(1M), \fBlogins\fR(1M), \fBpwck\fR(1M), \fBuserdel\fR(1M), \fBusermod\fR(1M), \fBgetdate\fR(3C), \fBauth_attr\fR(4), \fBpasswd\fR(4), \fBprof_attr\fR(4), -\fBproject\fR(4), \fBuser_attr\fR(4), \fBattributes\fR(5) +\fBproject\fR(4), \fBuser_attr\fR(4), \fBattributes\fR(5), \fBzfs\fR(1M) .SH DIAGNOSTICS -.sp .LP In case of an error, \fBuseradd\fR prints an error message and exits with a non-zero status. @@ -545,7 +549,6 @@ UX: useradd: ERROR: Cannot update system files - login cannot be created. .sp .SH NOTES -.sp .LP The \fBuseradd\fR utility adds definitions to only the local \fB/etc/group\fR, \fBetc/passwd\fR, \fB/etc/passwd\fR, \fB/etc/shadow\fR, \fB/etc/project\fR, and diff --git a/usr/src/man/man1m/userdel.1m b/usr/src/man/man1m/userdel.1m index 9d40e6cf73..09d31e3e39 100644 --- a/usr/src/man/man1m/userdel.1m +++ b/usr/src/man/man1m/userdel.1m @@ -14,12 +14,10 @@ userdel \- delete a user's login from the system .fi .SH DESCRIPTION -.sp .LP The \fBuserdel\fR utility deletes a user account from the system and makes the appropriate account-related changes to the system file and file system. .SH OPTIONS -.sp .LP The following options are supported: .sp @@ -31,10 +29,13 @@ The following options are supported: Remove the user's home directory from the system. This directory must exist. The files and directories under the home directory will no longer be accessible following successful execution of the command. +.sp +If the user's home directory is located on a separate \fBZFS\fR file system and +the \fB/etc/default/useradd\fR file contains the parameter \fBMANAGE_ZFS\fR set +to the value \fBYES\fR, the file system will be destroyed. .RE .SH OPERANDS -.sp .LP The following operands are supported: .sp @@ -47,7 +48,6 @@ An existing login name to be deleted. .RE .SH EXIT STATUS -.sp .LP The following exit values are returned: .sp @@ -107,6 +107,14 @@ Cannot remove or otherwise modify the home directory. .RE .SH FILES +.ne 2 +.na +\fB\fB/etc/default/useradd\fR\fR +.ad +.RS 18n +useradd, usermod and userdel configuration file +.RE + .sp .ne 2 .na @@ -144,15 +152,13 @@ system file containing additional user attributes .RE .SH SEE ALSO -.sp .LP \fBauths\fR(1), \fBpasswd\fR(1), \fBprofiles\fR(1), \fBroles\fR(1), \fBusers\fR(1B), \fBgroupadd\fR(1M), \fBgroupdel\fR(1M), \fBgroupmod\fR(1M), \fBlogins\fR(1M), \fBroleadd\fR(1M), \fBrolemod\fR(1M), \fBuseradd\fR(1M), \fBuserdel\fR(1M), \fBusermod\fR(1M), \fBpasswd\fR(4), \fBprof_attr\fR(4), -\fBuser_attr\fR(4), \fBattributes\fR(5) +\fBuser_attr\fR(4), \fBattributes\fR(5), \fBzfs\fR(1M) .SH NOTES -.sp .LP The \fBuserdel\fR utility only deletes an account definition that is in the local \fB/etc/group\fR, \fB/etc/passwd\fR, \fB/etc/shadow\fR, and diff --git a/usr/src/man/man1m/usermod.1m b/usr/src/man/man1m/usermod.1m index 46f4f9992b..ba78ca74a8 100644 --- a/usr/src/man/man1m/usermod.1m +++ b/usr/src/man/man1m/usermod.1m @@ -10,7 +10,7 @@ usermod \- modify a user's login information on the system .LP .nf \fBusermod\fR [\fB-u\fR \fIuid\fR [\fB-o\fR]] [\fB-g\fR \fIgroup\fR] [\fB-G\fR \fIgroup\fR [, \fIgroup\fR...]] - [\fB-d\fR \fIdir\fR [\fB-m\fR]] [\fB-s\fR \fIshell\fR] [\fB-c\fR \fIcomment\fR] [\fB-l\fR \fInew_name\fR] + [\fB-d\fR \fIdir\fR [\fB-m\fR [\fB-z|-Z\fR]]] [\fB-s\fR \fIshell\fR] [\fB-c\fR \fIcomment\fR] [\fB-l\fR \fInew_name\fR] [\fB-f\fR \fIinactive\fR] [\fB-e\fR \fIexpire\fR] [\fB-A\fR \fIauthorization\fR [, \fIauthorization\fR]] [\fB-P\fR \fIprofile\fR [, \fIprofile\fR]] [\fB-R\fR \fIrole\fR [, \fIrole\fR]] @@ -18,7 +18,6 @@ usermod \- modify a user's login information on the system .fi .SH DESCRIPTION -.sp .LP The \fBusermod\fR utility modifies a user's login definition on the system. It changes the definition of the specified login and makes the appropriate @@ -29,7 +28,6 @@ The system file entries created with this command have a limit of 512 characters per line. Specifying long arguments to several options might exceed this limit. .SH OPTIONS -.sp .LP The following options are supported: .sp @@ -163,7 +161,7 @@ requirements for usernames. .sp .ne 2 .na -\fB\fB-m\fR\fR +\fB\fB-m\fR\fR [\fB-z|-Z\fR] .ad .sp .6 .RS 4n @@ -171,6 +169,20 @@ Move the user's home directory to the new directory specified with the \fB-d\fR option. If the directory already exists, it must have permissions read/write/execute by \fIgroup\fR, where \fIgroup\fR is the user's primary group. +.sp +If the user's old home directory was located on a separate \fBZFS\fR file system +and the \fB/etc/default/useradd\fR file contains the parameter \fBMANAGE_ZFS\fR +set to the value \fBYES\fR, the file system will be destroyed after the home +directory is moved. If the parent directory of the user's new home directory is +located on a separate \fBZFS\fR filesystem and the \fB/etc/default/useradd\fR +file contains the parameter \fBMANAGE_ZFS\fR set to the value \fBYES\fR, a new +\fBZFS\fR file system will be created. +.sp +If the \fB-z\fR option is specified, \fBusermod\fR will always try to create a +new file system for the home directory and destroy the old one. +.sp +If the \fB-Z\fR option is specified, a new file system will never be created, +and the old one will never be destroyed. .RE .sp @@ -233,7 +245,6 @@ manually reassigned using \fBchown\fR(1). .RE .SH OPERANDS -.sp .LP The following operands are supported: .sp @@ -369,7 +380,6 @@ means of the \fBPROFS_GRANTED\fR key in \fBpolicy.conf\fR(4). .sp .SH EXIT STATUS -.sp .LP In case of an error, \fBusermod\fR prints an error message and exits with one of the following values: @@ -479,6 +489,15 @@ Unable to complete the move of the home directory to the new home directory. .RE .SH FILES +.ne 2 +.na +\fB\fB/etc/default/useradd\fR\fR +.ad +.sp .6 +.RS 4n +useradd, usermod and userdel configuration file +.RE + .sp .ne 2 .na @@ -530,7 +549,6 @@ system file containing additional user and role attributes .RE .SH ATTRIBUTES -.sp .LP See \fBattributes\fR(5) for descriptions of the following attributes: .sp @@ -546,16 +564,14 @@ Interface Stability Committed .TE .SH SEE ALSO -.sp .LP \fBchown\fR(1), \fBpasswd\fR(1), \fBusers\fR(1B), \fBgroupadd\fR(1M), \fBgroupdel\fR(1M), \fBgroupmod\fR(1M), \fBlogins\fR(1M), \fBpwconv\fR(1M), \fBroleadd\fR(1M), \fBroledel\fR(1M), \fBrolemod\fR(1M), \fBuseradd\fR(1M), \fBuserdel\fR(1M), \fBgetdate\fR(3C), \fBauth_attr\fR(4), \fBpasswd\fR(4), \fBpolicy.conf\fR(4), \fBprof_attr\fR(4), \fBuser_attr\fR(4), -\fBattributes\fR(5) +\fBattributes\fR(5), \fBzfs\fR(1M) .SH NOTES -.sp .LP The \fBusermod\fR utility modifies \fBpasswd\fR definitions only in the local \fB/etc/passwd\fR and \fB/etc/shadow\fR files. If a network nameservice such as -- 2.11.4.GIT