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