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)
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 */
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;
* 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
}
/*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;
struct kdc_request_state *state = NULL;
krb5_data encoded_req_body;
krb5_keyblock *as_encrypting_key = NULL;
+ krb5_data *response;
#if APPLE_PKINIT
}
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";
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);
krb5_free_kdc_req(kdc_context, request);
assert(did_log != 0);
- return errcode;
+ (*respond)(arg, errcode, response);
}
/*