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