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 }