su.c revision 74874
1/*
2 * Copyright (c) 1988, 1993, 1994
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by the University of
16 *	California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35static const char copyright[] =
36"@(#) Copyright (c) 1988, 1993, 1994\n\
37	The Regents of the University of California.  All rights reserved.\n";
38#endif /* not lint */
39
40#ifndef lint
41#if 0
42static char sccsid[] = "@(#)su.c	8.3 (Berkeley) 4/2/94";
43#endif
44static const char rcsid[] =
45  "$FreeBSD: head/usr.bin/su/su.c 74874 2001-03-27 19:40:51Z markm $";
46#endif /* not lint */
47
48#include <sys/param.h>
49#include <sys/time.h>
50#include <sys/resource.h>
51
52#include <err.h>
53#include <errno.h>
54#include <grp.h>
55#include <paths.h>
56#include <pwd.h>
57#include <stdio.h>
58#include <stdlib.h>
59#include <string.h>
60#include <syslog.h>
61#include <unistd.h>
62#include <libutil.h>
63#include <login_cap.h>
64
65#ifdef USE_PAM
66#include <security/pam_appl.h>
67#include <security/pam_misc.h>
68#include <signal.h>
69#include <sys/wait.h>
70
71static int export_pam_environment __P((void));
72static int ok_to_export __P((const char *));
73
74static pam_handle_t *pamh = NULL;
75static char **environ_pam;
76
77#define PAM_END { \
78	if ((retcode = pam_setcred(pamh, PAM_DELETE_CRED)) != PAM_SUCCESS) { \
79		syslog(LOG_ERR, "pam_setcred: %s", pam_strerror(pamh, retcode)); \
80	} \
81	if ((retcode = pam_end(pamh,retcode)) != PAM_SUCCESS) { \
82		syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, retcode)); \
83	} \
84}
85#else /* !USE_PAM */
86#ifdef	SKEY
87#include <skey.h>
88#endif
89#endif /* USE_PAM */
90
91#ifdef KERBEROS
92#include <openssl/des.h>
93#include <krb.h>
94#include <netdb.h>
95
96#define	ARGSTR	"-Kflmc:"
97
98static int kerberos(char *username, char *user, int uid, char *pword);
99static int koktologin(char *name, char *toname);
100
101int use_kerberos = 1;
102#else /* !KERBEROS */
103#define	ARGSTR	"-flmc:"
104#endif /* KERBEROS */
105
106char   *ontty __P((void));
107int	chshell __P((char *));
108static void usage __P((void));
109
110int
111main(argc, argv)
112	int argc;
113	char **argv;
114{
115	extern char **environ;
116	struct passwd *pwd;
117#ifdef WHEELSU
118	char *targetpass;
119	int iswheelsu;
120#endif /* WHEELSU */
121	char *p, *user, *shell=NULL, *username, *cleanenv = NULL, **nargv, **np;
122	uid_t ruid;
123	gid_t gid;
124	int asme, ch, asthem, fastlogin, prio, i;
125	enum { UNSET, YES, NO } iscsh = UNSET;
126	login_cap_t *lc;
127	char *class=NULL;
128	int setwhat;
129#ifdef USE_PAM
130	int retcode;
131	struct pam_conv conv = { misc_conv, NULL };
132	char myhost[MAXHOSTNAMELEN + 1], *mytty;
133	int statusp=0;
134	int child_pid, child_pgrp, ret_pid;
135#else /* !USE_PAM */
136	char **g;
137	struct group *gr;
138#endif /* USE_PAM */
139#ifdef KERBEROS
140	char *k;
141#endif
142	char shellbuf[MAXPATHLEN];
143
144#ifdef WHEELSU
145	iswheelsu =
146#endif /* WHEELSU */
147	asme = asthem = fastlogin = 0;
148	user = "root";
149	while((ch = getopt(argc, argv, ARGSTR)) != -1)
150		switch((char)ch) {
151#ifdef KERBEROS
152		case 'K':
153			use_kerberos = 0;
154			break;
155#endif
156		case 'f':
157			fastlogin = 1;
158			break;
159		case '-':
160		case 'l':
161			asme = 0;
162			asthem = 1;
163			break;
164		case 'm':
165			asme = 1;
166			asthem = 0;
167			break;
168		case 'c':
169			class = optarg;
170			break;
171		case '?':
172		default:
173			usage();
174		}
175
176	if (optind < argc)
177		user = argv[optind++];
178
179	if (strlen(user) > MAXLOGNAME - 1) {
180		errx(1, "username too long");
181	}
182
183	if (user == NULL)
184		usage();
185
186	if ((nargv = malloc (sizeof (char *) * (argc + 4))) == NULL) {
187	    errx(1, "malloc failure");
188	}
189
190	nargv[argc + 3] = NULL;
191	for (i = argc; i >= optind; i--)
192	    nargv[i + 3] = argv[i];
193	np = &nargv[i + 3];
194
195	argv += optind;
196
197#ifdef KERBEROS
198	k = auth_getval("auth_list");
199	if (k && !strstr(k, "kerberos"))
200	    use_kerberos = 0;
201#endif
202	errno = 0;
203	prio = getpriority(PRIO_PROCESS, 0);
204	if (errno)
205		prio = 0;
206	(void)setpriority(PRIO_PROCESS, 0, -2);
207	openlog("su", LOG_CONS, LOG_AUTH);
208
209	/* get current login name and shell */
210	ruid = getuid();
211	username = getlogin();
212	if (username == NULL || (pwd = getpwnam(username)) == NULL ||
213	    pwd->pw_uid != ruid)
214		pwd = getpwuid(ruid);
215	if (pwd == NULL)
216		errx(1, "who are you?");
217	username = strdup(pwd->pw_name);
218	gid = pwd->pw_gid;
219	if (username == NULL)
220		err(1, NULL);
221	if (asme) {
222		if (pwd->pw_shell != NULL && *pwd->pw_shell != '\0') {
223			/* copy: pwd memory is recycled */
224			shell = strncpy(shellbuf,  pwd->pw_shell, sizeof shellbuf);
225			shellbuf[sizeof shellbuf - 1] = '\0';
226		} else {
227			shell = _PATH_BSHELL;
228			iscsh = NO;
229		}
230	}
231
232#ifdef USE_PAM
233	retcode = pam_start("su", user, &conv, &pamh);
234	if (retcode != PAM_SUCCESS) {
235		syslog(LOG_ERR, "pam_start: %s", pam_strerror(pamh, retcode));
236		errx(1, "pam_start: %s", pam_strerror(pamh, retcode));
237	}
238
239	gethostname(myhost, sizeof(myhost));
240	retcode = pam_set_item(pamh, PAM_RHOST, myhost);
241	if (retcode != PAM_SUCCESS) {
242		syslog(LOG_ERR, "pam_set_item(PAM_RHOST): %s", pam_strerror(pamh, retcode));
243		errx(1, "pam_set_item(PAM_RHOST): %s", pam_strerror(pamh, retcode));
244	}
245
246	mytty = ttyname(STDERR_FILENO);
247	if (!mytty)
248		mytty = "tty";
249	retcode = pam_set_item(pamh, PAM_TTY, mytty);
250	if (retcode != PAM_SUCCESS) {
251		syslog(LOG_ERR, "pam_set_item(PAM_TTY): %s", pam_strerror(pamh, retcode));
252		errx(1, "pam_set_item(PAM_TTY): %s", pam_strerror(pamh, retcode));
253	}
254
255	if (ruid) {
256		retcode = pam_authenticate(pamh, 0);
257		if (retcode != PAM_SUCCESS) {
258			syslog(LOG_ERR, "pam_authenticate: %s", pam_strerror(pamh, retcode));
259			errx(1, "Sorry");
260		}
261
262		if ((retcode = pam_get_item(pamh, PAM_USER, (const void **) &p)) == PAM_SUCCESS) {
263			user = p;
264		} else
265			syslog(LOG_ERR, "pam_get_item(PAM_USER): %s",
266			       pam_strerror(pamh, retcode));
267
268		retcode = pam_acct_mgmt(pamh, 0);
269		if (retcode == PAM_NEW_AUTHTOK_REQD) {
270			retcode = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
271			if (retcode != PAM_SUCCESS) {
272				syslog(LOG_ERR, "pam_chauthtok: %s", pam_strerror(pamh, retcode));
273				errx(1, "Sorry");
274			}
275		}
276		if (retcode != PAM_SUCCESS) {
277			syslog(LOG_ERR, "pam_acct_mgmt: %s", pam_strerror(pamh, retcode));
278			errx(1, "Sorry");
279		}
280	}
281#endif /* USE_PAM */
282
283	/* get target login information, default to root */
284	if ((pwd = getpwnam(user)) == NULL) {
285		errx(1, "unknown login: %s", user);
286	}
287	if (class==NULL) {
288		lc = login_getpwclass(pwd);
289	} else {
290		if (ruid)
291			errx(1, "only root may use -c");
292		lc = login_getclass(class);
293		if (lc == NULL)
294			errx(1, "unknown class: %s", class);
295	}
296
297#ifndef USE_PAM
298#ifdef WHEELSU
299	targetpass = strdup(pwd->pw_passwd);
300#endif /* WHEELSU */
301
302	if (ruid) {
303#ifdef KERBEROS
304		if (use_kerberos && koktologin(username, user)
305		    && !pwd->pw_uid) {
306			warnx("kerberos: not in %s's ACL.", user);
307			use_kerberos = 0;
308		}
309#endif
310		{
311			/*
312			 * Only allow those with pw_gid==0 or those listed in
313			 * group zero to su to root.  If group zero entry is
314			 * missing or empty, then allow anyone to su to root.
315			 * iswheelsu will only be set if the user is EXPLICITLY
316			 * listed in group zero.
317			 */
318			if (pwd->pw_uid == 0 && (gr = getgrgid((gid_t)0)) &&
319			    gr->gr_mem && *(gr->gr_mem))
320				for (g = gr->gr_mem;; ++g) {
321					if (!*g) {
322						if (gid == 0)
323							break;
324						else
325							errx(1, "you are not in the correct group to su %s.", user);
326					}
327					if (strcmp(username, *g) == 0) {
328#ifdef WHEELSU
329						iswheelsu = 1;
330#endif /* WHEELSU */
331						break;
332					}
333				}
334		}
335		/* if target requires a password, verify it */
336		if (*pwd->pw_passwd) {
337#ifdef	SKEY
338#ifdef WHEELSU
339			if (iswheelsu) {
340				pwd = getpwnam(username);
341			}
342#endif /* WHEELSU */
343			p = skey_getpass("Password:", pwd, 1);
344			if (!(!strcmp(pwd->pw_passwd, skey_crypt(p, pwd->pw_passwd, pwd, 1))
345#ifdef WHEELSU
346			      || (iswheelsu && !strcmp(targetpass, crypt(p,targetpass)))
347#endif /* WHEELSU */
348			      ))
349#else /* !SKEY */
350			p = getpass("Password:");
351			if (strcmp(pwd->pw_passwd, crypt(p, pwd->pw_passwd)))
352#endif /* SKEY */
353			{
354#ifdef KERBEROS
355	    			if (!use_kerberos || (use_kerberos && kerberos(username, user, pwd->pw_uid, p)))
356#endif
357				{
358					syslog(LOG_AUTH|LOG_WARNING, "BAD SU %s to %s%s", username, user, ontty());
359					errx(1, "Sorry");
360				}
361			}
362#ifdef WHEELSU
363			if (iswheelsu) {
364				pwd = getpwnam(user);
365			}
366#endif /* WHEELSU */
367		}
368		if (pwd->pw_expire && time(NULL) >= pwd->pw_expire) {
369			syslog(LOG_AUTH|LOG_WARNING,
370				"BAD SU %s to %s%s", username,
371				user, ontty());
372			errx(1, "Sorry - account expired");
373		}
374	}
375#endif /* USE_PAM */
376
377	if (asme) {
378		/* if asme and non-standard target shell, must be root */
379		if (ruid && !chshell(pwd->pw_shell))
380			errx(1, "permission denied (shell).");
381	} else if (pwd->pw_shell && *pwd->pw_shell) {
382		shell = pwd->pw_shell;
383		iscsh = UNSET;
384	} else {
385		shell = _PATH_BSHELL;
386		iscsh = NO;
387	}
388
389	/* if we're forking a csh, we want to slightly muck the args */
390	if (iscsh == UNSET) {
391		p = strrchr(shell, '/');
392		if (p)
393			++p;
394		else
395			p = shell;
396		if ((iscsh = strcmp(p, "csh") ? NO : YES) == NO)
397		    iscsh = strcmp(p, "tcsh") ? NO : YES;
398	}
399
400	(void)setpriority(PRIO_PROCESS, 0, prio);
401
402	/*
403	 * PAM modules might add supplementary groups in
404	 * pam_setcred(), so initialize them first.
405	 */
406	if (setusercontext(lc, pwd, pwd->pw_uid, LOGIN_SETGROUP) < 0)
407		err(1, "setusercontext");
408
409#ifdef USE_PAM
410	retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED);
411	if (retcode != PAM_SUCCESS) {
412		syslog(LOG_ERR, "pam_setcred: %s", pam_strerror(pamh, retcode));
413	}
414
415	/*
416	 * We must fork() before setuid() because we need to call
417	 * pam_setcred(pamh, PAM_DELETE_CRED) as root.
418	 */
419
420	statusp = 1;
421	switch ((child_pid = fork())) {
422	default:
423            while ((ret_pid = waitpid(child_pid, &statusp, WUNTRACED)) != -1) {
424		if (WIFSTOPPED(statusp)) {
425		    child_pgrp = tcgetpgrp(1);
426		    kill(getpid(), SIGSTOP);
427		    tcsetpgrp(1, child_pgrp);
428		    kill(child_pid, SIGCONT);
429		    statusp = 1;
430		    continue;
431		}
432		break;
433            }
434	    if (ret_pid == -1)
435		err(1, "waitpid");
436	    PAM_END;
437	    exit(statusp);
438	case -1:
439	    err(1, "fork");
440	    PAM_END;
441	    exit (1);
442	case 0:
443#endif /* USE_PAM */
444
445	/*
446	 * Set all user context except for:
447	 *   Environmental variables
448	 *   Umask
449	 *   Login records (wtmp, etc)
450	 *   Path
451	 */
452	setwhat =  LOGIN_SETALL & ~(LOGIN_SETENV | LOGIN_SETUMASK |
453	    LOGIN_SETLOGIN | LOGIN_SETPATH | LOGIN_SETGROUP);
454
455	/*
456	 * Don't touch resource/priority settings if -m has been
457	 * used or -l and -c hasn't, and we're not su'ing to root.
458	 */
459        if ((asme || (!asthem && class == NULL)) && pwd->pw_uid)
460		setwhat &= ~(LOGIN_SETPRIORITY|LOGIN_SETRESOURCES);
461	if (setusercontext(lc, pwd, pwd->pw_uid, setwhat) < 0)
462		err(1, "setusercontext");
463
464	if (!asme) {
465		if (asthem) {
466			p = getenv("TERM");
467#ifdef KERBEROS
468			k = getenv("KRBTKFILE");
469#endif
470			environ = &cleanenv;
471
472#ifdef USE_PAM
473			/*
474			 * Add any environmental variables that the
475			 * PAM modules may have set.
476			 */
477			environ_pam = pam_getenvlist(pamh);
478			if (environ_pam)
479				export_pam_environment();
480#endif /* USE_PAM */
481
482			/* set the su'd user's environment & umask */
483			setusercontext(lc, pwd, pwd->pw_uid, LOGIN_SETPATH|LOGIN_SETUMASK|LOGIN_SETENV);
484			if (p)
485				(void)setenv("TERM", p, 1);
486#ifdef KERBEROS
487			if (k)
488				(void)setenv("KRBTKFILE", k, 1);
489#endif
490			if (chdir(pwd->pw_dir) < 0)
491				errx(1, "no directory");
492		}
493		if (asthem || pwd->pw_uid)
494			(void)setenv("USER", pwd->pw_name, 1);
495		(void)setenv("HOME", pwd->pw_dir, 1);
496		(void)setenv("SHELL", shell, 1);
497	}
498
499	login_close(lc);
500
501	if (iscsh == YES) {
502		if (fastlogin)
503			*np-- = "-f";
504		if (asme)
505			*np-- = "-m";
506	}
507
508	/* csh strips the first character... */
509	*np = asthem ? "-su" : iscsh == YES ? "_su" : "su";
510
511	if (ruid != 0)
512		syslog(LOG_NOTICE, "%s to %s%s",
513		    username, user, ontty());
514
515	execv(shell, np);
516	err(1, "%s", shell);
517#ifdef USE_PAM
518	}
519#endif /* USE_PAM */
520}
521
522#ifdef USE_PAM
523static int
524export_pam_environment()
525{
526	char	**pp;
527
528	for (pp = environ_pam; *pp != NULL; pp++) {
529		if (ok_to_export(*pp))
530			(void) putenv(*pp);
531		free(*pp);
532	}
533	return PAM_SUCCESS;
534}
535
536/*
537 * Sanity checks on PAM environmental variables:
538 * - Make sure there is an '=' in the string.
539 * - Make sure the string doesn't run on too long.
540 * - Do not export certain variables.  This list was taken from the
541 *   Solaris pam_putenv(3) man page.
542 */
543static int
544ok_to_export(s)
545	const char *s;
546{
547	static const char *noexport[] = {
548		"SHELL", "HOME", "LOGNAME", "MAIL", "CDPATH",
549		"IFS", "PATH", NULL
550	};
551	const char **pp;
552	size_t n;
553
554	if (strlen(s) > 1024 || strchr(s, '=') == NULL)
555		return 0;
556	if (strncmp(s, "LD_", 3) == 0)
557		return 0;
558	for (pp = noexport; *pp != NULL; pp++) {
559		n = strlen(*pp);
560		if (s[n] == '=' && strncmp(s, *pp, n) == 0)
561			return 0;
562	}
563	return 1;
564}
565#endif /* USE_PAM */
566
567static void
568usage()
569{
570	errx(1, "usage: su [%s] [login [args]]", ARGSTR);
571}
572
573int
574chshell(sh)
575	char *sh;
576{
577	int  r = 0;
578	char *cp;
579
580	setusershell();
581	while (!r && (cp = getusershell()) != NULL)
582		r = strcmp(cp, sh) == 0;
583	endusershell();
584	return r;
585}
586
587char *
588ontty()
589{
590	char *p;
591	static char buf[MAXPATHLEN + 4];
592
593	buf[0] = 0;
594	p = ttyname(STDERR_FILENO);
595	if (p)
596		snprintf(buf, sizeof(buf), " on %s", p);
597	return (buf);
598}
599
600#ifdef KERBEROS
601int
602kerberos(username, user, uid, pword)
603	char *username, *user;
604	int uid;
605	char *pword;
606{
607	KTEXT_ST ticket;
608	AUTH_DAT authdata;
609	int kerno;
610	u_long faddr;
611	char lrealm[REALM_SZ], krbtkfile[MAXPATHLEN];
612	char hostname[MAXHOSTNAMELEN], savehost[MAXHOSTNAMELEN];
613	char *krb_get_phost();
614	struct hostent *hp;
615
616	if (krb_get_lrealm(lrealm, 1) != KSUCCESS)
617		return (1);
618	(void)sprintf(krbtkfile, "%s_%s_%lu", TKT_ROOT, user,
619	    (unsigned long)getuid());
620
621	(void)setenv("KRBTKFILE", krbtkfile, 1);
622	(void)krb_set_tkt_string(krbtkfile);
623	/*
624	 * Set real as well as effective ID to 0 for the moment,
625	 * to make the kerberos library do the right thing.
626	 */
627	if (setuid(0) < 0) {
628		warn("setuid");
629		return (1);
630	}
631
632	/*
633	 * Little trick here -- if we are su'ing to root,
634	 * we need to get a ticket for "xxx.root", where xxx represents
635	 * the name of the person su'ing.  Otherwise (non-root case),
636	 * we need to get a ticket for "yyy.", where yyy represents
637	 * the name of the person being su'd to, and the instance is null
638	 *
639	 * We should have a way to set the ticket lifetime,
640	 * with a system default for root.
641	 */
642	kerno = krb_get_pw_in_tkt((uid == 0 ? username : user),
643		(uid == 0 ? "root" : ""), lrealm,
644	    	"krbtgt", lrealm, DEFAULT_TKT_LIFE, pword);
645
646	if (kerno != KSUCCESS) {
647		if (kerno == KDC_PR_UNKNOWN) {
648			warnx("kerberos: principal unknown: %s.%s@%s",
649				(uid == 0 ? username : user),
650				(uid == 0 ? "root" : ""), lrealm);
651			return (1);
652		}
653		warnx("kerberos: unable to su: %s", krb_err_txt[kerno]);
654		syslog(LOG_NOTICE,
655		    "BAD Kerberos SU: %s to %s%s: %s",
656		    username, user, ontty(), krb_err_txt[kerno]);
657		return (1);
658	}
659
660	if (chown(krbtkfile, uid, -1) < 0) {
661		warn("chown");
662		(void)unlink(krbtkfile);
663		return (1);
664	}
665
666	(void)setpriority(PRIO_PROCESS, 0, -2);
667
668	if (gethostname(hostname, sizeof(hostname)) == -1) {
669		warn("gethostname");
670		dest_tkt();
671		return (1);
672	}
673
674	(void)strncpy(savehost, krb_get_phost(hostname), sizeof(savehost));
675	savehost[sizeof(savehost) - 1] = '\0';
676
677	kerno = krb_mk_req(&ticket, "rcmd", savehost, lrealm, 33);
678
679	if (kerno == KDC_PR_UNKNOWN) {
680		warnx("Warning: TGT not verified.");
681		syslog(LOG_NOTICE,
682		    "%s to %s%s, TGT not verified (%s); %s.%s not registered?",
683		    username, user, ontty(), krb_err_txt[kerno],
684		    "rcmd", savehost);
685	} else if (kerno != KSUCCESS) {
686		warnx("Unable to use TGT: %s", krb_err_txt[kerno]);
687		syslog(LOG_NOTICE, "failed su: %s to %s%s: %s",
688		    username, user, ontty(), krb_err_txt[kerno]);
689		dest_tkt();
690		return (1);
691	} else {
692		if (!(hp = gethostbyname(hostname))) {
693			warnx("can't get addr of %s", hostname);
694			dest_tkt();
695			return (1);
696		}
697		memmove((char *)&faddr, (char *)hp->h_addr, sizeof(faddr));
698
699		if ((kerno = krb_rd_req(&ticket, "rcmd", savehost, faddr,
700		    &authdata, "")) != KSUCCESS) {
701			warnx("kerberos: unable to verify rcmd ticket: %s",
702			    krb_err_txt[kerno]);
703			syslog(LOG_NOTICE,
704			    "failed su: %s to %s%s: %s", username,
705			     user, ontty(), krb_err_txt[kerno]);
706			dest_tkt();
707			return (1);
708		}
709	}
710	return (0);
711}
712
713int
714koktologin(name, toname)
715	char *name, *toname;
716{
717	AUTH_DAT *kdata;
718	AUTH_DAT kdata_st;
719	char realm[REALM_SZ];
720
721	if (krb_get_lrealm(realm, 1) != KSUCCESS)
722		return (1);
723	kdata = &kdata_st;
724	memset((char *)kdata, 0, sizeof(*kdata));
725	(void)strncpy(kdata->pname, name, sizeof kdata->pname - 1);
726	(void)strncpy(kdata->pinst,
727	    ((strcmp(toname, "root") == 0) ? "root" : ""), sizeof kdata->pinst - 1);
728	(void)strncpy(kdata->prealm, realm, sizeof kdata->prealm - 1);
729	return (kuserok(kdata, toname));
730}
731#endif
732