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
main(int argc,char * argv[])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
warn(char * s)194 warn(char *s)
195 {
196 (void) fprintf(stderr, "%s\n", gettext(s));
197 }
198
199 void
error(char * s)200 error(char *s)
201 {
202 warn(s);
203 exit(1);
204 }
205
206 void
put_event(char * gname,int sorf)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
chkgrp(gname,p)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
usage(void)273 usage(void)
274 {
275 (void) fprintf(stderr, gettext(
276 "usage: newgrp [-l | -] [group]\n"));
277 exit(2);
278 }
279