From cbb4ede6d5a939f39f3325ad040406ac05c99713 Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Tue, 4 Oct 2011 20:16:07 +0000 Subject: [PATCH] Create e_data as pa_data in KDC interfaces 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 --- src/include/kdb.h | 12 +- src/include/krb5/preauth_plugin.h | 26 ++++- src/kdc/do_as_req.c | 100 +++++------------ src/kdc/do_tgs_req.c | 30 +++-- src/kdc/kdc_preauth.c | 70 +++++------- src/kdc/kdc_util.c | 9 +- src/kdc/kdc_util.h | 21 ++-- src/kdc/policy.c | 4 +- src/lib/kdb/Makefile.in | 2 +- src/lib/kdb/kdb5.c | 8 +- src/lib/krb5/libkrb5.exports | 1 + src/plugins/kdb/db2/kdb_db2.c | 2 +- src/plugins/kdb/db2/kdb_db2.h | 2 +- src/plugins/kdb/hdb/kdb_hdb.h | 2 +- src/plugins/kdb/hdb/kdb_windc.c | 14 ++- src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c | 2 +- src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h | 2 +- src/plugins/preauth/pkinit/pkinit.h | 1 - src/plugins/preauth/pkinit/pkinit_crypto.h | 6 +- .../preauth/pkinit/pkinit_crypto_openssl.c | 106 +++++------------- src/plugins/preauth/pkinit/pkinit_lib.c | 10 -- src/plugins/preauth/pkinit/pkinit_srv.c | 12 +- 22 files changed, 181 insertions(+), 261 deletions(-) diff --git a/src/include/kdb.h b/src/include/kdb.h index 809722eda..78f786f3b 100644 --- a/src/include/kdb.h +++ b/src/include/kdb.h @@ -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 diff --git a/src/include/krb5/preauth_plugin.h b/src/include/krb5/preauth_plugin.h index c620d6cdb..3f9dfcc35 100644 --- a/src/include/krb5/preauth_plugin.h +++ b/src/include/krb5/preauth_plugin.h @@ -126,6 +126,11 @@ */ #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, diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c index ff7d42185..7abbfac14 100644 --- a/src/kdc/do_as_req.c +++ b/src/kdc/do_as_req.c @@ -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; } diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c index aa3e84fd5..2ed73349f 100644 --- a/src/kdc/do_tgs_req.c +++ b/src/kdc/do_tgs_req.c @@ -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); diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c index ec10e170e..c94d9fefb 100644 --- a/src/kdc/kdc_preauth.c +++ b/src/kdc/kdc_preauth.c @@ -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 diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c index e18fb2c86..e03cb27cb 100644 --- a/src/kdc/kdc_util.c +++ b/src/kdc/kdc_util.c @@ -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; } diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h index 296d3e9fa..e0be83fe6 100644 --- a/src/kdc/kdc_util.h +++ b/src/kdc/kdc_util.h @@ -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, diff --git a/src/kdc/policy.c b/src/kdc/policy.c index 2d07b7583..486c3ff8b 100644 --- a/src/kdc/policy.c +++ b/src/kdc/policy.c @@ -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 /* diff --git a/src/lib/kdb/Makefile.in b/src/lib/kdb/Makefile.in index f647bb166..45503282a 100644 --- a/src/lib/kdb/Makefile.in +++ b/src/lib/kdb/Makefile.in @@ -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 diff --git a/src/lib/kdb/kdb5.c b/src/lib/kdb/kdb5.c index a3a0d6f49..011c83bf3 100644 --- a/src/lib/kdb/kdb5.c +++ b/src/lib/kdb/kdb5.c @@ -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; diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports index 87f462a7c..e31ebb9cb 100644 --- a/src/lib/krb5/libkrb5.exports +++ b/src/lib/krb5/libkrb5.exports @@ -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 diff --git a/src/plugins/kdb/db2/kdb_db2.c b/src/plugins/kdb/db2/kdb_db2.c index f24b6575d..f63b12e05 100644 --- a/src/plugins/kdb/db2/kdb_db2.c +++ b/src/plugins/kdb/db2/kdb_db2.c @@ -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; diff --git a/src/plugins/kdb/db2/kdb_db2.h b/src/plugins/kdb/db2/kdb_db2.h index 30a53f70a..a2cedb8ea 100644 --- a/src/plugins/kdb/db2/kdb_db2.h +++ b/src/plugins/kdb/db2/kdb_db2.h @@ -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, diff --git a/src/plugins/kdb/hdb/kdb_hdb.h b/src/plugins/kdb/hdb/kdb_hdb.h index 38f5001ad..210510194 100644 --- a/src/plugins/kdb/hdb/kdb_hdb.h +++ b/src/plugins/kdb/hdb/kdb_hdb.h @@ -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, diff --git a/src/plugins/kdb/hdb/kdb_windc.c b/src/plugins/kdb/hdb/kdb_windc.c index baafd8d2f..a5d1567bf 100644 --- a/src/plugins/kdb/hdb/kdb_windc.c +++ b/src/plugins/kdb/hdb/kdb_windc.c @@ -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); diff --git a/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c b/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c index 7811bdb74..217c9ce3a 100644 --- a/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c +++ b/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c @@ -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; diff --git a/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h b/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h index 1f45b6c9c..51a6facb7 100644 --- a/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h +++ b/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h @@ -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, diff --git a/src/plugins/preauth/pkinit/pkinit.h b/src/plugins/preauth/pkinit/pkinit.h index ffe2a14f7..2536aeeb1 100644 --- a/src/plugins/preauth/pkinit/pkinit.h +++ b/src/plugins/preauth/pkinit/pkinit.h @@ -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); diff --git a/src/plugins/preauth/pkinit/pkinit_crypto.h b/src/plugins/preauth/pkinit/pkinit_crypto.h index 7da5cb02f..5dac85427 100644 --- a/src/plugins/preauth/pkinit/pkinit_crypto.h +++ b/src/plugins/preauth/pkinit/pkinit_crypto.h @@ -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 diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c index be752f714..547ecc739 100644 --- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c +++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c @@ -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) { diff --git a/src/plugins/preauth/pkinit/pkinit_lib.c b/src/plugins/preauth/pkinit/pkinit_lib.c index f93c0743f..6b1018004 100644 --- a/src/plugins/preauth/pkinit/pkinit_lib.c +++ b/src/plugins/preauth/pkinit/pkinit_lib.c @@ -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) { diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c index 1967ea65c..2fbc24391 100644 --- a/src/plugins/preauth/pkinit/pkinit_srv.c +++ b/src/plugins/preauth/pkinit/pkinit_srv.c @@ -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[] = { -- 2.26.2