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
main(int argc,char ** argv)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