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