Allow krb5 and krb4 to be compiled in to the same login binary at once,

krb5 can request a forwardable TGT,
can get both krb4 and krb5 tickets, if explicitely configured to do so
by the krb5.conf.
This commit is contained in:
aidan 2000-05-30 06:56:16 +00:00
parent e78793c612
commit 39d1e5b7fd
3 changed files with 123 additions and 42 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: k5login.c,v 1.11 2000/02/14 03:17:43 aidan Exp $ */ /* $NetBSD: k5login.c,v 1.12 2000/05/30 06:56:16 aidan Exp $ */
/*- /*-
* Copyright (c) 1990 The Regents of the University of California. * Copyright (c) 1990 The Regents of the University of California.
@ -38,7 +38,7 @@
#if 0 #if 0
static char sccsid[] = "@(#)klogin.c 5.11 (Berkeley) 7/12/92"; static char sccsid[] = "@(#)klogin.c 5.11 (Berkeley) 7/12/92";
#endif #endif
__RCSID("$NetBSD: k5login.c,v 1.11 2000/02/14 03:17:43 aidan Exp $"); __RCSID("$NetBSD: k5login.c,v 1.12 2000/05/30 06:56:16 aidan Exp $");
#endif /* not lint */ #endif /* not lint */
#ifdef KERBEROS5 #ifdef KERBEROS5
@ -59,19 +59,20 @@ __RCSID("$NetBSD: k5login.c,v 1.11 2000/02/14 03:17:43 aidan Exp $");
krb5_context kcontext; krb5_context kcontext;
int notickets; int notickets;
char *krbtkfile_env; char *krb5tkfile_env;
extern char *tty; extern char *tty;
extern int login_krb5_forwardable_tgt;
extern int has_ccache;
static char tkt_location[MAXPATHLEN]; static char tkt_location[MAXPATHLEN];
static krb5_creds forw_creds; static krb5_creds forw_creds;
int have_forward; int have_forward;
static krb5_principal me, server; static krb5_principal me, server;
int use_krb5;
int k5_read_creds __P((char *)); int k5_read_creds __P((char *));
int k5_write_creds __P((void)); int k5_write_creds __P((void));
int klogin __P((struct passwd *, char *, char *, char *)); int k5login __P((struct passwd *, char *, char *, char *));
void kdestroy __P((void)); void k5destroy __P((void));
#ifndef krb5_realm_length #ifndef krb5_realm_length
#define krb5_realm_length(r) ((r).length) #define krb5_realm_length(r) ((r).length)
@ -94,9 +95,6 @@ k5_read_creds(username)
krb5_creds mcreds; krb5_creds mcreds;
krb5_ccache ccache; krb5_ccache ccache;
if (! use_krb5)
return(1);
have_forward = 0; have_forward = 0;
memset((char*) &mcreds, 0, sizeof(forw_creds)); memset((char*) &mcreds, 0, sizeof(forw_creds));
memset((char*) &forw_creds, 0, sizeof(forw_creds)); memset((char*) &forw_creds, 0, sizeof(forw_creds));
@ -136,7 +134,8 @@ k5_read_creds(username)
have_forward = 1; have_forward = 1;
strcpy(tkt_location, getenv("KRB5CCNAME")); strcpy(tkt_location, getenv("KRB5CCNAME"));
krbtkfile_env = tkt_location; krb5tkfile_env = tkt_location;
has_ccache = 1;
notickets = 0; notickets = 0;
nuke_ccache: nuke_ccache:
@ -150,8 +149,6 @@ k5_write_creds()
krb5_error_code code; krb5_error_code code;
krb5_ccache ccache; krb5_ccache ccache;
if (! use_krb5)
return(1);
if (!have_forward) if (!have_forward)
return(1); return(1);
code = krb5_cc_default(kcontext, &ccache); code = krb5_cc_default(kcontext, &ccache);
@ -184,7 +181,7 @@ nuke_ccache_contents:
* 1 if Kerberos failed (try local password in login) * 1 if Kerberos failed (try local password in login)
*/ */
int int
klogin(pw, instance, localhost, password) k5login(pw, instance, localhost, password)
struct passwd *pw; struct passwd *pw;
char *instance, *localhost, *password; char *instance, *localhost, *password;
{ {
@ -197,6 +194,9 @@ klogin(pw, instance, localhost, password)
char *realm, *client_name; char *realm, *client_name;
char *principal; char *principal;
if (login_krb5_forwardable_tgt)
options |= KDC_OPT_FORWARDABLE;
/* /*
* Root logins don't use Kerberos. * Root logins don't use Kerberos.
* If we have a realm, try getting a ticket-granting ticket * If we have a realm, try getting a ticket-granting ticket
@ -205,8 +205,7 @@ klogin(pw, instance, localhost, password)
* for a password. If that's ok, log the user in * for a password. If that's ok, log the user in
* without issuing any tickets. * without issuing any tickets.
*/ */
if (! use_krb5 || if (strcmp(pw->pw_name, "root") == 0 ||
strcmp(pw->pw_name, "root") == 0 ||
krb5_get_default_realm(kcontext, &realm)) krb5_get_default_realm(kcontext, &realm))
return (1); return (1);
@ -222,7 +221,8 @@ klogin(pw, instance, localhost, password)
else else
(void)snprintf(tkt_location, sizeof tkt_location, (void)snprintf(tkt_location, sizeof tkt_location,
"FILE:/tmp/krb5cc_root_%d.%s", pw->pw_uid, tty); "FILE:/tmp/krb5cc_root_%d.%s", pw->pw_uid, tty);
krbtkfile_env = tkt_location; krb5tkfile_env = tkt_location;
has_ccache = 1;
principal = (char *)malloc(strlen(pw->pw_name)+strlen(instance)+2); principal = (char *)malloc(strlen(pw->pw_name)+strlen(instance)+2);
strcpy(principal, pw->pw_name); /* XXX strcpy is safe */ strcpy(principal, pw->pw_name); /* XXX strcpy is safe */
@ -317,15 +317,15 @@ klogin(pw, instance, localhost, password)
* Remove any credentials * Remove any credentials
*/ */
void void
kdestroy() k5destroy()
{ {
krb5_error_code code; krb5_error_code code;
krb5_ccache ccache = NULL; krb5_ccache ccache = NULL;
if (! use_krb5 || krbtkfile_env == NULL) if (krb5tkfile_env == NULL)
return; return;
code = krb5_cc_resolve(kcontext, krbtkfile_env, &ccache); code = krb5_cc_resolve(kcontext, krb5tkfile_env, &ccache);
if (!code) if (!code)
code = krb5_cc_destroy(kcontext, ccache); code = krb5_cc_destroy(kcontext, ccache);
} }

View File

@ -1,4 +1,4 @@
/* $NetBSD: klogin.c,v 1.14 1999/07/30 01:56:49 mycroft Exp $ */ /* $NetBSD: klogin.c,v 1.15 2000/05/30 06:56:17 aidan Exp $ */
/*- /*-
* Copyright (c) 1990, 1993, 1994 * Copyright (c) 1990, 1993, 1994
@ -38,7 +38,7 @@
#if 0 #if 0
static char sccsid[] = "@(#)klogin.c 8.3 (Berkeley) 4/2/94"; static char sccsid[] = "@(#)klogin.c 8.3 (Berkeley) 4/2/94";
#endif #endif
__RCSID("$NetBSD: klogin.c,v 1.14 1999/07/30 01:56:49 mycroft Exp $"); __RCSID("$NetBSD: klogin.c,v 1.15 2000/05/30 06:56:17 aidan Exp $");
#endif /* not lint */ #endif /* not lint */
#ifdef KERBEROS #ifdef KERBEROS
@ -65,6 +65,7 @@ __RCSID("$NetBSD: klogin.c,v 1.14 1999/07/30 01:56:49 mycroft Exp $");
int notickets; int notickets;
char *krbtkfile_env; char *krbtkfile_env;
char *tty; char *tty;
extern int has_ccache;
static char tkt_location[MAXPATHLEN]; /* a pointer to this is returned... */ static char tkt_location[MAXPATHLEN]; /* a pointer to this is returned... */
@ -114,6 +115,7 @@ klogin(pw, instance, localhost, password)
(void)snprintf(tkt_location, sizeof tkt_location, (void)snprintf(tkt_location, sizeof tkt_location,
"%s_root_%d.%s", TKT_ROOT, pw->pw_uid, tty); "%s_root_%d.%s", TKT_ROOT, pw->pw_uid, tty);
krbtkfile_env = tkt_location; krbtkfile_env = tkt_location;
has_ccache = 1;
(void)krb_set_tkt_string(tkt_location); (void)krb_set_tkt_string(tkt_location);
/* /*

View File

@ -1,4 +1,4 @@
/* $NetBSD: login.c,v 1.56 2000/03/07 14:11:22 enami Exp $ */ /* $NetBSD: login.c,v 1.57 2000/05/30 06:56:17 aidan Exp $ */
/*- /*-
* Copyright (c) 1980, 1987, 1988, 1991, 1993, 1994 * Copyright (c) 1980, 1987, 1988, 1991, 1993, 1994
@ -44,7 +44,7 @@ __COPYRIGHT(
#if 0 #if 0
static char sccsid[] = "@(#)login.c 8.4 (Berkeley) 4/2/94"; static char sccsid[] = "@(#)login.c 8.4 (Berkeley) 4/2/94";
#endif #endif
__RCSID("$NetBSD: login.c,v 1.56 2000/03/07 14:11:22 enami Exp $"); __RCSID("$NetBSD: login.c,v 1.57 2000/05/30 06:56:17 aidan Exp $");
#endif /* not lint */ #endif /* not lint */
/* /*
@ -89,6 +89,24 @@ __RCSID("$NetBSD: login.c,v 1.56 2000/03/07 14:11:22 enami Exp $");
#include "pathnames.h" #include "pathnames.h"
#ifdef KERBEROS5
int login_krb5_get_tickets = 1;
int login_krb4_get_tickets = 0;
int login_krb5_forwardable_tgt = 0;
int login_krb5_retain_ccache = 0;
static struct login_confs {
char *flagname;
int *flag;
} login_conf_set[] = {
{ "krb5_get_tickets", &login_krb5_get_tickets },
{ "krb4_get_tickets", &login_krb4_get_tickets },
{ "forwardable", &login_krb5_forwardable_tgt },
{ "retain_ccache", &login_krb5_retain_ccache },
{ 0, 0 }
};
#endif
void badlogin __P((char *)); void badlogin __P((char *));
void checknologin __P((char *)); void checknologin __P((char *));
void dolastlog __P((int)); void dolastlog __P((int));
@ -100,14 +118,19 @@ void sigint __P((int));
void sleepexit __P((int)); void sleepexit __P((int));
const char *stypeof __P((const char *)); const char *stypeof __P((const char *));
void timedout __P((int)); void timedout __P((int));
#if defined(KERBEROS) || defined(KERBEROS5) #if defined(KERBEROS)
int klogin __P((struct passwd *, char *, char *, char *)); int klogin __P((struct passwd *, char *, char *, char *));
void kdestroy __P((void)); void kdestroy __P((void));
void dofork __P((void));
#endif #endif
#ifdef KERBEROS5 #ifdef KERBEROS5
int k5_read_creds __P((char*)); void login_get_kconf __P((krb5_context));
int k5_write_creds __P((void)); int k5login __P((struct passwd *, char *, char *, char *));
void k5destroy __P((void));
int k5_read_creds __P((char*));
int k5_write_creds __P((void));
#endif
#if defined(KERBEROS) || defined(KERBEROS5)
void dofork __P((void));
#endif #endif
#define TTYGRPNAME "tty" /* name of group to own ttys */ #define TTYGRPNAME "tty" /* name of group to own ttys */
@ -124,12 +147,15 @@ u_int timeout = 300;
#if defined(KERBEROS) || defined(KERBEROS5) #if defined(KERBEROS) || defined(KERBEROS5)
int notickets = 1; int notickets = 1;
char *instance; char *instance;
char *krbtkfile_env; int has_ccache = 0;
#endif
#ifdef KERBEROS
extern char *krbtkfile_env;
#endif #endif
#ifdef KERBEROS5 #ifdef KERBEROS5
extern krb5_context kcontext; extern krb5_context kcontext;
extern int have_forward; extern int have_forward;
extern int use_krb5; extern char *krb5tkfile_env;
#endif #endif
struct passwd *pwd; struct passwd *pwd;
@ -168,6 +194,9 @@ main(argc, argv)
#ifdef KERBEROS5 #ifdef KERBEROS5
krb5_error_code kerror; krb5_error_code kerror;
#endif #endif
#if defined(KERBEROS) || defined(KERBEROS5)
int got_tickets = 0;
#endif
#ifdef LOGIN_CAP #ifdef LOGIN_CAP
char *shell = NULL; char *shell = NULL;
login_cap_t *lc = NULL; login_cap_t *lc = NULL;
@ -203,7 +232,6 @@ main(argc, argv)
Fflag = fflag = hflag = pflag = sflag = 0; Fflag = fflag = hflag = pflag = sflag = 0;
#ifdef KERBEROS5 #ifdef KERBEROS5
have_forward = 0; have_forward = 0;
use_krb5 = 1;
#endif #endif
uid = getuid(); uid = getuid();
while ((ch = getopt(argc, argv, "Ffh:ps")) != -1) while ((ch = getopt(argc, argv, "Ffh:ps")) != -1)
@ -274,13 +302,18 @@ main(argc, argv)
if (kerror) { if (kerror) {
syslog(LOG_NOTICE, "%s when initializing Kerberos context", syslog(LOG_NOTICE, "%s when initializing Kerberos context",
error_message(kerror)); error_message(kerror));
use_krb5 = 0; login_krb5_get_tickets = 0;
} } else
login_get_kconf(kcontext);
#endif KERBEROS5 #endif KERBEROS5
for (cnt = 0;; ask = 1) { for (cnt = 0;; ask = 1) {
#if defined(KERBEROS) || defined(KERBEROS5) #if defined(KERBEROS)
kdestroy(); kdestroy();
#endif
#if defined(KERBEROS5)
if (login_krb5_get_tickets)
k5destroy();
#endif #endif
if (ask) { if (ask) {
fflag = 0; fflag = 0;
@ -341,7 +374,7 @@ main(argc, argv)
if (fflag && (uid == 0 || uid == pwd->pw_uid)) { if (fflag && (uid == 0 || uid == pwd->pw_uid)) {
/* already authenticated */ /* already authenticated */
#ifdef KERBEROS5 #ifdef KERBEROS5
if (Fflag) if (login_krb5_get_tickets && Fflag)
k5_read_creds(username); k5_read_creds(username);
#endif #endif
break; break;
@ -376,17 +409,30 @@ main(argc, argv)
goto skip; goto skip;
} }
#ifdef KERBEROS #ifdef KERBEROS
if (klogin(pwd, instance, localhost, p) == 0) { if (
#ifdef KERBEROS5
/* allow a user to get both krb4 and krb5 tickets, if
* desired. If krb5 is compiled in, the default action
* is to ignore krb4 and get krb5 tickets, but the user
* can override this in the krb5.conf. */
login_krb4_get_tickets &&
#endif
klogin(pwd, instance, localhost, p) == 0) {
rval = 0; rval = 0;
goto skip; got_tickets = 1;
} }
#endif #endif
#ifdef KERBEROS5 #ifdef KERBEROS5
if (klogin(pwd, instance, localhost, p) == 0) { if (login_krb5_get_tickets &&
k5login(pwd, instance, localhost, p) == 0) {
rval = 0; rval = 0;
goto skip; got_tickets = 1;
} }
#endif #endif
#if defined(KERBEROS) || defined(KERBEROS5)
if (got_tickets)
goto skip;
#endif
#ifdef SKEY #ifdef SKEY
if (skey_haskey(username) == 0 && if (skey_haskey(username) == 0 &&
skey_passcheck(username, p) != -1) { skey_passcheck(username, p) != -1) {
@ -544,7 +590,11 @@ main(argc, argv)
#if defined(KERBEROS) || defined(KERBEROS5) #if defined(KERBEROS) || defined(KERBEROS5)
/* Fork so that we can call kdestroy */ /* Fork so that we can call kdestroy */
if (krbtkfile_env) if (
#ifdef KERBEROS5
! login_krb5_retain_ccache &&
#endif
has_ccache)
dofork(); dofork();
#endif #endif
@ -611,8 +661,8 @@ main(argc, argv)
(void)setenv("KRBTKFILE", krbtkfile_env, 1); (void)setenv("KRBTKFILE", krbtkfile_env, 1);
#endif #endif
#ifdef KERBEROS5 #ifdef KERBEROS5
if (krbtkfile_env) if (krb5tkfile_env)
(void)setenv("KRB5CCNAME", krbtkfile_env, 1); (void)setenv("KRB5CCNAME", krb5tkfile_env, 1);
#endif #endif
if (tty[sizeof("tty")-1] == 'd') if (tty[sizeof("tty")-1] == 'd')
@ -696,12 +746,35 @@ main(argc, argv)
} }
#ifdef KERBEROS5 #ifdef KERBEROS5
k5_write_creds(); if (login_krb5_get_tickets)
k5_write_creds();
#endif #endif
execlp(pwd->pw_shell, tbuf, 0); execlp(pwd->pw_shell, tbuf, 0);
err(1, "%s", pwd->pw_shell); err(1, "%s", pwd->pw_shell);
} }
#if defined(KERBEROS5)
/* get flags (listed above) from the profile */
void
login_get_kconf(k)
krb5_context k;
{
int i;
krb5_data realm;
realm.length = 0;
if (krb5_get_default_realm(k, &realm.data) == 0)
realm.length = strlen(realm.data);
for (i = 0; login_conf_set[i].flagname; i++) {
krb5_appdefault_boolean(k, "login", &realm,
login_conf_set[i].flagname,
*login_conf_set[i].flag,
login_conf_set[i].flag);
}
}
#endif
#if defined(KERBEROS) || defined(KERBEROS5) #if defined(KERBEROS) || defined(KERBEROS5)
#define NBUFSIZ (MAXLOGNAME + 1 + 5) /* .root suffix */ #define NBUFSIZ (MAXLOGNAME + 1 + 5) /* .root suffix */
#else #else
@ -734,7 +807,13 @@ dofork()
/* Cleanup stuff */ /* Cleanup stuff */
/* Run kdestroy to destroy tickets */ /* Run kdestroy to destroy tickets */
#ifdef KERBEROS
kdestroy(); kdestroy();
#endif
#ifdef KERBEROS5
if (login_krb5_get_tickets)
k5destroy();
#endif
/* Leave */ /* Leave */
exit(0); exit(0);