summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/kdc/dispatch.c104
-rw-r--r--src/kdc/do_as_req.c14
-rw-r--r--src/kdc/kdc_util.h4
3 files changed, 80 insertions, 42 deletions
diff --git a/src/kdc/dispatch.c b/src/kdc/dispatch.c
index cb09c62ff9..5f9c810e24 100644
--- a/src/kdc/dispatch.c
+++ b/src/kdc/dispatch.c
@@ -36,6 +36,45 @@ static krb5_int32 last_usec = 0, last_os_random = 0;
static krb5_error_code make_too_big_error (krb5_data **out);
+struct dispatch_state {
+ loop_respond_fn respond;
+ void *arg;
+ krb5_data *request;
+ int is_tcp;
+};
+
+static void
+finish_dispatch(void *arg, krb5_error_code code, krb5_data *response)
+{
+ struct dispatch_state *state = arg;
+ loop_respond_fn oldrespond;
+ void *oldarg;
+
+ assert(state);
+ oldrespond = state->respond;
+ oldarg = state->arg;
+
+ if (state->is_tcp == 0 && response &&
+ response->length > max_dgram_reply_size) {
+ krb5_free_data(kdc_context, response);
+ response = NULL;
+ code = make_too_big_error(&response);
+ if (code)
+ krb5_klog_syslog(LOG_ERR, "error constructing "
+ "KRB_ERR_RESPONSE_TOO_BIG error: %s",
+ error_message(code));
+ }
+
+#ifndef NOCACHE
+ /* put the response into the lookaside buffer */
+ else if (!code)
+ kdc_insert_lookaside(state->request, response);
+#endif
+
+ free(state);
+ (*oldrespond)(oldarg, code, response);
+}
+
void
dispatch(void *cb, struct sockaddr *local_saddr, const krb5_fulladdr *from,
krb5_data *pkt, int is_tcp, loop_respond_fn respond, void *arg)
@@ -43,7 +82,18 @@ dispatch(void *cb, struct sockaddr *local_saddr, const krb5_fulladdr *from,
krb5_error_code retval;
krb5_kdc_req *as_req;
krb5_int32 now, now_usec;
- krb5_data *response;
+ krb5_data *response = NULL;
+ struct dispatch_state *state;
+
+ state = malloc(sizeof(*state));
+ if (!state) {
+ (*respond)(arg, ENOMEM, NULL);
+ return;
+ }
+ state->respond = respond;
+ state->arg = arg;
+ state->request = pkt;
+ state->is_tcp = is_tcp;
/* decode incoming packet, and dispatch */
@@ -54,20 +104,22 @@ dispatch(void *cb, struct sockaddr *local_saddr, const krb5_fulladdr *from,
const char *name = 0;
char buf[46];
- if (is_tcp == 0 && response->length > max_dgram_reply_size)
- goto too_big_for_udp;
-
- name = inet_ntop (ADDRTYPE2FAMILY (from->address->addrtype),
- from->address->contents, buf, sizeof (buf));
- if (name == 0)
- name = "[unknown address type]";
- krb5_klog_syslog(LOG_INFO,
- "DISPATCH: repeated (retransmitted?) request from %s, resending previous response",
- name);
- (*respond)(arg, 0, response);
+ if (is_tcp != 0 || response->length <= max_dgram_reply_size) {
+ name = inet_ntop (ADDRTYPE2FAMILY (from->address->addrtype),
+ from->address->contents, buf, sizeof (buf));
+ if (name == 0)
+ name = "[unknown address type]";
+ krb5_klog_syslog(LOG_INFO,
+ "DISPATCH: repeated (retransmitted?) request "
+ "from %s, resending previous response",
+ name);
+ }
+
+ finish_dispatch(state, 0, response);
return;
}
#endif
+
retval = krb5_crypto_us_timeofday(&now, &now_usec);
if (retval == 0) {
krb5_int32 usec_difference = now_usec-last_usec;
@@ -99,32 +151,16 @@ dispatch(void *cb, struct sockaddr *local_saddr, const krb5_fulladdr *from,
* process_as_req frees the request if it is called
*/
if (!(retval = setup_server_realm(as_req->server))) {
- retval = process_as_req(as_req, pkt, from, &response);
+ process_as_req(as_req, pkt, from, finish_dispatch, state);
+ return;
}
- else krb5_free_kdc_req(kdc_context, as_req);
+ else
+ krb5_free_kdc_req(kdc_context, as_req);
}
- }
- else
+ } else
retval = KRB5KRB_AP_ERR_MSG_TYPE;
-#ifndef NOCACHE
- /* put the response into the lookaside buffer */
- if (!retval)
- kdc_insert_lookaside(pkt, response);
-#endif
-
- if (is_tcp == 0 && response != NULL &&
- response->length > max_dgram_reply_size) {
- too_big_for_udp:
- krb5_free_data(kdc_context, response);
- retval = make_too_big_error(&response);
- if (retval) {
- krb5_klog_syslog(LOG_ERR,
- "error constructing KRB_ERR_RESPONSE_TOO_BIG error: %s",
- error_message(retval));
- }
- }
- (*respond)(arg, retval, retval == 0 ? response : NULL);
+ finish_dispatch(state, retval, response);
}
static krb5_error_code
diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c
index 87bccdb59f..3351fdf342 100644
--- a/src/kdc/do_as_req.c
+++ b/src/kdc/do_as_req.c
@@ -99,9 +99,9 @@ get_key_exp(krb5_db_entry *entry)
}
/*ARGSUSED*/
-krb5_error_code
+void
process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
- const krb5_fulladdr *from, krb5_data **response)
+ const krb5_fulladdr *from, loop_respond_fn respond, void *arg)
{
krb5_db_entry *client = NULL, *server = NULL;
krb5_kdc_rep reply;
@@ -127,6 +127,7 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
struct kdc_request_state *state = NULL;
krb5_data encoded_req_body;
krb5_keyblock *as_encrypting_key = NULL;
+ krb5_data *response;
#if APPLE_PKINIT
@@ -593,7 +594,7 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
}
errcode = krb5_encode_kdc_rep(kdc_context, KRB5_AS_REP, &reply_encpart,
- 0, as_encrypting_key, &reply, response);
+ 0, as_encrypting_key, &reply, &response);
reply.enc_part.kvno = client_key->key_data_kvno;
if (errcode) {
status = "ENCODE_KDC_REP";
@@ -639,11 +640,12 @@ egress:
errcode = prepare_error_as(state, request, errcode, &e_data,
(client != NULL) ? client->princ : NULL,
- response, status);
+ &response, status);
status = 0;
}
-discard: if (emsg)
+discard:
+ if (emsg)
krb5_free_error_message(kdc_context, emsg);
if (enc_tkt_reply.authorization_data != NULL)
krb5_free_authdata(kdc_context, enc_tkt_reply.authorization_data);
@@ -676,7 +678,7 @@ discard: if (emsg)
krb5_free_kdc_req(kdc_context, request);
assert(did_log != 0);
- return errcode;
+ (*respond)(arg, errcode, response);
}
/*
diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h
index af6c32cfc0..368f0806af 100644
--- a/src/kdc/kdc_util.h
+++ b/src/kdc/kdc_util.h
@@ -118,10 +118,10 @@ void
rep_etypes2str(char *s, size_t len, krb5_kdc_rep *rep);
/* do_as_req.c */
-krb5_error_code
+void
process_as_req (krb5_kdc_req *, krb5_data *,
const krb5_fulladdr *,
- krb5_data ** );
+ loop_respond_fn, void *);
/* do_tgs_req.c */
krb5_error_code