+ return (1);
+ return (0);
+}
+
+char *
+ontty()
+{
+ char *p, *ttyname();
+ static char buf[MAXPATHLEN + 4];
+
+ buf[0] = 0;
+ if (p = ttyname(STDERR_FILENO))
+ sprintf(buf, " on %s", p);
+ return (buf);
+}
+
+#ifdef KERBEROS
+kerberos(username, user, uid)
+ char *username, *user;
+ int uid;
+{
+ extern char *krb_err_txt[];
+ KTEXT_ST ticket;
+ AUTH_DAT authdata;
+ struct hostent *hp;
+ register char *p;
+ int kerno;
+ u_long faddr;
+ char lrealm[REALM_SZ], krbtkfile[MAXPATHLEN];
+ char hostname[MAXHOSTNAMELEN], savehost[MAXHOSTNAMELEN];
+ char *ontty(), *krb_get_phost();
+
+ if (krb_get_lrealm(lrealm, 1) != KSUCCESS)
+ return (1);
+ if (koktologin(username, lrealm, user) && !uid) {
+ (void)fprintf(stderr, "kerberos su: not in %s's ACL.\n", user);
+ return (1);
+ }
+ (void)sprintf(krbtkfile, "%s_%s_%d", TKT_ROOT, user, getuid());
+
+ (void)setenv("KRBTKFILE", krbtkfile, 1);
+ (void)krb_set_tkt_string(krbtkfile);
+ /*
+ * Set real as well as effective ID to 0 for the moment,
+ * to make the kerberos library do the right thing.
+ */
+ if (setuid(0) < 0) {
+ perror("su: setuid");
+ return (1);
+ }
+
+ /*
+ * Little trick here -- if we are su'ing to root,
+ * we need to get a ticket for "xxx.root", where xxx represents
+ * the name of the person su'ing. Otherwise (non-root case),
+ * we need to get a ticket for "yyy.", where yyy represents
+ * the name of the person being su'd to, and the instance is null
+ *
+ * We should have a way to set the ticket lifetime,
+ * with a system default for root.
+ */
+ kerno = krb_get_pw_in_tkt((uid == 0 ? username : user),
+ (uid == 0 ? "root" : ""), lrealm,
+ "krbtgt", lrealm, DEFAULT_TKT_LIFE, 0);
+
+ if (kerno != KSUCCESS) {
+ if (kerno == KDC_PR_UNKNOWN) {
+ fprintf(stderr, "principal unknown: %s.%s@%s\n",
+ (uid == 0 ? username : user),
+ (uid == 0 ? "root" : ""), lrealm);
+ return (1);
+ }
+ (void)fprintf(stderr, "su: unable to su: %s\n",
+ krb_err_txt[kerno]);
+ syslog(LOG_NOTICE|LOG_AUTH,
+ "BAD Kerberos SU: %s to %s%s: %s",
+ username, user, ontty(), krb_err_txt[kerno]);
+ return (1);
+ }
+
+ if (chown(krbtkfile, uid, -1) < 0) {
+ perror("su: chown:");
+ (void)unlink(krbtkfile);
+ return (1);
+ }
+
+ (void)setpriority(PRIO_PROCESS, 0, -2);
+
+ if (gethostname(hostname, sizeof(hostname)) == -1) {
+ perror("su: gethostname");
+ dest_tkt();
+ return (1);
+ }
+
+ (void)strncpy(savehost, krb_get_phost(hostname), sizeof(savehost));
+ savehost[sizeof(savehost) - 1] = '\0';
+
+ kerno = krb_mk_req(&ticket, "rcmd", savehost, lrealm, 33);
+
+ if (kerno == KDC_PR_UNKNOWN) {
+ (void)fprintf(stderr, "Warning: TGT not verified.\n");
+ syslog(LOG_NOTICE|LOG_AUTH,
+ "%s to %s%s, TGT not verified (%s); %s.%s not registered?",
+ username, user, ontty(), krb_err_txt[kerno],
+ "rcmd", savehost);
+ } else if (kerno != KSUCCESS) {
+ (void)fprintf(stderr, "Unable to use TGT: %s\n",
+ krb_err_txt[kerno]);
+ syslog(LOG_NOTICE|LOG_AUTH, "failed su: %s to %s%s: %s",
+ username, user, ontty(), krb_err_txt[kerno]);
+ dest_tkt();
+ return (1);
+ } else {
+ if (!(hp = gethostbyname(hostname))) {
+ (void)fprintf(stderr, "su: can't get addr of %s\n",
+ hostname);
+ dest_tkt();
+ return (1);
+ }
+ (void)bcopy((char *)hp->h_addr, (char *)&faddr, sizeof(faddr));
+
+ if ((kerno = krb_rd_req(&ticket, "rcmd", savehost, faddr,
+ &authdata, "")) != KSUCCESS) {
+ (void)fprintf(stderr,
+ "su: unable to verify rcmd ticket: %s\n",
+ krb_err_txt[kerno]);
+ syslog(LOG_NOTICE|LOG_AUTH,
+ "failed su: %s to %s%s: %s", username,
+ user, ontty(), krb_err_txt[kerno]);
+ dest_tkt();
+ return (1);
+ }
+ }
+ return (0);