xref: /illumos-gate/usr/src/cmd/oamuser/user/userdel.c (revision d8109ce4330e1b8ad6c29f9fccacec969066bb9d)
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