From 44518d20ff1957487590f2b09573bd37009fb783 Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Mon, 3 Oct 2011 19:13:57 +0000 Subject: [PATCH] Make do_as_req() respond via a callback From npmccallum@redhat.com with changes. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25292 dc483132-0cff-0310-8789-dd5450dbe970 --- src/kdc/dispatch.c | 104 +++++++++++++++++++++++++++++--------------- src/kdc/do_as_req.c | 14 +++--- src/kdc/kdc_util.h | 4 +- 3 files changed, 80 insertions(+), 42 deletions(-) diff --git a/src/kdc/dispatch.c b/src/kdc/dispatch.c index cb09c62ff..5f9c810e2 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 87bccdb59..3351fdf34 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 af6c32cfc..368f0806a 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 -- 2.26.2