su.c revision 21646
11590Srgrimes/*
21590Srgrimes * Copyright (c) 1988, 1993, 1994
31590Srgrimes *	The Regents of the University of California.  All rights reserved.
41590Srgrimes *
51590Srgrimes * Redistribution and use in source and binary forms, with or without
61590Srgrimes * modification, are permitted provided that the following conditions
71590Srgrimes * are met:
81590Srgrimes * 1. Redistributions of source code must retain the above copyright
91590Srgrimes *    notice, this list of conditions and the following disclaimer.
101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111590Srgrimes *    notice, this list of conditions and the following disclaimer in the
121590Srgrimes *    documentation and/or other materials provided with the distribution.
131590Srgrimes * 3. All advertising materials mentioning features or use of this software
141590Srgrimes *    must display the following acknowledgement:
151590Srgrimes *	This product includes software developed by the University of
161590Srgrimes *	California, Berkeley and its contributors.
171590Srgrimes * 4. Neither the name of the University nor the names of its contributors
181590Srgrimes *    may be used to endorse or promote products derived from this software
191590Srgrimes *    without specific prior written permission.
201590Srgrimes *
211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311590Srgrimes * SUCH DAMAGE.
321590Srgrimes */
331590Srgrimes
341590Srgrimes#ifndef lint
3514440Smarkmstatic const char copyright[] =
361590Srgrimes"@(#) Copyright (c) 1988, 1993, 1994\n\
371590Srgrimes	The Regents of the University of California.  All rights reserved.\n";
381590Srgrimes#endif /* not lint */
391590Srgrimes
401590Srgrimes#ifndef lint
4114440Smarkm/*
421590Srgrimesstatic char sccsid[] = "@(#)su.c	8.3 (Berkeley) 4/2/94";
4314440Smarkm*/
4414440Smarkmstatic const char rcsid[] =
4521646Sdavidn	"$Id: su.c,v 1.14 1996/10/07 10:00:58 joerg Exp $";
461590Srgrimes#endif /* not lint */
471590Srgrimes
481590Srgrimes#include <sys/param.h>
491590Srgrimes#include <sys/time.h>
501590Srgrimes#include <sys/resource.h>
511590Srgrimes
521590Srgrimes#include <err.h>
531590Srgrimes#include <errno.h>
541590Srgrimes#include <grp.h>
551590Srgrimes#include <paths.h>
561590Srgrimes#include <pwd.h>
571590Srgrimes#include <stdio.h>
581590Srgrimes#include <stdlib.h>
591590Srgrimes#include <string.h>
601590Srgrimes#include <syslog.h>
611590Srgrimes#include <unistd.h>
621590Srgrimes
6321646Sdavidn#ifdef LOGIN_CAP
6421646Sdavidn#include <login_cap.h>
6521646Sdavidn#ifdef LOGIN_CAP_AUTH
6621646Sdavidn#undef SKEY
6721646Sdavidn#undef KERBEROS
6821646Sdavidn#endif
6921646Sdavidn#endif
7021646Sdavidn
713702Spst#ifdef	SKEY
723702Spst#include <skey.h>
733702Spst#endif
743702Spst
751590Srgrimes#ifdef KERBEROS
7614024Smarkm#include <des.h>
771590Srgrimes#include <kerberosIV/krb.h>
781590Srgrimes#include <netdb.h>
791590Srgrimes
801590Srgrimes#define	ARGSTR	"-Kflm"
811590Srgrimes
8214440Smarkmstatic int kerberos(char *username, char *user, int uid, char *pword);
8314440Smarkmstatic int koktologin(char *name, char *toname);
8414440Smarkm
851590Srgrimesint use_kerberos = 1;
8621646Sdavidn#else /* !KERBEROS */
871590Srgrimes#define	ARGSTR	"-flm"
8821646Sdavidn#endif /* KERBEROS */
891590Srgrimes
901590Srgrimeschar   *ontty __P((void));
911590Srgrimesint	chshell __P((char *));
921590Srgrimes
931590Srgrimesint
941590Srgrimesmain(argc, argv)
951590Srgrimes	int argc;
961590Srgrimes	char **argv;
971590Srgrimes{
981590Srgrimes	extern char **environ;
991590Srgrimes	struct passwd *pwd;
1009502Swollman#ifdef WHEELSU
1019502Swollman	char *targetpass;
1029502Swollman	int iswheelsu;
1039502Swollman#endif /* WHEELSU */
10410586Sjoerg	char *p, **g, *user, *shell, *username, *cleanenv[20], **nargv, **np;
1051590Srgrimes	struct group *gr;
1061590Srgrimes	uid_t ruid;
10710586Sjoerg	int asme, ch, asthem, fastlogin, prio, i;
1081590Srgrimes	enum { UNSET, YES, NO } iscsh = UNSET;
10921646Sdavidn#ifdef LOGIN_CAP
11021646Sdavidn	login_cap_t *lc;
11121646Sdavidn	int setwhat;
11221646Sdavidn#ifdef LOGIN_CAP_AUTH
11321646Sdavidn	char *style, *approvep, *auth_method = NULL;
11421646Sdavidn#endif
11521646Sdavidn#endif
1161590Srgrimes	char shellbuf[MAXPATHLEN];
1171590Srgrimes
1189502Swollman#ifdef WHEELSU
1199502Swollman	iswheelsu =
1209502Swollman#endif /* WHEELSU */
1211590Srgrimes	asme = asthem = fastlogin = 0;
12210586Sjoerg	user = "root";
12310586Sjoerg	while(optind < argc)
12410586Sjoerg	    if((ch = getopt(argc, argv, ARGSTR)) != EOF)
1251590Srgrimes		switch((char)ch) {
1261590Srgrimes#ifdef KERBEROS
1271590Srgrimes		case 'K':
1281590Srgrimes			use_kerberos = 0;
1291590Srgrimes			break;
1301590Srgrimes#endif
1311590Srgrimes		case 'f':
1321590Srgrimes			fastlogin = 1;
1331590Srgrimes			break;
1341590Srgrimes		case '-':
1351590Srgrimes		case 'l':
1361590Srgrimes			asme = 0;
1371590Srgrimes			asthem = 1;
1381590Srgrimes			break;
1391590Srgrimes		case 'm':
1401590Srgrimes			asme = 1;
1411590Srgrimes			asthem = 0;
1421590Srgrimes			break;
1431590Srgrimes		case '?':
1441590Srgrimes		default:
1451590Srgrimes			(void)fprintf(stderr, "usage: su [%s] [login]\n",
14610586Sjoerg				      ARGSTR);
1471590Srgrimes			exit(1);
14810586Sjoerg		      }
14910586Sjoerg	    else
15010586Sjoerg	    {
15110586Sjoerg		user = argv[optind++];
15210586Sjoerg		break;
15310586Sjoerg	    }
15410586Sjoerg
15510586Sjoerg	if((nargv = malloc (sizeof (char *) * (argc + 4))) == NULL) {
15610586Sjoerg	    errx(1, "malloc failure");
15710586Sjoerg	}
15810586Sjoerg
15910586Sjoerg	nargv[argc + 3] = NULL;
16010586Sjoerg	for (i = argc; i >= optind; i--)
16110586Sjoerg	    nargv[i + 3] = argv[i];
16210586Sjoerg	np = &nargv[i + 3];
16310586Sjoerg
1641590Srgrimes	argv += optind;
1651590Srgrimes
1661590Srgrimes	errno = 0;
1671590Srgrimes	prio = getpriority(PRIO_PROCESS, 0);
1681590Srgrimes	if (errno)
1691590Srgrimes		prio = 0;
1701590Srgrimes	(void)setpriority(PRIO_PROCESS, 0, -2);
1711590Srgrimes	openlog("su", LOG_CONS, 0);
1721590Srgrimes
1731590Srgrimes	/* get current login name and shell */
1741590Srgrimes	ruid = getuid();
1751590Srgrimes	username = getlogin();
1761590Srgrimes	if (username == NULL || (pwd = getpwnam(username)) == NULL ||
1771590Srgrimes	    pwd->pw_uid != ruid)
1781590Srgrimes		pwd = getpwuid(ruid);
1791590Srgrimes	if (pwd == NULL)
1801590Srgrimes		errx(1, "who are you?");
1811590Srgrimes	username = strdup(pwd->pw_name);
1821590Srgrimes	if (username == NULL)
1831590Srgrimes		err(1, NULL);
18421646Sdavidn	if (asme) {
18521646Sdavidn		if (pwd->pw_shell != NULL && *pwd->pw_shell != '\0') {
18621646Sdavidn			/* copy: pwd memory is recycled */
18721646Sdavidn			shell = strncpy(shellbuf,  pwd->pw_shell, sizeof shellbuf);
18821646Sdavidn			shellbuf[sizeof shellbuf - 1] = '\0';
18921646Sdavidn		} else {
1901590Srgrimes			shell = _PATH_BSHELL;
1911590Srgrimes			iscsh = NO;
1921590Srgrimes		}
19321646Sdavidn	}
1941590Srgrimes
19521646Sdavidn#ifdef LOGIN_CAP_AUTH
19621646Sdavidn	if (auth_method = strchr(user, ':')) {
19721646Sdavidn		*auth_method = '\0';
19821646Sdavidn		auth_method++;
19921646Sdavidn		if (*auth_method == '\0')
20021646Sdavidn			auth_method = NULL;
20121646Sdavidn	}
20221646Sdavidn#endif /* !LOGIN_CAP_AUTH */
20321646Sdavidn
2041590Srgrimes	/* get target login information, default to root */
2051590Srgrimes	if ((pwd = getpwnam(user)) == NULL) {
2069502Swollman		errx(1, "unknown login: %s", user);
2071590Srgrimes	}
20821646Sdavidn#ifdef LOGIN_CAP
20921646Sdavidn	lc = login_getclass(pwd);
21021646Sdavidn#endif
2111590Srgrimes
2129502Swollman#ifdef WHEELSU
2139502Swollman	targetpass = strdup(pwd->pw_passwd);
2149502Swollman#endif /* WHEELSU */
2159502Swollman
2161590Srgrimes	if (ruid) {
2171590Srgrimes#ifdef KERBEROS
21814440Smarkm		if (use_kerberos && koktologin(username, user)
21914572Smarkm		    && !pwd->pw_uid) {
22014572Smarkm			warnx("kerberos: not in %s's ACL.", user);
22114572Smarkm			use_kerberos = 0;
22214572Smarkm		}
2231590Srgrimes#endif
22414440Smarkm		{
22514440Smarkm			/* only allow those in group zero to su to root. */
22614440Smarkm			if (pwd->pw_uid == 0 && (gr = getgrgid((gid_t)0)))
22714440Smarkm				for (g = gr->gr_mem;; ++g) {
22814440Smarkm					if (!*g)
22914440Smarkm						errx(1,
2301590Srgrimes			    "you are not in the correct group to su %s.",
23114440Smarkm						    user);
23214440Smarkm					if (strcmp(username, *g) == 0) {
2339502Swollman#ifdef WHEELSU
23414440Smarkm						iswheelsu = 1;
2359502Swollman#endif /* WHEELSU */
23614440Smarkm						break;
23714440Smarkm					}
2389502Swollman				}
23914440Smarkm		}
2401590Srgrimes		/* if target requires a password, verify it */
2411590Srgrimes		if (*pwd->pw_passwd) {
24221646Sdavidn#ifdef LOGIN_CAP_AUTH
24321646Sdavidn		/*
24421646Sdavidn		 * This hands off authorisation to an authorisation program,
24521646Sdavidn		 * depending on the styles available for the "auth-su",
24621646Sdavidn		 * authorisation styles.
24721646Sdavidn		 */
24821646Sdavidn		if ((style = login_getstyle(lc, auth_method, "su")) == NULL)
24921646Sdavidn			errx(1, "auth method available for su.\n");
25021646Sdavidn		if (authenticate(user, lc ? lc->lc_class : "default", style, "su") != 0) {
25121646Sdavidn#ifdef WHEELSU
25221646Sdavidn			if (!iswheelsu || authenticate(username, lc ? lc->lc_class : "default", style, "su") != 0) {
25321646Sdavidn#endif /* WHEELSU */
25421646Sdavidn			{
25521646Sdavidn			fprintf(stderr, "Sorry\n");
25621646Sdavidn			syslog(LOG_AUTH|LOG_WARNING,"BAD SU %s to %s%s", username, user, ontty());
25721646Sdavidn			exit(1);
25821646Sdavidn			}
25921646Sdavidn		}
26021646Sdavidn
26121646Sdavidn		/*
26221646Sdavidn		 * If authentication succeeds, run any approval
26321646Sdavidn		 * program, if applicable for this class.
26421646Sdavidn		 */
26521646Sdavidn		approvep = login_getcapstr(lc, "approve", NULL, NULL);
26621646Sdavidn		if (approvep==NULL || auth_script(approvep, approvep, username, lc->lc_class, 0) == 0) {
26721646Sdavidn			int     r = auth_scan(AUTH_OKAY);
26821646Sdavidn			/* See what the authorise program says */
26921646Sdavidn			if (!(r & AUTH_ROOTOKAY) && pwd->pw_uid == 0) {
27021646Sdavidn				fprintf(stderr, "Sorry\n");
27121646Sdavidn				syslog(LOG_AUTH|LOG_WARNING,"UNAPPROVED ROOT SU %s%s", user, ontty());
27221646Sdavidn				exit(1);
27321646Sdavidn			}
27421646Sdavidn		}
27521646Sdavidn#else /* !LOGIN_CAP_AUTH */
2763208Spst#ifdef	SKEY
2779502Swollman#ifdef WHEELSU
2789502Swollman			if (iswheelsu) {
2799502Swollman				pwd = getpwnam(username);
2809502Swollman			}
2819502Swollman#endif /* WHEELSU */
2823208Spst			p = skey_getpass("Password:", pwd, 1);
28321646Sdavidn			if (!(!strcmp(pwd->pw_passwd, skey_crypt(p, pwd->pw_passwd, pwd, 1))
2849502Swollman#ifdef WHEELSU
28521646Sdavidn			      || (iswheelsu && !strcmp(targetpass, crypt(p,targetpass)))
2869502Swollman#endif /* WHEELSU */
2879502Swollman			      )) {
2883208Spst#else
2891590Srgrimes			p = getpass("Password:");
2901590Srgrimes			if (strcmp(pwd->pw_passwd, crypt(p, pwd->pw_passwd))) {
2913208Spst#endif
29214440Smarkm#ifdef KERBEROS
29321646Sdavidn	    			if (!use_kerberos || (use_kerberos && kerberos(username, user, pwd->pw_uid, p)))
29414440Smarkm#endif
29514440Smarkm					{
29614440Smarkm					fprintf(stderr, "Sorry\n");
29721646Sdavidn					syslog(LOG_AUTH|LOG_WARNING, "BAD SU %s to %s%s", username, user, ontty());
29814440Smarkm					exit(1);
29914440Smarkm				}
3001590Srgrimes			}
3019502Swollman#ifdef WHEELSU
3029502Swollman			if (iswheelsu) {
3039502Swollman				pwd = getpwnam(user);
3049502Swollman			}
3059502Swollman#endif /* WHEELSU */
30621646Sdavidn#endif /* LOGIN_CAP_AUTH */
3071590Srgrimes		}
30810401Smpp		if (pwd->pw_expire && time(NULL) >= pwd->pw_expire) {
30910401Smpp			fprintf(stderr, "Sorry - account expired\n");
31010401Smpp			syslog(LOG_AUTH|LOG_WARNING,
31110401Smpp				"BAD SU %s to %s%s", username,
31210401Smpp				user, ontty());
31310401Smpp			exit(1);
31410401Smpp		}
3151590Srgrimes	}
3161590Srgrimes
3171590Srgrimes	if (asme) {
3181590Srgrimes		/* if asme and non-standard target shell, must be root */
3191590Srgrimes		if (!chshell(pwd->pw_shell) && ruid)
3201590Srgrimes			errx(1, "permission denied (shell).");
3211590Srgrimes	} else if (pwd->pw_shell && *pwd->pw_shell) {
3221590Srgrimes		shell = pwd->pw_shell;
3231590Srgrimes		iscsh = UNSET;
3241590Srgrimes	} else {
3251590Srgrimes		shell = _PATH_BSHELL;
3261590Srgrimes		iscsh = NO;
3271590Srgrimes	}
3281590Srgrimes
3291590Srgrimes	/* if we're forking a csh, we want to slightly muck the args */
3301590Srgrimes	if (iscsh == UNSET) {
33114440Smarkm		p = strrchr(shell, '/');
33214440Smarkm		if (p)
3331590Srgrimes			++p;
3341590Srgrimes		else
3351590Srgrimes			p = shell;
3367641Sjkh		if ((iscsh = strcmp(p, "csh") ? NO : YES) == NO)
3377641Sjkh		    iscsh = strcmp(p, "tcsh") ? NO : YES;
3381590Srgrimes	}
3391590Srgrimes
34021646Sdavidn	(void)setpriority(PRIO_PROCESS, 0, prio);
34121646Sdavidn
34221646Sdavidn#ifdef LOGIN_CAP
34321646Sdavidn	/* Set everything now except the environment & umask */
34421646Sdavidn	setwhat = LOGIN_SETALL & ~(LOGIN_SETPATH|LOGIN_SETUMASK|LOGIN_SETENV);
34521646Sdavidn	/*
34621646Sdavidn	 * Don't touch resource/priority settings if -m has been
34721646Sdavidn	 * used or -l hasn't, and we're not su'ing to root.
34821646Sdavidn	 */
34921646Sdavidn        if ((asme || !asthem) && pwd->pw_uid)
35021646Sdavidn		setwhat &= ~(LOGIN_SETPRIORITY|~LOGIN_SETRESOURCES);
35121646Sdavidn	if (setusercontext(lc, pwd, pwd->pw_uid, setwhat) < 0)
35221646Sdavidn		err(1, "setusercontext");
35321646Sdavidn#else
3541590Srgrimes	/* set permissions */
3551590Srgrimes	if (setgid(pwd->pw_gid) < 0)
3561590Srgrimes		err(1, "setgid");
3571590Srgrimes	if (initgroups(user, pwd->pw_gid))
3581590Srgrimes		errx(1, "initgroups failed");
3591590Srgrimes	if (setuid(pwd->pw_uid) < 0)
3601590Srgrimes		err(1, "setuid");
36121646Sdavidn#endif
3621590Srgrimes
3631590Srgrimes	if (!asme) {
3641590Srgrimes		if (asthem) {
3651590Srgrimes			p = getenv("TERM");
3664563Sats			cleanenv[0] = NULL;
3671590Srgrimes			environ = cleanenv;
36821646Sdavidn#ifdef LOGIN_CAP
36921646Sdavidn			/* set the su'd user's environment & umask */
37021646Sdavidn			setusercontext(lc, pwd, pwd->pw_uid, LOGIN_SETPATH|LOGIN_SETUMASK|LOGIN_SETENV);
37121646Sdavidn#else
3724563Sats			(void)setenv("PATH", _PATH_DEFPATH, 1);
37321646Sdavidn#endif
37418789Sjoerg			if (p)
37518789Sjoerg				(void)setenv("TERM", p, 1);
3761590Srgrimes			if (chdir(pwd->pw_dir) < 0)
3771590Srgrimes				errx(1, "no directory");
3781590Srgrimes		}
3791590Srgrimes		if (asthem || pwd->pw_uid)
3801590Srgrimes			(void)setenv("USER", pwd->pw_name, 1);
3811590Srgrimes		(void)setenv("HOME", pwd->pw_dir, 1);
3821590Srgrimes		(void)setenv("SHELL", shell, 1);
3831590Srgrimes	}
3841590Srgrimes	if (iscsh == YES) {
3851590Srgrimes		if (fastlogin)
3861590Srgrimes			*np-- = "-f";
3871590Srgrimes		if (asme)
3881590Srgrimes			*np-- = "-m";
3891590Srgrimes	}
3901590Srgrimes
3911590Srgrimes	/* csh strips the first character... */
3921590Srgrimes	*np = asthem ? "-su" : iscsh == YES ? "_su" : "su";
3931590Srgrimes
3941590Srgrimes	if (ruid != 0)
3951590Srgrimes		syslog(LOG_NOTICE|LOG_AUTH, "%s to %s%s",
3961590Srgrimes		    username, user, ontty());
3971590Srgrimes
39821646Sdavidn	login_close(lc);
3991590Srgrimes
4001590Srgrimes	execv(shell, np);
4011590Srgrimes	err(1, "%s", shell);
4021590Srgrimes}
4031590Srgrimes
4041590Srgrimesint
4051590Srgrimeschshell(sh)
4061590Srgrimes	char *sh;
4071590Srgrimes{
40821646Sdavidn	int  r = 0;
4091590Srgrimes	char *cp;
4101590Srgrimes
41121646Sdavidn	setusershell();
41221646Sdavidn	while (!r && (cp = getusershell()) != NULL)
41321646Sdavidn		r = strcmp(cp, sh) == 0;
41421646Sdavidn	endusershell();
41521646Sdavidn	return r;
4161590Srgrimes}
4171590Srgrimes
4181590Srgrimeschar *
4191590Srgrimesontty()
4201590Srgrimes{
4211590Srgrimes	char *p;
4221590Srgrimes	static char buf[MAXPATHLEN + 4];
4231590Srgrimes
4241590Srgrimes	buf[0] = 0;
42514440Smarkm	p = ttyname(STDERR_FILENO);
42614440Smarkm	if (p)
4271590Srgrimes		snprintf(buf, sizeof(buf), " on %s", p);
4281590Srgrimes	return (buf);
4291590Srgrimes}
4301590Srgrimes
4311590Srgrimes#ifdef KERBEROS
43214440Smarkmint
43314440Smarkmkerberos(username, user, uid, pword)
4341590Srgrimes	char *username, *user;
4351590Srgrimes	int uid;
43614440Smarkm	char *pword;
4371590Srgrimes{
4381590Srgrimes	extern char *krb_err_txt[];
4391590Srgrimes	KTEXT_ST ticket;
4401590Srgrimes	AUTH_DAT authdata;
4411590Srgrimes	int kerno;
4421590Srgrimes	u_long faddr;
44311233Sgibbs	struct sockaddr_in local_addr;
4441590Srgrimes	char lrealm[REALM_SZ], krbtkfile[MAXPATHLEN];
4451590Srgrimes	char hostname[MAXHOSTNAMELEN], savehost[MAXHOSTNAMELEN];
4461590Srgrimes	char *krb_get_phost();
4471590Srgrimes
4481590Srgrimes	if (krb_get_lrealm(lrealm, 1) != KSUCCESS)
4491590Srgrimes		return (1);
45014440Smarkm	(void)sprintf(krbtkfile, "%s_%s_%lu", TKT_ROOT, user,
45114440Smarkm	    (unsigned long)getuid());
4521590Srgrimes
4531590Srgrimes	(void)setenv("KRBTKFILE", krbtkfile, 1);
4541590Srgrimes	(void)krb_set_tkt_string(krbtkfile);
4551590Srgrimes	/*
4561590Srgrimes	 * Set real as well as effective ID to 0 for the moment,
4571590Srgrimes	 * to make the kerberos library do the right thing.
4581590Srgrimes	 */
4591590Srgrimes	if (setuid(0) < 0) {
4601590Srgrimes		warn("setuid");
4611590Srgrimes		return (1);
4621590Srgrimes	}
4631590Srgrimes
4641590Srgrimes	/*
4651590Srgrimes	 * Little trick here -- if we are su'ing to root,
4661590Srgrimes	 * we need to get a ticket for "xxx.root", where xxx represents
4671590Srgrimes	 * the name of the person su'ing.  Otherwise (non-root case),
4681590Srgrimes	 * we need to get a ticket for "yyy.", where yyy represents
4691590Srgrimes	 * the name of the person being su'd to, and the instance is null
4701590Srgrimes	 *
4711590Srgrimes	 * We should have a way to set the ticket lifetime,
4721590Srgrimes	 * with a system default for root.
4731590Srgrimes	 */
4741590Srgrimes	kerno = krb_get_pw_in_tkt((uid == 0 ? username : user),
4751590Srgrimes		(uid == 0 ? "root" : ""), lrealm,
47614440Smarkm	    	"krbtgt", lrealm, DEFAULT_TKT_LIFE, pword);
4771590Srgrimes
4781590Srgrimes	if (kerno != KSUCCESS) {
4791590Srgrimes		if (kerno == KDC_PR_UNKNOWN) {
4801590Srgrimes			warnx("kerberos: principal unknown: %s.%s@%s",
4811590Srgrimes				(uid == 0 ? username : user),
4821590Srgrimes				(uid == 0 ? "root" : ""), lrealm);
4831590Srgrimes			return (1);
4841590Srgrimes		}
4851590Srgrimes		warnx("kerberos: unable to su: %s", krb_err_txt[kerno]);
4861590Srgrimes		syslog(LOG_NOTICE|LOG_AUTH,
4871590Srgrimes		    "BAD Kerberos SU: %s to %s%s: %s",
4881590Srgrimes		    username, user, ontty(), krb_err_txt[kerno]);
4891590Srgrimes		return (1);
4901590Srgrimes	}
4911590Srgrimes
4921590Srgrimes	if (chown(krbtkfile, uid, -1) < 0) {
4931590Srgrimes		warn("chown");
4941590Srgrimes		(void)unlink(krbtkfile);
4951590Srgrimes		return (1);
4961590Srgrimes	}
4971590Srgrimes
4981590Srgrimes	(void)setpriority(PRIO_PROCESS, 0, -2);
4991590Srgrimes
5001590Srgrimes	if (gethostname(hostname, sizeof(hostname)) == -1) {
5011590Srgrimes		warn("gethostname");
5021590Srgrimes		dest_tkt();
5031590Srgrimes		return (1);
5041590Srgrimes	}
5051590Srgrimes
5061590Srgrimes	(void)strncpy(savehost, krb_get_phost(hostname), sizeof(savehost));
5071590Srgrimes	savehost[sizeof(savehost) - 1] = '\0';
5081590Srgrimes
5091590Srgrimes	kerno = krb_mk_req(&ticket, "rcmd", savehost, lrealm, 33);
5101590Srgrimes
5111590Srgrimes	if (kerno == KDC_PR_UNKNOWN) {
5121590Srgrimes		warnx("Warning: TGT not verified.");
5131590Srgrimes		syslog(LOG_NOTICE|LOG_AUTH,
5141590Srgrimes		    "%s to %s%s, TGT not verified (%s); %s.%s not registered?",
5151590Srgrimes		    username, user, ontty(), krb_err_txt[kerno],
5161590Srgrimes		    "rcmd", savehost);
5171590Srgrimes	} else if (kerno != KSUCCESS) {
5181590Srgrimes		warnx("Unable to use TGT: %s", krb_err_txt[kerno]);
5191590Srgrimes		syslog(LOG_NOTICE|LOG_AUTH, "failed su: %s to %s%s: %s",
5201590Srgrimes		    username, user, ontty(), krb_err_txt[kerno]);
5211590Srgrimes		dest_tkt();
5221590Srgrimes		return (1);
5231590Srgrimes	} else {
52411233Sgibbs		if ((kerno = krb_get_local_addr(&local_addr)) != KSUCCESS) {
52511233Sgibbs			warnx("Unable to get our local address: %s",
52611233Sgibbs			      krb_err_txt[kerno]);
5271590Srgrimes			dest_tkt();
5281590Srgrimes			return (1);
5291590Srgrimes		}
53011233Sgibbs		faddr = local_addr.sin_addr.s_addr;
5311590Srgrimes		if ((kerno = krb_rd_req(&ticket, "rcmd", savehost, faddr,
5321590Srgrimes		    &authdata, "")) != KSUCCESS) {
5331590Srgrimes			warnx("kerberos: unable to verify rcmd ticket: %s\n",
5341590Srgrimes			    krb_err_txt[kerno]);
5351590Srgrimes			syslog(LOG_NOTICE|LOG_AUTH,
5361590Srgrimes			    "failed su: %s to %s%s: %s", username,
5371590Srgrimes			     user, ontty(), krb_err_txt[kerno]);
5381590Srgrimes			dest_tkt();
5391590Srgrimes			return (1);
5401590Srgrimes		}
5411590Srgrimes	}
5421590Srgrimes	return (0);
5431590Srgrimes}
5441590Srgrimes
54514440Smarkmint
54614440Smarkmkoktologin(name, toname)
54714440Smarkm	char *name, *toname;
5481590Srgrimes{
5491590Srgrimes	AUTH_DAT *kdata;
5501590Srgrimes	AUTH_DAT kdata_st;
55114440Smarkm	char realm[REALM_SZ];
5521590Srgrimes
55314440Smarkm	if (krb_get_lrealm(realm, 1) != KSUCCESS)
55414440Smarkm		return (1);
5551590Srgrimes	kdata = &kdata_st;
5561590Srgrimes	memset((char *)kdata, 0, sizeof(*kdata));
55721646Sdavidn	(void)strncpy(kdata->pname, name, sizeof kdata->pname - 1);
55821646Sdavidn	(void)strncpy(kdata->pinst,
55921646Sdavidn	    ((strcmp(toname, "root") == 0) ? "root" : ""), sizeof kdata->pinst - 1);
56021646Sdavidn	(void)strncpy(kdata->prealm, realm, sizeof kdata->prealm - 1);
5611590Srgrimes	return (kuserok(kdata, toname));
5621590Srgrimes}
5631590Srgrimes#endif
564