1 /* @(#)idops.c	1.41 21/07/19 Copyright 1985-2021 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static	UConst char sccsid[] =
5 	"@(#)idops.c	1.41 21/07/19 Copyright 1985-2021 J. Schilling";
6 #endif
7 /*
8  *	uid und gid Routinen
9  *
10  *	Copyright (c) 1985-2021 J. Schilling
11  */
12 /*
13  * The contents of this file are subject to the terms of the
14  * Common Development and Distribution License, Version 1.0 only
15  * (the "License").  You may not use this file except in compliance
16  * with the License.
17  *
18  * See the file CDDL.Schily.txt in this distribution for details.
19  * A copy of the CDDL is also available via the Internet at
20  * http://www.opensource.org/licenses/cddl1.txt
21  *
22  * When distributing Covered Code, include this CDDL HEADER in each
23  * file and include the License file CDDL.Schily.txt from this distribution.
24  */
25 
26 #include <schily/mconfig.h>
27 #if	!defined(__CYGWIN32__) && !defined(__CYGWIN__)
28 #include <schily/stdio.h>
29 #include <schily/signal.h>
30 #include <schily/pwd.h>
31 #include <schily/shadow.h>
32 #	define	SUNAME	"root"
33 #include "bsh.h"
34 #include "str.h"
35 #include "abbrev.h"
36 #include "strsubs.h"
37 #include <schily/string.h>
38 #include <schily/syslog.h>
39 #include <schily/unistd.h>
40 #include <schily/stdlib.h>
41 
42 #define	UGROUP		0
43 #define	UPASSWD		1
44 #define	UGID		2
45 #define	UISIZE		4
46 #define	UNAME		0
47 
48 extern BOOL 	firstsh;
49 extern BOOL	vflg;
50 
51 extern	char	*crypt		__PR((const char *key, const char *salt));
52 
53 #ifdef	DO_SUID
54 EXPORT	void	bsuid		__PR((Argvec * vp, FILE ** std, int flag));
55 #endif
56 LOCAL	void	dosyslog	__PR((char *type));
57 LOCAL	int	readpw		__PR((FILE ** std, char *passwd, int size));
58 
59 
60 #ifdef	DO_SUID
61 
62 #if	defined(HAVE_GETSPNAM) || defined(HAVE_GETSPWNAM) || defined(HAVE_PW_PASSWD)
63 /* ARGSUSED */
64 EXPORT void
bsuid(vp,std,flag)65 bsuid(vp, std, flag)
66 	Argvec	*vp;
67 	FILE	*std[];
68 	int	flag;
69 {
70 	char		passwd[100];
71 	struct passwd	*pw;
72 #if	defined(HAVE_GETSPNAM) || defined(HAVE_GETSPWNAM)
73 #ifdef	HAVE_GETSPNAM
74 	struct spwd	*sp;
75 #else
76 	struct s_passwd	*sp;
77 #define	sp_pwdp		pw_passwd
78 #endif
79 #endif
80 	pid_t		child;
81 	char		*av0;
82 	char		*name;
83 	uid_t		new_uid;
84 	sigtype		o_sig2;
85 	sigtype		o_sig3;
86 	char		*init2;
87 	extern pid_t mypid;
88 	extern pid_t mypgrp;
89 	extern pid_t opgrp;
90 
91 	if (ev_eql("SUID", off)) {
92 		fprintf(std[2], "suid: restricted.\n");
93 		ex_status = 1;
94 		return;
95 	}
96 	if (vp->av_ac > 2) {
97 		wrong_args(vp, std);
98 		return;
99 	}
100 	name = (vp->av_ac == 2) ? vp->av_av[1] : SUNAME;
101 #if	defined(HAVE_GETSPNAM) || defined(HAVE_GETSPWNAM)
102 	seteuid(0);
103 	if ((pw = getpwnam(name)) == (struct passwd *)0 ||
104 #ifdef	HAVE_GETSPNAM
105 			(sp = getspnam(name)) == (struct spwd *)0) {
106 #else
107 			/*
108 			 * Note: getspwnam() (HP-UX) is in libsec.a
109 			 */
110 			(sp = getspwnam(name)) == (struct s_passwd *)0) {
111 #endif
112 		seteuid(getuid());
113 		fprintf(std[2], "Unknown login: %s\n", name);
114 		ex_status = 1;
115 		return;
116 	}
117 	seteuid(getuid());
118 #else
119 	if ((pw = getpwnam(name)) == (struct passwd *)0) {
120 		fprintf(std[2], "Unknown login: %s\n", name);
121 		ex_status = 1;
122 		return;
123 	}
124 #endif
125 #ifdef DEBUG
126 	printf("geteuid: %d, pw->pw_uid: %d.\n", geteuid(), pw->pw_uid);
127 #endif
128 	if (geteuid() == pw->pw_uid) {
129 		fprintf(std[2], "Already %s.\n", pw->pw_name);
130 		ex_status = 1;
131 		return;
132 	}
133 	new_uid = pw->pw_uid;
134 #if	defined(HAVE_GETSPNAM) || defined(HAVE_GETSPWNAM)
135 	if (geteuid() && (strlen(sp->sp_pwdp) > (unsigned)0)) {
136 #else
137 	if (geteuid() && (strlen(pw->pw_passwd) > (unsigned)0)) {
138 #endif
139 /*		char buf[20];*/
140 		char *bp;
141 
142 		if (readpw(std, passwd, sizeof (passwd)) < 0) {
143 			ex_status = 1;
144 			return;
145 		}
146 		fputc('\n', std[1]);
147 /*		bp = encrypt_password(passwd, buf);*/
148 
149 #if	defined(HAVE_GETSPNAM) || defined(HAVE_GETSPWNAM)
150 		bp = crypt(passwd, sp->sp_pwdp);
151 		if (!streql(bp, sp->sp_pwdp)) {
152 			seteuid(0);
153 #ifdef	HAVE_GETSPNAM
154 			if (!(sp = getspnam(SUNAME))) {
155 #else
156 			/*
157 			 * Note: getspwnam() (HP-UX) is in libsec.a
158 			 */
159 			if (!(sp = getspwnam(SUNAME))) {
160 #endif
161 				seteuid(getuid());
162 				ex_status = 1;
163 				return;
164 			}
165 			seteuid(getuid());
166 			bp = crypt(passwd, sp->sp_pwdp);
167 			if (*(sp->sp_pwdp) && !streql(bp, sp->sp_pwdp)) {
168 #else
169 		bp = crypt(passwd, pw->pw_passwd);
170 		if (!streql(bp, pw->pw_passwd)) {
171 			if (!(pw = getpwnam(SUNAME))) {
172 				ex_status = 1;
173 				return;
174 			}
175 			bp = crypt(passwd, pw->pw_passwd);
176 			if (*(pw->pw_passwd) && !streql(bp, pw->pw_passwd)) {
177 #endif /* HAVE_SHADOW_H */
178 				fprintf(std[2], "Sorry\n");
179 				dosyslog("BAD");
180 				ex_status = 1;
181 				return;
182 			}
183 		}
184 	}
185 	dosyslog("");
186 	o_sig2 = signal(SIGINT, (sigtype) SIG_IGN);
187 	o_sig3 = signal(SIGQUIT, (sigtype) SIG_IGN);
188 	signal(SIGINT, o_sig2);
189 	signal(SIGQUIT, o_sig3);
190 	if ((child = shfork(flag|NOSIG)) != 0) {
191 		if (child < 0) {
192 			ex_status = child;
193 			return;
194 		}
195 		ewait(child, WALL);
196 		return;
197 	}
198 	/*
199 	 * This is the child...
200 	 */
201 	if (!(flag & NOSIG)) {
202 		osig2 = o_sig2;
203 		osig3 = o_sig3;
204 		if (o_sig2 != (sigtype) SIG_IGN) {
205 			signal(SIGINT, o_sig2);
206 			osig2 = osig3 = (sigtype) SIG_DFL;
207 		}
208 	}
209 	signal(SIGTERM, (sigtype) SIG_IGN);
210 #ifdef	SIGTSTP
211 	signal(SIGTSTP, (sigtype) SIG_IGN);
212 #endif
213 #ifdef	SIGTTIN
214 	signal(SIGTTIN, (sigtype) SIG_IGN);
215 #endif
216 #ifdef	SIGTTOU
217 	signal(SIGTTOU, (sigtype) SIG_IGN);
218 #endif
219 	mypid = getpid();
220 	mypgrp = opgrp = getpgid(0);
221 	av0 = saved_av()[0];
222 	*av0 = '+';
223 	vflg = FALSE;
224 	ev_insert(concat(ignoreeofname, eql, off, (char *)NULL));
225 	init2 = concat(pw->pw_dir, slash, init2name, (char *)NULL);
226 	dofile(init2, GLOBAL_AB, NOTMS, std, FALSE);
227 	free(init2);
228 	ev_insert(concat(vp->av_ac == 2?"PROMPT=++":"PROMPT=",
229 						name, "> ", (char *)NULL));
230 #if	defined(HAVE_SETEUID)
231 	seteuid(0);
232 #else
233 #ifdef	HAVE_SETRESUID
234 	setresuid(-1, 0, -1);	/* HP-UX setresuid(ruid, euid, suid)*/
235 #else
236 #ifdef	HAVE_SETREUID		/* BSD & POSIX */
237 	setreuid(-1, 0);
238 #else
239 	/*
240 	 * Hier sollte nur dann eine Warnung/Abbruch kommen, wenn
241 	 * der bsh tats�chlich suid root installiert ist.
242 	 */
243 #if !defined(__EMX__) && !defined(__DJGPP__) && !defined(__BEOS__)
244 error  No function to set uid available
245 #endif
246 
247 #endif
248 #endif
249 #endif
250 	if (vp->av_ac == 2)	/* mit su admin wird man real admin */
251 		setuid(new_uid);
252 }
253 #else
254 /* ARGSUSED */
255 EXPORT void
bsuid(vp,std,flag)256 bsuid(vp, std, flag)
257 	Argvec	*vp;
258 	FILE	*std[];
259 	int	flag;
260 {
261 	fprintf(std[2], "suid: unsupported.\n");
262 	ex_status = 1;
263 }
264 #endif
265 
266 #ifdef	SYSLOG
267 LOCAL void
dosyslog(type)268 dosyslog(type)
269 	char	*type;
270 {
271 	char	*uname;
272 
273 	uname = getuname(geteuid());
274 	openlog("bsh", LOG_NULL);
275 	syslog(LOG_CRIT, "%sSU: %s %s", type, uname, ttyname(fdown(gstd[0])));
276 	closelog();
277 	free(uname);
278 }
279 #else
280 LOCAL void
dosyslog(type)281 dosyslog(type)
282 	char	*type;
283 {
284 #ifdef	DOSYSLOG
285 	extern	char	**evarray;
286 	extern	unsigned evasize;
287 	int	oeve = evaent;
288 	char	*s;
289 	char	*uname = getuname(geteuid());
290 	char	**oeva = evarray;
291 	unsigned oevs = evasize;
292 
293 	evarray = (char **)NULL;
294 	evasize = 0;
295 	evaent = 0;
296 	ev_inc();
297 	s = concat("syslog -i bsh -CRIT ",
298 		type, "SU: ", uname, " ", ttyname(fdown(gstd[0])), (char *)NULL);
299 	pushline(s);
300 	freetree(cmdline(0, gstd, FALSE));
301 	free(s);
302 	free(evarray);
303 	evarray	 = oeva;
304 	evasize = oevs;
305 	evaent = oeve;
306 #else
307 	return;
308 #endif
309 }
310 #endif
311 
312 LOCAL int
readpw(std,passwd,size)313 readpw(std, passwd, size)
314 	FILE	*std[];
315 	char	*passwd;
316 	int	size;
317 {
318 	int	code;
319 
320 #ifdef	INTERACTIVE
321 	set_append_modes(std[0]);
322 	set_insert_modes(std[0]);
323 	fprintf(std[1], "Password:");
324 	code = fgetline(std[0], passwd, size);
325 /*XXX ???	reset_tty_modes(std[0]);*/
326 	reset_tty_modes();
327 #else
328 	char	*p;
329 
330 	p = getpass("Password:");
331 	if (p == NULL)
332 		return (-1);
333 	strcpy(passwd, p);
334 	return (1);
335 #endif
336 #ifdef DEBUGX
337 	printf("Passwd: %s, retcode: %d, file: %d\n", passwd, code, f);
338 #endif
339 	return (code);
340 }
341 
342 #endif
343 
344 #endif	/* !__CYGWIN32__ && !__CYGWIN__ */
345