* IMplement etype_info in KDC. If the request contains any new
authorSam Hartman <hartmans@mit.edu>
Mon, 12 May 2003 02:59:06 +0000 (02:59 +0000)
committerSam Hartman <hartmans@mit.edu>
Mon, 12 May 2003 02:59:06 +0000 (02:59 +0000)
enctypes (currently AES but anything not explicitly listed as old)
then only etype_info2 is sent back in response.  Send back etype_info2
all the time.  Also send back etype_info2 to provide salt and
s2kparams with AS reply not just for preauth errors.

* Expose interface for getting string2key with parameters (previously
implemented but not exported)

* IN the client (at least for get_init_creds interface) prfer
etype_info2 to etype_info and pw_salt.  Pass s2kparams and use
string2key_with_params.

Ticket: 1454
Status: open
Target_Version: 1.3

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@15412 dc483132-0cff-0310-8789-dd5450dbe970

14 files changed:
src/include/ChangeLog
src/include/k5-int.h
src/include/krb5.hin
src/kdc/ChangeLog
src/kdc/kdc_preauth.c
src/lib/ChangeLog
src/lib/crypto/ChangeLog
src/lib/crypto/string_to_key.c
src/lib/krb5/krb/ChangeLog
src/lib/krb5/krb/get_in_tkt.c
src/lib/krb5/krb/gic_keytab.c
src/lib/krb5/krb/gic_pwd.c
src/lib/krb5/krb/preauth2.c
src/lib/krb5_32.def

index 00f359f4a0dedd810c4545ca417eb113e5476cf9..58a85676d15b949404b9a7812bdb1d55ae3fbfac 100644 (file)
@@ -1,3 +1,13 @@
+2003-05-08  Sam Hartman  <hartmans@mit.edu>
+
+       * krb5.hin: Add prototype for krb5_c_string_to_key_with_params
+
+       * k5-int.h: Add s2kparams to krb5_gic_get_as_key_fct
+
+2003-05-07  Sam Hartman  <hartmans@mit.edu>
+
+       * krb5.hin: Add KRB5_PADATA_ETYPE_INFO2
+
 2003-05-09  Ken Raeburn  <raeburn@mit.edu>
 
        * k5-int.h (struct _krb5_context): New fields conf_tgs_ktypes,
index 596784bef3ec2fb9d995a1965e81c12a5e005211..b9f8722c1a7c4ba2d7ddbd8f925b3dd3cda4a12a 100644 (file)
@@ -914,6 +914,7 @@ typedef krb5_error_code (*krb5_gic_get_as_key_fct)
                     krb5_prompter_fct,
                     void *prompter_data,
                     krb5_data *salt,
+     krb5_data *s2kparams,
                     krb5_keyblock *as_key,
                     void *gak_data);
 
@@ -936,7 +937,8 @@ krb5_get_init_creds
 krb5_error_code krb5_do_preauth
 (krb5_context, krb5_kdc_req *,
                krb5_pa_data **, krb5_pa_data ***,
-               krb5_data *, krb5_enctype *,
+               krb5_data *salt, krb5_data *s2kparams,
+ krb5_enctype *,
                krb5_keyblock *,
                krb5_prompter_fct, void *,
                krb5_gic_get_as_key_fct, void *);
index c1f66cb3ee0360672112c3f8a9aba3cbd7e28c31..7d033902c9319cb78ea4feb26577b7605f31c39e 100644 (file)
@@ -491,6 +491,13 @@ krb5_error_code KRB5_CALLCONV
     (krb5_context context, krb5_enctype enctype,
                    const krb5_data *string, const krb5_data *salt,
                    krb5_keyblock *key);
+krb5_error_code KRB5_CALLCONV
+krb5_c_string_to_key_with_params(krb5_context context,
+                                krb5_enctype enctype,
+                                const krb5_data *string,
+                                const krb5_data *salt,
+                                const krb5_data *params,
+                                krb5_keyblock *key);
 
 krb5_error_code KRB5_CALLCONV
     krb5_c_enctype_compare
@@ -874,7 +881,7 @@ krb5_error_code krb5_decrypt_data
 #define KRB5_PADATA_SAM_RESPONSE       13 /* draft challenge system response */
 #define KRB5_PADATA_PK_AS_REQ          14 /* PKINIT */
 #define KRB5_PADATA_PK_AS_REP          15 /* PKINIT */
-
+#define KRB5_PADATA_ETYPE_INFO2 19
 #define KRB5_PADATA_SAM_CHALLENGE_2    30 /* draft challenge system, updated */
 #define KRB5_PADATA_SAM_RESPONSE_2     31 /* draft challenge system, updated */
     
index bf28f9c93b6bfbcf594a657eeecc2257b419a628..64fbb48441df96a71963d2d3590130ea2e6af9b3 100644 (file)
@@ -1,3 +1,8 @@
+2003-05-08  Sam Hartman  <hartmans@mit.edu>
+
+       * kdc_preauth.c (return_pw_salt): Don't return pw-salt if the
+       client's enctype list  mandates it supports enctype-info2
+
 2003-05-09  Tom Yu  <tlyu@mit.edu>
 
        * kdc_util.c (kdc_process_tgs_req): Rename getremotesubkey ->
@@ -8,6 +13,14 @@
        * kdc_preauth.c (get_etype_info): Patch from Sun to reorganize
        code and make sure that even for md5 the database order is
        preserved. 
+       (enctype_requires_etype_info_2): new function; determines wether a
+       particular enctype in a client request means that the client  is
+       required to support etype_info2 by Kerberos clarifications.
+       (etype_info_helper): Renamed from get_etype_info  to abstract out
+       code in common between etype_info and etype_info2
+       (get_enctype_info): Return etype info only if request contains no
+       enctypes that  require etype_info2
+       (return_etype_info2): New function.
 
 2003-04-02  Sam Hartman  <hartmans@mit.edu>
 
index 8d7a2ff566ced44e1bb0a38d71aaed3c05757cfe..31e6f470578eb5ab1208425a0e4954d9d19f4ee9 100644 (file)
@@ -59,6 +59,8 @@
 #include "adm_proto.h"
 #include <syslog.h>
 
+#include <assert.h>
+
 /* XXX This is ugly and should be in a header file somewhere */
 #ifndef KRB5INT_DES_TYPES_DEFINED
 #define KRB5INT_DES_TYPES_DEFINED
@@ -104,6 +106,18 @@ static krb5_error_code get_etype_info
     (krb5_context, krb5_kdc_req *request,
                    krb5_db_entry *client, krb5_db_entry *server,
                    krb5_pa_data *data);
+static krb5_error_code
+get_etype_info2(krb5_context context, krb5_kdc_req *request,
+              krb5_db_entry *client, krb5_db_entry *server,
+                 krb5_pa_data *pa_data);
+static krb5_error_code
+return_etype_info2(krb5_context, krb5_pa_data * padata, 
+                  krb5_db_entry *client,
+                  krb5_kdc_req *request, krb5_kdc_rep *reply,
+                  krb5_key_data *client_key,
+                  krb5_keyblock *encrypting_key,
+                  krb5_pa_data **send_pa);
+
 static krb5_error_code return_pw_salt
     (krb5_context, krb5_pa_data * padata, 
                    krb5_db_entry *client,
@@ -155,6 +169,14 @@ static krb5_preauth_systems preauth_systems[] = {
        0,
        0
     },
+    {
+       "etype-info2",
+       KRB5_PADATA_ETYPE_INFO2,
+       0,
+       get_etype_info2,
+       0,
+       return_etype_info2
+    },
     {
        "pw-salt",
        KRB5_PADATA_PW_SALT,
@@ -431,6 +453,26 @@ cleanup:
     return (retval);
 }
 
+static krb5_boolean
+enctype_requires_etype_info_2(krb5_enctype enctype)
+{
+    switch(enctype) {
+    case ENCTYPE_DES_CBC_CRC:
+    case ENCTYPE_DES_CBC_MD4:
+    case ENCTYPE_DES_CBC_MD5:
+    case ENCTYPE_DES3_CBC_SHA1:
+    case ENCTYPE_DES3_CBC_RAW:
+    case ENCTYPE_ARCFOUR_HMAC:
+    case ENCTYPE_ARCFOUR_HMAC_EXP :
+    case ENCTYPE_LOCAL_DES3_HMAC_SHA1:
+       return 0;
+    default:
+       if (krb5_c_valid_enctype(enctype))
+           return 1;
+       else return 0;
+    }
+}
+
 static krb5_boolean
 request_contains_enctype (krb5_context context,  const krb5_kdc_req *request,
                          krb5_enctype enctype)
@@ -574,12 +616,13 @@ fail:
 /*
  * This function returns the etype information for a particular
  * client, to be passed back in the preauth list in the KRB_ERROR
- * message.
+ * message.  It supports generating both etype_info  and etype_info2
+ *  as most of the work is the same.   
  */
 static krb5_error_code
-get_etype_info(krb5_context context, krb5_kdc_req *request,
+etype_info_helper(krb5_context context, krb5_kdc_req *request,
               krb5_db_entry *client, krb5_db_entry *server,
-              krb5_pa_data *pa_data)
+              krb5_pa_data *pa_data, int etype_info2)
 {
     krb5_etype_info_entry **   entry = 0;
     krb5_key_data              *client_key;
@@ -607,6 +650,8 @@ get_etype_info(krb5_context context, krb5_kdc_req *request,
            db_etype = ENCTYPE_DES_CBC_MD5;
        
        if (request_contains_enctype(context, request, db_etype)) {
+           assert(etype_info2 ||
+                  !enctype_requires_etype_info_2(db_etype));
            if ((retval = _make_etype_info_entry(context, request, client_key,
                            db_etype, &entry[i])) != 0) {
                goto cleanup;
@@ -642,7 +687,10 @@ get_etype_info(krb5_context context, krb5_kdc_req *request,
            seen_des++;
        }
     }
-    retval = encode_krb5_etype_info((const krb5_etype_info_entry **) entry,
+    if (etype_info2)
+       retval = encode_krb5_etype_info2((const krb5_etype_info_entry **) entry,
+                                   &scratch);
+    else       retval = encode_krb5_etype_info((const krb5_etype_info_entry **) entry,
                                    &scratch);
     if (retval)
        goto cleanup;
@@ -658,6 +706,75 @@ cleanup:
     return retval;
 }
 
+static krb5_error_code
+get_etype_info(krb5_context context, krb5_kdc_req *request,
+              krb5_db_entry *client, krb5_db_entry *server,
+              krb5_pa_data *pa_data)
+{
+  int i;
+    for (i=0;  i < request->nktypes; i++) {
+       if (enctype_requires_etype_info_2(request->ktype[i])) 
+           return KRB5KDC_ERR_PADATA_TYPE_NOSUPP ;;;; /*Caller will
+                                                       * skip this
+                                                       * type*/
+    }
+    return etype_info_helper(context, request, client, server, pa_data, 0);
+}
+
+static krb5_error_code
+get_etype_info2(krb5_context context, krb5_kdc_req *request,
+              krb5_db_entry *client, krb5_db_entry *server,
+              krb5_pa_data *pa_data)
+{
+    return etype_info_helper( context, request, client, server, pa_data, 1);
+}
+
+static krb5_error_code
+return_etype_info2(krb5_context context, krb5_pa_data * padata, 
+                  krb5_db_entry *client,
+                  krb5_kdc_req *request, krb5_kdc_rep *reply,
+                  krb5_key_data *client_key,
+                  krb5_keyblock *encrypting_key,
+                  krb5_pa_data **send_pa)
+{
+    krb5_error_code retval;
+    krb5_pa_data *tmp_padata;
+    krb5_etype_info_entry **entry = NULL;
+    krb5_data *scratch = NULL;
+    tmp_padata = malloc( sizeof(krb5_pa_data));
+    if (tmp_padata == NULL)
+       return ENOMEM;
+    tmp_padata->pa_type = KRB5_PADATA_ETYPE_INFO2;
+    entry = malloc(2 * sizeof(krb5_etype_info_entry *));
+    if (entry == NULL) {
+       retval = ENOMEM;
+       goto cleanup;
+    }
+    entry[0] = NULL;
+    entry[1] = NULL;
+    retval = _make_etype_info_entry(context, request, client_key, client_key->key_data_type[0],
+                                   entry);
+    if (retval)
+       goto cleanup;
+    retval = encode_krb5_etype_info2((const krb5_etype_info_entry **) entry, &scratch);
+    if (retval)
+       goto cleanup;
+    tmp_padata->contents = scratch->data;
+    tmp_padata->length = scratch->length;
+    *send_pa = tmp_padata;
+ cleanup:
+    if (entry)
+       krb5_free_etype_info(context, entry);
+    if (retval) {
+       if (tmp_padata)
+           free(tmp_padata);
+       if (scratch)
+           krb5_free_data(context, scratch);
+    }
+    return retval;
+}
+
+
 static krb5_error_code
 return_pw_salt(krb5_context context, krb5_pa_data *in_padata,
               krb5_db_entry *client, krb5_kdc_req *request,
@@ -668,7 +785,12 @@ return_pw_salt(krb5_context context, krb5_pa_data *in_padata,
     krb5_pa_data *     padata;
     krb5_data *                scratch;
     krb5_data          salt_data;
+    int i;
     
+    for (i = 0; i < request->nktypes; i++) {
+       if (enctype_requires_etype_info_2(request->ktype[i]))
+           return 0;
+    }
     if (client_key->key_data_ver == 1 ||
        client_key->key_data_type[1] == KRB5_KDB_SALTTYPE_NORMAL)
        return 0;
index 2a1601859fc808e086283386cfd046a27e27214e..2051533052532abdf3837c07cdc3b488452e4102 100644 (file)
@@ -1,3 +1,7 @@
+2003-05-08  Sam Hartman  <hartmans@mit.edu>
+
+       * krb5_32.def: Add krb5_c_string_to_key_with_params
+
 2003-05-09  Tom Yu  <tlyu@mit.edu>
 
        * krb5_32.def: Add krb5_auth_con_getrecvsubkey,
index 1db5612524a39e7e04b4993ed6b9718c9ea6308c..07ba371ef0dd3990bb4fddccf3423e97689b5162 100644 (file)
@@ -1,3 +1,7 @@
+2003-05-08  Sam Hartman  <hartmans@mit.edu>
+
+       * string_to_key.c: Move krb5_c_string_to_key_with_params to krb5.h
+
 2003-04-13  Ken Raeburn  <raeburn@mit.edu>
 
        * pbkdf2.c (krb5int_pbkdf2): Provide a temporary buffer for the
index c9434e08da5aec8e688fe311f3a07ddc0f768e4c..3bd7a4e7301fcddbb81893cc9a874abc66d29d1e 100644 (file)
@@ -27,7 +27,6 @@
 #include "k5-int.h"
 #include "etypes.h"
 
-/* Eventually this declaration should move to krb5.h.  */
 krb5_error_code KRB5_CALLCONV
 krb5_c_string_to_key_with_params(krb5_context context,
                                 krb5_enctype enctype,
index 46c4754d614b843a99c827b3de27ae7a4557f336..b6e2480e1e4a59dd28248f95ed25e4746c04ab7f 100644 (file)
@@ -1,3 +1,21 @@
+2003-05-09  Sam Hartman  <hartmans@mit.edu>
+
+       * preauth2.c: Patch from Sun to reorganize code   for handling
+       etype_info requests.  More efficient  and easier to implement etype_info2
+       (krb5_do_preauth): Support enctype_info2
+
+2003-05-08  Sam Hartman  <hartmans@mit.edu>
+
+       * preauth2.c: Add s2kparams to the declaration of a preauth
+       function, to every instance of a preauth function and to every
+       call to gak_fct 
+
+       * get_in_tkt.c (krb5_get_init_creds): Add s2kparams support
+
+       * gic_keytab.c (krb5_get_as_key_keytab): Add s2kparams
+
+       * gic_pwd.c (krb5_get_as_key_password): Add s2kparams support
+
 2003-05-09  Ken Raeburn  <raeburn@mit.edu>
 
        * init_ctx.c (init_common): Copy tgs_ktypes array to
index dc06c535391b2be89e82db9a3993dbdb683e89df..2f426d721679c18bf24bfe98df3d029a411d90c6 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * lib/krb5/krb/get_in_tkt.c
  *
- * Copyright 1990,1991 by the Massachusetts Institute of Technology.
+ * Copyright 1990,1991, 2003 by the Massachusetts Institute of Technology.
  * All Rights Reserved.
  *
  * Export of this software from the United States of America may
@@ -734,6 +734,7 @@ krb5_get_init_creds(krb5_context context,
     krb5_deltat renew_life;
     int loopcount;
     krb5_data salt;
+    krb5_data s2kparams;
     krb5_keyblock as_key;
     krb5_error *err_reply;
     krb5_kdc_rep *local_as_reply;
@@ -742,6 +743,8 @@ krb5_get_init_creds(krb5_context context,
 
     /* initialize everything which will be freed at cleanup */
 
+    s2kparams.data = NULL;
+    s2kparams.length = 0;
     request.server = NULL;
     request.ktype = NULL;
     request.addresses = NULL;
@@ -927,7 +930,7 @@ krb5_get_init_creds(krb5_context context,
 
        if ((ret = krb5_do_preauth(context, &request,
                                  padata, &request.padata,
-                                 &salt, &etype, &as_key, prompter,
+                                 &salt, &s2kparams, &etype, &as_key, prompter,
                                   prompter_data, gak_fct, gak_data)))
            goto cleanup;
 
@@ -973,7 +976,7 @@ krb5_get_init_creds(krb5_context context,
 
     if ((ret = krb5_do_preauth(context, &request,
                               local_as_reply->padata, &padata,
-                              &salt, &etype, &as_key, prompter,
+                              &salt, &s2kparams, &etype, &as_key, prompter,
                               prompter_data, gak_fct, gak_data)))
        goto cleanup;
 
@@ -1005,7 +1008,7 @@ krb5_get_init_creds(krb5_context context,
 
        if ((ret = ((*gak_fct)(context, request.client,
                               local_as_reply->enc_part.enctype,
-                              prompter, prompter_data, &salt,
+                              prompter, prompter_data, &salt, &s2kparams,
                               &as_key, gak_data))))
            goto cleanup;
 
index a7cb773a097706335f081370e3780563629b2ade..e7fb1aec6a961c2647e39aeeb58a40695ce0eadc 100644 (file)
@@ -8,6 +8,7 @@ krb5_get_as_key_keytab(
     krb5_prompter_fct prompter,
     void *prompter_data,
     krb5_data *salt,
+    krb5_data *params,
     krb5_keyblock *as_key,
     void *gak_data)
 {
index 7b5e0bab307e191cb2a5ac43590ab51e1a2aeee1..54cf5f461c8b481a4aefa4ef74dc7698b615b418 100644 (file)
@@ -9,6 +9,7 @@ krb5_get_as_key_password(
     krb5_prompter_fct prompter,
     void *prompter_data,
     krb5_data *salt,
+    krb5_data *params,
     krb5_keyblock *as_key,
     void *gak_data)
 {
@@ -74,7 +75,8 @@ krb5_get_as_key_password(
        defsalt.length = 0;
     }
 
-    ret = krb5_c_string_to_key(context, etype, password, salt, as_key);
+    ret = krb5_c_string_to_key_with_params(context, etype, password, salt,
+                                          params->data?params:NULL, as_key);
 
     if (defsalt.length)
        krb5_xfree(defsalt.data);
index e50440e2b63f8964e3e450dd744ab3c313473086..5a9c1ba9e0bca7d6b8d98a584980cdf920d3cf50 100644 (file)
@@ -35,7 +35,7 @@ typedef krb5_error_code (*pa_function)(krb5_context,
                                       krb5_kdc_req *request,
                                       krb5_pa_data *in_padata,
                                       krb5_pa_data **out_padata,
-                                      krb5_data *salt,
+                                      krb5_data *salt, krb5_data *s2kparams,
                                       krb5_enctype *etype,
                                       krb5_keyblock *as_key,
                                       krb5_prompter_fct prompter_fct,
@@ -57,7 +57,7 @@ krb5_error_code pa_salt(krb5_context context,
                        krb5_kdc_req *request,
                        krb5_pa_data *in_padata,
                        krb5_pa_data **out_padata,
-                       krb5_data *salt,
+                       krb5_data *salt, krb5_data *s2kparams,
                        krb5_enctype *etype,
                        krb5_keyblock *as_key,
                        krb5_prompter_fct prompter, void *prompter_data,
@@ -94,6 +94,7 @@ krb5_error_code pa_enc_timestamp(krb5_context context,
                                 krb5_pa_data *in_padata,
                                 krb5_pa_data **out_padata,
                                 krb5_data *salt,
+                                krb5_data *s2kparams,
                                 krb5_enctype *etype,
                                 krb5_keyblock *as_key,
                                 krb5_prompter_fct prompter,
@@ -119,7 +120,7 @@ krb5_error_code pa_enc_timestamp(krb5_context context,
        if ((ret = ((*gak_fct)(context, request->client,
                              *etype ? *etype : request->ktype[0],
                              prompter, prompter_data,
-                             salt, as_key, gak_data))))
+                             salt, s2kparams, as_key, gak_data))))
            return(ret);
     }
 
@@ -233,6 +234,7 @@ krb5_error_code pa_sam(krb5_context context,
                       krb5_pa_data *in_padata,
                       krb5_pa_data **out_padata,
                       krb5_data *salt,
+                      krb5_data *s2kparams,
                       krb5_enctype *etype,
                       krb5_keyblock *as_key,
                       krb5_prompter_fct prompter,
@@ -283,7 +285,7 @@ krb5_error_code pa_sam(krb5_context context,
           *etype = ENCTYPE_DES_CBC_CRC;
 
        if ((ret = (gak_fct)(context, request->client, *etype, prompter,
-                       prompter_data, salt, as_key, gak_data)))
+                       prompter_data, salt, s2kparams, as_key, gak_data)))
           return(ret);
     }
     sprintf(name, "%.*s",
@@ -472,6 +474,7 @@ krb5_error_code pa_sam_2(krb5_context context,
                                krb5_pa_data *in_padata,
                                krb5_pa_data **out_padata,
                                krb5_data *salt,
+                        krb5_data *s2kparams,
                                krb5_enctype *etype,
                                krb5_keyblock *as_key,
                                krb5_prompter_fct prompter,
@@ -542,7 +545,7 @@ krb5_error_code pa_sam_2(krb5_context context,
 
        retval = (gak_fct)(context, request->client,
                        sc2b->sam_etype, prompter,
-                       prompter_data, salt, as_key, gak_data);
+                       prompter_data, salt, s2kparams, as_key, gak_data);
        if (retval) {
           krb5_free_sam_challenge_2(context, sc2);
           krb5_free_sam_challenge_2_body(context, sc2b);
@@ -827,86 +830,18 @@ static const pa_types_t pa_types[] = {
     },
 };
 
-static void
-sort_etype_info(krb5_context  context, krb5_kdc_req *request,
-                krb5_etype_info_entry **etype_info)
-{
-/* Originally adapted from a proposed solution in ticket 1006.  This
- * solution  is  not efficient, but implementing an efficient sort
- * with a comparison function based on order in the kdc request would
- * be difficult.*/
-    krb5_etype_info_entry *tmp;
-    int i, j, e;
-    krb5_boolean similar;
-
-    if (etype_info == NULL)
-       return;
-
-    /* First, move up etype_info_entries whose enctype exactly matches a
-     * requested enctype.
-     */
-    e = 0;
-    for ( i = 0 ; i < request->nktypes && etype_info[e] != NULL ; i++ )
-    {
-       if (request->ktype[i] == etype_info[e]->etype)
-       {
-           e++;
-           continue;
-       }
-       for ( j = e+1 ; etype_info[j] ; j++ )
-           if (request->ktype[i] == etype_info[j]->etype)
-               break;
-       if (etype_info[j] == NULL)
-           continue;
-
-       tmp = etype_info[j];
-       etype_info[j] = etype_info[e];
-       etype_info[e] = tmp;
-       e++;
-    }
-
-    /* Then move up etype_info_entries whose enctype is similar to a
-     * requested enctype.
-     */
-    for ( i = 0 ; i < request->nktypes && etype_info[e] != NULL ; i++ )
-    {
-       if (krb5_c_enctype_compare(context, request->ktype[i], etype_info[e]->etype, &similar) != 0)
-           continue;
-
-       if (similar)
-       {
-           e++;
-           continue;
-       }
-       for ( j = e+1 ; etype_info[j] ; j++ )
-       {
-           if (krb5_c_enctype_compare(context, request->ktype[i], etype_info[j]->etype, &similar) != 0)
-               continue;
-
-           if (similar)
-               break;
-       }
-       if (etype_info[j] == NULL)
-           continue;
-
-       tmp = etype_info[j];
-       etype_info[j] = etype_info[e];
-       etype_info[e] = tmp;
-       e++;
-    }
-}
-
-
 krb5_error_code
 krb5_do_preauth(krb5_context context,
                krb5_kdc_req *request,
                krb5_pa_data **in_padata, krb5_pa_data ***out_padata,
-               krb5_data *salt, krb5_enctype *etype,
+               krb5_data *salt, krb5_data *s2kparams,
+               krb5_enctype *etype,
                krb5_keyblock *as_key,
                krb5_prompter_fct prompter, void *prompter_data,
                krb5_gic_get_as_key_fct gak_fct, void *gak_data)
 {
     int h, i, j, out_pa_list_size;
+    int seen_etype_info2 = 0;
     krb5_pa_data *out_pa, **out_pa_list;
     krb5_data scratch;
     krb5_etype_info etype_info = NULL;
@@ -938,6 +873,7 @@ krb5_do_preauth(krb5_context context,
     for (h=0; h<(sizeof(paorder)/sizeof(paorder[0])); h++) {
        realdone = 0;
        for (i=0; in_padata[i] && !realdone; i++) {
+           int k, l, etype_found, valid_etype_found;
            /*
             * This is really gross, but is necessary to prevent
             * lossge when talking to a 1.0.x KDC, which returns an
@@ -946,8 +882,20 @@ krb5_do_preauth(krb5_context context,
             */
            switch (in_padata[i]->pa_type) {
            case KRB5_PADATA_ETYPE_INFO:
-               if (etype_info)
-                   continue;
+           case KRB5_PADATA_ETYPE_INFO2:
+           {
+               krb5_preauthtype pa_type = in_padata[i]->pa_type;
+               if (etype_info) {
+                   if (seen_etype_info2 || pa_type != KRB5_PADATA_ETYPE_INFO2)
+                       continue;
+                   if (pa_type == KRB5_PADATA_ETYPE_INFO2) {
+                       krb5_free_etype_info( context, etype_info);
+                       etype_info = NULL;
+                   }
+               }
+
+               if (pa_type == KRB5_PADATA_ETYPE_INFO2)
+                   seen_etype_info2++;
                scratch.length = in_padata[i]->length;
                scratch.data = (char *) in_padata[i]->contents;
                ret = decode_krb5_etype_info(&scratch, &etype_info);
@@ -963,10 +911,37 @@ krb5_do_preauth(krb5_context context,
                    etype_info = NULL;
                    break;
                }
-                sort_etype_info(context, request, etype_info);
-               salt->data = (char *) etype_info[0]->salt;
-               salt->length = etype_info[0]->length;
-               *etype = etype_info[0]->etype;
+               /*
+                * Select first etype in our request which is also in
+                * etype-info (preferring client request ktype order).
+                */
+               for (etype_found = 0, valid_etype_found = 0, k = 0;
+                    !etype_found && k < request->nktypes; k++) {
+                   for (l = 0; etype_info[l]; l++) {
+                       if (etype_info[l]->etype == request->ktype[k]) {
+                           etype_found++;
+                           break;
+                       }
+                       /* check if program has support for this etype for more
+                        * precise error reporting.
+                        */
+                       if (valid_enctype(etype_info[l]->etype))
+                           valid_etype_found++;
+                   }
+               }
+               if (!etype_found) {
+                   if (valid_etype_found)
+                       /* supported enctype but not requested */
+                       return KRB5_CONFIG_ETYPE_NOSUPP;
+                   else
+                       /* unsupported enctype */
+                       return KRB5_PROG_ETYPE_NOSUPP;
+
+               }
+               salt->data = (char *) etype_info[l]->salt;
+               salt->length = etype_info[l]->length;
+               *etype = etype_info[l]->etype;
+               *s2kparams = etype_info[l]->s2kparams;
 #ifdef DEBUG
                for (j = 0; etype_info[j]; j++) {
                    krb5_etype_info_entry *e = etype_info[j];
@@ -978,6 +953,7 @@ krb5_do_preauth(krb5_context context,
                }
 #endif
                break;
+           }
            case KRB5_PADATA_PW_SALT:
            case KRB5_PADATA_AFS3_SALT:
                if (etype_info)
@@ -993,7 +969,7 @@ krb5_do_preauth(krb5_context context,
 
                    if ((ret = ((*pa_types[j].fct)(context, request,
                                                   in_padata[i], &out_pa,
-                                                  salt, etype, as_key,
+                                                  salt, s2kparams, etype, as_key,
                                                   prompter, prompter_data,
                                                   gak_fct, gak_data)))) {
                        if (out_pa_list) {
index 257dd287e0ff28222c0f94b938efc7f994b53528..db136c44a3e1c31490d46c85c424102b3e3e0137 100644 (file)
@@ -67,6 +67,7 @@ EXPORTS
        krb5_c_random_make_octets
        krb5_c_random_seed
        krb5_c_string_to_key
+krb5_c_string_to_key_with_params
        krb5_c_valid_cksumtype
        krb5_c_valid_enctype
        krb5_c_verify_checksum