Use per-realm key/salt list to find appropriate keys. Fix gcc -Wall complaints
authorPaul Park <pjpark@mit.edu>
Tue, 15 Aug 1995 18:43:33 +0000 (18:43 +0000)
committerPaul Park <pjpark@mit.edu>
Tue, 15 Aug 1995 18:43:33 +0000 (18:43 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@6529 dc483132-0cff-0310-8789-dd5450dbe970

src/kdc/do_as_req.c
src/kdc/kdc_util.c

index dec2ae06b21e1549b94039d72524028c06740332..9abb73cb3c9cfa26b4f35301741b08da4178bb59 100644 (file)
@@ -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; i<kdc_active_realm->realm_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)
index e106f2ddccd6ecb5281b54cdcf9cef7ba32c974e..b7806ca616394bdbffa9fea99b97199f2cba150b 100644 (file)
@@ -29,6 +29,7 @@
 #include "extern.h"
 #include <stdio.h>
 #include <syslog.h>
+#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; i<kdc_active_realm->realm_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++;