1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* kdc/replay.c - Replay lookaside cache for the KDC, to avoid extra work */
4 * Copyright 1991 by the Massachusetts Institute of Technology.
7 * Export of this software from the United States of America may
8 * require a specific license from the United States Government.
9 * It is the responsibility of any person or organization contemplating
10 * export to obtain such a license before exporting.
12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13 * distribute this software and its documentation for any purpose and
14 * without fee is hereby granted, provided that the above copyright
15 * notice appear in all copies and that both that copyright notice and
16 * this permission notice appear in supporting documentation, and that
17 * the name of M.I.T. not be used in advertising or publicity pertaining
18 * to distribution of the software without specific, written prior
19 * permission. Furthermore if you modify this software you must label
20 * your software as modified software and not distribute it in such a
21 * fashion that it might be confused with the original M.I.T. software.
22 * M.I.T. makes no representations about the suitability of
23 * this software for any purpose. It is provided "as is" without express
24 * or implied warranty.
33 typedef struct _krb5_kdc_replay_ent {
34 struct _krb5_kdc_replay_ent *next;
37 krb5_data *req_packet;
38 krb5_data *reply_packet;
39 } krb5_kdc_replay_ent;
41 static krb5_kdc_replay_ent root_ptr = {0};
45 static int max_hits_per_entry = 0;
46 static int num_entries = 0;
48 #define STALE_TIME 2*60 /* two minutes */
49 #define STALE(ptr) (abs((ptr)->timein - timenow) >= STALE_TIME)
51 #define MATCH(ptr) (((ptr)->req_packet->length == inpkt->length) && \
52 !memcmp((ptr)->req_packet->data, inpkt->data, \
55 Todo: quench the size of the queue...
58 /* Removes the most recent cache entry for a given packet. */
60 kdc_remove_lookaside(krb5_context kcontext, krb5_data *inpkt)
62 register krb5_kdc_replay_ent *eptr, *last;
67 for (last = &root_ptr, eptr = root_ptr.next;
69 last = eptr, eptr = eptr->next) {
73 last->next = eptr->next;
74 krb5_free_data(kcontext, eptr->req_packet);
75 krb5_free_data(kcontext, eptr->reply_packet);
81 /* return TRUE if outpkt is filled in with a packet to reply with,
82 FALSE if the caller should do the work */
85 kdc_check_lookaside(krb5_data *inpkt, krb5_data **outpkt)
88 register krb5_kdc_replay_ent *eptr, *last, *hold;
90 if (krb5_timeofday(kdc_context, &timenow))
95 /* search for a replay entry in the queue, possibly removing
96 stale entries while we're here */
99 for (last = &root_ptr, eptr = root_ptr.next;
106 if (krb5_copy_data(kdc_context, eptr->reply_packet, outpkt))
110 /* return here, don't bother flushing even if it is stale.
111 if we just matched, we may get another retransmit... */
114 /* flush it and collect stats */
115 max_hits_per_entry = max(max_hits_per_entry, eptr->num_hits);
116 krb5_free_data(kdc_context, eptr->req_packet);
117 krb5_free_data(kdc_context, eptr->reply_packet);
119 last->next = eptr->next;
123 /* this isn't it, just move along */
131 /* insert a request & reply into the lookaside queue. assumes it's not
132 already there, and can fail softly due to other weird errors. */
135 kdc_insert_lookaside(krb5_data *inpkt, krb5_data *outpkt)
137 register krb5_kdc_replay_ent *eptr;
140 if (krb5_timeofday(kdc_context, &timenow))
143 /* this is a new entry */
144 eptr = (krb5_kdc_replay_ent *)calloc(1, sizeof(*eptr));
147 eptr->timein = timenow;
149 * This is going to hurt a lot malloc()-wise due to the need to
150 * allocate memory for the krb5_data and krb5_address elements.
153 if (krb5_copy_data(kdc_context, inpkt, &eptr->req_packet)) {
157 if (krb5_copy_data(kdc_context, outpkt, &eptr->reply_packet)) {
158 krb5_free_data(kdc_context, eptr->req_packet);
162 eptr->next = root_ptr.next;
163 root_ptr.next = eptr;
168 /* frees memory associated with the lookaside queue for memory profiling */
170 kdc_free_lookaside(krb5_context kcontext)
172 register krb5_kdc_replay_ent *eptr, *last, *hold;
174 for (last = &root_ptr, eptr = root_ptr.next;
175 eptr; eptr = eptr->next) {
176 krb5_free_data(kcontext, eptr->req_packet);
177 krb5_free_data(kcontext, eptr->reply_packet);
179 last->next = eptr->next;