From 00203d5d3f63d9ee1ba799698eb6ea026037997a Mon Sep 17 00:00:00 2001 From: Paul Park Date: Tue, 15 Aug 1995 18:43:33 +0000 Subject: [PATCH] Use per-realm key/salt list to find appropriate keys. Fix gcc -Wall complaints git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@6529 dc483132-0cff-0310-8789-dd5450dbe970 --- src/kdc/do_as_req.c | 137 ++++++++++++++++++++++++++------------------ src/kdc/kdc_util.c | 31 +++++++--- 2 files changed, 104 insertions(+), 64 deletions(-) diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c index dec2ae06b..9abb73cb3 100644 --- a/src/kdc/do_as_req.c +++ b/src/kdc/do_as_req.c @@ -38,8 +38,9 @@ #include "kdc_util.h" #include "policy.h" -#include "extern.h" +#include "adm.h" #include "adm_proto.h" +#include "extern.h" static krb5_error_code prepare_error_as PROTOTYPE((krb5_kdc_req *, int, @@ -68,10 +69,12 @@ check_padata (client, src_addr, padata, pa_id, flags) int i; /* Extract a client key from master key */ + retval = 0; for (i = 0; i < client->n_key_data; i++) { - if (retval = krb5_dbekd_decrypt_key_data(kdc_context, &master_encblock, - &client->key_data[i], - &tmpkey, NULL)) { + if ((retval = krb5_dbekd_decrypt_key_data(kdc_context, + &master_encblock, + &client->key_data[i], + &tmpkey, NULL))) { krb5_klog_syslog(LOG_ERR,"AS_REQ: Unable to extract client key: %s", error_message(retval)); return retval; @@ -113,7 +116,10 @@ krb5_data **response; /* filled in with a response packet */ static krb5_principal cpw = 0; char *status; krb5_encrypt_block eblock; - int ok_key = 0; + krb5_key_data *server_key, *client_key; +#ifdef KRBCONF_KDC_MODIFIES_KDB + krb5_boolean update_client = 0; +#endif /* KRBCONF_KDC_MODIFIES_KDB */ register int i; @@ -216,42 +222,27 @@ krb5_data **response; /* filled in with a response packet */ goto errout; } - { /* Get a key that fits the kvno and keytype */ - int max_kvno = 0; - - /* - * First find latest key unless a kvno is specified in which - * case we should only look for those keys. - * - * Note: specifing a kvno isn't defined yet - */ - for (i = 0; i < server.n_key_data; i++) { - if (max_kvno < server.key_data[i].key_data_kvno) { - max_kvno = server.key_data[i].key_data_kvno; - } - } - - /* This will change when the etype == keytype */ - for (i = 0; i < request->netypes; i++) { - krb5_keytype ok_keytype; - int j; - - if (!valid_etype(request->etype[i])) - continue; - - if (request->etype[i] == ETYPE_DES_CBC_MD5 && - !isflagset(server.attributes, KRB5_KDB_SUPPORT_DESMD5)) - continue; + /* This will change when the etype == keytype */ + for (i = 0; i < request->netypes; i++) { + if (!valid_etype(request->etype[i])) + continue; - ok_keytype = krb5_csarray[request->etype[i]]->system->proto_keytype; + if (request->etype[i] == ETYPE_DES_CBC_MD5 && + !isflagset(server.attributes, KRB5_KDB_SUPPORT_DESMD5)) + continue; - for (ok_key = 0; ok_key < server.n_key_data; ok_key++) { - if ((server.key_data[ok_key].key_data_kvno == max_kvno) && - (server.key_data[ok_key].key_data_type[0] == ok_keytype)) { - goto got_a_key; - } - } - } + /* + * Find the server key of the appropriate type. If we could specify + * a kvno, it would be supplied here. + */ + if (!krb5_dbe_find_keytype(kdc_context, + &server, + krb5_csarray[request->etype[i]]-> + system->proto_keytype, + -1, /* Ignore salttype */ + -1, /* Get highest kvno */ + &server_key)) + goto got_a_key; } /* unsupported etype */ @@ -365,11 +356,8 @@ got_a_key:; client.attributes |= KRB5_KDB_DISALLOW_ALL_TIX; } } - { - int one = 1; - - krb5_db_put_principal(kdc_context, &client, &one); - } + client.last_failed = kdc_time; + update_client = 1; #endif krb5_klog_syslog(LOG_INFO, "AS_REQ: PREAUTH FAILED: host %s, %s for %s (%s)", fromstring, cname, sname, error_message(retval)); @@ -418,7 +406,7 @@ got_a_key:; /* convert server.key into a real key (it may be encrypted in the database) */ if ((retval = krb5_dbekd_decrypt_key_data(kdc_context, &master_encblock, - &server.key_data[ok_key], + server_key, &encrypting_key, NULL))) goto errout; retval = krb5_encrypt_tkt_part(kdc_context, &eblock, &encrypting_key, @@ -427,17 +415,40 @@ got_a_key:; krb5_xfree(encrypting_key.contents); if (retval) goto errout; - ticket_reply.enc_part.kvno = server.key_data[i].key_data_kvno; + ticket_reply.enc_part.kvno = server_key->key_data_kvno; + + /* + * Find the appropriate client key. We search in the order specified + * by the key/salt list. + */ + client_key = (krb5_key_data *) NULL; + for (i=0; irealm_nkstypes; i++) { + krb5_key_salt_tuple *kslist; + + kslist = (krb5_key_salt_tuple *) kdc_active_realm->realm_kstypes; + if (!krb5_dbe_find_keytype(kdc_context, + &client, + kslist[i].ks_keytype, + kslist[i].ks_salttype, + -1, + &client_key)) + break; + } + if (!(client_key)) { + /* Cannot find an appropriate key */ + krb5_klog_syslog(LOG_INFO, + "AS_REQ: CANNOT FIND CLIENT KEY: host %s, %s for %s", + fromstring, cname, sname); + retval = prepare_error_as(request, KDC_ERR_ETYPE_NOSUPP, response); + goto errout; + } /* Start assembling the response */ reply.msg_type = KRB5_AS_REP; reply.padata = 0; - /* - * XXX If the client principal has more than one key we have a problem - * -- proven - */ - if (client.key_data[0].key_data_ver > 1) { + + if (client_key->key_data_ver > 1) { padat_tmp[0] = &padat_local; padat_tmp[1] = 0; @@ -446,7 +457,7 @@ got_a_key:; /* WARNING: sharing substructure here, but it's not a real problem, since nothing below will "pull out the rug" */ - switch (client.key_data[0].key_data_type[1]) { + switch (client_key->key_data_type[1]) { krb5_data *data_foo; case KRB5_KDB_SALTTYPE_NORMAL: reply.padata = (krb5_pa_data **) NULL; @@ -473,8 +484,8 @@ got_a_key:; reply.padata = padat_tmp; break; case KRB5_KDB_SALTTYPE_SPECIAL: - padat_tmp[0]->contents = client.key_data[0].key_data_contents[1]; - padat_tmp[0]->length = client.key_data[0].key_data_length[1]; + padat_tmp[0]->contents = client_key->key_data_contents[1]; + padat_tmp[0]->length = client_key->key_data_length[1]; reply.padata = padat_tmp; break; } @@ -503,11 +514,11 @@ got_a_key:; /* now encode/encrypt the response */ reply.enc_part.etype = useetype; - reply.enc_part.kvno = client.key_data[0].key_data_kvno; + reply.enc_part.kvno = client_key->key_data_kvno; /* convert client.key_data into a real key */ if ((retval = krb5_dbekd_decrypt_key_data(kdc_context, &master_encblock, - &client.key_data[0], + client_key, &encrypting_key, NULL))) goto errout; @@ -531,13 +542,25 @@ got_a_key:; krb5_klog_syslog(LOG_INFO, "AS_REQ; ISSUE: authtime %d, host %s, %s for %s", authtime, fromstring, cname, sname); +#ifdef KRBCONF_KDC_MODIFIES_KDB + /* + * If we get this far, we successfully did the AS_REQ. + */ + client.last_success = kdc_time; + client.fail_auth_count = 0; + update_client = 1; +#endif /* KRBCONF_KDC_MODIFIES_KDB */ + errout: if (cname) free(cname); if (sname) free(sname); - if (c_nprincs) + if (c_nprincs) { + if (update_client) + krb5_db_put_principal(kdc_context, &client, &c_nprincs); krb5_db_free_principal(kdc_context, &client, c_nprincs); + } if (s_nprincs) krb5_db_free_principal(kdc_context, &server, s_nprincs); if (session_key) diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c index e106f2ddc..b7806ca61 100644 --- a/src/kdc/kdc_util.c +++ b/src/kdc/kdc_util.c @@ -29,6 +29,7 @@ #include "extern.h" #include #include +#include "adm.h" #include "adm_proto.h" /* @@ -325,7 +326,9 @@ kdc_get_server_key(ticket, key, kvno) krb5_error_code retval; krb5_db_entry server; krb5_boolean more; - int nprincs, i, last_i; + int nprincs; + krb5_key_data * server_key; + int i; if (krb5_principal_compare(kdc_context, tgs_server, ticket->server)) { retval = krb5_copy_keyblock(kdc_context, &tgs_key, key); @@ -356,16 +359,29 @@ kdc_get_server_key(ticket, key, kvno) /* * Get the latest version of the server key_data and * convert the key into a real key (it may be encrypted in the database) + * + * Search the key list in the order specified by the key/salt list. */ - for (*kvno = last_i = i = 0; i < server.n_key_data; i++) { - if (*kvno < server.key_data[i].key_data_kvno) { - *kvno = server.key_data[i].key_data_kvno; - last_i = i; - } + server_key = (krb5_key_data *) NULL; + for (i=0; irealm_nkstypes; i++) { + krb5_key_salt_tuple *kslist; + + kslist = (krb5_key_salt_tuple *) kdc_active_realm->realm_kstypes; + if (!krb5_dbe_find_keytype(kdc_context, + &server, + kslist[i].ks_keytype, + -1, + -1, + &server_key)) + break; } + if (!server_key) + return(KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN); + + *kvno = server_key->key_data_kvno; if ((*key = (krb5_keyblock *)malloc(sizeof **key))) { retval = krb5_dbekd_decrypt_key_data(kdc_context, &master_encblock, - &server.key_data[last_i], + server_key, *key, NULL); } else retval = ENOMEM; @@ -903,6 +919,7 @@ krb5_data *data; int tag; /* tag number */ unsigned char savelen; /* saved length of our field */ + classes = -1; /* we assume that the first identifier/length will tell us how long the entire stream is. */ astream++; -- 2.26.2