1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 23 /* 24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 29 /* All Rights Reserved */ 30 31 32 #include <sys/types.h> 33 #include <sys/stat.h> 34 #include <stdio.h> 35 #include <userdefs.h> 36 #include <errno.h> 37 #include <strings.h> 38 #include <stdlib.h> 39 #include <sys/mntent.h> 40 #include <sys/mnttab.h> 41 #include <libzfs.h> 42 #include <libgen.h> 43 #include <limits.h> 44 #include <deflt.h> 45 46 #include "funcs.h" 47 #include "messages.h" 48 49 #define SBUFSZ 256 50 51 #define DEFAULT_USERADD "/etc/default/useradd" 52 53 static int rm_homedir(); 54 static char *get_mnt_special(); 55 56 static char cmdbuf[ SBUFSZ ]; /* buffer for system call */ 57 static char dhome[ PATH_MAX + 1 ]; /* buffer for dirname */ 58 static char bhome[ PATH_MAX + 1 ]; /* buffer for basename */ 59 static char pdir[ PATH_MAX + 1 ]; /* parent directory */ 60 static libzfs_handle_t *g_zfs = NULL; 61 62 /* 63 * Create a home directory and populate with files from skeleton 64 * directory. 65 */ 66 int 67 create_home(char *homedir, char *skeldir, uid_t uid, gid_t gid, int flags) 68 /* home directory to create */ 69 /* skel directory to copy if indicated */ 70 /* uid of new user */ 71 /* group id of new user */ 72 /* miscellaneous flags */ 73 { 74 struct stat stbuf; 75 char *dataset; 76 char *dname, *bname, *rp; 77 int created_fs = 0; 78 79 rp = realpath(homedir, NULL); 80 if (rp && (strcmp(rp, "/") == 0)) { 81 return (EX_HOMEDIR); 82 } 83 84 (void) strcpy(dhome, homedir); 85 (void) strcpy(bhome, homedir); 86 dname = dirname(dhome); 87 bname = basename(bhome); 88 (void) strcpy(pdir, dname); 89 90 if ((stat(pdir, &stbuf) != 0) || !S_ISDIR(stbuf.st_mode)) { 91 errmsg(M_OOPS, "access the parent directory", strerror(errno)); 92 return (EX_HOMEDIR); 93 } 94 95 if ((strcmp(stbuf.st_fstype, MNTTYPE_ZFS) == 0) && 96 (flags & MANAGE_ZFS)) { 97 if (g_zfs == NULL) 98 g_zfs = libzfs_init(); 99 if (g_zfs == NULL) { 100 errmsg(M_OOPS, "libzfs_init failure", strerror(errno)); 101 return (EX_HOMEDIR); 102 } 103 if ((dataset = get_mnt_special(pdir, stbuf.st_fstype)) 104 != NULL) { 105 char nm[ZFS_MAXNAMELEN]; 106 zfs_handle_t *zhp; 107 108 (void) snprintf(nm, ZFS_MAXNAMELEN, "%s/%s", 109 dataset, bname); 110 111 if ((zfs_create(g_zfs, nm, ZFS_TYPE_FILESYSTEM, NULL) 112 != 0) || 113 ((zhp = zfs_open(g_zfs, nm, ZFS_TYPE_FILESYSTEM)) == 114 NULL)) { 115 errmsg(M_OOPS, "create the home directory", 116 libzfs_error_description(g_zfs)); 117 libzfs_fini(g_zfs); 118 g_zfs = NULL; 119 return (EX_HOMEDIR); 120 } 121 122 if (zfs_mount(zhp, NULL, 0) != 0) { 123 errmsg(M_OOPS, "mount the home directory", 124 libzfs_error_description(g_zfs)); 125 (void) zfs_destroy(zhp, B_FALSE); 126 zfs_close(zhp); 127 libzfs_fini(g_zfs); 128 g_zfs = NULL; 129 return (EX_HOMEDIR); 130 } 131 132 zfs_close(zhp); 133 134 if (chmod(homedir, 135 S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) != 0) { 136 errmsg(M_OOPS, 137 "change permissions of home directory", 138 strerror(errno)); 139 libzfs_fini(g_zfs); 140 g_zfs = NULL; 141 return (EX_HOMEDIR); 142 } 143 144 created_fs = 1; 145 } else { 146 errmsg(M_NO_ZFS_MOUNTPOINT, pdir); 147 } 148 } 149 150 if (!created_fs) { 151 if (mkdir(homedir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) 152 != 0) { 153 errmsg(M_OOPS, "create the home directory", 154 strerror(errno)); 155 if (g_zfs != NULL) { 156 libzfs_fini(g_zfs); 157 g_zfs = NULL; 158 } 159 return (EX_HOMEDIR); 160 } 161 } 162 163 if (chown(homedir, uid, gid) != 0) { 164 errmsg(M_OOPS, "change ownership of home directory", 165 strerror(errno)); 166 if (g_zfs != NULL) { 167 libzfs_fini(g_zfs); 168 g_zfs = NULL; 169 } 170 return (EX_HOMEDIR); 171 } 172 173 if (skeldir != NULL) { 174 /* copy the skel_dir into the home directory */ 175 (void) sprintf(cmdbuf, "cd %s && find . -print | cpio -pd %s", 176 skeldir, homedir); 177 178 if (system(cmdbuf) != 0) { 179 errmsg(M_OOPS, "copy skeleton directory into home " 180 "directory", strerror(errno)); 181 (void) rm_homedir(homedir, flags); 182 if (g_zfs != NULL) { 183 libzfs_fini(g_zfs); 184 g_zfs = NULL; 185 } 186 return (EX_HOMEDIR); 187 } 188 189 /* make sure contents in the home dirctory have correct owner */ 190 (void) sprintf(cmdbuf, 191 "cd %s && find . -exec chown %ld:%ld {} \\;", 192 homedir, uid, gid); 193 if (system(cmdbuf) != 0) { 194 errmsg(M_OOPS, 195 "change owner and group of files home directory", 196 strerror(errno)); 197 (void) rm_homedir(homedir, flags); 198 if (g_zfs != NULL) { 199 libzfs_fini(g_zfs); 200 g_zfs = NULL; 201 } 202 return (EX_HOMEDIR); 203 } 204 205 } 206 if (g_zfs != NULL) { 207 libzfs_fini(g_zfs); 208 g_zfs = NULL; 209 } 210 return (EX_SUCCESS); 211 } 212 213 /* Remove a home directory structure */ 214 int 215 rm_homedir(char *dir, int flags) 216 { 217 struct stat stbuf; 218 char *nm, *rp; 219 220 rp = realpath(dir, NULL); 221 if (rp && (strcmp(rp, "/") == 0)) { 222 return (0); 223 } 224 225 if ((stat(dir, &stbuf) != 0) || !S_ISDIR(stbuf.st_mode)) 226 return (0); 227 228 if ((strcmp(stbuf.st_fstype, MNTTYPE_ZFS) == 0) && 229 (flags & MANAGE_ZFS)) { 230 if (g_zfs == NULL) 231 g_zfs = libzfs_init(); 232 233 if (g_zfs == NULL) { 234 errmsg(M_OOPS, "libzfs_init failure", strerror(errno)); 235 return (EX_HOMEDIR); 236 } 237 238 if ((nm = get_mnt_special(dir, stbuf.st_fstype)) != NULL) { 239 zfs_handle_t *zhp; 240 241 if ((zhp = zfs_open(g_zfs, nm, ZFS_TYPE_FILESYSTEM)) 242 != NULL) { 243 if ((zfs_unmount(zhp, NULL, 0) == 0) && 244 (zfs_destroy(zhp, B_FALSE) == 0)) { 245 zfs_close(zhp); 246 libzfs_fini(g_zfs); 247 g_zfs = NULL; 248 return (0); 249 } 250 251 errmsg(M_OOPS, "destroy the home directory", 252 libzfs_error_description(g_zfs)); 253 254 (void) zfs_mount(zhp, NULL, 0); 255 zfs_close(zhp); 256 257 libzfs_fini(g_zfs); 258 g_zfs = NULL; 259 return (EX_HOMEDIR); 260 } 261 } 262 } 263 264 (void) sprintf(cmdbuf, "rm -rf %s", dir); 265 266 if (g_zfs != NULL) { 267 libzfs_fini(g_zfs); 268 g_zfs = NULL; 269 } 270 271 return (system(cmdbuf)); 272 } 273 274 int 275 rm_files(char *homedir, char *user, int flags) 276 { 277 if (rm_homedir(homedir, flags) != 0) { 278 errmsg(M_RMFILES); 279 return (EX_HOMEDIR); 280 } 281 282 return (EX_SUCCESS); 283 } 284 285 int 286 get_default_zfs_flags() 287 { 288 int flags = 0; 289 290 if (defopen(DEFAULT_USERADD) == 0) { 291 char *defptr; 292 293 if ((defptr = defread(MANAGE_ZFS_OPT)) != NULL) { 294 char let = tolower(*defptr); 295 296 switch (let) { 297 case 'y': /* yes */ 298 flags |= MANAGE_ZFS; 299 case 'n': /* no */ 300 break; 301 } 302 } 303 (void) defopen((char *)NULL); 304 } 305 return (flags); 306 } 307 308 /* Get the name of a mounted filesytem */ 309 char * 310 get_mnt_special(char *mountp, char *fstype) 311 { 312 struct mnttab entry, search; 313 char *special = NULL; 314 FILE *fp; 315 316 search.mnt_special = search.mnt_mntopts = search.mnt_time = NULL; 317 search.mnt_mountp = mountp; 318 search.mnt_fstype = fstype; 319 320 if ((fp = fopen(MNTTAB, "r")) != NULL) { 321 if (getmntany(fp, &entry, &search) == 0) 322 special = entry.mnt_special; 323 324 (void) fclose(fp); 325 } 326 327 return (special); 328 } 329