|
|
1.1 root 1: /*
2: * $Source: /mit/kerberos/src/kuser/RCS/ksu.c,v $
3: * $Author: jtkohl $
4: */
5:
6: /*
7: * Copyright (c) 1988 The Regents of the University of California.
8: * All rights reserved.
9: *
10: * Redistribution and use in source and binary forms are permitted
11: * provided that the above copyright notice and this paragraph are
12: * duplicated in all such forms and that any documentation,
13: * advertising materials, and other materials related to such
14: * distribution and use acknowledge that the software was developed
15: * by the University of California, Berkeley. The name of the
16: * University may not be used to endorse or promote products derived
17: * from this software without specific prior written permission.
18: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
19: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
20: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21: */
22:
23: /*
24: * Kerberos additions Copyright 1987, 1988 by the Massachusetts Institute
25: * of Technology. For copying and distribution information, please see
26: * the file <mit-copyright.h>.
27: */
28:
29: #ifndef lint
30: static char rcsid_ksu_c[] =
31: "$Header: ksu.c,v 4.0 89/01/23 10:00:28 jtkohl Exp $";
32: #endif lint
33:
34: #ifndef lint
35: char copyright[] =
36: "@(#) Copyright (c) 1988 The Regents of the University of California.\n\
37: All rights reserved.\n";
38: #endif /* not lint */
39:
40: #ifndef lint
41: static char sccsid[] = "@(#)su.c 5.11 (Berkeley) 12/7/88";
42: #endif /* not lint */
43:
44: #include <kerberos/mit-copyright.h>
45: #include <sys/param.h>
46: #include <sys/time.h>
47: #include <sys/resource.h>
48: #include <syslog.h>
49: #include <stdio.h>
50: #include <pwd.h>
51: #include <grp.h>
52: #include <kerberos/krb.h>
53: #include <netdb.h>
54: #include <sys/ioctl.h>
55:
56: #ifndef LOG_AUTH
57: #define LOG_AUTH 0
58: #endif /* LOG_AUTH */
59:
60: /* for Ultrix and friends ... */
61: #ifndef MAXHOSTNAMELEN
62: #define MAXHOSTNAMELEN 64
63: #endif
64:
65: extern char *krb_err_txt[];
66: int kerno;
67: char lrealm[REALM_SZ];
68: char krbtkfile[128];
69:
70: #define MAXPWSIZE 128 /* Biggest string we accept for a password
71: (includes space for null terminator) */
72:
73: main(argc, argv)
74: int argc;
75: char **argv;
76: {
77: extern char **environ;
78: extern int errno, optind;
79: register struct passwd *pwd;
80: register char *p, **g;
81: struct group *gr;
82: uid_t ruid, getuid();
83: #ifdef NO_GETUSERSHELL
84: int ch, fulllogin, fastlogin, prio;
85: #else
86: int asme, ch, fulllogin, fastlogin, prio;
87: #endif /* NO_GETUSERSHELL */
88: enum { UNSET, YES, NO } iscsh = UNSET;
89: char *user, *shell, *username, *cleanenv[2], *nargv[4], **np;
90: char namebuf[50], shellbuf[MAXPATHLEN];
91: char *crypt(), *getpass(), *getenv(), *getlogin(), *rindex(), *strcpy();
92: #ifdef NOENCRYPTION
93: #define read_long_pw_string placebo_read_pw_string
94: #else
95: #define read_long_pw_string des_read_pw_string
96: #endif
97: int read_long_pw_string();
98: char pw_buf[MAXPWSIZE];
99: char *mytty;
100:
101: mytty = isatty(2) ? (char *) ttyname(2) : "(no tty)";
102:
103: np = &nargv[3];
104: *np-- = NULL;
105: #ifdef NO_GETUSERSHELL
106: fulllogin = fastlogin = 0;
107: #define GETOPTARG "-flm"
108: #else
109: asme = fulllogin = fastlogin = 0;
110: #define GETOPTARG "-fl"
111: #endif
112: while ((ch = getopt(argc, argv, GETOPTARG)) != EOF)
113: switch((char)ch) {
114: case 'f':
115: fastlogin = 1;
116: break;
117: case '-':
118: case 'l':
119: fulllogin = 1;
120: break;
121: #ifndef NO_GETUSERSHELL
122: case 'm':
123: asme = 1;
124: break;
125: #endif
126: case '?':
127: default:
128: #ifdef NO_GETUSERSHELL
129: fprintf(stderr, "usage: ksu [-fl] [login]\n");
130: #else
131: fprintf(stderr, "usage: ksu [-flm] [login]\n");
132: #endif /* NO_GETUSERSHELL */
133: exit(1);
134: }
135: argv += optind;
136:
137: errno = 0;
138: prio = getpriority(PRIO_PROCESS, 0);
139: if (errno)
140: prio = 0;
141: (void)setpriority(PRIO_PROCESS, 0, -2);
142:
143: /* get current login name and shell */
144: if ((pwd = getpwuid(ruid = getuid())) == NULL) {
145: fprintf(stderr, "ksu: who are you?\n");
146: exit(1);
147: }
148: username = strcpy(namebuf, pwd->pw_name);
149: #ifndef NO_GETUSERSHELL
150: if (asme)
151: if (pwd->pw_shell && *pwd->pw_shell)
152: shell = strcpy(shellbuf, pwd->pw_shell);
153: else {
154: shell = "/bin/sh";
155: iscsh = NO;
156: }
157: #endif
158:
159: /* get target login information */
160: user = *argv ? *argv : "root";
161: if ((pwd = getpwnam(user)) == NULL) {
162: fprintf(stderr, "ksu: unknown login %s\n", user);
163: exit(1);
164: }
165:
166: /*
167: * Only allow those with kerberos root instances in the /.klogin
168: * file to su to root.
169: */
170: if (pwd->pw_uid == 0) {
171: KTEXT_ST ticket;
172: AUTH_DAT authdata;
173: char hostname[MAXHOSTNAMELEN], savehost[MAXHOSTNAMELEN];
174: unsigned long faddr;
175: struct hostent *hp;
176:
177: /* First lets see if he has a chance! */
178: if (krb_get_lrealm(lrealm, 1) != KSUCCESS) {
179: fprintf(stderr,"Unable to get local realm\n");
180: exit(1);
181: }
182: if (koktologin(username, lrealm)) {
183: fprintf(stderr,"You are not allowed to ksu to root\n");
184: exit(1);
185: }
186: sprintf(krbtkfile, "/tmp/tkt_root_%d", getuid());
187: setuid(0); /* so ticket file has good protection */
188: if (read_long_pw_string(pw_buf, sizeof(pw_buf)-1,
189: "Your root instance password: ", 0)) {
190: fprintf(stderr,"Error reading password.\n");
191: exit(1);
192: }
193: p = pw_buf;
194: setenv("KRBTKFILE", krbtkfile, 1);
195: kerno = krb_get_pw_in_tkt(username, "root", lrealm, "krbtgt",
196: lrealm, 2, p);
197: bzero(p, strlen(p));
198: if (kerno != KSUCCESS) {
199: printf("Unable to ksu: %s\n", krb_err_txt[kerno]);
200: syslog(LOG_NOTICE|LOG_AUTH, "ksu: BAD SU %s on %s: %s",
201: username, mytty, krb_err_txt[kerno]);
202: exit(1);
203: }
204: setpriority(PRIO_PROCESS, 0, -2);
205: /*
206: * Now use the ticket for something useful, to make sure
207: * it is valid.
208: */
209: if (gethostname(hostname, sizeof(hostname)) == -1) {
210: perror("cannot retrieve hostname");
211: dest_tkt();
212: exit(1);
213: }
214: (void) strncpy(savehost, krb_get_phost(hostname),
215: sizeof(savehost));
216: savehost[sizeof(savehost)-1] = 0;
217:
218: kerno = krb_mk_req(&ticket, "rcmd", savehost, lrealm, 33);
219: if (kerno == KDC_PR_UNKNOWN) {
220: printf("Warning: tgt not verified\n");
221: syslog(LOG_NOTICE|LOG_AUTH, "ksu: %s on %s: tgt not verified",
222: username, mytty);
223: } else if (kerno != KSUCCESS) {
224: printf("Unable to use tgt: %s\n", krb_err_txt[kerno]);
225: syslog(LOG_NOTICE|LOG_AUTH, "ksu: failed su: %s on %s: %s",
226: username, mytty, krb_err_txt[kerno]);
227: dest_tkt();
228: exit(1);
229: } else {
230: if (!(hp = gethostbyname(hostname))) {
231: printf("Unable to get address of %s\n",hostname);
232: dest_tkt();
233: exit(1);
234: }
235: bcopy((char *)hp->h_addr, (char *) &faddr, sizeof(faddr));
236: if ((kerno = krb_rd_req(&ticket, "rcmd", savehost,
237: faddr, &authdata, "")) != KSUCCESS) {
238: printf("Unable to verify rcmd ticket: %s\n",
239: krb_err_txt[kerno]);
240: syslog(LOG_NOTICE|LOG_AUTH, "ksu: failed su: %s on %s: %s",
241: username, mytty, krb_err_txt[kerno]);
242: dest_tkt();
243: exit(1);
244: }
245: }
246: printf("Don't forget to kdestroy before exiting the root shell.\n");
247: } else
248: /* if target requires a password, verify it */
249: if (ruid && *pwd->pw_passwd) {
250: p = getpass("Password:");
251: if (strcmp(pwd->pw_passwd, crypt(p, pwd->pw_passwd))) {
252: fprintf(stderr, "Sorry\n");
253: if (pwd->pw_uid == 0)
254: syslog(LOG_CRIT|LOG_AUTH, "ksu: BAD SU %s on %s", username, mytty);
255: exit(1);
256: }
257: }
258:
259: #ifndef NO_GETUSERSHELL
260: if (asme) {
261: /* if asme and non-standard target shell, must be root */
262: if (!chshell(pwd->pw_shell) && ruid) {
263: fprintf(stderr, "ksu: Permission denied.\n");
264: dest_tkt();
265: exit(1);
266: }
267: }
268: else
269: #endif
270: if (pwd->pw_shell && *pwd->pw_shell) {
271: shell = pwd->pw_shell;
272: iscsh = UNSET;
273: } else {
274: shell = "/bin/sh";
275: iscsh = NO;
276: }
277:
278: /* if we're forking a csh, we want to slightly muck the args */
279: if (iscsh == UNSET) {
280: if (p = rindex(shell, '/'))
281: ++p;
282: else
283: p = shell;
284: iscsh = strcmp(p, "csh") ? NO : YES;
285: }
286:
287: /* set permissions */
288: if (setgid(pwd->pw_gid) < 0) {
289: perror("ksu: setgid");
290: dest_tkt();
291: exit(1);
292: }
293: if (initgroups(user, pwd->pw_gid)) {
294: fprintf(stderr, "ksu: initgroups failed\n");
295: dest_tkt();
296: exit(1);
297: }
298: if (setuid(pwd->pw_uid) < 0) {
299: perror("ksu: setuid");
300: dest_tkt();
301: exit(1);
302: }
303:
304: #ifndef NO_GETUSERSHELL
305: if (!asme) {
306: #endif
307: if (fulllogin) {
308: p = getenv("TERM");
309: cleanenv[0] = "PATH=:/usr/ucb:/bin:/usr/bin";
310: cleanenv[1] = NULL;
311: environ = cleanenv;
312: (void)setenv("TERM", p, 1);
313: if (chdir(pwd->pw_dir) < 0) {
314: fprintf(stderr, "ksu: no directory\n");
315: dest_tkt();
316: exit(1);
317: }
318: }
319: if (fulllogin || pwd->pw_uid)
320: (void)setenv("USER", pwd->pw_name, 1);
321: (void)setenv("HOME", pwd->pw_dir, 1);
322: (void)setenv("SHELL", shell, 1);
323: #ifndef NO_GETUSERSHELL
324: }
325: #endif
326:
327: if (iscsh == YES) {
328: if (fastlogin)
329: *np-- = "-f";
330: #ifndef NO_GETUSERSHELL
331: if (asme)
332: *np-- = "-m";
333: #endif
334: }
335:
336: /* csh strips the first character... */
337: *np = fulllogin ? "-ksu" : iscsh == YES ? "_ksu" : "ksu";
338:
339: if (pwd->pw_uid == 0)
340: syslog(LOG_NOTICE|LOG_AUTH, "ksu: %s on %s",
341: username, mytty);
342:
343: (void)setpriority(PRIO_PROCESS, 0, prio);
344:
345: execv(shell, np);
346: fprintf(stderr, "ksu: no shell.\n");
347: dest_tkt();
348: exit(1);
349: }
350:
351: #ifndef NO_GETUSERSHELL
352: chshell(sh)
353: char *sh;
354: {
355: char *cp, *getusershell();
356:
357: while ((cp = getusershell()) != NULL)
358: if (!strcmp(cp, sh))
359: return(1);
360: return(0);
361: }
362: #endif /* NO_GETUSERSHELL */
363:
364: koktologin(name, realm)
365: char *name;
366: char *realm;
367: {
368: struct auth_dat kdata_st;
369: AUTH_DAT *kdata = &kdata_st;
370: /* Cons together an AUTH_DAT structure for kuserok */
371: bzero((caddr_t) kdata, sizeof(*kdata));
372: strcpy(kdata->pname, name);
373: strcpy(kdata->pinst, "root");
374: strcpy(kdata->prealm, realm);
375: return (kuserok(kdata, "root"));
376: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.