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