From 39d1e5b7fd1e4708c32fd0687a5b886d80684af3 Mon Sep 17 00:00:00 2001 From: aidan Date: Tue, 30 May 2000 06:56:16 +0000 Subject: [PATCH] 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. --- usr.bin/login/k5login.c | 38 ++++++------- usr.bin/login/klogin.c | 6 +- usr.bin/login/login.c | 121 +++++++++++++++++++++++++++++++++------- 3 files changed, 123 insertions(+), 42 deletions(-) diff --git a/usr.bin/login/k5login.c b/usr.bin/login/k5login.c index ebf2a7969207..6ef76f7bbce0 100644 --- a/usr.bin/login/k5login.c +++ b/usr.bin/login/k5login.c @@ -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. @@ -38,7 +38,7 @@ #if 0 static char sccsid[] = "@(#)klogin.c 5.11 (Berkeley) 7/12/92"; #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 */ #ifdef KERBEROS5 @@ -59,19 +59,20 @@ __RCSID("$NetBSD: k5login.c,v 1.11 2000/02/14 03:17:43 aidan Exp $"); krb5_context kcontext; int notickets; -char *krbtkfile_env; +char *krb5tkfile_env; extern char *tty; +extern int login_krb5_forwardable_tgt; +extern int has_ccache; static char tkt_location[MAXPATHLEN]; static krb5_creds forw_creds; int have_forward; static krb5_principal me, server; -int use_krb5; int k5_read_creds __P((char *)); int k5_write_creds __P((void)); -int klogin __P((struct passwd *, char *, char *, char *)); -void kdestroy __P((void)); +int k5login __P((struct passwd *, char *, char *, char *)); +void k5destroy __P((void)); #ifndef krb5_realm_length #define krb5_realm_length(r) ((r).length) @@ -94,9 +95,6 @@ k5_read_creds(username) krb5_creds mcreds; krb5_ccache ccache; - if (! use_krb5) - return(1); - have_forward = 0; memset((char*) &mcreds, 0, sizeof(forw_creds)); memset((char*) &forw_creds, 0, sizeof(forw_creds)); @@ -136,7 +134,8 @@ k5_read_creds(username) have_forward = 1; strcpy(tkt_location, getenv("KRB5CCNAME")); - krbtkfile_env = tkt_location; + krb5tkfile_env = tkt_location; + has_ccache = 1; notickets = 0; nuke_ccache: @@ -150,8 +149,6 @@ k5_write_creds() krb5_error_code code; krb5_ccache ccache; - if (! use_krb5) - return(1); if (!have_forward) return(1); code = krb5_cc_default(kcontext, &ccache); @@ -184,7 +181,7 @@ nuke_ccache_contents: * 1 if Kerberos failed (try local password in login) */ int -klogin(pw, instance, localhost, password) +k5login(pw, instance, localhost, password) struct passwd *pw; char *instance, *localhost, *password; { @@ -197,6 +194,9 @@ klogin(pw, instance, localhost, password) char *realm, *client_name; char *principal; + if (login_krb5_forwardable_tgt) + options |= KDC_OPT_FORWARDABLE; + /* * Root logins don't use Kerberos. * 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 * without issuing any tickets. */ - if (! use_krb5 || - strcmp(pw->pw_name, "root") == 0 || + if (strcmp(pw->pw_name, "root") == 0 || krb5_get_default_realm(kcontext, &realm)) return (1); @@ -222,7 +221,8 @@ klogin(pw, instance, localhost, password) else (void)snprintf(tkt_location, sizeof tkt_location, "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); strcpy(principal, pw->pw_name); /* XXX strcpy is safe */ @@ -317,15 +317,15 @@ klogin(pw, instance, localhost, password) * Remove any credentials */ void -kdestroy() +k5destroy() { krb5_error_code code; krb5_ccache ccache = NULL; - if (! use_krb5 || krbtkfile_env == NULL) + if (krb5tkfile_env == NULL) return; - code = krb5_cc_resolve(kcontext, krbtkfile_env, &ccache); + code = krb5_cc_resolve(kcontext, krb5tkfile_env, &ccache); if (!code) code = krb5_cc_destroy(kcontext, ccache); } diff --git a/usr.bin/login/klogin.c b/usr.bin/login/klogin.c index 86f75df6b8e8..cf6db040aa50 100644 --- a/usr.bin/login/klogin.c +++ b/usr.bin/login/klogin.c @@ -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 @@ -38,7 +38,7 @@ #if 0 static char sccsid[] = "@(#)klogin.c 8.3 (Berkeley) 4/2/94"; #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 */ #ifdef KERBEROS @@ -65,6 +65,7 @@ __RCSID("$NetBSD: klogin.c,v 1.14 1999/07/30 01:56:49 mycroft Exp $"); int notickets; char *krbtkfile_env; char *tty; +extern int has_ccache; 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, "%s_root_%d.%s", TKT_ROOT, pw->pw_uid, tty); krbtkfile_env = tkt_location; + has_ccache = 1; (void)krb_set_tkt_string(tkt_location); /* diff --git a/usr.bin/login/login.c b/usr.bin/login/login.c index 3bd1b7eeef1e..12a95247b45b 100644 --- a/usr.bin/login/login.c +++ b/usr.bin/login/login.c @@ -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 @@ -44,7 +44,7 @@ __COPYRIGHT( #if 0 static char sccsid[] = "@(#)login.c 8.4 (Berkeley) 4/2/94"; #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 */ /* @@ -89,6 +89,24 @@ __RCSID("$NetBSD: login.c,v 1.56 2000/03/07 14:11:22 enami Exp $"); #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 checknologin __P((char *)); void dolastlog __P((int)); @@ -100,14 +118,19 @@ void sigint __P((int)); void sleepexit __P((int)); const char *stypeof __P((const char *)); void timedout __P((int)); -#if defined(KERBEROS) || defined(KERBEROS5) +#if defined(KERBEROS) int klogin __P((struct passwd *, char *, char *, char *)); void kdestroy __P((void)); -void dofork __P((void)); #endif #ifdef KERBEROS5 -int k5_read_creds __P((char*)); -int k5_write_creds __P((void)); +void login_get_kconf __P((krb5_context)); +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 #define TTYGRPNAME "tty" /* name of group to own ttys */ @@ -124,12 +147,15 @@ u_int timeout = 300; #if defined(KERBEROS) || defined(KERBEROS5) int notickets = 1; char *instance; -char *krbtkfile_env; +int has_ccache = 0; +#endif +#ifdef KERBEROS +extern char *krbtkfile_env; #endif #ifdef KERBEROS5 extern krb5_context kcontext; extern int have_forward; -extern int use_krb5; +extern char *krb5tkfile_env; #endif struct passwd *pwd; @@ -168,6 +194,9 @@ main(argc, argv) #ifdef KERBEROS5 krb5_error_code kerror; #endif +#if defined(KERBEROS) || defined(KERBEROS5) + int got_tickets = 0; +#endif #ifdef LOGIN_CAP char *shell = NULL; login_cap_t *lc = NULL; @@ -203,7 +232,6 @@ main(argc, argv) Fflag = fflag = hflag = pflag = sflag = 0; #ifdef KERBEROS5 have_forward = 0; - use_krb5 = 1; #endif uid = getuid(); while ((ch = getopt(argc, argv, "Ffh:ps")) != -1) @@ -274,13 +302,18 @@ main(argc, argv) if (kerror) { syslog(LOG_NOTICE, "%s when initializing Kerberos context", error_message(kerror)); - use_krb5 = 0; - } + login_krb5_get_tickets = 0; + } else + login_get_kconf(kcontext); #endif KERBEROS5 for (cnt = 0;; ask = 1) { -#if defined(KERBEROS) || defined(KERBEROS5) +#if defined(KERBEROS) kdestroy(); +#endif +#if defined(KERBEROS5) + if (login_krb5_get_tickets) + k5destroy(); #endif if (ask) { fflag = 0; @@ -341,7 +374,7 @@ main(argc, argv) if (fflag && (uid == 0 || uid == pwd->pw_uid)) { /* already authenticated */ #ifdef KERBEROS5 - if (Fflag) + if (login_krb5_get_tickets && Fflag) k5_read_creds(username); #endif break; @@ -376,17 +409,30 @@ main(argc, argv) goto skip; } #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; - goto skip; + got_tickets = 1; } #endif #ifdef KERBEROS5 - if (klogin(pwd, instance, localhost, p) == 0) { + if (login_krb5_get_tickets && + k5login(pwd, instance, localhost, p) == 0) { rval = 0; - goto skip; + got_tickets = 1; } #endif +#if defined(KERBEROS) || defined(KERBEROS5) + if (got_tickets) + goto skip; +#endif #ifdef SKEY if (skey_haskey(username) == 0 && skey_passcheck(username, p) != -1) { @@ -544,7 +590,11 @@ main(argc, argv) #if defined(KERBEROS) || defined(KERBEROS5) /* Fork so that we can call kdestroy */ - if (krbtkfile_env) + if ( +#ifdef KERBEROS5 + ! login_krb5_retain_ccache && +#endif + has_ccache) dofork(); #endif @@ -611,8 +661,8 @@ main(argc, argv) (void)setenv("KRBTKFILE", krbtkfile_env, 1); #endif #ifdef KERBEROS5 - if (krbtkfile_env) - (void)setenv("KRB5CCNAME", krbtkfile_env, 1); + if (krb5tkfile_env) + (void)setenv("KRB5CCNAME", krb5tkfile_env, 1); #endif if (tty[sizeof("tty")-1] == 'd') @@ -696,12 +746,35 @@ main(argc, argv) } #ifdef KERBEROS5 - k5_write_creds(); + if (login_krb5_get_tickets) + k5_write_creds(); #endif execlp(pwd->pw_shell, tbuf, 0); 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) #define NBUFSIZ (MAXLOGNAME + 1 + 5) /* .root suffix */ #else @@ -734,7 +807,13 @@ dofork() /* Cleanup stuff */ /* Run kdestroy to destroy tickets */ +#ifdef KERBEROS kdestroy(); +#endif +#ifdef KERBEROS5 + if (login_krb5_get_tickets) + k5destroy(); +#endif /* Leave */ exit(0);