summaryrefslogtreecommitdiffstats
path: root/src/lib
diff options
context:
space:
mode:
authorTheodore Tso <tytso@mit.edu>1999-02-18 04:28:12 +0000
committerTheodore Tso <tytso@mit.edu>1999-02-18 04:28:12 +0000
commit6af7079089f3ff2291f2ae77173f5f008e8dfc44 (patch)
tree9ae7044d416955443acbcfde01319c44e75c010a /src/lib
parent8b3e9817300fab24730423d5ad140917b710ed31 (diff)
Added debugging hooks to stdcc.c
Added broadcast event notification of the krb5 cache changing, for backwards compatibility with krb5.exe. Added support for the V2 Ccache API. In stdcc_util.c, replace the old matching algorithm with one that's closer to the original stdcc and file algorithm, and so is provably correct. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@11181 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/krb5/ccache/ccapi/stdcc.c93
-rw-r--r--src/lib/krb5/ccache/ccapi/stdcc_util.c206
2 files changed, 222 insertions, 77 deletions
diff --git a/src/lib/krb5/ccache/ccapi/stdcc.c b/src/lib/krb5/ccache/ccapi/stdcc.c
index 4912ba159..b81e82a7d 100644
--- a/src/lib/krb5/ccache/ccapi/stdcc.c
+++ b/src/lib/krb5/ccache/ccapi/stdcc.c
@@ -25,6 +25,7 @@
*
*/
+#define NEED_WINDOWS
#include "stdcc.h"
#include "stdcc_util.h"
#include "string.h"
@@ -32,6 +33,19 @@
#if defined(_MSDOS) || defined(_WIN32)
apiCB *gCntrlBlock = NULL;
+#else
+#define CC_API_VER2
+#endif
+
+#ifdef DEBUG
+#if defined(_MSDOS) || defined(_WIN32)
+#include <io.h>
+#define SHOW_DEBUG(buf) MessageBox((HWND)NULL, (buf), "ccapi debug", MB_OK)
+#endif
+ /* XXX need macintosh debugging statement if we want to debug */
+ /* on the mac */
+#else
+#define SHOW_DEBUG(buf)
#endif
/*
@@ -58,6 +72,31 @@ krb5_cc_ops krb5_cc_stdcc_ops = {
krb5_stdcc_set_flags,
};
+#if defined(_MSDOS) || defined(_WIN32)
+/*
+ * cache_changed be called after the cache changes.
+ * A notification message is is posted out to all top level
+ * windows so that they may recheck the cache based on the
+ * changes made. We register a unique message type with which
+ * we'll communicate to all other processes.
+ */
+void cache_changed()
+{
+ static unsigned int message = 0;
+
+ if (message == 0)
+ message = RegisterWindowMessage(WM_KERBEROS5_CHANGED);
+
+ SendMessage(HWND_BROADCAST, message, 0, 0);
+}
+#else /* _MSDOS || _WIN32 */
+
+void cache_changed()
+{
+ return;
+}
+#endif /* _MSDOS || _WIN32 */
+
struct err_xlate
{
int cc_err;
@@ -90,6 +129,9 @@ static krb5_error_code cc_err_xlate(int err)
{
const struct err_xlate *p;
+ if (err == CC_NOERROR)
+ return 0;
+
for (p = err_xlate_table; p->cc_err; p++) {
if (err == p->cc_err)
return p->krb5_err;
@@ -104,7 +146,11 @@ static krb5_error_code stdcc_setup(krb5_context context,
/* make sure the API has been intialized */
if (gCntrlBlock == NULL) {
+#ifdef CC_API_VER2
+ err = cc_initialize(&gCntrlBlock, CC_API_VER_2, NULL, NULL);
+#else
err = cc_initialize(&gCntrlBlock, CC_API_VER_1, NULL, NULL);
+#endif
if (err != CC_NOERROR)
return cc_err_xlate(err);
}
@@ -286,11 +332,9 @@ krb5_error_code KRB5_CALLCONV krb5_stdcc_initialize
err = cc_create(gCntrlBlock, ccapi_data->cache_name, cName,
CC_CRED_V5, 0L, &ccapi_data->NamedCache);
krb5_free_unparsed_name(context, cName);
+ cache_changed();
- if (err)
- return cc_err_xlate(err);
-
- return 0;
+ return cc_err_xlate(err);
}
/*
@@ -299,7 +343,7 @@ krb5_error_code KRB5_CALLCONV krb5_stdcc_initialize
* store some credentials in our cache
*/
krb5_error_code KRB5_CALLCONV krb5_stdcc_store
- (krb5_context context, krb5_ccache id , krb5_creds *creds )
+ (krb5_context context, krb5_ccache id, krb5_creds *creds )
{
krb5_error_code retval;
stdccCacheDataPtr ccapi_data = id->data;
@@ -324,6 +368,7 @@ krb5_error_code KRB5_CALLCONV krb5_stdcc_store
/* free the cred union */
err = cc_free_creds(gCntrlBlock, &cu);
+ cache_changed();
return err;
}
@@ -337,12 +382,22 @@ krb5_error_code KRB5_CALLCONV krb5_stdcc_start_seq_get
{
stdccCacheDataPtr ccapi_data = id->data;
krb5_error_code retval;
+ int err;
+ ccache_cit *iterator;
if ((retval = stdcc_setup(context, ccapi_data)))
return retval;
-
+
+#ifdef CC_API_VER2
+ err = cc_seq_fetch_creds_begin(gCntrlBlock, ccapi_data->NamedCache,
+ &iterator);
+ if (err != CC_NOERROR)
+ return cc_err_xlate(err);
+ *cursor = iterator;
+#else
/* all we have to do is initialize the cursor */
*cursor = NULL;
+#endif
return 0;
}
@@ -360,15 +415,29 @@ krb5_error_code KRB5_CALLCONV krb5_stdcc_next_cred
stdccCacheDataPtr ccapi_data = id->data;
int err;
cred_union *credU = NULL;
+ ccache_cit *iterator;
if ((retval = stdcc_setup(context, ccapi_data)))
return retval;
+#ifdef CC_API_VER2
+ iterator = *cursor;
+ if (iterator == 0)
+ return KRB5_CC_END;
+ err = cc_seq_fetch_creds_next(gCntrlBlock, &credU, iterator);
+
+ if (err = CC_END) {
+ cc_seq_fetch_creds_end(gCntrlBlock, &iterator);
+ *cursor = 0;
+ }
+#else
err = cc_seq_fetch_creds(gCntrlBlock, ccapi_data->NamedCache,
- &credU, (ccache_cit **)cursor);
+ &credU, (ccache_cit **)cursor);
+#endif
+
if (err != CC_NOERROR)
return cc_err_xlate(err);
-
+
/* copy data (with translation) */
dupCCtoK5(context, credU->cred.pV5Cred, creds);
@@ -451,6 +520,11 @@ krb5_error_code KRB5_CALLCONV krb5_stdcc_end_seq_get
if (*cursor == NULL)
return 0;
+#ifdef CC_API_VER2
+ err = cc_seq_fetch_creds_end(gCntrlBlock, (ccache_cit **)cursor);
+ if (err != CC_NOERROR)
+ return cc_err_xlate(err);
+#else
/*
* Finish calling cc_seq_fetch_creds to clear out the cursor
*/
@@ -462,6 +536,7 @@ krb5_error_code KRB5_CALLCONV krb5_stdcc_end_seq_get
cc_free_creds(gCntrlBlock, &credU);
}
+#endif
return(0);
}
@@ -515,6 +590,7 @@ krb5_stdcc_destroy (krb5_context context, krb5_ccache id)
/* destroy the named cache */
err = cc_destroy(gCntrlBlock, &ccapi_data->NamedCache);
+ cache_changed();
return cc_err_xlate(err);
}
@@ -614,6 +690,7 @@ krb5_error_code KRB5_CALLCONV krb5_stdcc_remove
/* free the temp cred union */
err = cc_free_creds(gCntrlBlock, &cu);
+ cache_changed();
if (err != CC_NOERROR)
return cc_err_xlate(err);
diff --git a/src/lib/krb5/ccache/ccapi/stdcc_util.c b/src/lib/krb5/ccache/ccapi/stdcc_util.c
index dd44109ad..3c6917ad9 100644
--- a/src/lib/krb5/ccache/ccapi/stdcc_util.c
+++ b/src/lib/krb5/ccache/ccapi/stdcc_util.c
@@ -310,13 +310,115 @@ void dupK5toCC(krb5_context context, krb5_creds *creds, cred_union **cu)
}
/*
- * bitTst
- * - utility function for below function
+ * Utility functions...
*/
-int bitTst(int var, int mask) {
+static krb5_boolean
+times_match(t1, t2)
+register const krb5_ticket_times *t1;
+register 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
+times_match_exact (t1, t2)
+ register const krb5_ticket_times *t1, *t2;
+{
+ return (t1->authtime == t2->authtime
+ && t1->starttime == t2->starttime
+ && t1->endtime == t2->endtime
+ && t1->renew_till == t2->renew_till);
+}
- return var & mask;
-}
+static krb5_boolean
+standard_fields_match(context, mcreds, creds)
+ krb5_context context;
+register const krb5_creds *mcreds, *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;
+register 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)
+ && mdatap->ad_type == datap->ad_type
+ && mdatap->length == datap->length
+ && !memcmp ((char *) mdatap->contents, (char *) datap->contents,
+ datap->length)) {
+ mdata++;
+ data++;
+ }
+
+ return !*mdata && !*data;
+}
+
+static krb5_boolean
+data_match(data1, data2)
+register 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;
+}
+
+#define MATCH_SET(bits) (whichfields & bits)
+#define flags_match(a,b) (((a) & (b)) == (a))
/* stdccCredsMatch
* - check to see if the creds match based on the whichFields variable
@@ -330,70 +432,36 @@ int stdccCredsMatch(krb5_context context, krb5_creds *base,
krb5_ticket_times b, m;
krb5_authdata **bp, **mp;
krb5_boolean retval;
-
- /* always check the standard fields */
- if ((krb5_principal_compare(context, base->client, match->client) &&
- krb5_principal_compare(context, base->server, match->server)) == FALSE)
- return FALSE;
-
- if (bitTst(whichfields, KRB5_TC_MATCH_TIMES)) {
- /*
- * test for matching times
- * according to the file cache implementation we do:
- */
- if (match->times.renew_till) {
- if (match->times.renew_till > base->times.renew_till)
- return FALSE; /* this one expires too late */
- }
- if (match->times.endtime) {
- if (match->times.endtime > base->times.endtime)
- return FALSE; /* this one expires too late */
- }
- }
-
- if (bitTst(whichfields, KRB5_TC_MATCH_IS_SKEY))
- if (base->is_skey != match->is_skey) return FALSE;
-
- if (bitTst(whichfields, KRB5_TC_MATCH_FLAGS))
- if (base->ticket_flags != match->ticket_flags) return FALSE;
-
- if (bitTst(whichfields, KRB5_TC_MATCH_TIMES_EXACT)) {
- b = base->times; m = match->times;
- if ((b.authtime != m.authtime) ||
- (b.starttime != m.starttime) ||
- (b.endtime != m.endtime) ||
- (b.renew_till != m.renew_till)) return FALSE;
- }
-
- if (bitTst(whichfields, KRB5_TC_MATCH_AUTHDATA)) {
- bp = base->authdata;
- mp = match->authdata;
- if ((bp != NULL) && (mp != NULL)) {
- while ( (bp) && (*bp != NULL) ){
- if (( (*bp)->ad_type != (*mp)->ad_type) ||
- ( (*bp)->length != (*mp)->length) ||
- ( memcmp( (*bp)->contents, (*mp)->contents, (*bp)->length) != 0)) return FALSE;
- mp++; bp++;
- }
- }
- }
+ if (((MATCH_SET(KRB5_TC_MATCH_SRV_NAMEONLY) &&
+ srvname_match(context, match, base)) ||
+ standard_fields_match(context, match, base))
+ &&
+ (! MATCH_SET(KRB5_TC_MATCH_IS_SKEY) ||
+ match->is_skey == base->is_skey)
+ &&
+ (! MATCH_SET(KRB5_TC_MATCH_FLAGS_EXACT) ||
+ match->ticket_flags == base->ticket_flags)
+ &&
+ (! MATCH_SET(KRB5_TC_MATCH_FLAGS) ||
+ flags_match(match->ticket_flags, base->ticket_flags))
+ &&
+ (! MATCH_SET(KRB5_TC_MATCH_TIMES_EXACT) ||
+ times_match_exact(&match->times, &base->times))
+ &&
+ (! MATCH_SET(KRB5_TC_MATCH_TIMES) ||
+ times_match(&match->times, &base->times))
+ &&
+ (! MATCH_SET(KRB5_TC_MATCH_AUTHDATA) ||
+ authdata_match (match->authdata, base->authdata))
+ &&
+ (! MATCH_SET(KRB5_TC_MATCH_2ND_TKT) ||
+ data_match (&match->second_ticket, &base->second_ticket))
+ &&
+ ((! MATCH_SET(KRB5_TC_MATCH_KTYPE))||
+ (match->keyblock.enctype == base->keyblock.enctype))
+ )
+ return TRUE;
+ return FALSE;
- if (bitTst(whichfields, KRB5_TC_MATCH_SRV_NAMEONLY)) {
- //taken from cc_retrv.c
- retval = krb5_principal_compare(context, base->client,match->client);
- if (!retval) return FALSE;
-
- }
-
- if (bitTst(whichfields, KRB5_TC_MATCH_2ND_TKT))
- if ( (base->second_ticket.length != match->second_ticket.length) ||
- (memcmp(base->second_ticket.data, match->second_ticket.data, base->second_ticket.length) != 0))
- return FALSE;
-
- if (bitTst(whichfields, KRB5_TC_MATCH_KTYPE))
- if (base->keyblock.enctype != match->keyblock.enctype) return FALSE;
-
- //if we fall through to here, they must match
- return TRUE;
}