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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 22 /* All Rights Reserved */ 23 24 25 /* 26 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 27 * Use is subject to license terms. 28 */ 29 30 #include <sys/types.h> 31 #include <sys/stat.h> 32 #include <stdio.h> 33 #include <ctype.h> 34 #include <limits.h> 35 #include <pwd.h> 36 #include <project.h> 37 #include <string.h> 38 #include <sys/types.h> 39 #include <sys/stat.h> 40 #include <userdefs.h> 41 #include <stdlib.h> 42 #include <errno.h> 43 #include <unistd.h> 44 #include <strings.h> 45 #include "users.h" 46 #include "messages.h" 47 #include "funcs.h" 48 49 /* 50 * userdel [-r ] login 51 * 52 * This command deletes user logins. Arguments are: 53 * 54 * -r - when given, this option removes home directory & its contents 55 * 56 * login - a string of printable chars except colon (:) 57 */ 58 59 extern int check_perm(), isbusy(), get_default_zfs_flags(); 60 extern int rm_files(), call_passmgmt(), edit_group(); 61 62 static char *logname; /* login name to delete */ 63 static char *nargv[20]; /* arguments for execvp of passmgmt */ 64 65 char *cmdname; 66 67 int 68 main(int argc, char **argv) 69 { 70 int ch, ret = 0, rflag = 0; 71 int zfs_flags = 0, argindex, tries; 72 struct passwd *pstruct; 73 struct stat statbuf; 74 #ifndef att 75 FILE *pwf; /* fille ptr for opened passwd file */ 76 #endif 77 char *usertype = NULL; 78 int rc; 79 80 cmdname = argv[0]; 81 82 if (geteuid() != 0) { 83 errmsg(M_PERM_DENIED); 84 exit(EX_NO_PERM); 85 } 86 87 opterr = 0; /* no print errors from getopt */ 88 usertype = getusertype(argv[0]); 89 90 while ((ch = getopt(argc, argv, "r")) != EOF) { 91 switch (ch) { 92 case 'r': 93 rflag++; 94 break; 95 case '?': 96 if (is_role(usertype)) 97 errmsg(M_DRUSAGE); 98 else 99 errmsg(M_DUSAGE); 100 exit(EX_SYNTAX); 101 } 102 } 103 104 if (optind != argc - 1) { 105 if (is_role(usertype)) 106 errmsg(M_DRUSAGE); 107 else 108 errmsg(M_DUSAGE); 109 exit(EX_SYNTAX); 110 } 111 112 logname = argv[optind]; 113 114 #ifdef att 115 pstruct = getpwnam(logname); 116 #else 117 /* 118 * Do this with fgetpwent to make sure we are only looking on local 119 * system (since passmgmt only works on local system). 120 */ 121 if ((pwf = fopen("/etc/passwd", "r")) == NULL) { 122 errmsg(M_OOPS, "open", "/etc/passwd"); 123 exit(EX_FAILURE); 124 } 125 while ((pstruct = fgetpwent(pwf)) != NULL) 126 if (strcmp(pstruct->pw_name, logname) == 0) 127 break; 128 129 fclose(pwf); 130 #endif 131 132 if (pstruct == NULL) { 133 errmsg(M_EXIST, logname); 134 exit(EX_NAME_NOT_EXIST); 135 } 136 137 if (isbusy(logname)) { 138 errmsg(M_BUSY, logname, "remove"); 139 exit(EX_BUSY); 140 } 141 142 /* that's it for validations - now do the work */ 143 /* set up arguments to passmgmt in nargv array */ 144 nargv[0] = PASSMGMT; 145 nargv[1] = "-d"; /* delete */ 146 argindex = 2; /* next argument */ 147 148 /* finally - login name */ 149 nargv[argindex++] = logname; 150 151 /* set the last to null */ 152 nargv[argindex++] = NULL; 153 154 /* remove home directory */ 155 if (rflag) { 156 /* Check Permissions */ 157 if (stat(pstruct->pw_dir, &statbuf)) { 158 errmsg(M_OOPS, "find status about home directory", 159 strerror(errno)); 160 exit(EX_HOMEDIR); 161 } 162 163 if (check_perm(statbuf, pstruct->pw_uid, pstruct->pw_gid, 164 S_IWOTH|S_IXOTH) != 0) { 165 errmsg(M_NO_PERM, logname, pstruct->pw_dir); 166 exit(EX_HOMEDIR); 167 } 168 zfs_flags = get_default_zfs_flags(); 169 170 if (rm_files(pstruct->pw_dir, logname, zfs_flags) != EX_SUCCESS) 171 exit(EX_HOMEDIR); 172 } 173 174 /* now call passmgmt */ 175 ret = PEX_FAILED; 176 for (tries = 3; ret != PEX_SUCCESS && tries--; ) { 177 switch (ret = call_passmgmt(nargv)) { 178 case PEX_SUCCESS: 179 ret = edit_group(logname, (char *)0, (int **)0, 1); 180 if (ret != EX_SUCCESS) 181 errmsg(M_UPDATE, "deleted"); 182 break; 183 184 case PEX_BUSY: 185 break; 186 187 case PEX_HOSED_FILES: 188 errmsg(M_HOSED_FILES); 189 exit(EX_INCONSISTENT); 190 break; 191 192 case PEX_SYNTAX: 193 case PEX_BADARG: 194 /* should NEVER occur that passmgmt usage is wrong */ 195 if (is_role(usertype)) 196 errmsg(M_DRUSAGE); 197 else 198 errmsg(M_DUSAGE); 199 exit(EX_SYNTAX); 200 break; 201 202 case PEX_BADUID: 203 /* 204 * uid is used - shouldn't happen but print message anyway 205 */ 206 errmsg(M_UID_USED, pstruct->pw_uid); 207 exit(EX_ID_EXISTS); 208 break; 209 210 case PEX_BADNAME: 211 /* invalid loname */ 212 errmsg(M_USED, logname); 213 exit(EX_NAME_EXISTS); 214 break; 215 216 default: 217 errmsg(M_UPDATE, "deleted"); 218 exit(ret); 219 break; 220 } 221 } 222 if (tries == 0) 223 errmsg(M_UPDATE, "deleted"); 224 225 /* 226 * Now, remove this user from all project entries 227 */ 228 229 rc = edit_project(logname, (char *)0, (projid_t **)0, 1); 230 if (rc != EX_SUCCESS) { 231 errmsg(M_UPDATE, "modified"); 232 exit(rc); 233 } 234 235 exit(ret); 236 /*NOTREACHED*/ 237 } 238