Create e_data as pa_data in KDC interfaces
authorGreg Hudson <ghudson@mit.edu>
Tue, 4 Oct 2011 20:16:07 +0000 (20:16 +0000)
committerGreg Hudson <ghudson@mit.edu>
Tue, 4 Oct 2011 20:16:07 +0000 (20:16 +0000)
All current known uses of e_data are encoded as pa-data or typed-data.
FAST requires that e_data be expressed as pa-data.  Change the DAL and
kdcpreauth interfaces so that e_data is returned as a sequence of
pa-data elements.  Add a preauth module flag to indicate that the
sequence should be encoded as typed-data in non-FAST errors.

ticket: 6969

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

22 files changed:
src/include/kdb.h
src/include/krb5/preauth_plugin.h
src/kdc/do_as_req.c
src/kdc/do_tgs_req.c
src/kdc/kdc_preauth.c
src/kdc/kdc_util.c
src/kdc/kdc_util.h
src/kdc/policy.c
src/lib/kdb/Makefile.in
src/lib/kdb/kdb5.c
src/lib/krb5/libkrb5.exports
src/plugins/kdb/db2/kdb_db2.c
src/plugins/kdb/db2/kdb_db2.h
src/plugins/kdb/hdb/kdb_hdb.h
src/plugins/kdb/hdb/kdb_windc.c
src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c
src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h
src/plugins/preauth/pkinit/pkinit.h
src/plugins/preauth/pkinit/pkinit_crypto.h
src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
src/plugins/preauth/pkinit/pkinit_lib.c
src/plugins/preauth/pkinit/pkinit_srv.c

index 809722eda3f7b4309da003307484965d9640378e..78f786f3b99a52c10797ddbaf3343d6327d7f083 100644 (file)
@@ -69,7 +69,7 @@
 
 /* This version will be incremented when incompatible changes are made to the
  * KDB API, and will be kept in sync with the libkdb major version. */
-#define KRB5_KDB_API_VERSION 5
+#define KRB5_KDB_API_VERSION 6
 
 /* Salt types */
 #define KRB5_KDB_SALTTYPE_NORMAL        0
@@ -640,14 +640,14 @@ krb5_error_code krb5_db_check_policy_as(krb5_context kcontext,
                                         krb5_db_entry *server,
                                         krb5_timestamp kdc_time,
                                         const char **status,
-                                        krb5_data *e_data);
+                                        krb5_pa_data ***e_data);
 
 krb5_error_code krb5_db_check_policy_tgs(krb5_context kcontext,
                                          krb5_kdc_req *request,
                                          krb5_db_entry *server,
                                          krb5_ticket *ticket,
                                          const char **status,
-                                         krb5_data *e_data);
+                                         krb5_pa_data ***e_data);
 
 void krb5_db_audit_as_req(krb5_context kcontext, krb5_kdc_req *request,
                           krb5_db_entry *client, krb5_db_entry *server,
@@ -796,7 +796,7 @@ krb5_dbe_free_string(krb5_context, char *);
  * This number indicates the date of the last incompatible change to the DAL.
  * The maj_ver field of the module's vtable structure must match this version.
  */
-#define KRB5_KDB_DAL_MAJOR_VERSION 2
+#define KRB5_KDB_DAL_MAJOR_VERSION 3
 
 /*
  * A krb5_context can hold one database object.  Modules should use
@@ -1269,7 +1269,7 @@ typedef struct _kdb_vftabl {
                                        krb5_db_entry *server,
                                        krb5_timestamp kdc_time,
                                        const char **status,
-                                       krb5_data *e_data);
+                                       krb5_pa_data ***e_data);
 
     /*
      * Optional: Perform a policy check on a TGS request, in addition to the
@@ -1286,7 +1286,7 @@ typedef struct _kdb_vftabl {
                                         krb5_db_entry *server,
                                         krb5_ticket *ticket,
                                         const char **status,
-                                        krb5_data *e_data);
+                                        krb5_pa_data ***e_data);
 
     /*
      * Optional: This method informs the module of a successful or unsuccessful
index c620d6cdb4b3868636370ecc2fb750ff080317ba..3f9dfcc351de3801caa125b677be64714026847d 100644 (file)
  */
 #define PA_PSEUDO       0x00000080
 
+/*
+ * For kdcpreauth mechanisms, indicates that e_data in non-FAST errors should
+ * be encoded as typed data instead of padata.
+ */
+#define PA_TYPED_E_DATA 0x00000100
 
 /*
  * clpreauth plugin interface definition.
@@ -413,18 +418,27 @@ typedef krb5_error_code
                             krb5_pa_data *pa_out);
 
 /*
- * Optional: verify preauthentication data sent by the client, setting the
- * TKT_FLG_PRE_AUTH or TKT_FLG_HW_AUTH flag in the enc_tkt_reply's "flags"
- * field as appropriate, and returning nonzero on failure.  Can create
- * per-request module data for consumption by the return_fn or free_modreq_fn
- * below.
+ * Responder for krb5_kdcpreauth_verify_fn.  Invoke with the arg parameter
+ * supplied to verify, the error code (0 for success), an optional module
+ * request state object to be consumed by return_fn or free_modreq_fn, optional
+ * e_data to be passed to the caller if code is nonzero, and optional
+ * authorization data to be included in the ticket.  In non-FAST replies,
+ * e_data will be encoded as typed-data if the module sets the PA_TYPED_E_DATA
+ * flag, and as pa-data otherwise.  e_data and authz_data will be freed by the
+ * KDC.
  */
 typedef void
 (*krb5_kdcpreauth_verify_respond_fn)(void *arg, krb5_error_code code,
                                      krb5_kdcpreauth_modreq modreq,
-                                     krb5_data *e_data,
+                                     krb5_pa_data **e_data,
                                      krb5_authdata **authz_data);
 
+/*
+ * Optional: verify preauthentication data sent by the client, setting the
+ * TKT_FLG_PRE_AUTH or TKT_FLG_HW_AUTH flag in the enc_tkt_reply's "flags"
+ * field as appropriate.  The implementation must invoke the respond function
+ * when complete, whether successful or not.
+ */
 typedef void
 (*krb5_kdcpreauth_verify_fn)(krb5_context context,
                              struct _krb5_db_entry_new *client,
index ff7d4218506419dd18b4b7a9d0c396681f54b907..7abbfac147862c34231b515ba8772a4c6110503e 100644 (file)
@@ -84,8 +84,8 @@
 
 static krb5_error_code
 prepare_error_as(struct kdc_request_state *, krb5_kdc_req *,
-                 int, krb5_data *, krb5_principal, krb5_data **,
-                 const char *);
+                 int, krb5_pa_data **, krb5_boolean, krb5_principal,
+                 krb5_data **, const char *);
 
 /* Determine the key-expiration value according to RFC 4120 section 5.4.2. */
 static krb5_timestamp
@@ -111,7 +111,8 @@ struct as_req_state {
     krb5_db_entry *server;
     krb5_kdc_req *request;
     const char *status;
-    krb5_data e_data;
+    krb5_pa_data **e_data;
+    krb5_boolean typed_e_data;
     krb5_kdc_rep reply;
     krb5_timestamp kdc_time;
     krb5_timestamp authtime;
@@ -368,7 +369,8 @@ egress:
                 errcode = KRB_ERR_GENERIC;
 
             errcode = prepare_error_as(state->rstate, state->request,
-                                       errcode, &state->e_data,
+                                       errcode, state->e_data,
+                                       state->typed_e_data,
                                        (state->client != NULL) ?
                                                state->client->princ :
                                                NULL,
@@ -405,7 +407,7 @@ egress:
         free(state->ticket_reply.enc_part.ciphertext.data);
     }
 
-    krb5_free_data_contents(kdc_context, &state->e_data);
+    krb5_free_pa_data(kdc_context, state->e_data);
     kdc_free_rstate(state->rstate);
     state->request->kdc_state = NULL;
     krb5_free_kdc_req(kdc_context, state->request);
@@ -464,7 +466,7 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
     state->client = NULL;
     state->server = NULL;
     state->request = request;
-    state->e_data = empty_data();
+    state->e_data = NULL;
     state->authtime = 0;
     state->req_pkt = req_pkt;
     state->rstate = NULL;
@@ -752,7 +754,8 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
     if (state->request->padata) {
         check_padata(kdc_context, state->client, state->req_pkt,
                      state->request, &state->enc_tkt_reply, &state->pa_context,
-                     &state->e_data, finish_preauth, state);
+                     &state->e_data, &state->typed_e_data, finish_preauth,
+                     state);
         return;
     }
 
@@ -760,71 +763,15 @@ errout:
     finish_process_as_req(state, errcode);
 }
 
-/*
- * If e_data contains a padata or typed data sequence, produce a padata
- * sequence for FAST in *pa_out.  If e_data contains neither, set *pa_out to
- * NULL and return successfully.
- */
-static krb5_error_code
-get_error_padata(const krb5_data *e_data, krb5_pa_data ***pa_out)
-{
-    krb5_error_code retval;
-    krb5_pa_data **pa = NULL, *pad;
-    krb5_typed_data **td = NULL;
-    size_t size, i;
-
-    *pa_out = NULL;
-
-    /* Try decoding e_data as padata. */
-    retval = decode_krb5_padata_sequence(e_data, &pa);
-    if (retval == 0) {
-        *pa_out = pa;
-        return 0;
-    }
-
-    /* Try decoding e_data as typed data.  If it doesn't decode, assume there
-     * is no error padata. */
-    retval = decode_krb5_typed_data(e_data, &td);
-    if (retval == ENOMEM)
-        return retval;
-    else if (retval != 0)
-        return 0;
-
-    /* Convert the typed data to padata. */
-    for (size = 0; td[size]; size++);
-    pa = k5alloc((size + 1) * sizeof(*pa), &retval);
-    if (pa == NULL)
-        goto cleanup;
-    for (i = 0; i < size; i++) {
-        pad = k5alloc(sizeof(*pad), &retval);
-        if (pad == NULL)
-            goto cleanup;
-        pad->pa_type = td[i]->type;
-        pad->contents = td[i]->data;
-        pad->length = td[i]->length;
-        pa[i] = pad;
-        td[i]->data = NULL;
-    }
-
-    *pa_out = pa;
-    pa = NULL;
-
-cleanup:
-    krb5_free_typed_data(kdc_context, td);
-    krb5_free_pa_data(kdc_context, pa);
-    return retval;
-}
-
 static krb5_error_code
 prepare_error_as (struct kdc_request_state *rstate, krb5_kdc_req *request,
-                  int error, krb5_data *e_data,
+                  int error, krb5_pa_data **e_data, krb5_boolean typed_e_data,
                   krb5_principal canon_client, krb5_data **response,
                   const char *status)
 {
     krb5_error errpkt;
     krb5_error_code retval;
-    krb5_data *scratch = NULL, *fast_edata = NULL;
-    krb5_pa_data **pa = NULL;
+    krb5_data *scratch = NULL, *e_data_asn1 = NULL, *fast_edata = NULL;
 
     errpkt.ctime = request->nonce;
     errpkt.cusec = 0;
@@ -836,18 +783,27 @@ prepare_error_as (struct kdc_request_state *rstate, krb5_kdc_req *request,
     errpkt.server = request->server;
     errpkt.client = (error == KRB5KDC_ERR_WRONG_REALM) ? canon_client :
         request->client;
-    errpkt.e_data = *e_data;
     errpkt.text = string2data((char *)status);
 
-    retval = get_error_padata(e_data, &pa);
-    if (retval)
-        goto cleanup;
-    retval = kdc_fast_handle_error(kdc_context, rstate, request, pa, &errpkt,
-                                   &fast_edata);
+    if (e_data != NULL) {
+        if (typed_e_data) {
+            retval = encode_krb5_typed_data((const krb5_typed_data **)e_data,
+                                            &e_data_asn1);
+        } else
+            retval = encode_krb5_padata_sequence(e_data, &e_data_asn1);
+        if (retval)
+            goto cleanup;
+        errpkt.e_data = *e_data_asn1;
+    } else
+        errpkt.e_data = empty_data();
+
+    retval = kdc_fast_handle_error(kdc_context, rstate, request, e_data,
+                                   &errpkt, &fast_edata);
     if (retval)
         goto cleanup;
     if (fast_edata != NULL)
         errpkt.e_data = *fast_edata;
+
     scratch = k5alloc(sizeof(*scratch), &retval);
     if (scratch == NULL)
         goto cleanup;
@@ -859,8 +815,8 @@ prepare_error_as (struct kdc_request_state *rstate, krb5_kdc_req *request,
     scratch = NULL;
 
 cleanup:
-    krb5_free_pa_data(kdc_context, pa);
     krb5_free_data(kdc_context, fast_edata);
+    krb5_free_data(kdc_context, e_data_asn1);
     free(scratch);
     return retval;
 }
index aa3e84fd515a4ff148380bd5fb5f5e8fd059f4af..2ed73349f284253ae218e2cd2757488ac647c965 100644 (file)
@@ -73,7 +73,7 @@ find_alternate_tgs(krb5_kdc_req *,krb5_db_entry **);
 
 static krb5_error_code
 prepare_error_tgs(struct kdc_request_state *, krb5_kdc_req *,krb5_ticket *,int,
-                  krb5_principal,krb5_data **,const char *, krb5_data *);
+                  krb5_principal,krb5_data **,const char *, krb5_pa_data **);
 
 static krb5_int32
 prep_reprocess_req(krb5_kdc_req *,krb5_principal *);
@@ -123,12 +123,11 @@ process_tgs_req(krb5_data *pkt, const krb5_fulladdr *from,
     struct kdc_request_state *state = NULL;
     krb5_pa_data *pa_tgs_req; /*points into request*/
     krb5_data scratch;
-    krb5_data e_data = empty_data(); /* backend-provided error data */
+    krb5_pa_data **e_data = NULL;
 
     reply.padata = 0; /* For cleanup handler */
     reply_encpart.enc_padata = 0;
     enc_tkt_reply.authorization_data = NULL;
-    e_data.data = NULL;
 
     session_key.contents = NULL;
 
@@ -929,7 +928,7 @@ cleanup:
 
         retval = prepare_error_tgs(state, request, header_ticket, errcode,
                                    (server != NULL) ? server->princ : NULL,
-                                   response, status, &e_data);
+                                   response, status, e_data);
         if (got_err) {
             krb5_free_error_message (kdc_context, status);
             status = 0;
@@ -969,7 +968,7 @@ cleanup:
         krb5_free_pa_data(kdc_context, reply_encpart.enc_padata);
     if (enc_tkt_reply.authorization_data != NULL)
         krb5_free_authdata(kdc_context, enc_tkt_reply.authorization_data);
-    krb5_free_data_contents(kdc_context, &e_data);
+    krb5_free_pa_data(kdc_context, e_data);
 
     return retval;
 }
@@ -979,11 +978,11 @@ prepare_error_tgs (struct kdc_request_state *state,
                    krb5_kdc_req *request, krb5_ticket *ticket, int error,
                    krb5_principal canon_server,
                    krb5_data **response, const char *status,
-                   krb5_data *e_data)
+                   krb5_pa_data **e_data)
 {
     krb5_error errpkt;
     krb5_error_code retval = 0;
-    krb5_data *scratch, *fast_edata = NULL;
+    krb5_data *scratch, *e_data_asn1 = NULL, *fast_edata = NULL;
 
     errpkt.ctime = request->nonce;
     errpkt.cusec = 0;
@@ -1005,20 +1004,33 @@ prepare_error_tgs (struct kdc_request_state *state,
         free(errpkt.text.data);
         return ENOMEM;
     }
-    errpkt.e_data = *e_data;
+
+    if (e_data != NULL) {
+        retval = encode_krb5_padata_sequence(e_data, &e_data_asn1);
+        if (retval) {
+            free(scratch);
+            free(errpkt.text.data);
+            return retval;
+        }
+        errpkt.e_data = *e_data_asn1;
+    } else
+        errpkt.e_data = empty_data();
+
     if (state) {
-        retval = kdc_fast_handle_error(kdc_context, state, request, NULL,
+        retval = kdc_fast_handle_error(kdc_context, state, request, e_data,
                                        &errpkt, &fast_edata);
     }
     if (retval) {
         free(scratch);
         free(errpkt.text.data);
+        krb5_free_data(kdc_context, e_data_asn1);
         return retval;
     }
     if (fast_edata)
         errpkt.e_data = *fast_edata;
     retval = krb5_mk_error(kdc_context, &errpkt, scratch);
     free(errpkt.text.data);
+    krb5_free_data(kdc_context, e_data_asn1);
     krb5_free_data(kdc_context, fast_edata);
     if (retval)
         free(scratch);
index ec10e170e586a79aa8cfa3064bbc8a280e181f48..c94d9fefb7858a5b4a9c3f8daabffd4daf19de6a 100644 (file)
@@ -821,17 +821,14 @@ const char *missing_required_preauth(krb5_db_entry *client,
 
 void
 get_preauth_hint_list(krb5_kdc_req *request, krb5_db_entry *client,
-                      krb5_db_entry *server, krb5_data *e_data)
+                      krb5_db_entry *server, krb5_pa_data ***e_data_out)
 {
     int hw_only;
     preauth_system *ap;
     krb5_pa_data **pa_data, **pa;
-    krb5_data *edat;
     krb5_error_code retval;
 
-    /* Zero these out in case we need to abort */
-    e_data->length = 0;
-    e_data->data = 0;
+    *e_data_out = NULL;
 
     hw_only = isflagset(client->attributes, KRB5_KDB_REQUIRES_HW_AUTH);
     /* Allocate two extra entries for the cookie and the terminator. */
@@ -873,11 +870,9 @@ get_preauth_hint_list(krb5_kdc_req *request, krb5_db_entry *client,
      * still reasonable to continue with the response
      */
     kdc_preauth_get_cookie(request->kdc_state, pa);
-    retval = encode_krb5_padata_sequence(pa_data, &edat);
-    if (retval)
-        goto errout;
-    *e_data = *edat;
-    free(edat);
+
+    *e_data_out = pa_data;
+    pa_data = NULL;
 
 errout:
     krb5_free_pa_data(kdc_context, pa_data);
@@ -947,12 +942,15 @@ struct padata_state {
     krb5_kdc_req *request;
     krb5_enc_tkt_part *enc_tkt_reply;
     void **padata_context;
-    krb5_data *e_data;
 
     preauth_system *pa_sys;
-    krb5_data *pa_e_data;
+    krb5_pa_data **pa_e_data;
+    krb5_boolean typed_e_data_flag;
     int pa_ok;
     krb5_error_code saved_code;
+
+    krb5_pa_data ***e_data_out;
+    krb5_boolean *typed_e_data_out;
 };
 
 static void
@@ -965,27 +963,12 @@ finish_check_padata(struct padata_state *state, krb5_error_code code)
     oldrespond = state->respond;
     oldarg = state->arg;
 
-    /* Don't bother copying and returning e-data on success */
-    if (state->pa_ok && state->pa_e_data != NULL) {
-        krb5_free_data(state->context, state->pa_e_data);
-        state->pa_e_data = NULL;
-    }
-
-    /* Return any e-data from the preauth that caused us to exit the loop */
-    if (state->pa_e_data != NULL) {
-        state->e_data->data = malloc(state->pa_e_data->length);
-        if (state->e_data->data == NULL) {
-            krb5_free_data(state->context, state->pa_e_data);
-            free(state);
-            (*oldrespond)(oldarg, KRB5KRB_ERR_GENERIC);
-            return;
-        }
-        memcpy(state->e_data->data, state->pa_e_data->data,
-               state->pa_e_data->length);
-        state->e_data->length = state->pa_e_data->length;
-        krb5_free_data(state->context, state->pa_e_data);
-        state->pa_e_data = NULL;
-    }
+    if (!state->pa_ok) {
+        /* Return any saved preauth e-data. */
+        *state->e_data_out = state->pa_e_data;
+        *state->typed_e_data_out = state->typed_e_data_flag;
+    } else
+        krb5_free_pa_data(state->context, state->pa_e_data);
 
     if (state->pa_ok) {
         free(state);
@@ -1048,11 +1031,12 @@ next_padata(struct padata_state *state);
 
 static void
 finish_verify_padata(void *arg, krb5_error_code code,
-                     krb5_kdcpreauth_modreq modreq, krb5_data *e_data,
+                     krb5_kdcpreauth_modreq modreq, krb5_pa_data **e_data,
                      krb5_authdata **authz_data)
 {
     struct padata_state *state = arg;
     const char *emsg;
+    krb5_boolean typed_e_data_flag;
 
     assert(state);
     kdc_active_realm = state->realm; /* Restore the realm. */
@@ -1070,6 +1054,8 @@ finish_verify_padata(void *arg, krb5_error_code code,
             authz_data = NULL;
         }
 
+        typed_e_data_flag = ((state->pa_sys->flags & PA_TYPED_E_DATA) != 0);
+
         /*
          * We'll return edata from either the first PA_REQUIRED module
          * that fails, or the first non-PA_REQUIRED module that fails.
@@ -1079,8 +1065,9 @@ finish_verify_padata(void *arg, krb5_error_code code,
         if (state->pa_sys->flags & PA_REQUIRED) {
             /* free up any previous edata we might have been saving */
             if (state->pa_e_data != NULL)
-                krb5_free_data(state->context, state->pa_e_data);
+                krb5_free_pa_data(state->context, state->pa_e_data);
             state->pa_e_data = e_data;
+            state->typed_e_data_flag = typed_e_data_flag;
 
             /* Make sure we use the current retval */
             state->pa_ok = 0;
@@ -1089,10 +1076,11 @@ finish_verify_padata(void *arg, krb5_error_code code,
         } else if (state->pa_e_data == NULL) {
             /* save the first error code and e-data */
             state->pa_e_data = e_data;
+            state->typed_e_data_flag = typed_e_data_flag;
             state->saved_code = code;
         } else if (e_data != NULL) {
             /* discard this extra e-data from non-PA_REQUIRED module */
-            krb5_free_data(state->context, e_data);
+            krb5_free_pa_data(state->context, e_data);
         }
     } else {
 #ifdef DEBUG
@@ -1101,7 +1089,7 @@ finish_verify_padata(void *arg, krb5_error_code code,
 
         /* Ignore any edata returned on success */
         if (e_data != NULL)
-            krb5_free_data(state->context, e_data);
+            krb5_free_pa_data(state->context, e_data);
 
         /* Add any authorization data to the ticket */
         if (authz_data != NULL) {
@@ -1169,8 +1157,9 @@ next:
 void
 check_padata (krb5_context context, krb5_db_entry *client, krb5_data *req_pkt,
               krb5_kdc_req *request, krb5_enc_tkt_part *enc_tkt_reply,
-              void **padata_context, krb5_data *e_data,
-              kdc_preauth_respond_fn respond, void *arg)
+              void **padata_context, krb5_pa_data ***e_data,
+              krb5_boolean *typed_e_data, kdc_preauth_respond_fn respond,
+              void *arg)
 {
     struct padata_state *state;
 
@@ -1198,7 +1187,8 @@ check_padata (krb5_context context, krb5_db_entry *client, krb5_data *req_pkt,
     state->request = request;
     state->enc_tkt_reply = enc_tkt_reply;
     state->padata_context = padata_context;
-    state->e_data = e_data;
+    state->e_data_out = e_data;
+    state->typed_e_data_out = typed_e_data;
     state->realm = kdc_active_realm;
 
 #ifdef DEBUG
index e18fb2c860e9e78eaaba2af598b5fcd07f1ff145..e03cb27cb0529d410b774f6dbc4f5ce5bab366a4 100644 (file)
@@ -865,7 +865,7 @@ check_anon(krb5_context context, krb5_principal client, krb5_principal server)
 int
 validate_as_request(register krb5_kdc_req *request, krb5_db_entry client,
                     krb5_db_entry server, krb5_timestamp kdc_time,
-                    const char **status, krb5_data *e_data)
+                    const char **status, krb5_pa_data ***e_data)
 {
     int errcode;
     krb5_error_code ret;
@@ -1168,7 +1168,7 @@ fetch_asn1_field(unsigned char *astream, unsigned int level,
 int
 validate_tgs_request(register krb5_kdc_req *request, krb5_db_entry server,
                      krb5_ticket *ticket, krb5_timestamp kdc_time,
-                     const char **status, krb5_data *e_data)
+                     const char **status, krb5_pa_data ***e_data)
 {
     int errcode;
     int st_idx = 0;
@@ -2083,9 +2083,8 @@ kdc_process_s4u2self_req(krb5_context context,
      */
     if (is_local_principal((*s4u_x509_user)->user_id.user)) {
         krb5_db_entry no_server;
-        krb5_data e_data;
+        krb5_pa_data **e_data = NULL;
 
-        e_data.data = NULL;
         code = krb5_db_get_principal(context, (*s4u_x509_user)->user_id.user,
                                      KRB5_KDB_FLAG_INCLUDE_PAC, &princ);
         if (code == KRB5_KDB_NOENTRY) {
@@ -2102,7 +2101,7 @@ kdc_process_s4u2self_req(krb5_context context,
                                    no_server, kdc_time, status, &e_data);
         if (code) {
             krb5_db_free_principal(context, princ);
-            krb5_free_data_contents(context, &e_data);
+            krb5_free_pa_data(context, e_data);
             return code;
         }
 
index 296d3e9fae536c169e8624c4abf63c9ae097446c..e0be83fe6135d63594c6edb84be908166e97c590 100644 (file)
@@ -74,7 +74,7 @@ kdc_get_server_key (krb5_ticket *, unsigned int,
 int
 validate_as_request (krb5_kdc_req *, krb5_db_entry,
                      krb5_db_entry, krb5_timestamp,
-                     const char **, krb5_data *);
+                     const char **, krb5_pa_data ***);
 
 int
 validate_forwardable(krb5_kdc_req *, krb5_db_entry,
@@ -84,7 +84,7 @@ validate_forwardable(krb5_kdc_req *, krb5_db_entry,
 int
 validate_tgs_request (krb5_kdc_req *, krb5_db_entry,
                       krb5_ticket *, krb5_timestamp,
-                      const char **, krb5_data *);
+                      const char **, krb5_pa_data ***);
 
 int
 fetch_asn1_field (unsigned char *, unsigned int, unsigned int, krb5_data *);
@@ -151,12 +151,12 @@ kdc_err(krb5_context call_context, errcode_t code, const char *fmt, ...)
 int
 against_local_policy_as (krb5_kdc_req *, krb5_db_entry,
                          krb5_db_entry, krb5_timestamp,
-                         const char **, krb5_data *);
+                         const char **, krb5_pa_data ***);
 
 int
 against_local_policy_tgs (krb5_kdc_req *, krb5_db_entry,
                           krb5_ticket *, const char **,
-                          krb5_data *);
+                          krb5_pa_data ***);
 
 /* kdc_preauth.c */
 krb5_boolean
@@ -170,7 +170,7 @@ void
 get_preauth_hint_list (krb5_kdc_req * request,
                        krb5_db_entry *client,
                        krb5_db_entry *server,
-                       krb5_data *e_data);
+                       krb5_pa_data ***e_data_out);
 void
 load_preauth_plugins(krb5_context context);
 void
@@ -179,12 +179,11 @@ unload_preauth_plugins(krb5_context context);
 typedef void (*kdc_preauth_respond_fn)(void *arg, krb5_error_code code);
 
 void
-check_padata (krb5_context context,
-              krb5_db_entry *client, krb5_data *req_pkt,
-              krb5_kdc_req *request,
-              krb5_enc_tkt_part *enc_tkt_reply,
-              void **padata_context, krb5_data *e_data,
-              kdc_preauth_respond_fn respond, void *state);
+check_padata (krb5_context context, krb5_db_entry *client, krb5_data *req_pkt,
+              krb5_kdc_req *request, krb5_enc_tkt_part *enc_tkt_reply,
+              void **padata_context, krb5_pa_data ***e_data,
+              krb5_boolean *typed_e_data, kdc_preauth_respond_fn respond,
+              void *state);
 
 krb5_error_code
 return_padata (krb5_context context, krb5_db_entry *client,
index 2d07b7583d2f707f0a428f25b9bd4f18f5d6b347..486c3ff8b915700505f8cfd9f9259edcc4c9b11b 100644 (file)
@@ -57,7 +57,7 @@
 int
 against_local_policy_as(register krb5_kdc_req *request, krb5_db_entry client,
                         krb5_db_entry server, krb5_timestamp kdc_time,
-                        const char **status, krb5_data *e_data)
+                        const char **status, krb5_pa_data ***e_data)
 {
 #if 0
     /* An AS request must include the addresses field */
@@ -76,7 +76,7 @@ against_local_policy_as(register krb5_kdc_req *request, krb5_db_entry client,
 krb5_error_code
 against_local_policy_tgs(register krb5_kdc_req *request, krb5_db_entry server,
                          krb5_ticket *ticket, const char **status,
-                         krb5_data *e_data)
+                         krb5_pa_data ***e_data)
 {
 #if 0
     /*
index f647bb166ab9408354d5a883e3b600a8a5c40d48..45503282a19fd81ee357e08e9f9e357ba3b0feb6 100644 (file)
@@ -11,7 +11,7 @@ DEFS=
 
 # Keep LIBMAJOR in sync with KRB5_KDB_API_VERSION in include/kdb.h.
 LIBBASE=kdb5
-LIBMAJOR=5
+LIBMAJOR=6
 LIBMINOR=0
 LIBINITFUNC=kdb_init_lock_list
 LIBFINIFUNC=kdb_fini_lock_list
index a3a0d6f49c2d65c46c5bd3917aaac29f4a32f5c2..011c83bf380c28ab81887d67be7641f03764e182 100644 (file)
@@ -2483,13 +2483,13 @@ krb5_error_code
 krb5_db_check_policy_as(krb5_context kcontext, krb5_kdc_req *request,
                         krb5_db_entry *client, krb5_db_entry *server,
                         krb5_timestamp kdc_time, const char **status,
-                        krb5_data *e_data)
+                        krb5_pa_data ***e_data)
 {
     krb5_error_code ret;
     kdb_vftabl *v;
 
     *status = NULL;
-    *e_data = empty_data();
+    *e_data = NULL;
     ret = get_vftabl(kcontext, &v);
     if (ret)
         return ret;
@@ -2502,13 +2502,13 @@ krb5_db_check_policy_as(krb5_context kcontext, krb5_kdc_req *request,
 krb5_error_code
 krb5_db_check_policy_tgs(krb5_context kcontext, krb5_kdc_req *request,
                          krb5_db_entry *server, krb5_ticket *ticket,
-                         const char **status, krb5_data *e_data)
+                         const char **status, krb5_pa_data ***e_data)
 {
     krb5_error_code ret;
     kdb_vftabl *v;
 
     *status = NULL;
-    *e_data = empty_data();
+    *e_data = NULL;
     ret = get_vftabl(kcontext, &v);
     if (ret)
         return ret;
index 87f462a7c1163d89718a422f7392f999fba9b19b..e31ebb9cbf35252851e639c1f2882e2f89071c79 100644 (file)
@@ -96,6 +96,7 @@ encode_krb5_sp80056a_other_info
 encode_krb5_tgs_rep
 encode_krb5_tgs_req
 encode_krb5_ticket
+encode_krb5_typed_data
 et_asn1_error_table
 et_k524_error_table
 et_kdb5_error_table
index f24b6575d83da10ee7acd3e75ea4882d02d68d33..f63b12e057534899804a906d5aa981d035adec1d 100644 (file)
@@ -1410,7 +1410,7 @@ krb5_error_code
 krb5_db2_check_policy_as(krb5_context kcontext, krb5_kdc_req *request,
                          krb5_db_entry *client, krb5_db_entry *server,
                          krb5_timestamp kdc_time, const char **status,
-                         krb5_data *e_data)
+                         krb5_pa_data ***e_data)
 {
     krb5_error_code retval;
 
index 30a53f70a87440fa5a75a5205ac23f50d2a8b1e5..a2cedb8eaf169ef8ffb6db27f9f79e7a5e4f9e9f 100644 (file)
@@ -135,7 +135,7 @@ krb5_error_code
 krb5_db2_check_policy_as(krb5_context kcontext, krb5_kdc_req *request,
                          krb5_db_entry *client, krb5_db_entry *server,
                          krb5_timestamp kdc_time, const char **status,
-                         krb5_data *e_data);
+                         krb5_pa_data ***e_data);
 
 void
 krb5_db2_audit_as_req(krb5_context kcontext, krb5_kdc_req *request,
index 38f5001ad44258cb46eaa74242babc89a711e734..21051019464dbc776ef73b64b9e72f7d12186093 100644 (file)
@@ -171,7 +171,7 @@ kh_db_check_policy_as(krb5_context kcontext,
                       krb5_db_entry *server,
                       krb5_timestamp kdc_time,
                       const char **status,
-                      krb5_data *e_data);
+                      krb5_pa_data ***e_data);
 
 krb5_error_code
 kh_hdb_windc_init(krb5_context context,
index baafd8d2f7370ace811180d5e04961f7f4cc4eac..a5d1567bf4c1cfda7951d5341163a9c24e9bda4c 100644 (file)
@@ -495,10 +495,12 @@ kh_db_check_policy_as(krb5_context context,
                       krb5_db_entry *server,
                       krb5_timestamp kdc_time,
                       const char **status,
-                      krb5_data *e_data)
+                      krb5_pa_data ***e_data_out)
 {
     kh_db_context *kh = KH_DB_CONTEXT(context);
     krb5_error_code code;
+    krb5_data d;
+    krb5_pa_data **e_data;
     heim_octet_string he_data;
     KDC_REQ hkdcreq;
     Principal *hclient = NULL;
@@ -552,8 +554,14 @@ kh_db_check_policy_as(krb5_context context,
                                   KH_DB_ENTRY(client),
                                   &hkdcreq, &he_data);
 
-    e_data->data   = he_data.data;
-    e_data->length = he_data.length;
+    if (he_data.data != NULL) {
+        d = make_data(he_data.data, he_data.length);
+        code = decode_krb5_padata_sequence(&d, &e_data);
+        if (code == 0)
+            *e_data_out = e_data;
+        free(he_data.data);
+        code = 0;
+    }
 
 cleanup:
     kh_free_HostAddresses(context, hkdcreq.req_body.addresses);
index 7811bdb740a9d85fa9a0d2d592c1c445d89c251c..217c9ce3a88ca1030cada413df9313bb40dc9089 100644 (file)
@@ -541,7 +541,7 @@ krb5_error_code
 krb5_ldap_check_policy_as(krb5_context kcontext, krb5_kdc_req *request,
                           krb5_db_entry *client, krb5_db_entry *server,
                           krb5_timestamp kdc_time, const char **status,
-                          krb5_data *e_data)
+                          krb5_pa_data ***e_data)
 {
     krb5_error_code retval;
 
index 1f45b6c9c60544856c902a9bc422e60df6f71b2e..51a6facb78c4b79b2765a1ce8b9c83680596b87e 100644 (file)
@@ -293,7 +293,7 @@ krb5_error_code
 krb5_ldap_check_policy_as(krb5_context kcontext, krb5_kdc_req *request,
                           krb5_db_entry *client, krb5_db_entry *server,
                           krb5_timestamp kdc_time, const char **status,
-                          krb5_data *e_data);
+                          krb5_pa_data ***e_data);
 
 void
 krb5_ldap_audit_as_req(krb5_context kcontext, krb5_kdc_req *request,
index ffe2a14f7ad5d41bde5b0bfd2d7c79f4dd021792..2536aeeb1fcf46e61741838e43dda23546385586 100644 (file)
@@ -304,7 +304,6 @@ void init_krb5_auth_pack(krb5_auth_pack **in);
 void init_krb5_auth_pack_draft9(krb5_auth_pack_draft9 **in);
 void init_krb5_pa_pk_as_rep(krb5_pa_pk_as_rep **in);
 void init_krb5_pa_pk_as_rep_draft9(krb5_pa_pk_as_rep_draft9 **in);
-void init_krb5_typed_data(krb5_typed_data **in);
 void init_krb5_subject_pk_info(krb5_subject_pk_info **in);
 
 void free_krb5_pa_pk_as_req(krb5_pa_pk_as_req **in);
index 7da5cb02f9ceed6def0ab219122c4ed38af89fbe..5dac85427153bb0f7004970c07c75655cf155493 100644 (file)
@@ -559,7 +559,7 @@ krb5_error_code pkinit_create_td_dh_parameters
        pkinit_req_crypto_context req_cryptoctx,        /* IN */
        pkinit_identity_crypto_context id_cryptoctx,    /* IN */
        pkinit_plg_opts *opts,                          /* IN */
-       krb5_data **edata);                             /* OUT */
+       krb5_pa_data ***e_data_out);                    /* OUT */
 
 /*
  * this function processes edata that contains TD-DH-PARAMETERS.
@@ -584,7 +584,7 @@ krb5_error_code pkinit_create_td_invalid_certificate
        pkinit_plg_crypto_context plg_cryptoctx,        /* IN */
        pkinit_req_crypto_context req_cryptoctx,        /* IN */
        pkinit_identity_crypto_context id_cryptoctx,    /* IN */
-       krb5_data **edata);                             /* OUT */
+       krb5_pa_data ***e_data_out);                    /* OUT */
 
 /*
  * this function creates edata that contains TD-TRUSTED-CERTIFIERS
@@ -594,7 +594,7 @@ krb5_error_code pkinit_create_td_trusted_certifiers
        pkinit_plg_crypto_context plg_cryptoctx,        /* IN */
        pkinit_req_crypto_context req_cryptoctx,        /* IN */
        pkinit_identity_crypto_context id_cryptoctx,    /* IN */
-       krb5_data **edata);                             /* OUT */
+       krb5_pa_data ***e_data_out);                    /* OUT */
 
 /*
  * this function processes edata that contains either
index be752f71407c8277e1ea5d6e28825ddf949aee73..547ecc7390eccccaee0cc640d7f7490ddeafa67c 100644 (file)
@@ -108,7 +108,7 @@ static krb5_error_code pkinit_create_sequence_of_principal_identifiers
 (krb5_context context, pkinit_plg_crypto_context plg_cryptoctx,
  pkinit_req_crypto_context req_cryptoctx,
  pkinit_identity_crypto_context id_cryptoctx,
- int type, krb5_data **out_data);
+ int type, krb5_pa_data ***e_data_out);
 
 #ifndef WITHOUT_PKCS11
 static krb5_error_code pkinit_find_private_key
@@ -2973,12 +2973,12 @@ pkinit_create_sequence_of_principal_identifiers(
     pkinit_req_crypto_context req_cryptoctx,
     pkinit_identity_crypto_context id_cryptoctx,
     int type,
-    krb5_data **out_data)
+    krb5_pa_data ***e_data_out)
 {
     krb5_error_code retval = KRB5KRB_ERR_GENERIC;
     krb5_external_principal_identifier **krb5_trusted_certifiers = NULL;
-    krb5_data *td_certifiers = NULL, *data = NULL;
-    krb5_typed_data **typed_data = NULL;
+    krb5_data *td_certifiers = NULL;
+    krb5_pa_data **pa_data = NULL;
 
     switch(type) {
     case TD_TRUSTED_CERTIFIERS:
@@ -3011,49 +3011,27 @@ pkinit_create_sequence_of_principal_identifiers(
     print_buffer_bin((unsigned char *)td_certifiers->data,
                      td_certifiers->length, "/tmp/kdc_td_certifiers");
 #endif
-    typed_data = malloc(2 * sizeof(krb5_typed_data *));
-    if (typed_data == NULL) {
+    pa_data = malloc(2 * sizeof(krb5_pa_data *));
+    if (pa_data == NULL) {
         retval = ENOMEM;
         goto cleanup;
     }
-    typed_data[1] = NULL;
-    init_krb5_typed_data(&typed_data[0]);
-    if (typed_data[0] == NULL) {
+    pa_data[1] = NULL;
+    pa_data[0] = malloc(sizeof(krb5_pa_data));
+    if (pa_data[0] == NULL) {
         retval = ENOMEM;
         goto cleanup;
     }
-    typed_data[0]->type = type;
-    typed_data[0]->length = td_certifiers->length;
-    typed_data[0]->data = (unsigned char *)td_certifiers->data;
-    retval = k5int_encode_krb5_typed_data((const krb5_typed_data **)typed_data,
-                                          &data);
-    if (retval) {
-        pkiDebug("encode_krb5_typed_data failed\n");
-        goto cleanup;
-    }
-#ifdef DEBUG_ASN1
-    print_buffer_bin((unsigned char *)data->data, data->length,
-                     "/tmp/kdc_edata");
-#endif
-    *out_data = malloc(sizeof(krb5_data));
-    (*out_data)->length = data->length;
-    (*out_data)->data = malloc(data->length);
-    memcpy((*out_data)->data, data->data, data->length);
-
+    pa_data[0]->pa_type = type;
+    pa_data[0]->length = td_certifiers->length;
+    pa_data[0]->contents = (krb5_octet *)td_certifiers->data;
+    *e_data_out = pa_data;
     retval = 0;
 
 cleanup:
     if (krb5_trusted_certifiers != NULL)
         free_krb5_external_principal_identifier(&krb5_trusted_certifiers);
-
-    if (data != NULL) {
-        free(data->data);
-        free(data);
-    }
-
     free(td_certifiers);
-    free_krb5_typed_data(&typed_data);
-
     return retval;
 }
 
@@ -3062,13 +3040,13 @@ pkinit_create_td_trusted_certifiers(krb5_context context,
                                     pkinit_plg_crypto_context plg_cryptoctx,
                                     pkinit_req_crypto_context req_cryptoctx,
                                     pkinit_identity_crypto_context id_cryptoctx,
-                                    krb5_data **out_data)
+                                    krb5_pa_data ***e_data_out)
 {
     krb5_error_code retval = KRB5KRB_ERR_GENERIC;
 
     retval = pkinit_create_sequence_of_principal_identifiers(context,
                                                              plg_cryptoctx, req_cryptoctx, id_cryptoctx,
-                                                             TD_TRUSTED_CERTIFIERS, out_data);
+                                                             TD_TRUSTED_CERTIFIERS, e_data_out);
 
     return retval;
 }
@@ -3079,13 +3057,13 @@ pkinit_create_td_invalid_certificate(
     pkinit_plg_crypto_context plg_cryptoctx,
     pkinit_req_crypto_context req_cryptoctx,
     pkinit_identity_crypto_context id_cryptoctx,
-    krb5_data **out_data)
+    krb5_pa_data ***e_data_out)
 {
     krb5_error_code retval = KRB5KRB_ERR_GENERIC;
 
     retval = pkinit_create_sequence_of_principal_identifiers(context,
                                                              plg_cryptoctx, req_cryptoctx, id_cryptoctx,
-                                                             TD_INVALID_CERTIFICATES, out_data);
+                                                             TD_INVALID_CERTIFICATES, e_data_out);
 
     return retval;
 }
@@ -3096,13 +3074,13 @@ pkinit_create_td_dh_parameters(krb5_context context,
                                pkinit_req_crypto_context req_cryptoctx,
                                pkinit_identity_crypto_context id_cryptoctx,
                                pkinit_plg_opts *opts,
-                               krb5_data **out_data)
+                               krb5_pa_data ***e_data_out)
 {
     krb5_error_code retval = ENOMEM;
     unsigned int buf1_len = 0, buf2_len = 0, buf3_len = 0, i = 0;
     unsigned char *buf1 = NULL, *buf2 = NULL, *buf3 = NULL;
-    krb5_typed_data **typed_data = NULL;
-    krb5_data *data = NULL, *encoded_algId = NULL;
+    krb5_pa_data **pa_data = NULL;
+    krb5_data *encoded_algId = NULL;
     krb5_algorithm_identifier **algId = NULL;
 
     if (opts->dh_min_bits > 4096)
@@ -3211,53 +3189,27 @@ pkinit_create_td_dh_parameters(krb5_context context,
     print_buffer_bin((unsigned char *)encoded_algId->data,
                      encoded_algId->length, "/tmp/kdc_td_dh_params");
 #endif
-    typed_data = malloc(2 * sizeof(krb5_typed_data *));
-    if (typed_data == NULL) {
+    pa_data = malloc(2 * sizeof(krb5_pa_data *));
+    if (pa_data == NULL) {
         retval = ENOMEM;
         goto cleanup;
     }
-    typed_data[1] = NULL;
-    init_krb5_typed_data(&typed_data[0]);
-    if (typed_data == NULL) {
+    pa_data[1] = NULL;
+    pa_data[0] = malloc(sizeof(krb5_pa_data));
+    if (pa_data[0] == NULL) {
         retval = ENOMEM;
         goto cleanup;
     }
-    typed_data[0]->type = TD_DH_PARAMETERS;
-    typed_data[0]->length = encoded_algId->length;
-    typed_data[0]->data = (unsigned char *)encoded_algId->data;
-    retval = k5int_encode_krb5_typed_data((const krb5_typed_data**)typed_data,
-                                          &data);
-    if (retval) {
-        pkiDebug("encode_krb5_typed_data failed\n");
-        goto cleanup;
-    }
-#ifdef DEBUG_ASN1
-    print_buffer_bin((unsigned char *)data->data, data->length,
-                     "/tmp/kdc_edata");
-#endif
-    *out_data = malloc(sizeof(krb5_data));
-    if (*out_data == NULL)
-        goto cleanup;
-    (*out_data)->length = data->length;
-    (*out_data)->data = malloc(data->length);
-    if ((*out_data)->data == NULL) {
-        free(*out_data);
-        *out_data = NULL;
-        goto cleanup;
-    }
-    memcpy((*out_data)->data, data->data, data->length);
-
+    pa_data[0]->pa_type = TD_DH_PARAMETERS;
+    pa_data[0]->length = encoded_algId->length;
+    pa_data[0]->contents = (krb5_octet *)encoded_algId->data;
+    *e_data_out = pa_data;
     retval = 0;
 cleanup:
 
     free(buf1);
     free(buf2);
     free(buf3);
-    if (data != NULL) {
-        free(data->data);
-        free(data);
-    }
-    free_krb5_typed_data(&typed_data);
     free(encoded_algId);
 
     if (algId != NULL) {
index f93c0743f42ddcd28a3e1ba0d01e53e1d18c10b0..6b1018004794f7e5e5ea0d29e00b799dec60cb8a 100644 (file)
@@ -391,16 +391,6 @@ init_krb5_pa_pk_as_rep_draft9(krb5_pa_pk_as_rep_draft9 **in)
     (*in)->u.encKeyPack.data = NULL;
 }
 
-void
-init_krb5_typed_data(krb5_typed_data **in)
-{
-    (*in) = malloc(sizeof(krb5_typed_data));
-    if ((*in) == NULL) return;
-    (*in)->type = 0;
-    (*in)->length = 0;
-    (*in)->data = NULL;
-}
-
 void
 init_krb5_subject_pk_info(krb5_subject_pk_info **in)
 {
index 1967ea65c89fb905437d38a25f3e722a704c33f5..2fbc243913136405a6131b7cfa028841ba1fcf50 100644 (file)
@@ -66,7 +66,7 @@ pkinit_create_edata(krb5_context context,
                     pkinit_identity_crypto_context id_cryptoctx,
                     pkinit_plg_opts *opts,
                     krb5_error_code err_code,
-                    krb5_data **e_data)
+                    krb5_pa_data ***e_data_out)
 {
     krb5_error_code retval = KRB5KRB_ERR_GENERIC;
 
@@ -75,16 +75,16 @@ pkinit_create_edata(krb5_context context,
     switch(err_code) {
     case KRB5KDC_ERR_CANT_VERIFY_CERTIFICATE:
         retval = pkinit_create_td_trusted_certifiers(context,
-                                                     plg_cryptoctx, req_cryptoctx, id_cryptoctx, e_data);
+                                                     plg_cryptoctx, req_cryptoctx, id_cryptoctx, e_data_out);
         break;
     case KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED:
         retval = pkinit_create_td_dh_parameters(context, plg_cryptoctx,
-                                                req_cryptoctx, id_cryptoctx, opts, e_data);
+                                                req_cryptoctx, id_cryptoctx, opts, e_data_out);
         break;
     case KRB5KDC_ERR_INVALID_CERTIFICATE:
     case KRB5KDC_ERR_REVOKED_CERTIFICATE:
         retval = pkinit_create_td_invalid_certificate(context,
-                                                      plg_cryptoctx, req_cryptoctx, id_cryptoctx, e_data);
+                                                      plg_cryptoctx, req_cryptoctx, id_cryptoctx, e_data_out);
         break;
     default:
         pkiDebug("no edata needed for error %d (%s)\n",
@@ -314,7 +314,7 @@ pkinit_server_verify_padata(krb5_context context,
     krb5_data k5data;
     int is_signed = 1;
     krb5_keyblock *armor_key;
-    krb5_data *e_data = NULL;
+    krb5_pa_data **e_data = NULL;
     krb5_kdcpreauth_modreq modreq = NULL;
 
     pkiDebug("pkinit_verify_padata: entered!\n");
@@ -1147,7 +1147,7 @@ pkinit_server_get_flags(krb5_context kcontext, krb5_preauthtype patype)
 {
     if (patype == KRB5_PADATA_PKINIT_KX)
         return PA_INFO;
-    return PA_SUFFICIENT | PA_REPLACES_KEY;
+    return PA_SUFFICIENT | PA_REPLACES_KEY | PA_TYPED_E_DATA;
 }
 
 static krb5_preauthtype supported_server_pa_types[] = {