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