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