diff options
author | Greg Hudson <ghudson@mit.edu> | 2011-10-04 20:16:07 +0000 |
---|---|---|
committer | Greg Hudson <ghudson@mit.edu> | 2011-10-04 20:16:07 +0000 |
commit | cbb4ede6d5a939f39f3325ad040406ac05c99713 (patch) | |
tree | 70eb9e23b1ac63b45b0596ec70609d742fde45d2 /src/kdc | |
parent | a046e6135690f97adfa6bb4065d7367cf6142c40 (diff) | |
download | krb5-cbb4ede6d5a939f39f3325ad040406ac05c99713.tar.gz krb5-cbb4ede6d5a939f39f3325ad040406ac05c99713.tar.xz krb5-cbb4ede6d5a939f39f3325ad040406ac05c99713.zip |
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
Diffstat (limited to 'src/kdc')
-rw-r--r-- | src/kdc/do_as_req.c | 100 | ||||
-rw-r--r-- | src/kdc/do_tgs_req.c | 30 | ||||
-rw-r--r-- | src/kdc/kdc_preauth.c | 70 | ||||
-rw-r--r-- | src/kdc/kdc_util.c | 9 | ||||
-rw-r--r-- | src/kdc/kdc_util.h | 21 | ||||
-rw-r--r-- | src/kdc/policy.c | 4 |
6 files changed, 95 insertions, 139 deletions
diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c index ff7d421850..7abbfac147 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 aa3e84fd51..2ed73349f2 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 ec10e170e5..c94d9fefb7 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 e18fb2c860..e03cb27cb0 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 296d3e9fae..e0be83fe61 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 2d07b7583d..486c3ff8b9 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 /* |