xref: /illumos-gate/usr/src/cmd/oamuser/user/userdel.c (revision c651b32e)
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();
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, argindex, tries;
71 	struct passwd *pstruct;
72 	struct stat statbuf;
73 #ifndef att
74 	FILE *pwf;		/* fille ptr for opened passwd file */
75 #endif
76 	char *usertype = NULL;
77 	int rc;
78 
79 	cmdname = argv[0];
80 
81 	if( geteuid() != 0 ) {
82 		errmsg( M_PERM_DENIED );
83 		exit( EX_NO_PERM );
84 	}
85 
86 	opterr = 0;			/* no print errors from getopt */
87 	usertype = getusertype(argv[0]);
88 
89 	while( (ch = getopt(argc, argv, "r")) != EOF ) {
90 		switch(ch) {
91 			case 'r':
92 				rflag++;
93 				break;
94 			case '?':
95 				if (is_role(usertype))
96 					errmsg( M_DRUSAGE );
97 				else
98 					errmsg( M_DUSAGE );
99 				exit( EX_SYNTAX );
100 		}
101 	}
102 
103 	if( optind != argc - 1 ) {
104 		if (is_role(usertype))
105 			errmsg( M_DRUSAGE );
106 		else
107 			errmsg( M_DUSAGE );
108 		exit( EX_SYNTAX );
109 	}
110 
111 	logname = argv[optind];
112 
113 #ifdef att
114 	pstruct = getpwnam(logname);
115 #else
116 	/*
117 	 * Do this with fgetpwent to make sure we are only looking on local
118 	 * system (since passmgmt only works on local system).
119 	 */
120 	if ((pwf = fopen("/etc/passwd", "r")) == NULL) {
121 		errmsg( M_OOPS, "open", "/etc/passwd");
122 		exit(EX_FAILURE);
123 	}
124 	while ((pstruct = fgetpwent(pwf)) != NULL)
125 		if (strcmp(pstruct->pw_name, logname) == 0)
126 			break;
127 
128 	fclose(pwf);
129 #endif
130 
131 	if (pstruct == NULL) {
132 		errmsg( M_EXIST, logname );
133 		exit( EX_NAME_NOT_EXIST );
134 	}
135 
136 	if( isbusy(logname) ) {
137 		errmsg( M_BUSY, logname, "remove" );
138 		exit( EX_BUSY );
139 	}
140 
141 	/* that's it for validations - now do the work */
142 	/* set up arguments to  passmgmt in nargv array */
143 	nargv[0] = PASSMGMT;
144 	nargv[1] = "-d";	/* delete */
145 	argindex = 2;		/* next argument */
146 
147 	/* finally - login name */
148 	nargv[argindex++] = logname;
149 
150 	/* set the last to null */
151 	nargv[argindex++] = NULL;
152 
153 	/* remove home directory */
154 	if( rflag ) {
155 		/* Check Permissions */
156 		if( stat( pstruct->pw_dir, &statbuf ) ) {
157 			errmsg(M_OOPS, "find status about home directory",
158 			    strerror(errno));
159 			exit( EX_HOMEDIR );
160 		}
161 
162 		if( check_perm( statbuf, pstruct->pw_uid, pstruct->pw_gid,
163 		    S_IWOTH|S_IXOTH ) != 0 ) {
164 			errmsg( M_NO_PERM, logname, pstruct->pw_dir );
165 			exit( EX_HOMEDIR );
166 		}
167 
168 		if( rm_files(pstruct->pw_dir, logname) != EX_SUCCESS )
169 			exit( EX_HOMEDIR );
170 	}
171 
172 	/* now call passmgmt */
173 	ret = PEX_FAILED;
174 	for( tries = 3; ret != PEX_SUCCESS && tries--; ) {
175 		switch( ret = call_passmgmt( nargv ) ) {
176 		case PEX_SUCCESS:
177 			ret = edit_group( logname, (char *)0, (int **)0, 1 );
178 			if( ret != EX_SUCCESS )
179 				errmsg( M_UPDATE, "deleted" );
180 			break;
181 
182 		case PEX_BUSY:
183 			break;
184 
185 		case PEX_HOSED_FILES:
186 			errmsg( M_HOSED_FILES );
187 			exit( EX_INCONSISTENT );
188 			break;
189 
190 		case PEX_SYNTAX:
191 		case PEX_BADARG:
192 			/* should NEVER occur that passmgmt usage is wrong */
193 			if (is_role(usertype))
194 				errmsg( M_DRUSAGE );
195 			else
196 				errmsg( M_DUSAGE );
197 			exit( EX_SYNTAX );
198 			break;
199 
200 		case PEX_BADUID:
201 			/* uid is used - shouldn't happen but print message anyway */
202 			errmsg( M_UID_USED, pstruct->pw_uid );
203 			exit( EX_ID_EXISTS );
204 			break;
205 
206 		case PEX_BADNAME:
207 			/* invalid loname */
208 			errmsg( M_USED, logname);
209 			exit( EX_NAME_EXISTS );
210 			break;
211 
212 		default:
213 			errmsg( M_UPDATE, "deleted" );
214 			exit( ret );
215 			break;
216 		}
217 	}
218 	if( tries == 0 )
219 		errmsg( M_UPDATE, "deleted" );
220 
221 /*
222  * Now, remove this user from all project entries
223  */
224 
225 	rc = edit_project(logname, (char *)0, (projid_t **)0, 1);
226 	if (rc != EX_SUCCESS) {
227 		errmsg(M_UPDATE, "modified");
228 		exit(rc);
229 	}
230 
231 	exit( ret );
232 	/*NOTREACHED*/
233 }
234