xref: /illumos-gate/usr/src/cmd/newgrp/newgrp.c (revision fe0e7ec4)
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