xref: /illumos-gate/usr/src/cmd/newgrp/newgrp.c (revision 7c478bd9)
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 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23 /*	  All Rights Reserved  	*/
24 
25 
26 /*
27  * Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
28  * Use is subject to license terms.
29  */
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 main(argc, argv)
75 char *argv[];
76 {
77 	register char *s;
78 	register struct passwd *p;
79 	char *rname();
80 	gid_t chkgrp();
81 	int eflag = 0;
82 	int flag;
83 	uid_t uid;
84 	char *shell, *dir, *name;
85 	size_t len;
86 
87 #ifdef	DEBUG
88 	chroot(".");
89 #endif
90 
91 	(void) setlocale(LC_ALL, "");
92 #if !defined(TEXT_DOMAIN)		/* Should be defined by cc -D */
93 #define	TEXT_DOMAIN	"SYS_TEST"	/* Use this only if it weren't */
94 #endif
95 	(void) textdomain(TEXT_DOMAIN);
96 
97 	if ((p = getpwuid(getuid())) == NULL)
98 		error(NG);
99 	endpwent();
100 
101 	while ((flag = getopt(argc, argv, "l")) != EOF) {
102 		switch (flag) {
103 		case 'l':
104 			eflag++;
105 			break;
106 
107 		default:
108 			usage();
109 			break;
110 		}
111 	}
112 
113 	argc -= optind;
114 	argv = &argv[optind];
115 
116 	if (argc > 0 && *argv[0] == '-') {
117 		if (eflag)
118 			usage();
119 		eflag++;
120 		argv++;
121 		--argc;
122 	}
123 
124 	if (argc > 0)
125 		p->pw_gid = chkgrp(argv[0], p);
126 
127 	uid = p->pw_uid;
128 
129 	len = strlen(p->pw_dir) + 1;
130 	if ((dir = (char *)malloc(len)) == NULL)
131 		error("newgrp: Memory request failed");
132 	(void) strncpy(dir, p->pw_dir, len);
133 	len = strlen(p->pw_name) + 1;
134 	if ((name = (char *)malloc(len)) == NULL)
135 		error("newgrp: Memory request failed");
136 	(void) strncpy(name, p->pw_name, len);
137 
138 	if (setgid(p->pw_gid) < 0 || setuid(getuid()) < 0)
139 		error(NG);
140 
141 	if (!*p->pw_shell) {
142 		if ((shell = getenv("SHELL")) != NULL) {
143 			p->pw_shell = shell;
144 		} else {
145 			p->pw_shell = SHELL;
146 		}
147 	}
148 
149 	if (eflag) {
150 		char *simple;
151 
152 		len = strlen(dir) + 6;
153 		if ((homedir = (char *)malloc(len)) == NULL)
154 			error("newgrp: Memory request failed");
155 		(void) snprintf(homedir, len, "HOME=%s", dir);
156 		len = strlen(name) + 9;
157 		if ((logname = (char *)malloc(len)) == NULL)
158 			error("newgrp: Memory request failed");
159 		(void) snprintf(logname, len, "LOGNAME=%s", name);
160 
161 
162 		envinit[2] = logname;
163 		chdir(dir);
164 		envinit[0] = homedir;
165 		if (uid == 0)
166 			envinit[1] = supath;
167 		else
168 			envinit[1] = path;
169 		envinit[3] = NULL;
170 		environ = envinit;
171 
172 		len = strlen(p->pw_shell) + 2;
173 		if ((shell = (char *)malloc(len)) == NULL)
174 			error("newgrp: Memory request failed");
175 		(void) snprintf(shell, len, "-%s", p->pw_shell);
176 		simple = strrchr(shell, '/');
177 		if (simple) {
178 			*(shell+1) = '\0';
179 			shell = strcat(shell, ++simple);
180 		}
181 	}
182 	else
183 		shell = p->pw_shell;
184 
185 	execl(p->pw_shell, shell, NULL);
186 	error(NS);
187 }
188 
189 warn(s)
190 char *s;
191 {
192 	fprintf(stderr, "%s\n", gettext(s));
193 }
194 
195 error(s)
196 char *s;
197 {
198 	warn(s);
199 	exit(1);
200 }
201 
202 gid_t
203 chkgrp(gname, p)
204 char	*gname;
205 struct	passwd *p;
206 {
207 	register char **t;
208 	register struct group *g;
209 
210 	g = getgrnam(gname);
211 	endgrent();
212 	if (g == NULL) {
213 		warn(UG);
214 		return (getgid());
215 	}
216 	if (p->pw_gid == g->gr_gid || getuid() == 0)
217 		return (g->gr_gid);
218 	for (t = g->gr_mem; *t; ++t) {
219 		if (strcmp(p->pw_name, *t) == 0)
220 			return (g->gr_gid);
221 	}
222 	if (*g->gr_passwd) {
223 		if (!isatty(fileno(stdin))) {
224 			error(PD);
225 		}
226 		if (strcmp(g->gr_passwd,
227 		    crypt(getpass(PW), g->gr_passwd)) == 0) {
228 			audit_newgrp_login(gname, 0);
229 			return (g->gr_gid);
230 		}
231 		audit_newgrp_login(gname, 1);
232 	}
233 	warn(NG);
234 	return (getgid());
235 }
236 
237 /*
238  * return pointer to rightmost component of pathname
239  */
240 char *
241 rname(pn)
242 char *pn;
243 {
244 	register char *q;
245 
246 	q = pn;
247 	while (*pn)
248 		if (*pn++ == '/')
249 			q = pn;
250 	return (q);
251 }
252 
253 usage()
254 {
255 	fprintf(stderr, gettext(
256 		"usage: newgrp [-l | -] [group]\n"));
257 	exit(2);
258 }
259