krb5-clients/1089: Patch to kinit.c using previously sent change
bbense@stanford.edu
bbense at stanford.edu
Tue Apr 16 16:10:29 EDT 2002
>Number: 1089
>Category: krb5-clients
>Synopsis: patch to use appdefaults
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: krb5-unassigned
>State: open
>Class: change-request
>Submitter-Id: unknown
>Arrival-Date: Tue Apr 16 16:11:01 EDT 2002
>Last-Modified:
>Originator: Booker C. Bense
>Organization:
Stanford University
>Release: krb5-1.2.2
>Environment:
UNIX
System: SunOS shred.Stanford.EDU 5.7 Generic_106541-15 sun4u sparc SUNW,Ultra-5_10
Architecture: sun4
>Description:
Patch to use appdefaults api previous sent. I have a similar
patch for login.c if you are interested.
>How-To-Repeat:
>Fix:
This patch uses the appdefaults api to control the behaviour
of kinit.
===================================================================
RCS file: /afs/ir/dev/cvs/kerberos/krb5/clients/kinit/kinit.c,v
retrieving revision 1.1.1.3
retrieving revision 1.19
diff -u -r1.1.1.3 -r1.19
--- /usr/users/bbense/work/kerberos/krb5/clients/kinit/kinit.c 5 Jul 2000 22:46:08 -0000 1.1.1.3
+++ /usr/users/bbense/work/kerberos/krb5/clients/kinit/kinit.c 31 Aug 2001 16:24:02 -0000 1.19
@@ -34,9 +34,19 @@
#else
#undef HAVE_KRB524
#endif
+
+#ifdef STANFORD
+#ifndef ORGANIZATION
+#define DEFAULT_AKLOG_PROGRAM "/etc/leland/aklog"
+#define ORGANIZATION "Stanford University (Leland)"
+#endif /*ORGANIZATION*/
+#endif
+
#include <string.h>
#include <stdio.h>
#include <time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
#ifdef GETOPT_LONG
#include <getopt.h>
@@ -91,6 +101,24 @@
#endif /* _WIN32 */
#endif /* HAVE_PWD_H */
+/* Define the strings for default searching (got these from appl/bsd/login.c) */
+/* This is really a run-time option */
+#define KINIT_USE_KRB524 "krb4_convert"
+/* These can be controlled via command line options. */
+#define KINIT_DEFAULT_COUNT 6
+#define KINIT_GET_KRB5TKT "krb5_get_tickets"
+#define KINIT_GETK5_INDEX 0
+#define KINIT_GET_KRB4TKT "krb4_get_tickets"
+#define KINIT_GETK4_INDEX 1
+#define KINIT_DEFAULT_LIFE "default_lifetime"
+#define KINIT_LIFETM_INDEX 2
+#define KINIT_GET_TOKEN "krb_run_aklog"
+#define KINIT_GETTK_INDEX 3
+#define KINIT_TOKEN_PROGRAM "aklog_path"
+#define KINIT_TOKPG_INDEX 4
+#define KINIT_FORWARDABLE "krb5_get_forwardable"
+#define KINIT_FORWD_INDEX 5
+
static char *progname;
static char* progname_v5 = 0;
@@ -99,8 +127,9 @@
static char* progname_v524 = 0;
#endif
-static int got_k5 = 0;
+
static int got_k4 = 0;
+static int got_k5 = 0;
static int default_k5 = 1;
#if defined(KRB5_KRB4_COMPAT) && defined(KINIT_DEFAULT_BOTH)
@@ -112,7 +141,11 @@
static int authed_k5 = 0;
static int authed_k4 = 0;
+#ifdef STANFORD
+#define KRB4_BACKUP_DEFAULT_LIFE_SECS 25*60*60 /* 25 hours */
+#else
#define KRB4_BACKUP_DEFAULT_LIFE_SECS 10*60*60 /* 10 hours */
+#endif
typedef enum { INIT_PW, INIT_KT, RENEW, VALIDATE } action_type;
@@ -140,6 +173,12 @@
char* k4_cache_name;
action_type action;
+
+ char* token_program;
+ int get_token;
+ int use_k4;
+ int use_k5;
+
};
struct k5_data
@@ -210,11 +249,17 @@
"[-A" USAGE_LONG_ADDRESSES "] "
USAGE_BREAK
"[-v] [-R] "
+#ifdef STANFORD
+ "[-k [-K keytab_file]] "
+ USAGE_BREAK
+ "[-t [-T program]]"
+#else
"[-k [-t keytab_file]] "
+#endif
USAGE_BREAK
"[-c cachename] "
- "[-S service_name] [principal]"
- "\n\n",
+ "[-S service_name] [principal]"
+ "\n\n",
progname);
#define KRB_AVAIL_STRING(x) ((x)?"available":"not available")
@@ -237,7 +282,7 @@
#define ULINE(indent, col1, col2) \
fprintf(stderr, USAGE_OPT_FMT, indent, col1, col2)
- ULINE(" ", "options:", "valid with Kerberos:");
+ ULINE(" ", "options:", "valid with Kerberos:");
fprintf(stderr, "\t-5 Kerberos 5 ()\n", KRB_AVAIL_STRING(got_k5));
fprintf(stderr, "\t-4 Kerberos 4 ()\n", KRB_AVAIL_STRING(got_k4));
fprintf(stderr, "\t (Default behavior is to try )\n",
@@ -257,7 +302,13 @@
ULINE("\t", "-v validate", OPTTYPE_KRB5);
ULINE("\t", "-R renew", OPTTYPE_BOTH);
ULINE("\t", "-k use keytab", OPTTYPE_BOTH);
+#ifdef STANFORD
+ ULINE("\t", "-K filename of keytab to use", OPTTYPE_BOTH);
+ ULINE("\t", "-t get afs token", OPTTYPE_BOTH);
+ ULINE("\t", "-T program to run to get afstoken", OPTTYPE_BOTH);
+#else
ULINE("\t", "-t filename of keytab to use", OPTTYPE_BOTH);
+#endif
ULINE("\t", "-c Kerberos 5 cache name", OPTTYPE_KRB5);
/* This options is not yet available: */
/* ULINE("\t", "-C Kerberos 4 cache name", OPTTYPE_KRB4); */
@@ -266,10 +317,11 @@
}
char *
-parse_options(argc, argv, opts)
+parse_options(argc, argv, opts,default_list)
int argc;
char **argv;
struct k_opts* opts;
+ krb5_appdefault_list_item *default_list;
{
krb5_error_code code;
int errflg = 0;
@@ -277,7 +329,11 @@
int use_k5 = 0;
int i;
+#ifdef STANFORD
+ while ((i = GETOPT(argc, argv, "r:fpFP54AVl:s:c:kK:tT:RS:v"))
+#else
while ((i = GETOPT(argc, argv, "r:fpFP54AVl:s:c:kt:RS:v"))
+#endif
!= -1) {
switch (i) {
case 'V':
@@ -289,6 +345,9 @@
if (code != 0 || opts->lifetime == 0) {
fprintf(stderr, "Bad lifetime value \n", optarg);
errflg++;
+ } else {
+ /* Don't read in any default */
+ default_list[KINIT_LIFETM_INDEX].store = NULL ;
}
break;
case 'r':
@@ -301,6 +360,7 @@
break;
case 'f':
opts->forwardable = 1;
+ default_list[KINIT_FORWD_INDEX].store = NULL ;
break;
case 'F':
opts->not_forwardable = 1;
@@ -338,6 +398,35 @@
case 'k':
opts->action = INIT_KT;
break;
+#ifdef STANFORD
+ case 'K':
+ if (opts->keytab_name)
+ {
+ fprintf(stderr, "Only one -K option allowed.\n");
+ errflg++;
+ } else {
+ opts->keytab_name = optarg;
+ }
+ break;
+ case 't': /* get afs token */
+
+ opts->get_token = 1 ;
+ default_list[KINIT_GETTK_INDEX].store = NULL ;
+ break;
+ case 'T':
+ if (opts->token_program != NULL)
+ {
+ fprintf(stderr, "Only one -T option allowed.\n");
+ errflg++;
+ } else {
+ /* -T implies -t or does it ?*/
+ opts->get_token = 1;
+ default_list[KINIT_GETTK_INDEX].store = NULL ;
+ opts->token_program = optarg;
+ default_list[KINIT_TOKPG_INDEX].store = NULL ;
+ }
+ break;
+#else
case 't':
if (opts->keytab_name)
{
@@ -347,6 +436,7 @@
opts->keytab_name = optarg;
}
break;
+#endif
case 'R':
opts->action = RENEW;
break;
@@ -387,7 +477,11 @@
#endif
exit(3);
}
- use_k4 = 1;
+ opts->use_k4 = 1;
+ default_list[KINIT_GETK4_INDEX].store = NULL ;
+ /* -4 implies K4 only */
+ opts->use_k5 = 0;
+ default_list[KINIT_GETK5_INDEX].store = NULL ;
break;
case '5':
if (!got_k5)
@@ -395,7 +489,11 @@
fprintf(stderr, "Kerberos 5 support could not be loaded\n");
exit(3);
}
- use_k5 = 1;
+ opts->use_k5 = 1;
+ default_list[KINIT_GETK5_INDEX].store = NULL ;
+ /* -5 implies K5 only */
+ opts->use_k4 = 0 ;
+ default_list[KINIT_GETK4_INDEX].store = NULL ;
break;
default:
errflg++;
@@ -424,16 +522,16 @@
argv[optind+1]);
errflg++;
}
-
+ /****** Need to rexamine this *******/
/* At this point, if errorless, we know we only have one option
selection */
- if (!use_k5 && !use_k4) {
- use_k5 = default_k5;
- use_k4 = default_k4;
+ if (!opts->use_k5 && !opts->use_k4) {
+ opts->use_k5 = default_k5;
+ opts->use_k4 = default_k4;
}
/* Now, we encode the OPTTYPE stuff here... */
- if (!use_k5 &&
+ if (!opts->use_k5 &&
(opts->starttime || opts->rlife || opts->forwardable ||
opts->proxiable || opts->addresses || opts->not_forwardable ||
opts->not_proxiable || opts->no_addresses ||
@@ -442,7 +540,7 @@
fprintf(stderr, "Specified option that requires Kerberos 5\n");
errflg++;
}
- if (!use_k4 &&
+ if (!opts->use_k4 &&
opts->k4_cache_name)
{
fprintf(stderr, "Specified option that require Kerberos 4\n");
@@ -450,9 +548,9 @@
}
if (
#ifdef HAVE_KRB524
- !use_k5
+ !opts->use_k5
#else
- use_k4
+ opts->use_k4
#endif
&& (opts->service_name || opts->keytab_name ||
(opts->action == INIT_KT) || (opts->action == RENEW))
@@ -466,13 +564,91 @@
usage();
}
- got_k5 = got_k5 && use_k5;
- got_k4 = got_k4 && use_k4;
-
opts->principal_name = (optind == argc-1) ? argv[optind] : 0;
return opts->principal_name;
}
+/*
+ * Initialize defaults_list for use with krb5_appdefaults_read
+ */
+
+void
+init_defaults(opts,default_list)
+ krb5_appdefault_list_item *default_list;
+ struct k_opts* opts ;
+
+{
+
+ /* Get K5 tgt */
+ default_list[KINIT_GETK5_INDEX].option = KINIT_GET_KRB5TKT ;
+ default_list[KINIT_GETK5_INDEX].default_value = "yes" ;
+ default_list[KINIT_GETK5_INDEX].parse_function = krb5_string_to_boolean ;
+ default_list[KINIT_GETK5_INDEX].store =(void *) &(opts->use_k5);
+
+ /* Get k4 tgt */
+ default_list[KINIT_GETK4_INDEX].option = KINIT_GET_KRB4TKT ;
+#ifdef STANFORD
+ default_list[KINIT_GETK4_INDEX].default_value = "yes" ;
+#else
+ default_list[KINIT_GETK4_INDEX].default_value = "no" ;
+#endif
+ default_list[KINIT_GETK4_INDEX].parse_function = krb5_string_to_boolean ;
+ default_list[KINIT_GETK4_INDEX].store =(void *) &(opts->use_k4);
+
+ /* Lifetime */
+ default_list[KINIT_LIFETM_INDEX].option = KINIT_DEFAULT_LIFE ;
+#ifdef STANFORD
+ default_list[KINIT_LIFETM_INDEX].default_value = "25hrs" ;
+#else
+ default_list[KINIT_LIFETM_INDEX].default_value = "10hrs" ;
+#endif
+ default_list[KINIT_LIFETM_INDEX].parse_function = krb5_string_to_deltat ;
+ default_list[KINIT_LIFETM_INDEX].store =(void *) &(opts->lifetime);
+
+ /* run aklog */
+
+ default_list[KINIT_GETTK_INDEX].option = KINIT_GET_TOKEN ;
+ default_list[KINIT_GETTK_INDEX].default_value = "no" ;
+ default_list[KINIT_GETTK_INDEX].parse_function = krb5_string_to_boolean ;
+ default_list[KINIT_GETTK_INDEX].store =(void *) &(opts->get_token);
+
+ /* aklog path :strdup and free stringval*/
+
+ default_list[KINIT_TOKPG_INDEX].option = KINIT_TOKEN_PROGRAM ;
+ default_list[KINIT_TOKPG_INDEX].default_value = "/usr/pubsw/bin/aklog" ;
+ default_list[KINIT_TOKPG_INDEX].parse_function = krb5_string_to_string ;
+ default_list[KINIT_TOKPG_INDEX].store =(void *) &(opts->token_program);
+
+ /* Get forwardable tgt */
+
+ default_list[KINIT_FORWD_INDEX].option = KINIT_FORWARDABLE ;
+ default_list[KINIT_FORWD_INDEX].default_value = "no" ;
+ default_list[KINIT_FORWD_INDEX].parse_function = krb5_string_to_boolean ;
+ default_list[KINIT_FORWD_INDEX].store =(void *) &(opts->forwardable);
+
+}
+
+
+int
+read_defaults(opts,default_list,k5)
+ struct k_opts* opts;
+ struct k5_data* k5;
+ krb5_appdefault_list_item *default_list;
+{
+ int rcode;
+ if ( k5->me != NULL ) {
+ rcode = krb5_appdefault_read(k5->ctx,progname,
+ krb5_princ_realm(k5->ctx,k5->me),
+ default_list,KINIT_DEFAULT_COUNT);
+ } else {
+ rcode = krb5_appdefault_read(k5->ctx,progname,
+ NULL,
+ default_list,KINIT_DEFAULT_COUNT);
+ }
+ return rcode ;
+}
+
+
int
k5_begin(opts, k5, k4)
struct k_opts* opts;
@@ -482,13 +658,15 @@
char* progname = progname_v5;
krb5_error_code code = 0;
- if (!got_k5)
+ if (!opts->use_k5)
return 0;
+
if (code = krb5_init_context(&k5->ctx)) {
com_err(progname, code, "while initializing Kerberos 5 library");
return 0;
}
+
if (opts->k5_cache_name)
{
code = krb5_cc_resolve(k5->ctx, opts->k5_cache_name, &k5->cc);
@@ -553,19 +731,26 @@
com_err(progname, code, "when unparsing name");
return 0;
}
+#ifndef STANFORD
+ /* I'm not sure this is the right way to do this. If opts->principal_name
+ is available on the cmd line, we need to preserve it for k4_begin.
+ If it's not we want it to be null when k4_begin runs. This ifdef
+ seems to me to be a signal that the design is wrong. opts->principal
+ name should only be used for input, not output. If it's not set
+ by the cmd line it should be left alone.
+ */
opts->principal_name = k5->name;
+#endif
#ifdef KRB5_KRB4_COMPAT
- if (got_k4)
- {
- /* Translate to a Kerberos 4 principal */
- code = krb5_524_conv_principal(k5->ctx, k5->me,
- k4->aname, k4->inst, k4->realm);
- if (code) {
+
+ /* Translate to a Kerberos 4 principal */
+ code = krb5_524_conv_principal(k5->ctx, k5->me,
+ k4->aname, k4->inst, k4->realm);
+ if (code) {
k4->aname[0] = 0;
k4->inst[0] = 0;
k4->realm[0] = 0;
- }
}
#endif
return 1;
@@ -596,12 +781,16 @@
int k_errno = 0;
#endif
- if (!got_k4)
+ if (!opts->use_k4)
return 0;
#ifdef KRB5_KRB4_COMPAT
+#ifndef STANFORD
+ /* Since we want K4 to work in the face of a bad krb5.conf file */
+ /* We can't believe the answer that we get from k5_begin */
if (k4->aname[0])
goto skip;
+#endif
if (opts->principal_name)
{
@@ -643,15 +832,21 @@
}
}
+#ifdef STANFORD
+ krb_get_lrealm(k4->realm, 1) ;
+#else
if (!k4->realm[0])
krb_get_lrealm(k4->realm, 1);
-
+#endif
if (k4->inst[0])
sprintf(k4->name, ".@", k4->aname, k4->inst, k4->realm);
else
- sprintf(k4->name, "@", k4->aname, k4->realm);
- opts->principal_name = k4->name;
-
+ sprintf(k4->name, "@", k4->aname, k4->realm);
+#ifdef STANFORD
+ /* opts->principal_name should not be used for output only input*/
+ if ( opts->principal_name == NULL)
+ opts->principal_name = k4->name;
+#endif
skip:
if (k4->aname[0] && !k_isname(k4->aname))
{
@@ -727,7 +922,7 @@
krb5_error_code code = 0;
krb5_get_init_creds_opt options;
- if (!got_k5)
+ if (!opts->use_k5 || k5->me == NULL)
return 0;
krb5_get_init_creds_opt_init(&options);
@@ -868,7 +1063,7 @@
int k_errno = 0;
#endif
- if (!got_k4)
+ if (!opts->use_k4)
return 0;
if (opts->starttime)
@@ -876,15 +1071,8 @@
#ifdef KRB5_KRB4_COMPAT
if (!k4->lifetime)
- k4->lifetime = opts->lifetime;
- if (!k4->lifetime)
- k4->lifetime = KRB4_BACKUP_DEFAULT_LIFE_SECS;
-
- k4->lifetime /= (5 * 60);
- if (k4->lifetime < 1)
- k4->lifetime = 1;
- if (k4->lifetime > 255)
- k4->lifetime = 255;
+ k4->lifetime = krb_time_to_life(0,opts->lifetime);
+
switch (opts->action)
{
@@ -894,7 +1082,7 @@
krb5_error_code code;
char prompt[1024];
- sprintf(prompt, "Password for : ", opts->principal_name);
+ sprintf(prompt, "Password for : ", k4->name);
stash_password[0] = 0;
/*
Note: krb5_read_password does not actually look at the
@@ -906,7 +1094,7 @@
if (code || pwsize == 0)
{
fprintf(stderr, "Error while reading password for ''\n",
- opts->principal_name);
+ k4->name);
memset(stash_password, 0, sizeof(stash_password));
return 0;
}
@@ -953,8 +1141,9 @@
#ifdef HAVE_KRB524
/* Convert krb5 tickets to krb4. */
-int try_convert524(k5)
+int try_convert524(opts,k5)
struct k5_data* k5;
+ struct k_opts* opts;
{
char * progname = progname_v524;
krb5_error_code code = 0;
@@ -964,7 +1153,7 @@
krb5_creds increds;
CREDENTIALS v4creds;
- if (!got_k4 || !got_k5)
+ if (!opts->use_k4 || !got_k5)
return 0;
memset((char *) &increds, 0, sizeof(increds));
@@ -1052,6 +1241,9 @@
struct k_opts opts;
struct k5_data k5;
struct k4_data k4;
+
+ krb5_appdefault_list_item default_list[ KINIT_DEFAULT_COUNT];
+ int retval ;
progname = GET_PROGNAME(argv[0]);
progname_v5 = getvprogname("5");
@@ -1082,16 +1274,44 @@
memset(&k5, 0, sizeof(k5));
memset(&k4, 0, sizeof(k4));
+ memset(&default_list,0,sizeof(default_list));
+
+ init_defaults(&opts,default_list) ;
- parse_options(argc, argv, &opts);
+ parse_options(argc, argv, &opts,default_list);
got_k5 = k5_begin(&opts, &k5, &k4);
- got_k4 = k4_begin(&opts, &k4);
+ /* need K5 principal */
+
+ retval = read_defaults(&opts,default_list,&k5) ;
+
+ got_k4 = k4_begin(&opts, &k4);
+#ifdef STANFORD
+ /* Happy greeting message */
+ {
+ char host[MAXHOSTNAMELEN] ;
+ host[0] ='\0';
+ if ( opts.action != VALIDATE ) {
+ if ( gethostname(host,MAXHOSTNAMELEN)) {
+ strncat(host,"unknown",MAXHOSTNAMELEN);
+ }
+ printf(" ()\n",ORGANIZATION,host);
+ }
+ }
+#endif
+
authed_k5 = k5_kinit(&opts, &k5);
#ifdef HAVE_KRB524
- if (authed_k5)
- authed_k4 = try_convert524(&k5);
+ /* Check the config file default */
+ if (authed_k5) {
+ krb5_appdefault_boolean(k5.ctx,progname,
+ krb5_princ_realm(k5.ctx,k5.me),KINIT_USE_KRB524,
+ TRUE, &retval) ;
+ if ( retval ) {
+ authed_k4 = try_convert524(&opts,&k5);
+ }
+ }
#endif
if (!authed_k4)
authed_k4 = k4_kinit(&opts, &k4, k5.ctx);
@@ -1106,8 +1326,48 @@
k5_end(&k5);
k4_end(&k4);
-
- if ((got_k5 && !authed_k5) || (got_k4 && !authed_k4))
+ /* This was ||, I think && is a better choice. */
+ if ((opts.use_k5 && !authed_k5) && (opts.use_k4 && !authed_k4))
exit(1);
+
+ if ( opts.get_token ) {
+ /* Since we have unistd.h from above use access rather than stat */
+ if ( access( opts.token_program, X_OK ) == 0 ) {
+ /* Some linuxes use bash as the /bin/sh for the system
+ * call. This interacts badly with afs tokens, due
+ * to a bug in the getgroups call.
+ */
+ my_system( opts.token_program) ;
+ } else {
+ fprintf(stderr,"Cannot execute :: to get token.\n",opts.token_program);
+ }
+
+ }
+
return 0;
}
+
+int
+my_system( char *cmd) {
+
+ int status ;
+ int pid,child;
+ /* Low budget version of system call */
+
+ if ( (pid = fork()) < 0 ) { /* syserr */
+ fprintf(stderr,"fork failed.\n" );
+ return (-1) ;
+ } else if ( pid == 0 ) { /*child */
+ if ( execl(cmd,cmd,(char * )0 ) ) {
+ fprintf(stderr,"error execing \n",cmd);
+ }
+ } else { /* parent */
+ child = wait(&status);
+ if ( child != pid ) { /* This branch should never happen */
+ fprintf(stderr,"Got funky children pid != child\n");
+ return(-1) ;
+ }
+ status = WEXITSTATUS(status);
+ }
+ return status ;
+}
>Audit-Trail:
>Unformatted:
More information about the krb5-bugs
mailing list