Home | History | Annotate | Line # | Download | only in su
su.c revision 1.21
      1  1.21    kleink /*	$NetBSD: su.c,v 1.21 1998/04/02 11:13:33 kleink Exp $	*/
      2  1.12  christos 
      3   1.1       cgd /*
      4   1.1       cgd  * Copyright (c) 1988 The Regents of the University of California.
      5   1.1       cgd  * All rights reserved.
      6   1.1       cgd  *
      7   1.1       cgd  * Redistribution and use in source and binary forms, with or without
      8   1.1       cgd  * modification, are permitted provided that the following conditions
      9   1.1       cgd  * are met:
     10   1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     11   1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     12   1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     13   1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     14   1.1       cgd  *    documentation and/or other materials provided with the distribution.
     15   1.1       cgd  * 3. All advertising materials mentioning features or use of this software
     16   1.1       cgd  *    must display the following acknowledgement:
     17   1.1       cgd  *	This product includes software developed by the University of
     18   1.1       cgd  *	California, Berkeley and its contributors.
     19   1.1       cgd  * 4. Neither the name of the University nor the names of its contributors
     20   1.1       cgd  *    may be used to endorse or promote products derived from this software
     21   1.1       cgd  *    without specific prior written permission.
     22   1.1       cgd  *
     23   1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24   1.1       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25   1.1       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26   1.1       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27   1.1       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28   1.1       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29   1.1       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30   1.1       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31   1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32   1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33   1.1       cgd  * SUCH DAMAGE.
     34   1.1       cgd  */
     35   1.1       cgd 
     36  1.19     lukem #include <sys/cdefs.h>
     37   1.1       cgd #ifndef lint
     38  1.19     lukem __COPYRIGHT(
     39  1.19     lukem     "@(#) Copyright (c) 1988 The Regents of the University of California.\n\
     40  1.19     lukem  All rights reserved.\n");
     41   1.1       cgd #endif /* not lint */
     42   1.1       cgd 
     43   1.1       cgd #ifndef lint
     44  1.12  christos #if 0
     45  1.13       tls static char sccsid[] = "@(#)su.c	8.3 (Berkeley) 4/2/94";*/
     46  1.12  christos #else
     47  1.21    kleink __RCSID("$NetBSD: su.c,v 1.21 1998/04/02 11:13:33 kleink Exp $");
     48  1.12  christos #endif
     49   1.1       cgd #endif /* not lint */
     50   1.1       cgd 
     51   1.1       cgd #include <sys/param.h>
     52   1.1       cgd #include <sys/time.h>
     53   1.1       cgd #include <sys/resource.h>
     54  1.13       tls #include <err.h>
     55  1.11  christos #include <errno.h>
     56  1.17     lukem #include <grp.h>
     57  1.17     lukem #include <paths.h>
     58  1.17     lukem #include <pwd.h>
     59  1.17     lukem #include <stdio.h>
     60  1.17     lukem #include <skey.h>
     61   1.7       jtc #include <stdlib.h>
     62   1.1       cgd #include <string.h>
     63  1.17     lukem #include <syslog.h>
     64  1.21    kleink #include <time.h>
     65  1.17     lukem #include <tzfile.h>
     66   1.1       cgd #include <unistd.h>
     67   1.1       cgd 
     68   1.1       cgd #ifdef KERBEROS
     69   1.1       cgd #include <kerberosIV/des.h>
     70   1.1       cgd #include <kerberosIV/krb.h>
     71   1.1       cgd #include <netdb.h>
     72   1.1       cgd 
     73   1.1       cgd #define	ARGSTR	"-Kflm"
     74   1.1       cgd 
     75   1.1       cgd int use_kerberos = 1;
     76  1.11  christos 
     77  1.11  christos static int kerberos __P((char *, char *, int));
     78  1.11  christos static int koktologin __P((char *, char *, char *));
     79  1.11  christos 
     80   1.1       cgd #else
     81   1.1       cgd #define	ARGSTR	"-flm"
     82   1.1       cgd #endif
     83   1.1       cgd 
     84  1.18     lukem #ifndef	SUGROUP
     85  1.18     lukem #define	SUGROUP	"wheel"
     86  1.18     lukem #endif
     87  1.18     lukem 
     88  1.11  christos 
     89  1.11  christos int main __P((int, char **));
     90  1.11  christos 
     91  1.11  christos static int chshell __P((char *));
     92  1.11  christos static char *ontty __P((void));
     93  1.11  christos 
     94   1.2       sef 
     95   1.7       jtc int
     96   1.1       cgd main(argc, argv)
     97   1.1       cgd 	int argc;
     98   1.1       cgd 	char **argv;
     99   1.1       cgd {
    100  1.11  christos 	extern char *__progname;
    101   1.1       cgd 	extern char **environ;
    102  1.13       tls 	struct passwd *pwd;
    103  1.17     lukem 	char *p;
    104   1.1       cgd 	struct group *gr;
    105  1.17     lukem 	struct timeval tp;
    106  1.11  christos 	uid_t ruid;
    107   1.1       cgd 	int asme, ch, asthem, fastlogin, prio;
    108   1.1       cgd 	enum { UNSET, YES, NO } iscsh = UNSET;
    109   1.8   mycroft 	char *user, *shell, *avshell, *username, *cleanenv[10], **np;
    110   1.8   mycroft 	char shellbuf[MAXPATHLEN], avshellbuf[MAXPATHLEN];
    111   1.1       cgd 
    112   1.1       cgd 	asme = asthem = fastlogin = 0;
    113  1.17     lukem 	shell = NULL;
    114  1.19     lukem 	while ((ch = getopt(argc, argv, ARGSTR)) != -1)
    115   1.1       cgd 		switch((char)ch) {
    116   1.1       cgd #ifdef KERBEROS
    117   1.1       cgd 		case 'K':
    118   1.1       cgd 			use_kerberos = 0;
    119   1.1       cgd 			break;
    120   1.1       cgd #endif
    121   1.1       cgd 		case 'f':
    122   1.1       cgd 			fastlogin = 1;
    123   1.1       cgd 			break;
    124   1.1       cgd 		case '-':
    125   1.1       cgd 		case 'l':
    126   1.1       cgd 			asme = 0;
    127   1.1       cgd 			asthem = 1;
    128   1.1       cgd 			break;
    129   1.1       cgd 		case 'm':
    130   1.1       cgd 			asme = 1;
    131   1.1       cgd 			asthem = 0;
    132   1.1       cgd 			break;
    133   1.1       cgd 		case '?':
    134   1.1       cgd 		default:
    135  1.11  christos 			(void)fprintf(stderr,
    136  1.11  christos 			    "Usage: %s [%s] [login [shell arguments]]\n",
    137  1.11  christos 			    __progname, ARGSTR);
    138   1.1       cgd 			exit(1);
    139   1.1       cgd 		}
    140   1.1       cgd 	argv += optind;
    141   1.1       cgd 
    142   1.1       cgd 	errno = 0;
    143   1.1       cgd 	prio = getpriority(PRIO_PROCESS, 0);
    144   1.1       cgd 	if (errno)
    145   1.1       cgd 		prio = 0;
    146   1.1       cgd 	(void)setpriority(PRIO_PROCESS, 0, -2);
    147   1.1       cgd 	openlog("su", LOG_CONS, 0);
    148   1.1       cgd 
    149   1.1       cgd 	/* get current login name and shell */
    150   1.1       cgd 	ruid = getuid();
    151   1.1       cgd 	username = getlogin();
    152   1.1       cgd 	if (username == NULL || (pwd = getpwnam(username)) == NULL ||
    153   1.1       cgd 	    pwd->pw_uid != ruid)
    154   1.1       cgd 		pwd = getpwuid(ruid);
    155   1.1       cgd 	if (pwd == NULL) {
    156  1.13       tls 		errx(1, "who are you?");
    157   1.1       cgd 	}
    158   1.1       cgd 	username = strdup(pwd->pw_name);
    159   1.1       cgd 	if (asme)
    160   1.1       cgd 		if (pwd->pw_shell && *pwd->pw_shell)
    161  1.15       mrg 			shell = strncpy(shellbuf, pwd->pw_shell,
    162  1.15       mrg 			    sizeof(shellbuf) + 1);
    163   1.1       cgd 		else {
    164   1.1       cgd 			shell = _PATH_BSHELL;
    165   1.1       cgd 			iscsh = NO;
    166   1.1       cgd 		}
    167   1.1       cgd 
    168   1.1       cgd 	/* get target login information, default to root */
    169   1.1       cgd 	user = *argv ? *argv : "root";
    170   1.2       sef 	np = *argv ? argv : argv-1;
    171   1.2       sef 
    172   1.1       cgd 	if ((pwd = getpwnam(user)) == NULL) {
    173  1.13       tls 		errx(1, "unknown login %s", user);
    174   1.1       cgd 	}
    175   1.1       cgd 
    176   1.1       cgd 	if (ruid) {
    177   1.1       cgd #ifdef KERBEROS
    178   1.1       cgd 	    if (!use_kerberos || kerberos(username, user, pwd->pw_uid))
    179   1.1       cgd #endif
    180   1.1       cgd 	    {
    181  1.18     lukem 		/* Only allow those in group SUGROUP to su to root,
    182  1.18     lukem 		   but only if that group has any members.
    183  1.18     lukem 		   If SUGROUP has no members, allow anyone to su root */
    184  1.18     lukem 		if (pwd->pw_uid == 0 &&
    185  1.18     lukem 		    (gr = getgrnam(SUGROUP)) && *gr->gr_mem) {
    186  1.18     lukem 			char **g;
    187  1.18     lukem 
    188  1.18     lukem 			for (g = gr->gr_mem; ; g++) {
    189  1.18     lukem 				if (*g == NULL)
    190  1.18     lukem 					errx(1,
    191  1.18     lukem 	    "you are not listed in the correct secondary group (%s) to su %s.",
    192  1.18     lukem 					    SUGROUP, user);
    193  1.18     lukem 				if (strcmp(username, *g) == 0)
    194  1.17     lukem 					break;
    195  1.18     lukem 			}
    196   1.1       cgd 		}
    197   1.1       cgd 		/* if target requires a password, verify it */
    198   1.1       cgd 		if (*pwd->pw_passwd) {
    199   1.1       cgd 			p = getpass("Password:");
    200  1.10   deraadt #ifdef SKEY
    201  1.10   deraadt 			if (strcasecmp(p, "s/key") == 0) {
    202  1.13       tls 				if (skey_haskey(user))
    203  1.13       tls 					errx(1, "Sorry, you have no s/key.");
    204  1.13       tls 				else {
    205  1.10   deraadt 					if (skey_authenticate(user)) {
    206  1.10   deraadt 						goto badlogin;
    207  1.10   deraadt 					}
    208  1.10   deraadt 				}
    209  1.10   deraadt 
    210  1.10   deraadt 			} else
    211  1.10   deraadt #endif
    212   1.1       cgd 			if (strcmp(pwd->pw_passwd, crypt(p, pwd->pw_passwd))) {
    213  1.10   deraadt badlogin:
    214   1.1       cgd 				fprintf(stderr, "Sorry\n");
    215   1.1       cgd 				syslog(LOG_AUTH|LOG_WARNING,
    216   1.1       cgd 					"BAD SU %s to %s%s", username,
    217   1.1       cgd 					user, ontty());
    218   1.1       cgd 				exit(1);
    219   1.1       cgd 			}
    220   1.1       cgd 		}
    221   1.1       cgd 	    }
    222   1.1       cgd 	}
    223   1.1       cgd 
    224   1.1       cgd 	if (asme) {
    225   1.1       cgd 		/* if asme and non-standard target shell, must be root */
    226  1.13       tls 		if (!chshell(pwd->pw_shell) && ruid)
    227  1.13       tls 			errx(1,"permission denied (shell).");
    228   1.1       cgd 	} else if (pwd->pw_shell && *pwd->pw_shell) {
    229   1.1       cgd 		shell = pwd->pw_shell;
    230   1.1       cgd 		iscsh = UNSET;
    231   1.1       cgd 	} else {
    232   1.1       cgd 		shell = _PATH_BSHELL;
    233   1.1       cgd 		iscsh = NO;
    234   1.1       cgd 	}
    235   1.1       cgd 
    236  1.17     lukem 	if ((p = strrchr(shell, '/')) != NULL)
    237   1.9       cgd 		avshell = p+1;
    238   1.9       cgd 	else
    239   1.9       cgd 		avshell = shell;
    240   1.9       cgd 
    241   1.1       cgd 	/* if we're forking a csh, we want to slightly muck the args */
    242   1.9       cgd 	if (iscsh == UNSET)
    243  1.11  christos 		iscsh = strstr(avshell, "csh") ? YES : NO;
    244   1.1       cgd 
    245   1.1       cgd 	/* set permissions */
    246  1.13       tls 	if (setgid(pwd->pw_gid) < 0)
    247  1.13       tls 		err(1, "setgid");
    248  1.13       tls 	if (initgroups(user, pwd->pw_gid))
    249  1.13       tls 		errx(1, "initgroups failed");
    250  1.13       tls 	if (setuid(pwd->pw_uid) < 0)
    251  1.13       tls 		err(1, "setuid");
    252   1.1       cgd 
    253   1.1       cgd 	if (!asme) {
    254   1.1       cgd 		if (asthem) {
    255   1.1       cgd 			p = getenv("TERM");
    256   1.8   mycroft 			cleanenv[0] = NULL;
    257   1.1       cgd 			environ = cleanenv;
    258   1.8   mycroft 			(void)setenv("PATH", _PATH_DEFPATH, 1);
    259  1.11  christos 			if (p)
    260  1.11  christos 				(void)setenv("TERM", p, 1);
    261  1.13       tls 			if (chdir(pwd->pw_dir) < 0)
    262  1.13       tls 				errx(1, "no directory");
    263   1.1       cgd 		}
    264   1.5       jtc 		if (asthem || pwd->pw_uid)
    265   1.1       cgd 			(void)setenv("USER", pwd->pw_name, 1);
    266   1.1       cgd 		(void)setenv("HOME", pwd->pw_dir, 1);
    267   1.1       cgd 		(void)setenv("SHELL", shell, 1);
    268   1.1       cgd 	}
    269   1.1       cgd 
    270  1.12  christos 	if (iscsh == YES) {
    271  1.12  christos 		if (fastlogin)
    272  1.12  christos 			*np-- = "-f";
    273  1.12  christos 		if (asme)
    274  1.12  christos 			*np-- = "-m";
    275  1.12  christos 	}
    276   1.1       cgd 
    277   1.8   mycroft 	if (asthem) {
    278   1.8   mycroft 		avshellbuf[0] = '-';
    279  1.15       mrg 		(void)strncpy(avshellbuf+1, avshell, sizeof(avshellbuf) - 2);
    280   1.8   mycroft 		avshell = avshellbuf;
    281   1.8   mycroft 	} else if (iscsh == YES) {
    282   1.8   mycroft 		/* csh strips the first character... */
    283   1.8   mycroft 		avshellbuf[0] = '_';
    284  1.15       mrg 		(void)strncpy(avshellbuf+1, avshell, sizeof(avshellbuf) - 2);
    285   1.8   mycroft 		avshell = avshellbuf;
    286   1.8   mycroft 	}
    287  1.12  christos 	*np = avshell;
    288  1.11  christos 
    289  1.17     lukem 	if (pwd->pw_change || pwd->pw_expire)
    290  1.17     lukem 		(void)gettimeofday(&tp, (struct timezone *)NULL);
    291  1.17     lukem 	if (pwd->pw_change)
    292  1.17     lukem 		if (tp.tv_sec >= pwd->pw_change) {
    293  1.17     lukem 			(void)printf("%s -- %s's password has expired.\n",
    294  1.17     lukem 				     (ruid ? "Sorry" : "Note"), user);
    295  1.17     lukem 			if (ruid != 0)
    296  1.17     lukem 				exit(1);
    297  1.17     lukem 		} else if (pwd->pw_change - tp.tv_sec <
    298  1.17     lukem 		    _PASSWORD_WARNDAYS * SECSPERDAY)
    299  1.17     lukem 			(void)printf("Warning: %s's password expires on %s",
    300  1.17     lukem 				     user, ctime(&pwd->pw_change));
    301  1.17     lukem 	if (pwd->pw_expire)
    302  1.17     lukem 		if (tp.tv_sec >= pwd->pw_expire) {
    303  1.17     lukem 			(void)printf("%s -- %s's account has expired.\n",
    304  1.17     lukem 				     (ruid ? "Sorry" : "Note"), user);
    305  1.17     lukem 			if (ruid != 0)
    306  1.17     lukem 				exit(1);
    307  1.17     lukem 		} else if (pwd->pw_expire - tp.tv_sec <
    308  1.17     lukem 		    _PASSWORD_WARNDAYS * SECSPERDAY)
    309  1.17     lukem 			(void)printf("Warning: %s's account expires on %s",
    310  1.17     lukem 				     user, ctime(&pwd->pw_expire));
    311  1.17     lukem 
    312   1.1       cgd 	if (ruid != 0)
    313   1.1       cgd 		syslog(LOG_NOTICE|LOG_AUTH, "%s to %s%s",
    314   1.1       cgd 		    username, user, ontty());
    315   1.1       cgd 
    316   1.1       cgd 	(void)setpriority(PRIO_PROCESS, 0, prio);
    317   1.1       cgd 
    318  1.12  christos 	execv(shell, np);
    319  1.13       tls 	err(1, "%s", shell);
    320   1.1       cgd }
    321  1.11  christos 
    322  1.11  christos static int
    323   1.1       cgd chshell(sh)
    324   1.1       cgd 	char *sh;
    325   1.1       cgd {
    326  1.13       tls 	char *cp;
    327   1.1       cgd 
    328   1.1       cgd 	while ((cp = getusershell()) != NULL)
    329   1.1       cgd 		if (!strcmp(cp, sh))
    330   1.1       cgd 			return (1);
    331   1.1       cgd 	return (0);
    332   1.1       cgd }
    333   1.1       cgd 
    334  1.11  christos static char *
    335   1.1       cgd ontty()
    336   1.1       cgd {
    337  1.19     lukem 	char *p;
    338   1.1       cgd 	static char buf[MAXPATHLEN + 4];
    339   1.1       cgd 
    340   1.1       cgd 	buf[0] = 0;
    341  1.17     lukem 	if ((p = ttyname(STDERR_FILENO)) != NULL)
    342  1.15       mrg 		(void)snprintf(buf, sizeof buf, " on %s", p);
    343   1.1       cgd 	return (buf);
    344   1.1       cgd }
    345   1.1       cgd 
    346   1.1       cgd #ifdef KERBEROS
    347  1.11  christos static int
    348   1.1       cgd kerberos(username, user, uid)
    349   1.1       cgd 	char *username, *user;
    350   1.1       cgd 	int uid;
    351   1.1       cgd {
    352   1.1       cgd 	KTEXT_ST ticket;
    353   1.1       cgd 	AUTH_DAT authdata;
    354   1.1       cgd 	struct hostent *hp;
    355   1.1       cgd 	int kerno;
    356   1.1       cgd 	u_long faddr;
    357   1.1       cgd 	char lrealm[REALM_SZ], krbtkfile[MAXPATHLEN];
    358   1.1       cgd 	char hostname[MAXHOSTNAMELEN], savehost[MAXHOSTNAMELEN];
    359   1.1       cgd 
    360   1.1       cgd 	if (krb_get_lrealm(lrealm, 1) != KSUCCESS)
    361   1.1       cgd 		return (1);
    362   1.1       cgd 	if (koktologin(username, lrealm, user) && !uid) {
    363  1.13       tls 		warnx("kerberos: not in %s's ACL.", user);
    364   1.1       cgd 		return (1);
    365   1.1       cgd 	}
    366  1.15       mrg 	(void)(void)snprintf(krbtkfile, sizeof krbtkfile, "%s_%s_%d", TKT_ROOT,
    367  1.15       mrg 	    user, getuid());
    368   1.1       cgd 
    369   1.1       cgd 	(void)setenv("KRBTKFILE", krbtkfile, 1);
    370   1.1       cgd 	(void)krb_set_tkt_string(krbtkfile);
    371   1.1       cgd 	/*
    372   1.1       cgd 	 * Set real as well as effective ID to 0 for the moment,
    373   1.1       cgd 	 * to make the kerberos library do the right thing.
    374   1.1       cgd 	 */
    375   1.1       cgd 	if (setuid(0) < 0) {
    376  1.13       tls 		warn("setuid");
    377   1.1       cgd 		return (1);
    378   1.1       cgd 	}
    379   1.1       cgd 
    380   1.1       cgd 	/*
    381   1.1       cgd 	 * Little trick here -- if we are su'ing to root,
    382   1.1       cgd 	 * we need to get a ticket for "xxx.root", where xxx represents
    383   1.1       cgd 	 * the name of the person su'ing.  Otherwise (non-root case),
    384   1.1       cgd 	 * we need to get a ticket for "yyy.", where yyy represents
    385   1.1       cgd 	 * the name of the person being su'd to, and the instance is null
    386   1.1       cgd 	 *
    387   1.1       cgd 	 * We should have a way to set the ticket lifetime,
    388   1.1       cgd 	 * with a system default for root.
    389   1.1       cgd 	 */
    390   1.1       cgd 	kerno = krb_get_pw_in_tkt((uid == 0 ? username : user),
    391   1.1       cgd 		(uid == 0 ? "root" : ""), lrealm,
    392  1.17     lukem 		"krbtgt", lrealm, DEFAULT_TKT_LIFE, 0);
    393   1.1       cgd 
    394   1.1       cgd 	if (kerno != KSUCCESS) {
    395   1.1       cgd 		if (kerno == KDC_PR_UNKNOWN) {
    396  1.13       tls 			warnx("kerberos: principal unknown: %s.%s@%s",
    397   1.1       cgd 				(uid == 0 ? username : user),
    398   1.1       cgd 				(uid == 0 ? "root" : ""), lrealm);
    399   1.1       cgd 			return (1);
    400   1.1       cgd 		}
    401  1.13       tls 		warnx("kerberos: unable to su: %s", krb_err_txt[kerno]);
    402   1.1       cgd 		syslog(LOG_NOTICE|LOG_AUTH,
    403   1.1       cgd 		    "BAD Kerberos SU: %s to %s%s: %s",
    404   1.1       cgd 		    username, user, ontty(), krb_err_txt[kerno]);
    405   1.1       cgd 		return (1);
    406   1.1       cgd 	}
    407   1.1       cgd 
    408   1.1       cgd 	if (chown(krbtkfile, uid, -1) < 0) {
    409  1.13       tls 		warn("chown");
    410   1.1       cgd 		(void)unlink(krbtkfile);
    411   1.1       cgd 		return (1);
    412   1.1       cgd 	}
    413   1.1       cgd 
    414   1.1       cgd 	(void)setpriority(PRIO_PROCESS, 0, -2);
    415   1.1       cgd 
    416   1.1       cgd 	if (gethostname(hostname, sizeof(hostname)) == -1) {
    417  1.13       tls 		warn("gethostname");
    418   1.1       cgd 		dest_tkt();
    419   1.1       cgd 		return (1);
    420   1.1       cgd 	}
    421   1.1       cgd 
    422   1.1       cgd 	(void)strncpy(savehost, krb_get_phost(hostname), sizeof(savehost));
    423   1.1       cgd 	savehost[sizeof(savehost) - 1] = '\0';
    424   1.1       cgd 
    425   1.1       cgd 	kerno = krb_mk_req(&ticket, "rcmd", savehost, lrealm, 33);
    426   1.1       cgd 
    427   1.1       cgd 	if (kerno == KDC_PR_UNKNOWN) {
    428  1.13       tls 		warnx("Warning: TGT not verified.");
    429   1.1       cgd 		syslog(LOG_NOTICE|LOG_AUTH,
    430   1.1       cgd 		    "%s to %s%s, TGT not verified (%s); %s.%s not registered?",
    431   1.1       cgd 		    username, user, ontty(), krb_err_txt[kerno],
    432   1.1       cgd 		    "rcmd", savehost);
    433   1.1       cgd 	} else if (kerno != KSUCCESS) {
    434  1.13       tls 		warnx("Unable to use TGT: %s", krb_err_txt[kerno]);
    435   1.1       cgd 		syslog(LOG_NOTICE|LOG_AUTH, "failed su: %s to %s%s: %s",
    436   1.1       cgd 		    username, user, ontty(), krb_err_txt[kerno]);
    437   1.1       cgd 		dest_tkt();
    438   1.1       cgd 		return (1);
    439   1.1       cgd 	} else {
    440   1.1       cgd 		if (!(hp = gethostbyname(hostname))) {
    441  1.13       tls 			warnx("can't get addr of %s", hostname);
    442   1.1       cgd 			dest_tkt();
    443   1.1       cgd 			return (1);
    444   1.1       cgd 		}
    445  1.13       tls 		memmove((char *)&faddr, (char *)hp->h_addr, sizeof(faddr));
    446   1.1       cgd 
    447   1.1       cgd 		if ((kerno = krb_rd_req(&ticket, "rcmd", savehost, faddr,
    448   1.1       cgd 		    &authdata, "")) != KSUCCESS) {
    449  1.13       tls 			warnx("kerberos: unable to verify rcmd ticket: %s\n",
    450   1.1       cgd 			    krb_err_txt[kerno]);
    451   1.1       cgd 			syslog(LOG_NOTICE|LOG_AUTH,
    452   1.1       cgd 			    "failed su: %s to %s%s: %s", username,
    453   1.1       cgd 			     user, ontty(), krb_err_txt[kerno]);
    454   1.1       cgd 			dest_tkt();
    455   1.1       cgd 			return (1);
    456   1.1       cgd 		}
    457   1.1       cgd 	}
    458   1.1       cgd 	return (0);
    459   1.1       cgd }
    460   1.1       cgd 
    461  1.11  christos static int
    462   1.1       cgd koktologin(name, realm, toname)
    463   1.1       cgd 	char *name, *realm, *toname;
    464   1.1       cgd {
    465  1.19     lukem 	AUTH_DAT *kdata;
    466   1.1       cgd 	AUTH_DAT kdata_st;
    467   1.1       cgd 
    468   1.1       cgd 	kdata = &kdata_st;
    469  1.13       tls 	memset((char *)kdata, 0, sizeof(*kdata));
    470  1.15       mrg 	(void)strncpy(kdata->pname, name, sizeof(kdata->pname) - 1);
    471  1.16  explorer 	(void)strncpy(kdata->pinst,
    472  1.15       mrg 	    ((strcmp(toname, "root") == 0) ? "root" : ""), sizeof(kdata->pinst) - 1);
    473  1.16  explorer 	(void)strncpy(kdata->prealm, realm, sizeof(kdata->prealm) - 1);
    474   1.1       cgd 	return (kuserok(kdata, toname));
    475   1.1       cgd }
    476   1.1       cgd #endif
    477