diff options
author | Greg Hudson <ghudson@mit.edu> | 2011-10-15 15:35:46 +0000 |
---|---|---|
committer | Greg Hudson <ghudson@mit.edu> | 2011-10-15 15:35:46 +0000 |
commit | 249e5254d4d4cff2bda07deafc25d7d87ea5ac0f (patch) | |
tree | 1671eafde44d27a5f1ab74c78f96fa85cdad98ae | |
parent | 5a9995350dbe2e6ab679d62e3d5074259ae2168a (diff) | |
download | krb5-249e5254d4d4cff2bda07deafc25d7d87ea5ac0f.tar.gz krb5-249e5254d4d4cff2bda07deafc25d7d87ea5ac0f.tar.xz krb5-249e5254d4d4cff2bda07deafc25d7d87ea5ac0f.zip |
Drop retransmits while processing requests
Supporting asynchronous preauth modules means that the KDC can receive
a retransmitted request before it finishes processing the initial
request. Ignore those retransmits instead of processing them.
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25350 dc483132-0cff-0310-8789-dd5450dbe970
-rw-r--r-- | src/kdc/dispatch.c | 29 | ||||
-rw-r--r-- | src/kdc/kdc_util.h | 1 | ||||
-rw-r--r-- | src/kdc/replay.c | 23 |
3 files changed, 46 insertions, 7 deletions
diff --git a/src/kdc/dispatch.c b/src/kdc/dispatch.c index 5f9c810e24..eeb95ff737 100644 --- a/src/kdc/dispatch.c +++ b/src/kdc/dispatch.c @@ -54,6 +54,11 @@ finish_dispatch(void *arg, krb5_error_code code, krb5_data *response) oldrespond = state->respond; oldarg = state->arg; +#ifndef NOCACHE + /* Remove our NULL cache entry to indicate request completion. */ + kdc_remove_lookaside(kdc_context, state->request); +#endif + if (state->is_tcp == 0 && response && response->length > max_dgram_reply_size) { krb5_free_data(kdc_context, response); @@ -67,7 +72,7 @@ finish_dispatch(void *arg, krb5_error_code code, krb5_data *response) #ifndef NOCACHE /* put the response into the lookaside buffer */ - else if (!code) + else if (!code && response) kdc_insert_lookaside(state->request, response); #endif @@ -104,20 +109,30 @@ 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) { + if (!response || 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); + if (response) + krb5_klog_syslog(LOG_INFO, + "DISPATCH: repeated (retransmitted?) request " + "from %s, resending previous response", name); + else + krb5_klog_syslog(LOG_INFO, + "DISPATCH: repeated (retransmitted?) request " + "from %s during request processing, dropping " + "repeated request", name); } - finish_dispatch(state, 0, response); + finish_dispatch(state, response ? 0 : KRB5KDC_ERR_DISCARD, response); return; } + + /* Insert a NULL entry into the lookaside to indicate that this request + * is currently being processed. */ + kdc_insert_lookaside(pkt, NULL); #endif retval = krb5_crypto_us_timeofday(&now, &now_usec); diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h index a31eec568d..bdeaa5f7db 100644 --- a/src/kdc/kdc_util.h +++ b/src/kdc/kdc_util.h @@ -236,6 +236,7 @@ handle_authdata (krb5_context context, /* replay.c */ krb5_boolean kdc_check_lookaside (krb5_data *, krb5_data **); void kdc_insert_lookaside (krb5_data *, krb5_data *); +void kdc_remove_lookaside (krb5_context kcontext, krb5_data *); void kdc_free_lookaside(krb5_context); /* kdc_util.c */ diff --git a/src/kdc/replay.c b/src/kdc/replay.c index 96c84807e0..63ff95ee2c 100644 --- a/src/kdc/replay.c +++ b/src/kdc/replay.c @@ -55,6 +55,29 @@ static int num_entries = 0; Todo: quench the size of the queue... */ +/* Removes the most recent cache entry for a given packet. */ +void +kdc_remove_lookaside(krb5_context kcontext, krb5_data *inpkt) +{ + register krb5_kdc_replay_ent *eptr, *last; + + if (!root_ptr.next) + return; + + for (last = &root_ptr, eptr = root_ptr.next; + eptr; + last = eptr, eptr = eptr->next) { + if (!MATCH(eptr)) + continue; + + last->next = eptr->next; + krb5_free_data(kcontext, eptr->req_packet); + krb5_free_data(kcontext, eptr->reply_packet); + free(eptr); + return; + } +} + /* return TRUE if outpkt is filled in with a packet to reply with, FALSE if the caller should do the work */ |