1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 24*7c478bd9Sstevel@tonic-gate 25*7c478bd9Sstevel@tonic-gate 26*7c478bd9Sstevel@tonic-gate /* 27*7c478bd9Sstevel@tonic-gate * Copyright 2002 Sun Microsystems, Inc. All rights reserved. 28*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 29*7c478bd9Sstevel@tonic-gate */ 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate /* 34*7c478bd9Sstevel@tonic-gate * newgrp [-l | -] [group] 35*7c478bd9Sstevel@tonic-gate * 36*7c478bd9Sstevel@tonic-gate * rules 37*7c478bd9Sstevel@tonic-gate * if no arg, group id in password file is used 38*7c478bd9Sstevel@tonic-gate * else if group id == id in password file 39*7c478bd9Sstevel@tonic-gate * else if login name is in member list 40*7c478bd9Sstevel@tonic-gate * else if password is present and user knows it 41*7c478bd9Sstevel@tonic-gate * else too bad 42*7c478bd9Sstevel@tonic-gate */ 43*7c478bd9Sstevel@tonic-gate #include <stdio.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 45*7c478bd9Sstevel@tonic-gate #include <pwd.h> 46*7c478bd9Sstevel@tonic-gate #include <grp.h> 47*7c478bd9Sstevel@tonic-gate #include <crypt.h> 48*7c478bd9Sstevel@tonic-gate #include <string.h> 49*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 50*7c478bd9Sstevel@tonic-gate #include <locale.h> 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate #define SHELL "/usr/bin/sh" 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate #define PATH "PATH=:/usr/bin:" 55*7c478bd9Sstevel@tonic-gate #define SUPATH "PATH=:/usr/sbin:/usr/bin" 56*7c478bd9Sstevel@tonic-gate #define ELIM 128 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate char PW[] = "newgrp: Password: "; 59*7c478bd9Sstevel@tonic-gate char NG[] = "newgrp: Sorry"; 60*7c478bd9Sstevel@tonic-gate char PD[] = "newgrp: Permission denied"; 61*7c478bd9Sstevel@tonic-gate char UG[] = "newgrp: Unknown group"; 62*7c478bd9Sstevel@tonic-gate char NS[] = "newgrp: You have no shell"; 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate char *homedir; 65*7c478bd9Sstevel@tonic-gate char *logname; 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate char *envinit[ELIM]; 68*7c478bd9Sstevel@tonic-gate extern char **environ; 69*7c478bd9Sstevel@tonic-gate char *path = PATH; 70*7c478bd9Sstevel@tonic-gate char *supath = SUPATH; 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate extern void audit_newgrp_login(char *, int); 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate main(argc, argv) 75*7c478bd9Sstevel@tonic-gate char *argv[]; 76*7c478bd9Sstevel@tonic-gate { 77*7c478bd9Sstevel@tonic-gate register char *s; 78*7c478bd9Sstevel@tonic-gate register struct passwd *p; 79*7c478bd9Sstevel@tonic-gate char *rname(); 80*7c478bd9Sstevel@tonic-gate gid_t chkgrp(); 81*7c478bd9Sstevel@tonic-gate int eflag = 0; 82*7c478bd9Sstevel@tonic-gate int flag; 83*7c478bd9Sstevel@tonic-gate uid_t uid; 84*7c478bd9Sstevel@tonic-gate char *shell, *dir, *name; 85*7c478bd9Sstevel@tonic-gate size_t len; 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 88*7c478bd9Sstevel@tonic-gate chroot("."); 89*7c478bd9Sstevel@tonic-gate #endif 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 92*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 93*7c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 94*7c478bd9Sstevel@tonic-gate #endif 95*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate if ((p = getpwuid(getuid())) == NULL) 98*7c478bd9Sstevel@tonic-gate error(NG); 99*7c478bd9Sstevel@tonic-gate endpwent(); 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate while ((flag = getopt(argc, argv, "l")) != EOF) { 102*7c478bd9Sstevel@tonic-gate switch (flag) { 103*7c478bd9Sstevel@tonic-gate case 'l': 104*7c478bd9Sstevel@tonic-gate eflag++; 105*7c478bd9Sstevel@tonic-gate break; 106*7c478bd9Sstevel@tonic-gate 107*7c478bd9Sstevel@tonic-gate default: 108*7c478bd9Sstevel@tonic-gate usage(); 109*7c478bd9Sstevel@tonic-gate break; 110*7c478bd9Sstevel@tonic-gate } 111*7c478bd9Sstevel@tonic-gate } 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate argc -= optind; 114*7c478bd9Sstevel@tonic-gate argv = &argv[optind]; 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate if (argc > 0 && *argv[0] == '-') { 117*7c478bd9Sstevel@tonic-gate if (eflag) 118*7c478bd9Sstevel@tonic-gate usage(); 119*7c478bd9Sstevel@tonic-gate eflag++; 120*7c478bd9Sstevel@tonic-gate argv++; 121*7c478bd9Sstevel@tonic-gate --argc; 122*7c478bd9Sstevel@tonic-gate } 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate if (argc > 0) 125*7c478bd9Sstevel@tonic-gate p->pw_gid = chkgrp(argv[0], p); 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate uid = p->pw_uid; 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate len = strlen(p->pw_dir) + 1; 130*7c478bd9Sstevel@tonic-gate if ((dir = (char *)malloc(len)) == NULL) 131*7c478bd9Sstevel@tonic-gate error("newgrp: Memory request failed"); 132*7c478bd9Sstevel@tonic-gate (void) strncpy(dir, p->pw_dir, len); 133*7c478bd9Sstevel@tonic-gate len = strlen(p->pw_name) + 1; 134*7c478bd9Sstevel@tonic-gate if ((name = (char *)malloc(len)) == NULL) 135*7c478bd9Sstevel@tonic-gate error("newgrp: Memory request failed"); 136*7c478bd9Sstevel@tonic-gate (void) strncpy(name, p->pw_name, len); 137*7c478bd9Sstevel@tonic-gate 138*7c478bd9Sstevel@tonic-gate if (setgid(p->pw_gid) < 0 || setuid(getuid()) < 0) 139*7c478bd9Sstevel@tonic-gate error(NG); 140*7c478bd9Sstevel@tonic-gate 141*7c478bd9Sstevel@tonic-gate if (!*p->pw_shell) { 142*7c478bd9Sstevel@tonic-gate if ((shell = getenv("SHELL")) != NULL) { 143*7c478bd9Sstevel@tonic-gate p->pw_shell = shell; 144*7c478bd9Sstevel@tonic-gate } else { 145*7c478bd9Sstevel@tonic-gate p->pw_shell = SHELL; 146*7c478bd9Sstevel@tonic-gate } 147*7c478bd9Sstevel@tonic-gate } 148*7c478bd9Sstevel@tonic-gate 149*7c478bd9Sstevel@tonic-gate if (eflag) { 150*7c478bd9Sstevel@tonic-gate char *simple; 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate len = strlen(dir) + 6; 153*7c478bd9Sstevel@tonic-gate if ((homedir = (char *)malloc(len)) == NULL) 154*7c478bd9Sstevel@tonic-gate error("newgrp: Memory request failed"); 155*7c478bd9Sstevel@tonic-gate (void) snprintf(homedir, len, "HOME=%s", dir); 156*7c478bd9Sstevel@tonic-gate len = strlen(name) + 9; 157*7c478bd9Sstevel@tonic-gate if ((logname = (char *)malloc(len)) == NULL) 158*7c478bd9Sstevel@tonic-gate error("newgrp: Memory request failed"); 159*7c478bd9Sstevel@tonic-gate (void) snprintf(logname, len, "LOGNAME=%s", name); 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate 162*7c478bd9Sstevel@tonic-gate envinit[2] = logname; 163*7c478bd9Sstevel@tonic-gate chdir(dir); 164*7c478bd9Sstevel@tonic-gate envinit[0] = homedir; 165*7c478bd9Sstevel@tonic-gate if (uid == 0) 166*7c478bd9Sstevel@tonic-gate envinit[1] = supath; 167*7c478bd9Sstevel@tonic-gate else 168*7c478bd9Sstevel@tonic-gate envinit[1] = path; 169*7c478bd9Sstevel@tonic-gate envinit[3] = NULL; 170*7c478bd9Sstevel@tonic-gate environ = envinit; 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate len = strlen(p->pw_shell) + 2; 173*7c478bd9Sstevel@tonic-gate if ((shell = (char *)malloc(len)) == NULL) 174*7c478bd9Sstevel@tonic-gate error("newgrp: Memory request failed"); 175*7c478bd9Sstevel@tonic-gate (void) snprintf(shell, len, "-%s", p->pw_shell); 176*7c478bd9Sstevel@tonic-gate simple = strrchr(shell, '/'); 177*7c478bd9Sstevel@tonic-gate if (simple) { 178*7c478bd9Sstevel@tonic-gate *(shell+1) = '\0'; 179*7c478bd9Sstevel@tonic-gate shell = strcat(shell, ++simple); 180*7c478bd9Sstevel@tonic-gate } 181*7c478bd9Sstevel@tonic-gate } 182*7c478bd9Sstevel@tonic-gate else 183*7c478bd9Sstevel@tonic-gate shell = p->pw_shell; 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate execl(p->pw_shell, shell, NULL); 186*7c478bd9Sstevel@tonic-gate error(NS); 187*7c478bd9Sstevel@tonic-gate } 188*7c478bd9Sstevel@tonic-gate 189*7c478bd9Sstevel@tonic-gate warn(s) 190*7c478bd9Sstevel@tonic-gate char *s; 191*7c478bd9Sstevel@tonic-gate { 192*7c478bd9Sstevel@tonic-gate fprintf(stderr, "%s\n", gettext(s)); 193*7c478bd9Sstevel@tonic-gate } 194*7c478bd9Sstevel@tonic-gate 195*7c478bd9Sstevel@tonic-gate error(s) 196*7c478bd9Sstevel@tonic-gate char *s; 197*7c478bd9Sstevel@tonic-gate { 198*7c478bd9Sstevel@tonic-gate warn(s); 199*7c478bd9Sstevel@tonic-gate exit(1); 200*7c478bd9Sstevel@tonic-gate } 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate gid_t 203*7c478bd9Sstevel@tonic-gate chkgrp(gname, p) 204*7c478bd9Sstevel@tonic-gate char *gname; 205*7c478bd9Sstevel@tonic-gate struct passwd *p; 206*7c478bd9Sstevel@tonic-gate { 207*7c478bd9Sstevel@tonic-gate register char **t; 208*7c478bd9Sstevel@tonic-gate register struct group *g; 209*7c478bd9Sstevel@tonic-gate 210*7c478bd9Sstevel@tonic-gate g = getgrnam(gname); 211*7c478bd9Sstevel@tonic-gate endgrent(); 212*7c478bd9Sstevel@tonic-gate if (g == NULL) { 213*7c478bd9Sstevel@tonic-gate warn(UG); 214*7c478bd9Sstevel@tonic-gate return (getgid()); 215*7c478bd9Sstevel@tonic-gate } 216*7c478bd9Sstevel@tonic-gate if (p->pw_gid == g->gr_gid || getuid() == 0) 217*7c478bd9Sstevel@tonic-gate return (g->gr_gid); 218*7c478bd9Sstevel@tonic-gate for (t = g->gr_mem; *t; ++t) { 219*7c478bd9Sstevel@tonic-gate if (strcmp(p->pw_name, *t) == 0) 220*7c478bd9Sstevel@tonic-gate return (g->gr_gid); 221*7c478bd9Sstevel@tonic-gate } 222*7c478bd9Sstevel@tonic-gate if (*g->gr_passwd) { 223*7c478bd9Sstevel@tonic-gate if (!isatty(fileno(stdin))) { 224*7c478bd9Sstevel@tonic-gate error(PD); 225*7c478bd9Sstevel@tonic-gate } 226*7c478bd9Sstevel@tonic-gate if (strcmp(g->gr_passwd, 227*7c478bd9Sstevel@tonic-gate crypt(getpass(PW), g->gr_passwd)) == 0) { 228*7c478bd9Sstevel@tonic-gate audit_newgrp_login(gname, 0); 229*7c478bd9Sstevel@tonic-gate return (g->gr_gid); 230*7c478bd9Sstevel@tonic-gate } 231*7c478bd9Sstevel@tonic-gate audit_newgrp_login(gname, 1); 232*7c478bd9Sstevel@tonic-gate } 233*7c478bd9Sstevel@tonic-gate warn(NG); 234*7c478bd9Sstevel@tonic-gate return (getgid()); 235*7c478bd9Sstevel@tonic-gate } 236*7c478bd9Sstevel@tonic-gate 237*7c478bd9Sstevel@tonic-gate /* 238*7c478bd9Sstevel@tonic-gate * return pointer to rightmost component of pathname 239*7c478bd9Sstevel@tonic-gate */ 240*7c478bd9Sstevel@tonic-gate char * 241*7c478bd9Sstevel@tonic-gate rname(pn) 242*7c478bd9Sstevel@tonic-gate char *pn; 243*7c478bd9Sstevel@tonic-gate { 244*7c478bd9Sstevel@tonic-gate register char *q; 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate q = pn; 247*7c478bd9Sstevel@tonic-gate while (*pn) 248*7c478bd9Sstevel@tonic-gate if (*pn++ == '/') 249*7c478bd9Sstevel@tonic-gate q = pn; 250*7c478bd9Sstevel@tonic-gate return (q); 251*7c478bd9Sstevel@tonic-gate } 252*7c478bd9Sstevel@tonic-gate 253*7c478bd9Sstevel@tonic-gate usage() 254*7c478bd9Sstevel@tonic-gate { 255*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 256*7c478bd9Sstevel@tonic-gate "usage: newgrp [-l | -] [group]\n")); 257*7c478bd9Sstevel@tonic-gate exit(2); 258*7c478bd9Sstevel@tonic-gate } 259