summaryrefslogtreecommitdiffstats
path: root/src/kdc
diff options
context:
space:
mode:
authorGreg Hudson <ghudson@mit.edu>2011-10-04 20:16:07 +0000
committerGreg Hudson <ghudson@mit.edu>2011-10-04 20:16:07 +0000
commitcbb4ede6d5a939f39f3325ad040406ac05c99713 (patch)
tree70eb9e23b1ac63b45b0596ec70609d742fde45d2 /src/kdc
parenta046e6135690f97adfa6bb4065d7367cf6142c40 (diff)
downloadkrb5-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.c100
-rw-r--r--src/kdc/do_tgs_req.c30
-rw-r--r--src/kdc/kdc_preauth.c70
-rw-r--r--src/kdc/kdc_util.c9
-rw-r--r--src/kdc/kdc_util.h21
-rw-r--r--src/kdc/policy.c4
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
/*