xref: /illumos-gate/usr/src/cmd/oamuser/user/homedir.c (revision d0b12b66)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate 
237c478bd9Sstevel@tonic-gate /*
2449335bdeSbasabi  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
257c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
267c478bd9Sstevel@tonic-gate  */
277c478bd9Sstevel@tonic-gate 
2849335bdeSbasabi /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
2949335bdeSbasabi /*	  All Rights Reserved  	*/
3049335bdeSbasabi 
3149335bdeSbasabi 
327c478bd9Sstevel@tonic-gate #include <sys/types.h>
337fc68ddfSAlbert Lee #include <sys/stat.h>
347c478bd9Sstevel@tonic-gate #include <stdio.h>
357c478bd9Sstevel@tonic-gate #include <userdefs.h>
367c478bd9Sstevel@tonic-gate #include <errno.h>
37ace1a5f1Sdp #include <strings.h>
387fc68ddfSAlbert Lee #include <stdlib.h>
397fc68ddfSAlbert Lee #include <sys/mntent.h>
407fc68ddfSAlbert Lee #include <sys/mnttab.h>
417fc68ddfSAlbert Lee #include <libzfs.h>
427fc68ddfSAlbert Lee #include <libgen.h>
437fc68ddfSAlbert Lee #include <limits.h>
447fc68ddfSAlbert Lee #include <deflt.h>
457fc68ddfSAlbert Lee 
467fc68ddfSAlbert Lee #include "funcs.h"
477c478bd9Sstevel@tonic-gate #include "messages.h"
487c478bd9Sstevel@tonic-gate 
497fc68ddfSAlbert Lee #define	SBUFSZ	256
507fc68ddfSAlbert Lee 
517fc68ddfSAlbert Lee #define	DEFAULT_USERADD	"/etc/default/useradd"
527c478bd9Sstevel@tonic-gate 
537fc68ddfSAlbert Lee static int rm_homedir();
547fc68ddfSAlbert Lee static char *get_mnt_special();
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate static char cmdbuf[ SBUFSZ ];	/* buffer for system call */
577fc68ddfSAlbert Lee static char dhome[ PATH_MAX + 1 ]; /* buffer for dirname */
587fc68ddfSAlbert Lee static char bhome[ PATH_MAX + 1 ]; /* buffer for basename */
597fc68ddfSAlbert Lee static char pdir[ PATH_MAX + 1 ]; /* parent directory */
607fc68ddfSAlbert Lee static libzfs_handle_t *g_zfs = NULL;
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate /*
637fc68ddfSAlbert Lee  * Create a home directory and populate with files from skeleton
647fc68ddfSAlbert Lee  * directory.
657fc68ddfSAlbert Lee  */
667c478bd9Sstevel@tonic-gate int
create_home(char * homedir,char * skeldir,uid_t uid,gid_t gid,int flags)677fc68ddfSAlbert Lee create_home(char *homedir, char *skeldir, uid_t uid, gid_t gid, int flags)
6849335bdeSbasabi 		/* home directory to create */
6949335bdeSbasabi 		/* skel directory to copy if indicated */
7049335bdeSbasabi 		/* uid of new user */
7149335bdeSbasabi 		/* group id of new user */
727fc68ddfSAlbert Lee 		/* miscellaneous flags */
737c478bd9Sstevel@tonic-gate {
747fc68ddfSAlbert Lee 	struct stat stbuf;
757fc68ddfSAlbert Lee 	char *dataset;
767fc68ddfSAlbert Lee 	char *dname, *bname, *rp;
777fc68ddfSAlbert Lee 	int created_fs = 0;
787fc68ddfSAlbert Lee 
797fc68ddfSAlbert Lee 	rp = realpath(homedir, NULL);
807fc68ddfSAlbert Lee 	if (rp && (strcmp(rp, "/") == 0)) {
817fc68ddfSAlbert Lee 		return (EX_HOMEDIR);
827c478bd9Sstevel@tonic-gate 	}
837c478bd9Sstevel@tonic-gate 
847fc68ddfSAlbert Lee 	(void) strcpy(dhome, homedir);
857fc68ddfSAlbert Lee 	(void) strcpy(bhome, homedir);
867fc68ddfSAlbert Lee 	dname = dirname(dhome);
877fc68ddfSAlbert Lee 	bname = basename(bhome);
887fc68ddfSAlbert Lee 	(void) strcpy(pdir, dname);
897fc68ddfSAlbert Lee 
907fc68ddfSAlbert Lee 	if ((stat(pdir, &stbuf) != 0) || !S_ISDIR(stbuf.st_mode)) {
917fc68ddfSAlbert Lee 		errmsg(M_OOPS, "access the parent directory", strerror(errno));
927fc68ddfSAlbert Lee 		return (EX_HOMEDIR);
937fc68ddfSAlbert Lee 	}
947fc68ddfSAlbert Lee 
957fc68ddfSAlbert Lee 	if ((strcmp(stbuf.st_fstype, MNTTYPE_ZFS) == 0) &&
967fc68ddfSAlbert Lee 	    (flags & MANAGE_ZFS)) {
977fc68ddfSAlbert Lee 		if (g_zfs == NULL)
987fc68ddfSAlbert Lee 			g_zfs = libzfs_init();
997fc68ddfSAlbert Lee 		if (g_zfs == NULL) {
1007fc68ddfSAlbert Lee 			errmsg(M_OOPS, "libzfs_init failure", strerror(errno));
1017fc68ddfSAlbert Lee 			return (EX_HOMEDIR);
1027fc68ddfSAlbert Lee 		}
1037fc68ddfSAlbert Lee 		if ((dataset = get_mnt_special(pdir, stbuf.st_fstype))
1047fc68ddfSAlbert Lee 		    != NULL) {
1059adfa60dSMatthew Ahrens 			char nm[ZFS_MAX_DATASET_NAME_LEN];
1067fc68ddfSAlbert Lee 			zfs_handle_t *zhp;
1077fc68ddfSAlbert Lee 
1089adfa60dSMatthew Ahrens 			(void) snprintf(nm, sizeof (nm), "%s/%s",
1097fc68ddfSAlbert Lee 			    dataset, bname);
1107fc68ddfSAlbert Lee 
1117fc68ddfSAlbert Lee 			if ((zfs_create(g_zfs, nm, ZFS_TYPE_FILESYSTEM, NULL)
1127fc68ddfSAlbert Lee 				!= 0) ||
1137fc68ddfSAlbert Lee 			    ((zhp = zfs_open(g_zfs, nm, ZFS_TYPE_FILESYSTEM)) ==
1147fc68ddfSAlbert Lee 			    NULL)) {
1157fc68ddfSAlbert Lee 				errmsg(M_OOPS, "create the home directory",
1167fc68ddfSAlbert Lee 				    libzfs_error_description(g_zfs));
1177fc68ddfSAlbert Lee 				libzfs_fini(g_zfs);
1187fc68ddfSAlbert Lee 				g_zfs = NULL;
1197fc68ddfSAlbert Lee 				return (EX_HOMEDIR);
1207fc68ddfSAlbert Lee 			}
1217fc68ddfSAlbert Lee 
1227fc68ddfSAlbert Lee 			if (zfs_mount(zhp, NULL, 0) != 0) {
1237fc68ddfSAlbert Lee 				errmsg(M_OOPS, "mount the home directory",
1247fc68ddfSAlbert Lee 				    libzfs_error_description(g_zfs));
1257fc68ddfSAlbert Lee 				(void) zfs_destroy(zhp, B_FALSE);
1267fc68ddfSAlbert Lee 				zfs_close(zhp);
1277fc68ddfSAlbert Lee 				libzfs_fini(g_zfs);
1287fc68ddfSAlbert Lee 				g_zfs = NULL;
1297fc68ddfSAlbert Lee 				return (EX_HOMEDIR);
1307fc68ddfSAlbert Lee 			}
1317fc68ddfSAlbert Lee 
1327fc68ddfSAlbert Lee 			zfs_close(zhp);
1337fc68ddfSAlbert Lee 
1347fc68ddfSAlbert Lee 			if (chmod(homedir,
1357fc68ddfSAlbert Lee 				S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) != 0) {
1367fc68ddfSAlbert Lee 				errmsg(M_OOPS,
1377fc68ddfSAlbert Lee 				    "change permissions of home directory",
1387fc68ddfSAlbert Lee 				    strerror(errno));
1397fc68ddfSAlbert Lee 				libzfs_fini(g_zfs);
1407fc68ddfSAlbert Lee 				g_zfs = NULL;
1417fc68ddfSAlbert Lee 				return (EX_HOMEDIR);
1427fc68ddfSAlbert Lee 			}
1437fc68ddfSAlbert Lee 
1447fc68ddfSAlbert Lee 			created_fs = 1;
1457fc68ddfSAlbert Lee 		} else {
1467fc68ddfSAlbert Lee 			errmsg(M_NO_ZFS_MOUNTPOINT, pdir);
1477fc68ddfSAlbert Lee 		}
1487fc68ddfSAlbert Lee 	}
1497fc68ddfSAlbert Lee 
1507fc68ddfSAlbert Lee 	if (!created_fs) {
1517fc68ddfSAlbert Lee 		if (mkdir(homedir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
1527fc68ddfSAlbert Lee 			!= 0) {
1537fc68ddfSAlbert Lee 			errmsg(M_OOPS, "create the home directory",
1547fc68ddfSAlbert Lee 			    strerror(errno));
1557fc68ddfSAlbert Lee 			if (g_zfs != NULL) {
1567fc68ddfSAlbert Lee 				libzfs_fini(g_zfs);
1577fc68ddfSAlbert Lee 				g_zfs = NULL;
1587fc68ddfSAlbert Lee 			}
1597fc68ddfSAlbert Lee 			return (EX_HOMEDIR);
1607fc68ddfSAlbert Lee 		}
1617fc68ddfSAlbert Lee 	}
1627fc68ddfSAlbert Lee 
1637fc68ddfSAlbert Lee 	if (chown(homedir, uid, gid) != 0) {
1647fc68ddfSAlbert Lee 		errmsg(M_OOPS, "change ownership of home directory",
165ace1a5f1Sdp 		    strerror(errno));
1667fc68ddfSAlbert Lee 		if (g_zfs != NULL) {
1677fc68ddfSAlbert Lee 			libzfs_fini(g_zfs);
1687fc68ddfSAlbert Lee 			g_zfs = NULL;
1697fc68ddfSAlbert Lee 		}
1707fc68ddfSAlbert Lee 		return (EX_HOMEDIR);
1717c478bd9Sstevel@tonic-gate 	}
1727c478bd9Sstevel@tonic-gate 
1737fc68ddfSAlbert Lee 	if (skeldir != NULL) {
1747c478bd9Sstevel@tonic-gate 		/* copy the skel_dir into the home directory */
1757fc68ddfSAlbert Lee 		(void) sprintf(cmdbuf, "cd %s && find . -print | cpio -pd %s",
1767c478bd9Sstevel@tonic-gate 			skeldir, homedir);
1777c478bd9Sstevel@tonic-gate 
1787fc68ddfSAlbert Lee 		if (system(cmdbuf) != 0) {
179ace1a5f1Sdp 			errmsg(M_OOPS, "copy skeleton directory into home "
180ace1a5f1Sdp 			    "directory", strerror(errno));
1817fc68ddfSAlbert Lee 			(void) rm_homedir(homedir, flags);
1827fc68ddfSAlbert Lee 			if (g_zfs != NULL) {
1837fc68ddfSAlbert Lee 				libzfs_fini(g_zfs);
1847fc68ddfSAlbert Lee 				g_zfs = NULL;
1857fc68ddfSAlbert Lee 			}
1867fc68ddfSAlbert Lee 			return (EX_HOMEDIR);
1877c478bd9Sstevel@tonic-gate 		}
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate 		/* make sure contents in the home dirctory have correct owner */
1907fc68ddfSAlbert Lee 		(void) sprintf(cmdbuf,
1917fc68ddfSAlbert Lee 		    "cd %s && find . -exec chown %ld:%ld {} \\;",
1927fc68ddfSAlbert Lee 		    homedir, uid, gid);
1937fc68ddfSAlbert Lee 		if (system(cmdbuf) != 0) {
1947fc68ddfSAlbert Lee 			errmsg(M_OOPS,
1957fc68ddfSAlbert Lee 			    "change owner and group of files home directory",
196ace1a5f1Sdp 			    strerror(errno));
1977fc68ddfSAlbert Lee 			(void) rm_homedir(homedir, flags);
1987fc68ddfSAlbert Lee 			if (g_zfs != NULL) {
1997fc68ddfSAlbert Lee 				libzfs_fini(g_zfs);
2007fc68ddfSAlbert Lee 				g_zfs = NULL;
2017fc68ddfSAlbert Lee 			}
2027fc68ddfSAlbert Lee 			return (EX_HOMEDIR);
2037fc68ddfSAlbert Lee 		}
2047fc68ddfSAlbert Lee 
2057fc68ddfSAlbert Lee 	}
2067fc68ddfSAlbert Lee 	if (g_zfs != NULL) {
2077fc68ddfSAlbert Lee 		libzfs_fini(g_zfs);
2087fc68ddfSAlbert Lee 		g_zfs = NULL;
2097fc68ddfSAlbert Lee 	}
2107fc68ddfSAlbert Lee 	return (EX_SUCCESS);
2117fc68ddfSAlbert Lee }
2127fc68ddfSAlbert Lee 
2137fc68ddfSAlbert Lee /* Remove a home directory structure */
2147fc68ddfSAlbert Lee int
rm_homedir(char * dir,int flags)2157fc68ddfSAlbert Lee rm_homedir(char *dir, int flags)
2167fc68ddfSAlbert Lee {
2177fc68ddfSAlbert Lee 	struct stat stbuf;
2187fc68ddfSAlbert Lee 	char *nm, *rp;
2197c478bd9Sstevel@tonic-gate 
2207fc68ddfSAlbert Lee 	rp = realpath(dir, NULL);
2217fc68ddfSAlbert Lee 	if (rp && (strcmp(rp, "/") == 0)) {
2227fc68ddfSAlbert Lee 		return (0);
2237fc68ddfSAlbert Lee 	}
2247fc68ddfSAlbert Lee 
2257fc68ddfSAlbert Lee 	if ((stat(dir, &stbuf) != 0) || !S_ISDIR(stbuf.st_mode))
2267fc68ddfSAlbert Lee 		return (0);
2277fc68ddfSAlbert Lee 
2287fc68ddfSAlbert Lee 	if ((strcmp(stbuf.st_fstype, MNTTYPE_ZFS) == 0) &&
2297fc68ddfSAlbert Lee 	    (flags & MANAGE_ZFS)) {
2307fc68ddfSAlbert Lee 		if (g_zfs == NULL)
2317fc68ddfSAlbert Lee 			g_zfs = libzfs_init();
2327fc68ddfSAlbert Lee 
2337fc68ddfSAlbert Lee 		if (g_zfs == NULL) {
2347fc68ddfSAlbert Lee 			errmsg(M_OOPS, "libzfs_init failure", strerror(errno));
2357fc68ddfSAlbert Lee 			return (EX_HOMEDIR);
2367c478bd9Sstevel@tonic-gate 		}
2377c478bd9Sstevel@tonic-gate 
2387fc68ddfSAlbert Lee 		if ((nm = get_mnt_special(dir, stbuf.st_fstype)) != NULL) {
2397fc68ddfSAlbert Lee 			zfs_handle_t *zhp;
2407fc68ddfSAlbert Lee 
2417fc68ddfSAlbert Lee 			if ((zhp = zfs_open(g_zfs, nm, ZFS_TYPE_FILESYSTEM))
2427fc68ddfSAlbert Lee 			    != NULL) {
2437fc68ddfSAlbert Lee 				if ((zfs_unmount(zhp, NULL, 0) == 0) &&
2447fc68ddfSAlbert Lee 				    (zfs_destroy(zhp, B_FALSE) == 0)) {
2457fc68ddfSAlbert Lee 					zfs_close(zhp);
2467fc68ddfSAlbert Lee 					libzfs_fini(g_zfs);
2477fc68ddfSAlbert Lee 					g_zfs = NULL;
2487fc68ddfSAlbert Lee 					return (0);
2497fc68ddfSAlbert Lee 				}
2507fc68ddfSAlbert Lee 
2517fc68ddfSAlbert Lee 				errmsg(M_OOPS, "destroy the home directory",
2527fc68ddfSAlbert Lee 				    libzfs_error_description(g_zfs));
2537fc68ddfSAlbert Lee 
2547fc68ddfSAlbert Lee 				(void) zfs_mount(zhp, NULL, 0);
2557fc68ddfSAlbert Lee 				zfs_close(zhp);
2567fc68ddfSAlbert Lee 
2577fc68ddfSAlbert Lee 				libzfs_fini(g_zfs);
2587fc68ddfSAlbert Lee 				g_zfs = NULL;
2597fc68ddfSAlbert Lee 				return (EX_HOMEDIR);
2607fc68ddfSAlbert Lee 			}
2617c478bd9Sstevel@tonic-gate 		}
2627c478bd9Sstevel@tonic-gate 	}
2637fc68ddfSAlbert Lee 
2647fc68ddfSAlbert Lee 	(void) sprintf(cmdbuf, "rm -rf %s", dir);
2657fc68ddfSAlbert Lee 
2667fc68ddfSAlbert Lee 	if (g_zfs != NULL) {
2677fc68ddfSAlbert Lee 		libzfs_fini(g_zfs);
2687fc68ddfSAlbert Lee 		g_zfs = NULL;
2697fc68ddfSAlbert Lee 	}
2707fc68ddfSAlbert Lee 
2717fc68ddfSAlbert Lee 	return (system(cmdbuf));
2727fc68ddfSAlbert Lee }
2737fc68ddfSAlbert Lee 
2747fc68ddfSAlbert Lee int
rm_files(char * homedir,char * user,int flags)2757fc68ddfSAlbert Lee rm_files(char *homedir, char *user, int flags)
2767fc68ddfSAlbert Lee {
2777fc68ddfSAlbert Lee 	if (rm_homedir(homedir, flags) != 0) {
2787fc68ddfSAlbert Lee 		errmsg(M_RMFILES);
2797fc68ddfSAlbert Lee 		return (EX_HOMEDIR);
2807fc68ddfSAlbert Lee 	}
2817fc68ddfSAlbert Lee 
2827fc68ddfSAlbert Lee 	return (EX_SUCCESS);
2837c478bd9Sstevel@tonic-gate }
2847c478bd9Sstevel@tonic-gate 
28549335bdeSbasabi int
get_default_zfs_flags()2867fc68ddfSAlbert Lee get_default_zfs_flags()
2877fc68ddfSAlbert Lee {
2887fc68ddfSAlbert Lee 	int flags = 0;
2897fc68ddfSAlbert Lee 
2907fc68ddfSAlbert Lee 	if (defopen(DEFAULT_USERADD) == 0) {
2917fc68ddfSAlbert Lee 		char *defptr;
2927fc68ddfSAlbert Lee 
2937fc68ddfSAlbert Lee 		if ((defptr = defread(MANAGE_ZFS_OPT)) != NULL) {
2947fc68ddfSAlbert Lee 			char let = tolower(*defptr);
2957fc68ddfSAlbert Lee 
2967fc68ddfSAlbert Lee 			switch (let) {
2977fc68ddfSAlbert Lee 				case 'y':	/* yes */
2987fc68ddfSAlbert Lee 					flags |= MANAGE_ZFS;
2997fc68ddfSAlbert Lee 				case 'n':	/* no */
3007fc68ddfSAlbert Lee 					break;
3017fc68ddfSAlbert Lee 			}
3027fc68ddfSAlbert Lee 		}
3037fc68ddfSAlbert Lee 		(void) defopen((char *)NULL);
3047fc68ddfSAlbert Lee 	}
3057fc68ddfSAlbert Lee 	return (flags);
3067fc68ddfSAlbert Lee }
3077fc68ddfSAlbert Lee 
308*d0b12b66SToomas Soome /* Get the name of a mounted filesystem */
3097fc68ddfSAlbert Lee char *
get_mnt_special(char * mountp,char * fstype)3107fc68ddfSAlbert Lee get_mnt_special(char *mountp, char *fstype)
3117c478bd9Sstevel@tonic-gate {
3127fc68ddfSAlbert Lee 	struct mnttab entry, search;
3137fc68ddfSAlbert Lee 	char *special = NULL;
3147fc68ddfSAlbert Lee 	FILE *fp;
3157fc68ddfSAlbert Lee 
3167fc68ddfSAlbert Lee 	search.mnt_special = search.mnt_mntopts = search.mnt_time = NULL;
3177fc68ddfSAlbert Lee 	search.mnt_mountp = mountp;
3187fc68ddfSAlbert Lee 	search.mnt_fstype = fstype;
3197fc68ddfSAlbert Lee 
3207fc68ddfSAlbert Lee 	if ((fp = fopen(MNTTAB, "r")) != NULL) {
3217fc68ddfSAlbert Lee 		if (getmntany(fp, &entry, &search) == 0)
3227fc68ddfSAlbert Lee 			special = entry.mnt_special;
3237fc68ddfSAlbert Lee 
3247fc68ddfSAlbert Lee 		(void) fclose(fp);
3257fc68ddfSAlbert Lee 	}
3267fc68ddfSAlbert Lee 
3277fc68ddfSAlbert Lee 	return (special);
3287c478bd9Sstevel@tonic-gate }
329