From 30e52cc927d6738230ec1c182320b7d32e606781 Mon Sep 17 00:00:00 2001 From: Ken Raeburn Date: Wed, 1 Sep 1999 21:12:02 +0000 Subject: [PATCH] implement KRB5_TC_SUPPORTED_KTYPES and common _retrieve methods; from 1.1 branch git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@11768 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/krb5/ccache/ChangeLog | 12 ++ src/lib/krb5/ccache/Makefile.in | 3 + src/lib/krb5/ccache/cc_retr.c | 283 +++++++++++++++++++++++++ src/lib/krb5/ccache/ccapi/ChangeLog | 5 + src/lib/krb5/ccache/ccapi/stdcc.c | 17 ++ src/lib/krb5/ccache/file/ChangeLog | 5 + src/lib/krb5/ccache/file/fcc_retrv.c | 20 ++ src/lib/krb5/ccache/memory/ChangeLog | 5 + src/lib/krb5/ccache/memory/mcc_retrv.c | 20 ++ src/lib/krb5/ccache/stdio/ChangeLog | 5 + src/lib/krb5/ccache/stdio/scc_retrv.c | 20 ++ 11 files changed, 395 insertions(+) create mode 100644 src/lib/krb5/ccache/cc_retr.c diff --git a/src/lib/krb5/ccache/ChangeLog b/src/lib/krb5/ccache/ChangeLog index 508078644..3ec681fd9 100644 --- a/src/lib/krb5/ccache/ChangeLog +++ b/src/lib/krb5/ccache/ChangeLog @@ -1,3 +1,15 @@ +1999-08-23 Ken Raeburn + + * cc_retr.c: New file. + (krb5_cc_retrieve_cred_seq): New function, derived from + fcc_retrieve but takes an optional list of enctypes to look for in + priority order. + (krb5_cc_retrieve_cred_default): New function. Same signature as + original fcc_retrieve but if new flag KRB5_TC_SUPPORTED_KTYPES is + set, calls krb5_get_tgs_ktypes to get a list of enctypes to look + for. + * Makefile.in (STLIBOBJS, OBJS, SRCS): Add it. + Tue May 18 19:52:56 1999 Danilo Almeida * Makefile.in: Remove - from recursive Win32 make invocation. diff --git a/src/lib/krb5/ccache/Makefile.in b/src/lib/krb5/ccache/Makefile.in index eafa55773..a9d426595 100644 --- a/src/lib/krb5/ccache/Makefile.in +++ b/src/lib/krb5/ccache/Makefile.in @@ -21,18 +21,21 @@ STLIBOBJS= \ cccopy.o \ ccdefault.o \ ccdefops.o \ + cc_retr.o \ ser_cc.o OBJS= $(OUTPRE)ccbase.$(OBJEXT) \ $(OUTPRE)cccopy.$(OBJEXT) \ $(OUTPRE)ccdefault.$(OBJEXT) \ $(OUTPRE)ccdefops.$(OBJEXT) \ + $(OUTPRE)cc_retr.$(OBJEXT) \ $(OUTPRE)ser_cc.$(OBJEXT) SRCS= $(srcdir)/ccbase.c \ $(srcdir)/cccopy.c \ $(srcdir)/ccdefault.c \ $(srcdir)/ccdefops.c \ + $(srcdir)/cc_retr.c \ $(srcdir)/ser_cc.c all-unix:: all-libobjs diff --git a/src/lib/krb5/ccache/cc_retr.c b/src/lib/krb5/ccache/cc_retr.c new file mode 100644 index 000000000..e786335d0 --- /dev/null +++ b/src/lib/krb5/ccache/cc_retr.c @@ -0,0 +1,283 @@ +/* + * lib/krb5/ccache/cc_retr.c + * + * Copyright 1990,1991,1999 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * + */ + +#include "k5-int.h" + +#define KRB5_OK 0 + +#define set(bits) (whichfields & bits) +#define flags_match(a,b) (((a) & (b)) == (a)) +#define times_match_exact(t1,t2) (memcmp((char *)(t1), (char *)(t2), sizeof(*(t1))) == 0) + +static krb5_boolean +times_match(t1, t2) + const krb5_ticket_times *t1; + const krb5_ticket_times *t2; +{ + if (t1->renew_till) { + if (t1->renew_till > t2->renew_till) + return FALSE; /* this one expires too late */ + } + if (t1->endtime) { + if (t1->endtime > t2->endtime) + return FALSE; /* this one expires too late */ + } + /* only care about expiration on a times_match */ + return TRUE; +} + +static krb5_boolean +standard_fields_match(context, mcreds, creds) +krb5_context context; +const krb5_creds *mcreds; +const krb5_creds *creds; +{ + return (krb5_principal_compare(context, mcreds->client,creds->client) + && krb5_principal_compare(context, mcreds->server,creds->server)); +} + +/* only match the server name portion, not the server realm portion */ + +static krb5_boolean +srvname_match(context, mcreds, creds) + krb5_context context; + const krb5_creds *mcreds, *creds; +{ + krb5_boolean retval; + krb5_principal_data p1, p2; + + retval = krb5_principal_compare(context, mcreds->client,creds->client); + if (retval != TRUE) + return retval; + /* + * Hack to ignore the server realm for the purposes of the compare. + */ + p1 = *mcreds->server; + p2 = *creds->server; + p1.realm = p2.realm; + return krb5_principal_compare(context, &p1, &p2); +} + +static krb5_boolean +authdata_match(mdata, data) + krb5_authdata * const *mdata, * const *data; +{ + const krb5_authdata *mdatap, *datap; + + if (mdata == data) + return TRUE; + + if (mdata == NULL) + return *data == NULL; + + if (data == NULL) + return *mdata == NULL; + + while ((mdatap = *mdata) && (datap = *data)) { + if ((mdatap->ad_type != datap->ad_type) || + (mdatap->length != datap->length) || + (memcmp ((char *)mdatap->contents, + (char *)datap->contents, mdatap->length) != 0)) + return FALSE; + mdata++; + data++; + } + return (*mdata == NULL) && (*data == NULL); +} + +static krb5_boolean +data_match(data1, data2) + const krb5_data *data1, *data2; +{ + if (!data1) { + if (!data2) + return TRUE; + else + return FALSE; + } + if (!data2) return FALSE; + + if (data1->length != data2->length) + return FALSE; + else + return memcmp(data1->data, data2->data, data1->length) ? FALSE : TRUE; +} + +static int +pref (krb5_enctype my_ktype, int nktypes, krb5_enctype *ktypes) +{ + int i; + for (i = 0; i < nktypes; i++) + if (my_ktype == ktypes[i]) + return i; + return -1; +} + +/* + * Effects: + * Searches the credentials cache for a credential matching mcreds, + * with the fields specified by whichfields. If one if found, it is + * returned in creds, which should be freed by the caller with + * krb5_free_credentials(). + * + * The fields are interpreted in the following way (all constants are + * preceded by KRB5_TC_). MATCH_IS_SKEY requires the is_skey field to + * match exactly. MATCH_TIMES requires the requested lifetime to be + * at least as great as that specified; MATCH_TIMES_EXACT requires the + * requested lifetime to be exactly that specified. MATCH_FLAGS + * requires only the set bits in mcreds be set in creds; + * MATCH_FLAGS_EXACT requires all bits to match. + * + * Flag SUPPORTED_KTYPES means check all matching entries that have + * any supported enctype (according to tgs_enctypes) and return the one + * with the enctype listed earliest. Return CC_NOT_KTYPE if a match + * is found *except* for having a supported enctype. + * + * Errors: + * system errors + * permission errors + * KRB5_CC_NOMEM + * KRB5_CC_NOT_KTYPE + */ + +static krb5_error_code +krb5_cc_retrieve_cred_seq (context, id, whichfields, + mcreds, creds, nktypes, ktypes) + krb5_context context; + krb5_ccache id; + krb5_flags whichfields; + krb5_creds *mcreds; + krb5_creds *creds; + int nktypes; + krb5_enctype *ktypes; +{ + /* This function could be considerably faster if it kept indexing */ + /* information.. sounds like a "next version" idea to me. :-) */ + + krb5_cc_cursor cursor; + krb5_error_code kret; + krb5_error_code nomatch_err = KRB5_CC_NOTFOUND; + struct { + krb5_creds creds; + int pref; + } fetched, best; + int have_creds = 0; +#define fetchcreds (fetched.creds) + + kret = krb5_cc_start_seq_get(context, id, &cursor); + if (kret != KRB5_OK) + return kret; + + while ((kret = krb5_cc_next_cred(context, id, &cursor, &fetchcreds)) == KRB5_OK) { + if (((set(KRB5_TC_MATCH_SRV_NAMEONLY) && + srvname_match(context, mcreds, &fetchcreds)) || + standard_fields_match(context, mcreds, &fetchcreds)) + && + (! set(KRB5_TC_MATCH_IS_SKEY) || + mcreds->is_skey == fetchcreds.is_skey) + && + (! set(KRB5_TC_MATCH_FLAGS_EXACT) || + mcreds->ticket_flags == fetchcreds.ticket_flags) + && + (! set(KRB5_TC_MATCH_FLAGS) || + flags_match(mcreds->ticket_flags, fetchcreds.ticket_flags)) + && + (! set(KRB5_TC_MATCH_TIMES_EXACT) || + times_match_exact(&mcreds->times, &fetchcreds.times)) + && + (! set(KRB5_TC_MATCH_TIMES) || + times_match(&mcreds->times, &fetchcreds.times)) + && + ( ! set(KRB5_TC_MATCH_AUTHDATA) || + authdata_match(mcreds->authdata, fetchcreds.authdata)) + && + (! set(KRB5_TC_MATCH_2ND_TKT) || + data_match (&mcreds->second_ticket, &fetchcreds.second_ticket)) + && + ((! set(KRB5_TC_MATCH_KTYPE))|| + (mcreds->keyblock.enctype == fetchcreds.keyblock.enctype))) + { + if (ktypes) { + fetched.pref = pref (fetchcreds.keyblock.enctype, + nktypes, ktypes); + if (fetched.pref < 0) + nomatch_err = KRB5_CC_NOT_KTYPE; + else if (!have_creds || fetched.pref < best.pref) { + if (have_creds) + krb5_free_cred_contents (context, &best.creds); + else + have_creds = 1; + best = fetched; + continue; + } + } else { + krb5_cc_end_seq_get(context, id, &cursor); + *creds = fetchcreds; + return KRB5_OK; + } + } + + /* This one doesn't match */ + krb5_free_cred_contents(context, &fetchcreds); + } + + /* If we get here, a match wasn't found */ + krb5_cc_end_seq_get(context, id, &cursor); + if (have_creds) { + *creds = best.creds; + return KRB5_OK; + } else + return nomatch_err; +} + +krb5_error_code KRB5_CALLCONV +krb5_cc_retrieve_cred_default (context, id, flags, mcreds, creds) + krb5_context context; + krb5_ccache id; + krb5_flags flags; + krb5_creds *mcreds; + krb5_creds *creds; +{ + krb5_enctype *ktypes; + int nktypes; + krb5_error_code ret; + + if (flags & KRB5_TC_SUPPORTED_KTYPES) { + ret = krb5_get_tgs_ktypes (context, mcreds->server, &ktypes); + if (ret) + return ret; + nktypes = 0; + while (ktypes[nktypes]) + nktypes++; + + ret = krb5_cc_retrieve_cred_seq (context, id, flags, mcreds, creds, + nktypes, ktypes); + free (ktypes); + return ret; + } else { + return krb5_cc_retrieve_cred_seq (context, id, flags, mcreds, creds, + 0, 0); + } +} diff --git a/src/lib/krb5/ccache/ccapi/ChangeLog b/src/lib/krb5/ccache/ccapi/ChangeLog index dfe92f16f..c6ca9f7ea 100644 --- a/src/lib/krb5/ccache/ccapi/ChangeLog +++ b/src/lib/krb5/ccache/ccapi/ChangeLog @@ -1,3 +1,8 @@ +1999-08-23 Ken Raeburn + + * stdcc.c (krb5_stdcc_retrieve): Replace with a version that calls + krb5_cc_retrieve_cred_default. + 1999-08-05 Alexandra Ellwood * stdcc_util.c (deep_free_cc_v5_creds): diff --git a/src/lib/krb5/ccache/ccapi/stdcc.c b/src/lib/krb5/ccache/ccapi/stdcc.c index db93102ca..18cc870b4 100644 --- a/src/lib/krb5/ccache/ccapi/stdcc.c +++ b/src/lib/krb5/ccache/ccapi/stdcc.c @@ -478,6 +478,7 @@ krb5_error_code KRB5_CALLCONV krb5_stdcc_next_cred * * - try to find a matching credential in the cache */ +#if 0 krb5_error_code KRB5_CALLCONV krb5_stdcc_retrieve (krb5_context context, krb5_ccache id, @@ -523,6 +524,22 @@ krb5_error_code KRB5_CALLCONV krb5_stdcc_retrieve return KRB5_CC_NOTFOUND; } +#else +#include "k5-int.h" + +krb5_error_code KRB5_CALLCONV +krb5_stdcc_retrieve(context, id, whichfields, mcreds, creds) + krb5_context context; + krb5_ccache id; + krb5_flags whichfields; + krb5_creds *mcreds; + krb5_creds *creds; +{ + return krb5_cc_retrieve_cred_default (context, id, whichfields, + mcreds, creds); +} + +#endif /* * end seq diff --git a/src/lib/krb5/ccache/file/ChangeLog b/src/lib/krb5/ccache/file/ChangeLog index f99e78246..0da5c9701 100644 --- a/src/lib/krb5/ccache/file/ChangeLog +++ b/src/lib/krb5/ccache/file/ChangeLog @@ -1,3 +1,8 @@ +1999-08-23 Ken Raeburn + + * fcc_retrv.c (krb5_fcc_retrieve): Replace with a version that + calls krb5_cc_retrieve_cred_default. + 1999-06-10 Danilo Almeida * fcc_ops.c (krb5_cache_change): Use PostMessage instead of diff --git a/src/lib/krb5/ccache/file/fcc_retrv.c b/src/lib/krb5/ccache/file/fcc_retrv.c index 5f4e71d7c..c3d1f48cb 100644 --- a/src/lib/krb5/ccache/file/fcc_retrv.c +++ b/src/lib/krb5/ccache/file/fcc_retrv.c @@ -24,6 +24,8 @@ * This file contains the source code for krb5_fcc_retrieve. */ +#if 0 + #include "fcc.h" #ifdef macintosh @@ -230,3 +232,21 @@ authdata_match(mdata, data) } return (*mdata == NULL) && (*data == NULL); } + +#else + +#include "k5-int.h" + +krb5_error_code KRB5_CALLCONV +krb5_fcc_retrieve(context, id, whichfields, mcreds, creds) + krb5_context context; + krb5_ccache id; + krb5_flags whichfields; + krb5_creds *mcreds; + krb5_creds *creds; +{ + return krb5_cc_retrieve_cred_default (context, id, whichfields, + mcreds, creds); +} + +#endif diff --git a/src/lib/krb5/ccache/memory/ChangeLog b/src/lib/krb5/ccache/memory/ChangeLog index 4ff0ffafd..9a68c4118 100644 --- a/src/lib/krb5/ccache/memory/ChangeLog +++ b/src/lib/krb5/ccache/memory/ChangeLog @@ -1,3 +1,8 @@ +1999-08-23 Ken Raeburn + + * mcc_retrv.c (krb5_mcc_retrieve): Replace with a version that + calls krb5_cc_retrieve_cred_default. + Mon May 10 15:25:06 1999 Danilo Almeida * Makefile.in: Do win32 build in subdir. diff --git a/src/lib/krb5/ccache/memory/mcc_retrv.c b/src/lib/krb5/ccache/memory/mcc_retrv.c index ae3510129..6ae6d290d 100644 --- a/src/lib/krb5/ccache/memory/mcc_retrv.c +++ b/src/lib/krb5/ccache/memory/mcc_retrv.c @@ -24,6 +24,8 @@ * This file contains the source code for krb5_mcc_retrieve. */ +#if 0 + #include "mcc.h" #define set(bits) (whichfields & bits) @@ -223,3 +225,21 @@ authdata_match(mdata, data) } return (*mdata == NULL) && (*data == NULL); } + +#else + +#include "k5-int.h" + +krb5_error_code KRB5_CALLCONV +krb5_mcc_retrieve(context, id, whichfields, mcreds, creds) + krb5_context context; + krb5_ccache id; + krb5_flags whichfields; + krb5_creds *mcreds; + krb5_creds *creds; +{ + return krb5_cc_retrieve_cred_default (context, id, whichfields, + mcreds, creds); +} + +#endif diff --git a/src/lib/krb5/ccache/stdio/ChangeLog b/src/lib/krb5/ccache/stdio/ChangeLog index 5b7e7ea1a..9a402a46c 100644 --- a/src/lib/krb5/ccache/stdio/ChangeLog +++ b/src/lib/krb5/ccache/stdio/ChangeLog @@ -1,3 +1,8 @@ +1999-08-23 Ken Raeburn + + * scc_retrv.c (krb5_scc_retrieve): Replace with a version that + calls krb5_cc_retrieve_cred_default. + 1998-11-13 Theodore Ts'o * Makefile.in: Set the myfulldir and mydir variables (which are diff --git a/src/lib/krb5/ccache/stdio/scc_retrv.c b/src/lib/krb5/ccache/stdio/scc_retrv.c index 7498d906e..00a780097 100644 --- a/src/lib/krb5/ccache/stdio/scc_retrv.c +++ b/src/lib/krb5/ccache/stdio/scc_retrv.c @@ -24,6 +24,8 @@ * This file contains the source code for krb5_scc_retrieve. */ +#if 0 + #include "scc.h" #define set(bits) (whichfields & bits) @@ -217,3 +219,21 @@ krb5_scc_retrieve(context, id, whichfields, mcreds, creds) krb5_scc_end_seq_get(context, id, &cursor); return KRB5_CC_NOTFOUND; } + +#else + +#include "k5-int.h" + +krb5_error_code KRB5_CALLCONV +krb5_scc_retrieve(context, id, whichfields, mcreds, creds) + krb5_context context; + krb5_ccache id; + krb5_flags whichfields; + krb5_creds *mcreds; + krb5_creds *creds; +{ + return krb5_cc_retrieve_cred_default (context, id, whichfields, + mcreds, creds); +} + +#endif -- 2.26.2