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