xref: /illumos-gate/usr/src/cmd/oamuser/user/homedir.c (revision 7fc68ddf)
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>
33*7fc68ddfSAlbert 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>
38*7fc68ddfSAlbert Lee #include <stdlib.h>
39*7fc68ddfSAlbert Lee #include <sys/mntent.h>
40*7fc68ddfSAlbert Lee #include <sys/mnttab.h>
41*7fc68ddfSAlbert Lee #include <libzfs.h>
42*7fc68ddfSAlbert Lee #include <libgen.h>
43*7fc68ddfSAlbert Lee #include <limits.h>
44*7fc68ddfSAlbert Lee #include <deflt.h>
45*7fc68ddfSAlbert Lee 
46*7fc68ddfSAlbert Lee #include "funcs.h"
477c478bd9Sstevel@tonic-gate #include "messages.h"
487c478bd9Sstevel@tonic-gate 
49*7fc68ddfSAlbert Lee #define	SBUFSZ	256
50*7fc68ddfSAlbert Lee 
51*7fc68ddfSAlbert Lee #define	DEFAULT_USERADD	"/etc/default/useradd"
527c478bd9Sstevel@tonic-gate 
53*7fc68ddfSAlbert Lee static int rm_homedir();
54*7fc68ddfSAlbert Lee static char *get_mnt_special();
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate static char cmdbuf[ SBUFSZ ];	/* buffer for system call */
57*7fc68ddfSAlbert Lee static char dhome[ PATH_MAX + 1 ]; /* buffer for dirname */
58*7fc68ddfSAlbert Lee static char bhome[ PATH_MAX + 1 ]; /* buffer for basename */
59*7fc68ddfSAlbert Lee static char pdir[ PATH_MAX + 1 ]; /* parent directory */
60*7fc68ddfSAlbert Lee static libzfs_handle_t *g_zfs = NULL;
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate /*
63*7fc68ddfSAlbert Lee  * Create a home directory and populate with files from skeleton
64*7fc68ddfSAlbert Lee  * directory.
65*7fc68ddfSAlbert Lee  */
667c478bd9Sstevel@tonic-gate int
67*7fc68ddfSAlbert 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 */
72*7fc68ddfSAlbert Lee 		/* miscellaneous flags */
737c478bd9Sstevel@tonic-gate {
74*7fc68ddfSAlbert Lee 	struct stat stbuf;
75*7fc68ddfSAlbert Lee 	char *dataset;
76*7fc68ddfSAlbert Lee 	char *dname, *bname, *rp;
77*7fc68ddfSAlbert Lee 	int created_fs = 0;
78*7fc68ddfSAlbert Lee 
79*7fc68ddfSAlbert Lee 	rp = realpath(homedir, NULL);
80*7fc68ddfSAlbert Lee 	if (rp && (strcmp(rp, "/") == 0)) {
81*7fc68ddfSAlbert Lee 		return (EX_HOMEDIR);
827c478bd9Sstevel@tonic-gate 	}
837c478bd9Sstevel@tonic-gate 
84*7fc68ddfSAlbert Lee 	(void) strcpy(dhome, homedir);
85*7fc68ddfSAlbert Lee 	(void) strcpy(bhome, homedir);
86*7fc68ddfSAlbert Lee 	dname = dirname(dhome);
87*7fc68ddfSAlbert Lee 	bname = basename(bhome);
88*7fc68ddfSAlbert Lee 	(void) strcpy(pdir, dname);
89*7fc68ddfSAlbert Lee 
90*7fc68ddfSAlbert Lee 	if ((stat(pdir, &stbuf) != 0) || !S_ISDIR(stbuf.st_mode)) {
91*7fc68ddfSAlbert Lee 		errmsg(M_OOPS, "access the parent directory", strerror(errno));
92*7fc68ddfSAlbert Lee 		return (EX_HOMEDIR);
93*7fc68ddfSAlbert Lee 	}
94*7fc68ddfSAlbert Lee 
95*7fc68ddfSAlbert Lee 	if ((strcmp(stbuf.st_fstype, MNTTYPE_ZFS) == 0) &&
96*7fc68ddfSAlbert Lee 	    (flags & MANAGE_ZFS)) {
97*7fc68ddfSAlbert Lee 		if (g_zfs == NULL)
98*7fc68ddfSAlbert Lee 			g_zfs = libzfs_init();
99*7fc68ddfSAlbert Lee 		if (g_zfs == NULL) {
100*7fc68ddfSAlbert Lee 			errmsg(M_OOPS, "libzfs_init failure", strerror(errno));
101*7fc68ddfSAlbert Lee 			return (EX_HOMEDIR);
102*7fc68ddfSAlbert Lee 		}
103*7fc68ddfSAlbert Lee 		if ((dataset = get_mnt_special(pdir, stbuf.st_fstype))
104*7fc68ddfSAlbert Lee 		    != NULL) {
105*7fc68ddfSAlbert Lee 			char nm[ZFS_MAXNAMELEN];
106*7fc68ddfSAlbert Lee 			zfs_handle_t *zhp;
107*7fc68ddfSAlbert Lee 
108*7fc68ddfSAlbert Lee 			(void) snprintf(nm, ZFS_MAXNAMELEN, "%s/%s",
109*7fc68ddfSAlbert Lee 			    dataset, bname);
110*7fc68ddfSAlbert Lee 
111*7fc68ddfSAlbert Lee 			if ((zfs_create(g_zfs, nm, ZFS_TYPE_FILESYSTEM, NULL)
112*7fc68ddfSAlbert Lee 				!= 0) ||
113*7fc68ddfSAlbert Lee 			    ((zhp = zfs_open(g_zfs, nm, ZFS_TYPE_FILESYSTEM)) ==
114*7fc68ddfSAlbert Lee 			    NULL)) {
115*7fc68ddfSAlbert Lee 				errmsg(M_OOPS, "create the home directory",
116*7fc68ddfSAlbert Lee 				    libzfs_error_description(g_zfs));
117*7fc68ddfSAlbert Lee 				libzfs_fini(g_zfs);
118*7fc68ddfSAlbert Lee 				g_zfs = NULL;
119*7fc68ddfSAlbert Lee 				return (EX_HOMEDIR);
120*7fc68ddfSAlbert Lee 			}
121*7fc68ddfSAlbert Lee 
122*7fc68ddfSAlbert Lee 			if (zfs_mount(zhp, NULL, 0) != 0) {
123*7fc68ddfSAlbert Lee 				errmsg(M_OOPS, "mount the home directory",
124*7fc68ddfSAlbert Lee 				    libzfs_error_description(g_zfs));
125*7fc68ddfSAlbert Lee 				(void) zfs_destroy(zhp, B_FALSE);
126*7fc68ddfSAlbert Lee 				zfs_close(zhp);
127*7fc68ddfSAlbert Lee 				libzfs_fini(g_zfs);
128*7fc68ddfSAlbert Lee 				g_zfs = NULL;
129*7fc68ddfSAlbert Lee 				return (EX_HOMEDIR);
130*7fc68ddfSAlbert Lee 			}
131*7fc68ddfSAlbert Lee 
132*7fc68ddfSAlbert Lee 			zfs_close(zhp);
133*7fc68ddfSAlbert Lee 
134*7fc68ddfSAlbert Lee 			if (chmod(homedir,
135*7fc68ddfSAlbert Lee 				S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) != 0) {
136*7fc68ddfSAlbert Lee 				errmsg(M_OOPS,
137*7fc68ddfSAlbert Lee 				    "change permissions of home directory",
138*7fc68ddfSAlbert Lee 				    strerror(errno));
139*7fc68ddfSAlbert Lee 				libzfs_fini(g_zfs);
140*7fc68ddfSAlbert Lee 				g_zfs = NULL;
141*7fc68ddfSAlbert Lee 				return (EX_HOMEDIR);
142*7fc68ddfSAlbert Lee 			}
143*7fc68ddfSAlbert Lee 
144*7fc68ddfSAlbert Lee 			created_fs = 1;
145*7fc68ddfSAlbert Lee 		} else {
146*7fc68ddfSAlbert Lee 			errmsg(M_NO_ZFS_MOUNTPOINT, pdir);
147*7fc68ddfSAlbert Lee 		}
148*7fc68ddfSAlbert Lee 	}
149*7fc68ddfSAlbert Lee 
150*7fc68ddfSAlbert Lee 	if (!created_fs) {
151*7fc68ddfSAlbert Lee 		if (mkdir(homedir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
152*7fc68ddfSAlbert Lee 			!= 0) {
153*7fc68ddfSAlbert Lee 			errmsg(M_OOPS, "create the home directory",
154*7fc68ddfSAlbert Lee 			    strerror(errno));
155*7fc68ddfSAlbert Lee 			if (g_zfs != NULL) {
156*7fc68ddfSAlbert Lee 				libzfs_fini(g_zfs);
157*7fc68ddfSAlbert Lee 				g_zfs = NULL;
158*7fc68ddfSAlbert Lee 			}
159*7fc68ddfSAlbert Lee 			return (EX_HOMEDIR);
160*7fc68ddfSAlbert Lee 		}
161*7fc68ddfSAlbert Lee 	}
162*7fc68ddfSAlbert Lee 
163*7fc68ddfSAlbert Lee 	if (chown(homedir, uid, gid) != 0) {
164*7fc68ddfSAlbert Lee 		errmsg(M_OOPS, "change ownership of home directory",
165ace1a5f1Sdp 		    strerror(errno));
166*7fc68ddfSAlbert Lee 		if (g_zfs != NULL) {
167*7fc68ddfSAlbert Lee 			libzfs_fini(g_zfs);
168*7fc68ddfSAlbert Lee 			g_zfs = NULL;
169*7fc68ddfSAlbert Lee 		}
170*7fc68ddfSAlbert Lee 		return (EX_HOMEDIR);
1717c478bd9Sstevel@tonic-gate 	}
1727c478bd9Sstevel@tonic-gate 
173*7fc68ddfSAlbert Lee 	if (skeldir != NULL) {
1747c478bd9Sstevel@tonic-gate 		/* copy the skel_dir into the home directory */
175*7fc68ddfSAlbert Lee 		(void) sprintf(cmdbuf, "cd %s && find . -print | cpio -pd %s",
1767c478bd9Sstevel@tonic-gate 			skeldir, homedir);
1777c478bd9Sstevel@tonic-gate 
178*7fc68ddfSAlbert Lee 		if (system(cmdbuf) != 0) {
179ace1a5f1Sdp 			errmsg(M_OOPS, "copy skeleton directory into home "
180ace1a5f1Sdp 			    "directory", strerror(errno));
181*7fc68ddfSAlbert Lee 			(void) rm_homedir(homedir, flags);
182*7fc68ddfSAlbert Lee 			if (g_zfs != NULL) {
183*7fc68ddfSAlbert Lee 				libzfs_fini(g_zfs);
184*7fc68ddfSAlbert Lee 				g_zfs = NULL;
185*7fc68ddfSAlbert Lee 			}
186*7fc68ddfSAlbert Lee 			return (EX_HOMEDIR);
1877c478bd9Sstevel@tonic-gate 		}
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate 		/* make sure contents in the home dirctory have correct owner */
190*7fc68ddfSAlbert Lee 		(void) sprintf(cmdbuf,
191*7fc68ddfSAlbert Lee 		    "cd %s && find . -exec chown %ld:%ld {} \\;",
192*7fc68ddfSAlbert Lee 		    homedir, uid, gid);
193*7fc68ddfSAlbert Lee 		if (system(cmdbuf) != 0) {
194*7fc68ddfSAlbert Lee 			errmsg(M_OOPS,
195*7fc68ddfSAlbert Lee 			    "change owner and group of files home directory",
196ace1a5f1Sdp 			    strerror(errno));
197*7fc68ddfSAlbert Lee 			(void) rm_homedir(homedir, flags);
198*7fc68ddfSAlbert Lee 			if (g_zfs != NULL) {
199*7fc68ddfSAlbert Lee 				libzfs_fini(g_zfs);
200*7fc68ddfSAlbert Lee 				g_zfs = NULL;
201*7fc68ddfSAlbert Lee 			}
202*7fc68ddfSAlbert Lee 			return (EX_HOMEDIR);
203*7fc68ddfSAlbert Lee 		}
204*7fc68ddfSAlbert Lee 
205*7fc68ddfSAlbert Lee 	}
206*7fc68ddfSAlbert Lee 	if (g_zfs != NULL) {
207*7fc68ddfSAlbert Lee 		libzfs_fini(g_zfs);
208*7fc68ddfSAlbert Lee 		g_zfs = NULL;
209*7fc68ddfSAlbert Lee 	}
210*7fc68ddfSAlbert Lee 	return (EX_SUCCESS);
211*7fc68ddfSAlbert Lee }
212*7fc68ddfSAlbert Lee 
213*7fc68ddfSAlbert Lee /* Remove a home directory structure */
214*7fc68ddfSAlbert Lee int
215*7fc68ddfSAlbert Lee rm_homedir(char *dir, int flags)
216*7fc68ddfSAlbert Lee {
217*7fc68ddfSAlbert Lee 	struct stat stbuf;
218*7fc68ddfSAlbert Lee 	char *nm, *rp;
2197c478bd9Sstevel@tonic-gate 
220*7fc68ddfSAlbert Lee 	rp = realpath(dir, NULL);
221*7fc68ddfSAlbert Lee 	if (rp && (strcmp(rp, "/") == 0)) {
222*7fc68ddfSAlbert Lee 		return (0);
223*7fc68ddfSAlbert Lee 	}
224*7fc68ddfSAlbert Lee 
225*7fc68ddfSAlbert Lee 	if ((stat(dir, &stbuf) != 0) || !S_ISDIR(stbuf.st_mode))
226*7fc68ddfSAlbert Lee 		return (0);
227*7fc68ddfSAlbert Lee 
228*7fc68ddfSAlbert Lee 	if ((strcmp(stbuf.st_fstype, MNTTYPE_ZFS) == 0) &&
229*7fc68ddfSAlbert Lee 	    (flags & MANAGE_ZFS)) {
230*7fc68ddfSAlbert Lee 		if (g_zfs == NULL)
231*7fc68ddfSAlbert Lee 			g_zfs = libzfs_init();
232*7fc68ddfSAlbert Lee 
233*7fc68ddfSAlbert Lee 		if (g_zfs == NULL) {
234*7fc68ddfSAlbert Lee 			errmsg(M_OOPS, "libzfs_init failure", strerror(errno));
235*7fc68ddfSAlbert Lee 			return (EX_HOMEDIR);
2367c478bd9Sstevel@tonic-gate 		}
2377c478bd9Sstevel@tonic-gate 
238*7fc68ddfSAlbert Lee 		if ((nm = get_mnt_special(dir, stbuf.st_fstype)) != NULL) {
239*7fc68ddfSAlbert Lee 			zfs_handle_t *zhp;
240*7fc68ddfSAlbert Lee 
241*7fc68ddfSAlbert Lee 			if ((zhp = zfs_open(g_zfs, nm, ZFS_TYPE_FILESYSTEM))
242*7fc68ddfSAlbert Lee 			    != NULL) {
243*7fc68ddfSAlbert Lee 				if ((zfs_unmount(zhp, NULL, 0) == 0) &&
244*7fc68ddfSAlbert Lee 				    (zfs_destroy(zhp, B_FALSE) == 0)) {
245*7fc68ddfSAlbert Lee 					zfs_close(zhp);
246*7fc68ddfSAlbert Lee 					libzfs_fini(g_zfs);
247*7fc68ddfSAlbert Lee 					g_zfs = NULL;
248*7fc68ddfSAlbert Lee 					return (0);
249*7fc68ddfSAlbert Lee 				}
250*7fc68ddfSAlbert Lee 
251*7fc68ddfSAlbert Lee 				errmsg(M_OOPS, "destroy the home directory",
252*7fc68ddfSAlbert Lee 				    libzfs_error_description(g_zfs));
253*7fc68ddfSAlbert Lee 
254*7fc68ddfSAlbert Lee 				(void) zfs_mount(zhp, NULL, 0);
255*7fc68ddfSAlbert Lee 				zfs_close(zhp);
256*7fc68ddfSAlbert Lee 
257*7fc68ddfSAlbert Lee 				libzfs_fini(g_zfs);
258*7fc68ddfSAlbert Lee 				g_zfs = NULL;
259*7fc68ddfSAlbert Lee 				return (EX_HOMEDIR);
260*7fc68ddfSAlbert Lee 			}
2617c478bd9Sstevel@tonic-gate 		}
2627c478bd9Sstevel@tonic-gate 	}
263*7fc68ddfSAlbert Lee 
264*7fc68ddfSAlbert Lee 	(void) sprintf(cmdbuf, "rm -rf %s", dir);
265*7fc68ddfSAlbert Lee 
266*7fc68ddfSAlbert Lee 	if (g_zfs != NULL) {
267*7fc68ddfSAlbert Lee 		libzfs_fini(g_zfs);
268*7fc68ddfSAlbert Lee 		g_zfs = NULL;
269*7fc68ddfSAlbert Lee 	}
270*7fc68ddfSAlbert Lee 
271*7fc68ddfSAlbert Lee 	return (system(cmdbuf));
272*7fc68ddfSAlbert Lee }
273*7fc68ddfSAlbert Lee 
274*7fc68ddfSAlbert Lee int
275*7fc68ddfSAlbert Lee rm_files(char *homedir, char *user, int flags)
276*7fc68ddfSAlbert Lee {
277*7fc68ddfSAlbert Lee 	if (rm_homedir(homedir, flags) != 0) {
278*7fc68ddfSAlbert Lee 		errmsg(M_RMFILES);
279*7fc68ddfSAlbert Lee 		return (EX_HOMEDIR);
280*7fc68ddfSAlbert Lee 	}
281*7fc68ddfSAlbert Lee 
282*7fc68ddfSAlbert Lee 	return (EX_SUCCESS);
2837c478bd9Sstevel@tonic-gate }
2847c478bd9Sstevel@tonic-gate 
28549335bdeSbasabi int
286*7fc68ddfSAlbert Lee get_default_zfs_flags()
287*7fc68ddfSAlbert Lee {
288*7fc68ddfSAlbert Lee 	int flags = 0;
289*7fc68ddfSAlbert Lee 
290*7fc68ddfSAlbert Lee 	if (defopen(DEFAULT_USERADD) == 0) {
291*7fc68ddfSAlbert Lee 		char *defptr;
292*7fc68ddfSAlbert Lee 
293*7fc68ddfSAlbert Lee 		if ((defptr = defread(MANAGE_ZFS_OPT)) != NULL) {
294*7fc68ddfSAlbert Lee 			char let = tolower(*defptr);
295*7fc68ddfSAlbert Lee 
296*7fc68ddfSAlbert Lee 			switch (let) {
297*7fc68ddfSAlbert Lee 				case 'y':	/* yes */
298*7fc68ddfSAlbert Lee 					flags |= MANAGE_ZFS;
299*7fc68ddfSAlbert Lee 				case 'n':	/* no */
300*7fc68ddfSAlbert Lee 					break;
301*7fc68ddfSAlbert Lee 			}
302*7fc68ddfSAlbert Lee 		}
303*7fc68ddfSAlbert Lee 		(void) defopen((char *)NULL);
304*7fc68ddfSAlbert Lee 	}
305*7fc68ddfSAlbert Lee 	return (flags);
306*7fc68ddfSAlbert Lee }
307*7fc68ddfSAlbert Lee 
308*7fc68ddfSAlbert Lee /* Get the name of a mounted filesytem */
309*7fc68ddfSAlbert Lee char *
310*7fc68ddfSAlbert Lee get_mnt_special(char *mountp, char *fstype)
3117c478bd9Sstevel@tonic-gate {
312*7fc68ddfSAlbert Lee 	struct mnttab entry, search;
313*7fc68ddfSAlbert Lee 	char *special = NULL;
314*7fc68ddfSAlbert Lee 	FILE *fp;
315*7fc68ddfSAlbert Lee 
316*7fc68ddfSAlbert Lee 	search.mnt_special = search.mnt_mntopts = search.mnt_time = NULL;
317*7fc68ddfSAlbert Lee 	search.mnt_mountp = mountp;
318*7fc68ddfSAlbert Lee 	search.mnt_fstype = fstype;
319*7fc68ddfSAlbert Lee 
320*7fc68ddfSAlbert Lee 	if ((fp = fopen(MNTTAB, "r")) != NULL) {
321*7fc68ddfSAlbert Lee 		if (getmntany(fp, &entry, &search) == 0)
322*7fc68ddfSAlbert Lee 			special = entry.mnt_special;
323*7fc68ddfSAlbert Lee 
324*7fc68ddfSAlbert Lee 		(void) fclose(fp);
325*7fc68ddfSAlbert Lee 	}
326*7fc68ddfSAlbert Lee 
327*7fc68ddfSAlbert Lee 	return (special);
3287c478bd9Sstevel@tonic-gate }
329