krb5 commit: Eliminate some KDC globals

Tom Yu tlyu at MIT.EDU
Mon Oct 15 20:27:43 EDT 2012


https://github.com/krb5/krb5/commit/0a2f14f752c32a24200363cc6b6ae64a92f81379
commit 0a2f14f752c32a24200363cc6b6ae64a92f81379
Author: Tom Yu <tlyu at mit.edu>
Date:   Fri Sep 7 20:18:41 2012 -0400

    Eliminate some KDC globals
    
    Make kdc_active_realm a local variable in every function that needs
    it.  Pass it around in various state structures as needed.  Keep the
    macros that reference its members remain for now.

 src/kdc/dispatch.c            |   48 +++++++---
 src/kdc/do_as_req.c           |   34 +++++---
 src/kdc/do_tgs_req.c          |   74 +++++++++------
 src/kdc/extern.c              |    2 +-
 src/kdc/extern.h              |   68 --------------
 src/kdc/fast_util.c           |   32 +++++--
 src/kdc/kdc_preauth.c         |   22 +++---
 src/kdc/kdc_util.c            |  196 +++++++++++++++++++++-------------------
 src/kdc/kdc_util.h            |   64 +++++--------
 src/kdc/main.c                |   85 ++++++++++--------
 src/kdc/realm_data.h          |  107 ++++++++++++++++++++++
 src/kdc/replay.c              |   20 +++--
 src/kdc/reqstate.h            |   53 +++++++++++
 src/kdc/rtest.c               |    7 ++-
 src/lib/apputils/net-server.c |    4 +-
 15 files changed, 489 insertions(+), 327 deletions(-)

diff --git a/src/kdc/dispatch.c b/src/kdc/dispatch.c
index e3f43bc..68c67f4 100644
--- a/src/kdc/dispatch.c
+++ b/src/kdc/dispatch.c
@@ -28,19 +28,23 @@
 #include "kdc_util.h"
 #include "extern.h"
 #include "adm_proto.h"
+#include "realm_data.h"
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <string.h>
 
 static krb5_int32 last_usec = 0, last_os_random = 0;
 
-static krb5_error_code make_too_big_error (krb5_data **out);
+static krb5_error_code make_too_big_error(kdc_realm_t *kdc_active_realm,
+                                          krb5_data **out);
 
 struct dispatch_state {
     loop_respond_fn respond;
     void *arg;
     krb5_data *request;
     int is_tcp;
+    kdc_realm_t *active_realm;
+    krb5_context kdc_err_context;
 };
 
 static void
@@ -49,12 +53,13 @@ finish_dispatch(struct dispatch_state *state, krb5_error_code code,
 {
     loop_respond_fn oldrespond = state->respond;
     void *oldarg = state->arg;
+    kdc_realm_t *kdc_active_realm = state->active_realm;
 
     if (state->is_tcp == 0 && response &&
         response->length > (unsigned int)max_dgram_reply_size) {
         krb5_free_data(kdc_context, response);
         response = NULL;
-        code = make_too_big_error(&response);
+        code = make_too_big_error(kdc_active_realm, &response);
         if (code)
             krb5_klog_syslog(LOG_ERR, "error constructing "
                              "KRB_ERR_RESPONSE_TOO_BIG error: %s",
@@ -69,16 +74,17 @@ static void
 finish_dispatch_cache(void *arg, krb5_error_code code, krb5_data *response)
 {
     struct dispatch_state *state = arg;
+    krb5_context kdc_err_context = state->kdc_err_context;
 
 #ifndef NOCACHE
     /* Remove the null cache entry unless we actually want to discard this
      * request. */
     if (code != KRB5KDC_ERR_DISCARD)
-        kdc_remove_lookaside(kdc_context, state->request);
+        kdc_remove_lookaside(kdc_err_context, state->request);
 
     /* Put the response into the lookaside buffer (if we produced one). */
     if (code == 0 && response != NULL)
-        kdc_insert_lookaside(state->request, response);
+        kdc_insert_lookaside(kdc_err_context, state->request, response);
 #endif
 
     finish_dispatch(state, code, response);
@@ -94,6 +100,8 @@ dispatch(void *cb, struct sockaddr *local_saddr,
     krb5_int32 now, now_usec;
     krb5_data *response = NULL;
     struct dispatch_state *state;
+    struct server_handle *handle = cb;
+    krb5_context kdc_err_context = handle->kdc_err_context;
 
     state = k5alloc(sizeof(*state), &retval);
     if (state == NULL) {
@@ -104,12 +112,13 @@ dispatch(void *cb, struct sockaddr *local_saddr,
     state->arg = arg;
     state->request = pkt;
     state->is_tcp = is_tcp;
+    state->kdc_err_context = kdc_err_context;
 
     /* decode incoming packet, and dispatch */
 
 #ifndef NOCACHE
     /* try the replay lookaside buffer */
-    if (kdc_check_lookaside(pkt, &response)) {
+    if (kdc_check_lookaside(kdc_err_context, pkt, &response)) {
         /* a hit! */
         const char *name = 0;
         char buf[46];
@@ -134,7 +143,7 @@ dispatch(void *cb, struct sockaddr *local_saddr,
 
     /* Insert a NULL entry into the lookaside to indicate that this request
      * is currently being processed. */
-    kdc_insert_lookaside(pkt, NULL);
+    kdc_insert_lookaside(kdc_err_context, pkt, NULL);
 #endif
 
     retval = krb5_crypto_us_timeofday(&now, &now_usec);
@@ -145,21 +154,21 @@ dispatch(void *cb, struct sockaddr *local_saddr,
             last_os_random = now;
         /* Grab random data from OS every hour*/
         if(now-last_os_random >= 60*60) {
-            krb5_c_random_os_entropy(kdc_context, 0, NULL);
+            krb5_c_random_os_entropy(kdc_err_context, 0, NULL);
             last_os_random = now;
         }
 
         data.length = sizeof(krb5_int32);
         data.data = (void *) &usec_difference;
 
-        krb5_c_random_add_entropy(kdc_context,
+        krb5_c_random_add_entropy(kdc_err_context,
                                   KRB5_C_RANDSOURCE_TIMING, &data);
         last_usec = now_usec;
     }
     /* try TGS_REQ first; they are more common! */
 
     if (krb5_is_tgs_req(pkt)) {
-        retval = process_tgs_req(pkt, from, &response);
+        retval = process_tgs_req(handle, pkt, from, &response);
     } else if (krb5_is_as_req(pkt)) {
         if (!(retval = decode_krb5_as_req(pkt, &as_req))) {
             /*
@@ -167,13 +176,15 @@ dispatch(void *cb, struct sockaddr *local_saddr,
              * pointer.
              * process_as_req frees the request if it is called
              */
-            if (!(retval = setup_server_realm(as_req->server))) {
-                process_as_req(as_req, pkt, from, vctx, finish_dispatch_cache,
-                               state);
+            state->active_realm = setup_server_realm(handle, as_req->server);
+            if (state->active_realm != NULL) {
+                process_as_req(as_req, pkt, from, state->active_realm, vctx,
+                               finish_dispatch_cache, state);
                 return;
+            } else {
+                retval = KRB5KDC_ERR_WRONG_REALM;
+                krb5_free_kdc_req(kdc_err_context, as_req);
             }
-            else
-                krb5_free_kdc_req(kdc_context, as_req);
         }
     } else
         retval = KRB5KRB_AP_ERR_MSG_TYPE;
@@ -182,7 +193,7 @@ dispatch(void *cb, struct sockaddr *local_saddr,
 }
 
 static krb5_error_code
-make_too_big_error (krb5_data **out)
+make_too_big_error(kdc_realm_t *kdc_active_realm, krb5_data **out)
 {
     krb5_error errpkt;
     krb5_error_code retval;
@@ -213,3 +224,10 @@ make_too_big_error (krb5_data **out)
     *out = scratch;
     return 0;
 }
+
+krb5_context get_context(void *handle)
+{
+    struct server_handle *sh = handle;
+
+    return sh->kdc_err_context;
+}
diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c
index 4ca712d..79da300 100644
--- a/src/kdc/do_as_req.c
+++ b/src/kdc/do_as_req.c
@@ -119,6 +119,8 @@ struct as_req_state {
     const krb5_fulladdr *from;
 
     krb5_error_code preauth_err;
+
+    kdc_realm_t *active_realm;
 };
 
 static void
@@ -134,6 +136,7 @@ finish_process_as_req(struct as_req_state *state, krb5_error_code errcode)
     krb5_enctype useenctype;
     loop_respond_fn oldrespond;
     void *oldarg;
+    kdc_realm_t *kdc_active_realm = state->active_realm;
 
     assert(state);
     oldrespond = state->respond;
@@ -315,7 +318,7 @@ finish_process_as_req(struct as_req_state *state, krb5_error_code errcode)
            state->reply.enc_part.ciphertext.length);
     free(state->reply.enc_part.ciphertext.data);
 
-    log_as_req(state->from, state->request, &state->reply,
+    log_as_req(kdc_context, state->from, state->request, &state->reply,
                state->client, state->cname, state->server,
                state->sname, state->authtime, 0, 0, 0);
     did_log = 1;
@@ -330,7 +333,8 @@ egress:
         emsg = krb5_get_error_message(kdc_context, errcode);
 
     if (state->status) {
-        log_as_req(state->from, state->request, &state->reply, state->client,
+        log_as_req(kdc_context,
+                   state->from, state->request, &state->reply, state->client,
                    state->cname, state->server, state->sname, state->authtime,
                    state->status, errcode, emsg);
         did_log = 1;
@@ -438,8 +442,8 @@ finish_preauth(void *arg, krb5_error_code code)
 /*ARGSUSED*/
 void
 process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
-               const krb5_fulladdr *from, verto_ctx *vctx,
-               loop_respond_fn respond, void *arg)
+               const krb5_fulladdr *from, kdc_realm_t *kdc_active_realm,
+               verto_ctx *vctx, loop_respond_fn respond, void *arg)
 {
     krb5_error_code errcode;
     krb5_timestamp rtime;
@@ -458,17 +462,18 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
     state->request = request;
     state->req_pkt = req_pkt;
     state->from = from;
+    state->active_realm = kdc_active_realm;
 
+    errcode = kdc_make_rstate(kdc_active_realm, &state->rstate);
+    if (errcode != 0) {
+        (*respond)(arg, errcode, NULL);
+        return;
+    }
     if (state->request->msg_type != KRB5_AS_REQ) {
         state->status = "msg_type mismatch";
         errcode = KRB5_BADMSGTYPE;
         goto errout;
     }
-    errcode = kdc_make_rstate(&state->rstate);
-    if (errcode != 0) {
-        state->status = "constructing state";
-        goto errout;
-    }
     if (fetch_asn1_field((unsigned char *) req_pkt->data,
                          1, 4, &encoded_req_body) != 0) {
         errcode = ASN1_BAD_ID;
@@ -558,7 +563,7 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
      * If the backend returned a principal that is not in the local
      * realm, then we need to refer the client to that realm.
      */
-    if (!is_local_principal(state->client->princ)) {
+    if (!is_local_principal(kdc_active_realm, state->client->princ)) {
         /* Entry is a referral to another realm */
         state->status = "REFERRAL";
         errcode = KRB5KDC_ERR_WRONG_REALM;
@@ -589,7 +594,8 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
     }
     state->authtime = state->kdc_time; /* for audit_as_request() */
 
-    if ((errcode = validate_as_request(state->request, *state->client,
+    if ((errcode = validate_as_request(kdc_active_realm,
+                                       state->request, *state->client,
                                        *state->server, state->kdc_time,
                                        &state->status, &state->e_data))) {
         if (!state->status)
@@ -601,7 +607,7 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
     /*
      * Select the keytype for the ticket session key.
      */
-    if ((useenctype = select_session_keytype(kdc_context, state->server,
+    if ((useenctype = select_session_keytype(kdc_active_realm, state->server,
                                              state->request->nktypes,
                                              state->request->ktype)) == 0) {
         /* unsupported ktype */
@@ -669,7 +675,8 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
     } else
         state->enc_tkt_reply.times.starttime = state->kdc_time;
 
-    kdc_get_ticket_endtime(kdc_context, state->enc_tkt_reply.times.starttime,
+    kdc_get_ticket_endtime(kdc_active_realm,
+                           state->enc_tkt_reply.times.starttime,
                            kdc_infinity, state->request->till, state->client,
                            state->server, &state->enc_tkt_reply.times.endtime);
 
@@ -759,6 +766,7 @@ prepare_error_as (struct kdc_request_state *rstate, krb5_kdc_req *request,
     krb5_error errpkt;
     krb5_error_code retval;
     krb5_data *scratch = NULL, *e_data_asn1 = NULL, *fast_edata = NULL;
+    kdc_realm_t *kdc_active_realm = rstate->realm_data;
 
     errpkt.ctime = request->nonce;
     errpkt.cusec = 0;
diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c
index 8a6d93c..c45fe87 100644
--- a/src/kdc/do_tgs_req.c
+++ b/src/kdc/do_tgs_req.c
@@ -69,19 +69,21 @@
 #include <ctype.h>
 
 static krb5_error_code
-find_alternate_tgs(krb5_kdc_req *,krb5_db_entry **);
+find_alternate_tgs(struct kdc_request_state *, krb5_kdc_req *,
+                   krb5_db_entry **);
 
 static krb5_error_code
 prepare_error_tgs(struct kdc_request_state *, krb5_kdc_req *,krb5_ticket *,int,
                   krb5_principal,krb5_data **,const char *, krb5_pa_data **);
 
 static krb5_int32
-prep_reprocess_req(krb5_kdc_req *,krb5_principal *);
+prep_reprocess_req(struct kdc_request_state *, krb5_kdc_req *,
+                   krb5_principal *);
 
 /*ARGSUSED*/
 krb5_error_code
-process_tgs_req(krb5_data *pkt, const krb5_fulladdr *from,
-                krb5_data **response)
+process_tgs_req(struct server_handle *handle, krb5_data *pkt,
+                const krb5_fulladdr *from, krb5_data **response)
 {
     krb5_keyblock * subkey = 0;
     krb5_keyblock * tgskey = 0;
@@ -124,6 +126,7 @@ process_tgs_req(krb5_data *pkt, const krb5_fulladdr *from,
     krb5_pa_data *pa_tgs_req; /*points into request*/
     krb5_data scratch;
     krb5_pa_data **e_data = NULL;
+    kdc_realm_t *kdc_active_realm = NULL;
 
     reply.padata = 0; /* For cleanup handler */
     reply_encpart.enc_padata = 0;
@@ -135,18 +138,25 @@ process_tgs_req(krb5_data *pkt, const krb5_fulladdr *from,
     if (retval)
         return retval;
     if (request->msg_type != KRB5_TGS_REQ) {
-        krb5_free_kdc_req(kdc_context, request);
+        krb5_free_kdc_req(handle->kdc_err_context, request);
         return KRB5_BADMSGTYPE;
     }
 
     /*
      * setup_server_realm() sets up the global realm-specific data pointer.
      */
-    if ((retval = setup_server_realm(request->server))) {
-        krb5_free_kdc_req(kdc_context, request);
-        return retval;
+    kdc_active_realm = setup_server_realm(handle, request->server);
+    if (kdc_active_realm == NULL) {
+        krb5_free_kdc_req(handle->kdc_err_context, request);
+        return KRB5KDC_ERR_WRONG_REALM;
+    }
+    errcode = kdc_make_rstate(kdc_active_realm, &state);
+    if (errcode !=0) {
+        krb5_free_kdc_req(handle->kdc_err_context, request);
+        return errcode;
     }
-    errcode = kdc_process_tgs_req(request, from, pkt, &header_ticket,
+    errcode = kdc_process_tgs_req(kdc_active_realm,
+                                  request, from, pkt, &header_ticket,
                                   &krbtgt, &tgskey, &subkey, &pa_tgs_req);
     if (header_ticket && header_ticket->enc_part2 &&
         (errcode2 = krb5_unparse_name(kdc_context,
@@ -168,11 +178,6 @@ process_tgs_req(krb5_data *pkt, const krb5_fulladdr *from,
         status="UNEXPECTED NULL in header_ticket";
         goto cleanup;
     }
-    errcode = kdc_make_rstate(&state);
-    if (errcode !=0) {
-        status = "making state";
-        goto cleanup;
-    }
     scratch.length = pa_tgs_req->length;
     scratch.data = (char *) pa_tgs_req->contents;
     errcode = kdc_find_fast(&request, &scratch, subkey,
@@ -238,7 +243,7 @@ tgt_again:
                     tgs_1 = krb5_princ_component(kdc_context, tgs_server, 1);
 
                     if (!tgs_1 || !data_eq(*server_1, *tgs_1)) {
-                        errcode = find_alternate_tgs(request, &server);
+                        errcode = find_alternate_tgs(state, request, &server);
                         firstpass = 0;
                         if (errcode == 0)
                             goto tgt_again;
@@ -249,7 +254,7 @@ tgt_again:
                 goto cleanup;
 
             } else if ( db_ref_done == FALSE) {
-                retval = prep_reprocess_req(request, &krbtgt_princ);
+                retval = prep_reprocess_req(state, request, &krbtgt_princ);
                 if (!retval) {
                     krb5_free_principal(kdc_context, request->server);
                     request->server = NULL;
@@ -275,7 +280,8 @@ tgt_again:
         goto cleanup;
     }
 
-    if ((retval = validate_tgs_request(request, *server, header_ticket,
+    if ((retval = validate_tgs_request(kdc_active_realm,
+                                       request, *server, header_ticket,
                                        kdc_time, &status, &e_data))) {
         if (!status)
             status = "UNKNOWN_REASON";
@@ -283,14 +289,14 @@ tgt_again:
         goto cleanup;
     }
 
-    if (!is_local_principal(header_enc_tkt->client))
+    if (!is_local_principal(kdc_active_realm, header_enc_tkt->client))
         setflag(c_flags, KRB5_KDB_FLAG_CROSS_REALM);
 
     is_referral = krb5_is_tgs_principal(server->princ) &&
         !krb5_principal_compare(kdc_context, tgs_server, server->princ);
 
     /* Check for protocol transition */
-    errcode = kdc_process_s4u2self_req(kdc_context,
+    errcode = kdc_process_s4u2self_req(kdc_active_realm,
                                        request,
                                        header_enc_tkt->client,
                                        server,
@@ -327,7 +333,8 @@ tgt_again:
         /*
          * Get the key for the second ticket, and decrypt it.
          */
-        if ((errcode = kdc_get_server_key(request->second_ticket[st_idx],
+        if ((errcode = kdc_get_server_key(kdc_context,
+                                          request->second_ticket[st_idx],
                                           c_flags,
                                           TRUE, /* match_enctype */
                                           &st_client,
@@ -362,7 +369,7 @@ tgt_again:
 
         if (isflagset(request->kdc_options, KDC_OPT_CNAME_IN_ADDL_TKT)) {
             /* Do constrained delegation protocol and authorization checks */
-            errcode = kdc_process_s4u2proxy_req(kdc_context,
+            errcode = kdc_process_s4u2proxy_req(kdc_active_realm,
                                                 request,
                                                 request->second_ticket[st_idx]->enc_part2,
                                                 st_client,
@@ -388,7 +395,7 @@ tgt_again:
      * Select the keytype for the ticket session key.
      */
     if ((useenctype == 0) &&
-        (useenctype = select_session_keytype(kdc_context, server,
+        (useenctype = select_session_keytype(kdc_active_realm, server,
                                              request->nktypes,
                                              request->ktype)) == 0) {
         /* unsupported ktype */
@@ -545,7 +552,7 @@ tgt_again:
         /* not a renew request */
         enc_tkt_reply.times.starttime = kdc_time;
 
-        kdc_get_ticket_endtime(kdc_context, enc_tkt_reply.times.starttime,
+        kdc_get_ticket_endtime(kdc_active_realm, enc_tkt_reply.times.starttime,
                                header_enc_tkt->times.endtime, request->till,
                                client, server, &enc_tkt_reply.times.endtime);
 
@@ -702,8 +709,9 @@ tgt_again:
      * listed).
      */
     /* realm compare is like strcmp, but knows how to deal with these args */
-    if (realm_compare(header_ticket->server, tgs_server) ||
-        realm_compare(header_ticket->server, enc_tkt_reply.client)) {
+    if (krb5_realm_compare(kdc_context, header_ticket->server, tgs_server) ||
+        krb5_realm_compare(kdc_context, header_ticket->server,
+                           enc_tkt_reply.client)) {
         /* tgt issued by local realm or issued by realm of client */
         enc_tkt_reply.transited = header_enc_tkt->transited;
     } else {
@@ -744,7 +752,7 @@ tgt_again:
         unsigned int tlen;
         char *tdots;
 
-        errcode = kdc_check_transited_list (kdc_context,
+        errcode = kdc_check_transited_list (kdc_active_realm,
                                             &enc_tkt_reply.transited.tr_contents,
                                             krb5_princ_realm (kdc_context, header_enc_tkt->client),
                                             krb5_princ_realm (kdc_context, request->server));
@@ -825,7 +833,8 @@ tgt_again:
     /* Start assembling the response */
     reply.msg_type = KRB5_TGS_REP;
     if (isflagset(c_flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION) &&
-        find_pa_data(request->padata, KRB5_PADATA_S4U_X509_USER) != NULL) {
+        krb5int_find_pa_data(kdc_context, request->padata,
+                             KRB5_PADATA_S4U_X509_USER) != NULL) {
         errcode = kdc_make_s4u2self_rep(kdc_context,
                                         subkey,
                                         header_ticket->enc_part2->session,
@@ -987,6 +996,7 @@ prepare_error_tgs (struct kdc_request_state *state,
     krb5_error errpkt;
     krb5_error_code retval = 0;
     krb5_data *scratch, *e_data_asn1 = NULL, *fast_edata = NULL;
+    kdc_realm_t *kdc_active_realm = state->realm_data;
 
     errpkt.ctime = request->nonce;
     errpkt.cusec = 0;
@@ -1050,12 +1060,14 @@ prepare_error_tgs (struct kdc_request_state *state,
  * some intermediate realm.
  */
 static krb5_error_code
-find_alternate_tgs(krb5_kdc_req *request, krb5_db_entry **server_ptr)
+find_alternate_tgs(struct kdc_request_state *state,
+                   krb5_kdc_req *request, krb5_db_entry **server_ptr)
 {
     krb5_error_code retval;
     krb5_principal *plist = NULL, *pl2, tmpprinc;
     krb5_data tmp;
     krb5_db_entry *server = NULL;
+    kdc_realm_t *kdc_active_realm = state->realm_data;
 
     *server_ptr = NULL;
 
@@ -1100,7 +1112,7 @@ find_alternate_tgs(krb5_kdc_req *request, krb5_db_entry **server_ptr)
 
         krb5_free_principal(kdc_context, request->server);
         request->server = tmpprinc;
-        log_tgs_alt_tgt(request->server);
+        log_tgs_alt_tgt(kdc_context, request->server);
         *server_ptr = server;
         server = NULL;
         goto cleanup;
@@ -1114,12 +1126,14 @@ cleanup:
 }
 
 static krb5_int32
-prep_reprocess_req(krb5_kdc_req *request, krb5_principal *krbtgt_princ)
+prep_reprocess_req(struct kdc_request_state *state, krb5_kdc_req *request,
+                   krb5_principal *krbtgt_princ)
 {
     krb5_error_code retval = KRB5KRB_AP_ERR_BADMATCH;
     char **realms, **cpp, *temp_buf=NULL;
     krb5_data *comp1 = NULL, *comp2 = NULL;
     char *comp1_str = NULL;
+    kdc_realm_t *kdc_active_realm = state->realm_data;
 
     /* By now we know that server principal name is unknown.
      * If CANONICALIZE flag is set in the request
diff --git a/src/kdc/extern.c b/src/kdc/extern.c
index 7307bfc..fe62749 100644
--- a/src/kdc/extern.c
+++ b/src/kdc/extern.c
@@ -31,11 +31,11 @@
 #include "k5-int.h"
 #include "kdb.h"
 #include "extern.h"
+#include "realm_data.h"
 
 /* real declarations of KDC's externs */
 kdc_realm_t     **kdc_realmlist = (kdc_realm_t **) NULL;
 int             kdc_numrealms = 0;
-kdc_realm_t     *kdc_active_realm = (kdc_realm_t *) NULL;
 krb5_data empty_string = {0, 0, ""};
 krb5_timestamp kdc_infinity = KRB5_INT32_MAX; /* XXX */
 krb5_keyblock   psr_key;
diff --git a/src/kdc/extern.h b/src/kdc/extern.h
index c601e57..7dc658f 100644
--- a/src/kdc/extern.h
+++ b/src/kdc/extern.h
@@ -26,74 +26,6 @@
 #ifndef __KRB5_KDC_EXTERN__
 #define __KRB5_KDC_EXTERN__
 
-typedef struct __kdc_realm_data {
-    /*
-     * General Kerberos per-realm data.
-     */
-    char *              realm_name;     /* Realm name                       */
-/* XXX the real context should go away once the db_context is done.
- * The db_context is then associated with the realm keytab using
- * krb5_ktkdb_resolv(). There should be nothing in the context which
- * cannot span multiple realms -- proven */
-    krb5_context        realm_context;  /* Context to be used for realm     */
-    krb5_keytab         realm_keytab;   /* keytab to be used for this realm */
-    char *              realm_profile;  /* Profile file for this realm      */
-    char *              realm_host_based_services; /* do referral processing for these services
-                                                    * If '*' - allow all referrals */
-    char *              realm_no_host_referral; /* no referral for these services.
-                                                 * If '*' - disallow all referrals and
-                                                 * ignore realm_host_based_services */
-    /*
-     * Database per-realm data.
-     */
-    char *              realm_stash;    /* Stash file name for realm        */
-    char *              realm_mpname;   /* Master principal name for realm  */
-    krb5_principal      realm_mprinc;   /* Master principal for realm       */
-    /*
-     * Note realm_mkey is mkey read from stash or keyboard and may not be the
-     * latest.
-     */
-    krb5_keyblock       realm_mkey;     /* Master key for this realm        */
-    /*
-     * TGS per-realm data.
-     */
-    krb5_principal      realm_tgsprinc; /* TGS principal for this realm     */
-    /*
-     * Other per-realm data.
-     */
-    char                *realm_ports;   /* Per-realm KDC UDP port */
-    char                *realm_tcp_ports; /* Per-realm KDC TCP port */
-    /*
-     * Per-realm parameters.
-     */
-    krb5_deltat         realm_maxlife;  /* Maximum ticket life for realm    */
-    krb5_deltat         realm_maxrlife; /* Maximum renewable life for realm */
-    krb5_boolean        realm_reject_bad_transit; /* Accept unverifiable transited_realm ? */
-    krb5_boolean        realm_restrict_anon;  /* Anon to local TGT only */
-    krb5_boolean        realm_assume_des_crc_sess;  /* Assume princs support des-cbc-crc for session keys */
-} kdc_realm_t;
-
-extern kdc_realm_t      **kdc_realmlist;
-extern int              kdc_numrealms;
-extern kdc_realm_t      *kdc_active_realm;
-
-kdc_realm_t *find_realm_data (char *, krb5_ui_4);
-
-/*
- * Replace previously used global variables with the active (e.g. request's)
- * realm data.  This allows us to support multiple realms with minimal logic
- * changes.
- */
-#define kdc_context                     kdc_active_realm->realm_context
-#define max_life_for_realm              kdc_active_realm->realm_maxlife
-#define max_renewable_life_for_realm    kdc_active_realm->realm_maxrlife
-#define master_keyblock                 kdc_active_realm->realm_mkey
-#define master_princ                    kdc_active_realm->realm_mprinc
-#define tgs_server                      kdc_active_realm->realm_tgsprinc
-#define reject_bad_transit              kdc_active_realm->realm_reject_bad_transit
-#define restrict_anon                   kdc_active_realm->realm_restrict_anon
-#define assume_des_crc_sess             kdc_active_realm->realm_assume_des_crc_sess
-
 /* various externs for KDC */
 extern krb5_data        empty_string;   /* an empty string */
 extern krb5_timestamp   kdc_infinity;   /* greater than all other timestamps */
diff --git a/src/kdc/fast_util.c b/src/kdc/fast_util.c
index f3e037d..1ce27d6 100644
--- a/src/kdc/fast_util.c
+++ b/src/kdc/fast_util.c
@@ -46,6 +46,7 @@ static krb5_error_code armor_ap_request
     krb5_auth_context authcontext = NULL;
     krb5_ticket *ticket = NULL;
     krb5_keyblock *subkey = NULL;
+    kdc_realm_t *kdc_active_realm = state->realm_data;
 
     assert(armor->armor_type == KRB5_FAST_ARMOR_AP_REQUEST);
     krb5_clear_error_message(kdc_context);
@@ -103,6 +104,8 @@ encrypt_fast_reply(struct kdc_request_state *state,
     krb5_error_code retval = 0;
     krb5_enc_data encrypted_reply;
     krb5_data *encoded_response = NULL;
+    kdc_realm_t *kdc_active_realm = state->realm_data;
+
     assert(state->armor_key);
     retval = encode_krb5_fast_response(response, &encoded_response);
     if (retval== 0)
@@ -138,14 +141,15 @@ kdc_find_fast(krb5_kdc_req **requestptr,
     krb5_checksum *cksum;
     krb5_boolean cksum_valid;
     krb5_keyblock empty_keyblock;
+    kdc_realm_t *kdc_active_realm = state->realm_data;
 
     if (inner_body_out != NULL)
         *inner_body_out = NULL;
     scratch.data = NULL;
     krb5_clear_error_message(kdc_context);
     memset(&empty_keyblock, 0, sizeof(krb5_keyblock));
-    fast_padata = find_pa_data(request->padata,
-                               KRB5_PADATA_FX_FAST);
+    fast_padata = krb5int_find_pa_data(kdc_context,
+                                       request->padata, KRB5_PADATA_FX_FAST);
     if (fast_padata !=  NULL){
         scratch.length = fast_padata->length;
         scratch.data = (char *) fast_padata->contents;
@@ -230,8 +234,9 @@ kdc_find_fast(krb5_kdc_req **requestptr,
                 retval = KRB5KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTION;
         }
         if (retval == 0)
-            cookie_padata = find_pa_data(fast_req->req_body->padata,
-                                         KRB5_PADATA_FX_COOKIE);
+            cookie_padata = krb5int_find_pa_data(kdc_context,
+                                                 fast_req->req_body->padata,
+                                                 KRB5_PADATA_FX_COOKIE);
         if (retval == 0) {
             state->fast_options = fast_req->fast_options;
             krb5_free_kdc_req( kdc_context, request);
@@ -239,7 +244,11 @@ kdc_find_fast(krb5_kdc_req **requestptr,
             fast_req->req_body = NULL;
         }
     }
-    else cookie_padata = find_pa_data(request->padata, KRB5_PADATA_FX_COOKIE);
+    else {
+        cookie_padata = krb5int_find_pa_data(kdc_context,
+                                             request->padata,
+                                             KRB5_PADATA_FX_COOKIE);
+    }
     if (retval == 0 && cookie_padata != NULL) {
         krb5_pa_data *new_padata = malloc(sizeof (krb5_pa_data));
         if (new_padata == NULL) {
@@ -272,12 +281,13 @@ kdc_find_fast(krb5_kdc_req **requestptr,
 
 
 krb5_error_code
-kdc_make_rstate(struct kdc_request_state **out)
+kdc_make_rstate(kdc_realm_t *active_realm, struct kdc_request_state **out)
 {
     struct kdc_request_state *state = malloc( sizeof(struct kdc_request_state));
     if (state == NULL)
         return ENOMEM;
     memset( state, 0, sizeof(struct kdc_request_state));
+    state->realm_data = active_realm;
     *out = state;
     return 0;
 }
@@ -285,6 +295,8 @@ kdc_make_rstate(struct kdc_request_state **out)
 void
 kdc_free_rstate (struct kdc_request_state *s)
 {
+    kdc_realm_t *kdc_active_realm = s->realm_data;
+
     if (s == NULL)
         return;
     if (s->armor_key)
@@ -312,6 +324,7 @@ kdc_fast_response_handle_padata(struct kdc_request_state *state,
     krb5_cksumtype cksumtype = CKSUMTYPE_RSA_MD5;
     krb5_pa_data *empty_padata[] = {NULL};
     krb5_keyblock *strengthen_key = NULL;
+    kdc_realm_t *kdc_active_realm = state->realm_data;
 
     if (!state->armor_key)
         return 0;
@@ -401,6 +414,7 @@ kdc_fast_handle_error(krb5_context context,
     krb5_pa_data *outer_pa[3], *cookie = NULL;
     krb5_pa_data **inner_pa = NULL;
     size_t size = 0;
+    kdc_realm_t *kdc_active_realm = state->realm_data;
 
     *fast_edata_out = NULL;
     memset(outer_pa, 0, sizeof(outer_pa));
@@ -424,7 +438,8 @@ kdc_fast_handle_error(krb5_context context,
         pa[0].length = encoded_fx_error->length;
         pa[0].contents = (unsigned char *) encoded_fx_error->data;
         inner_pa[size++] = &pa[0];
-        if (find_pa_data(inner_pa, KRB5_PADATA_FX_COOKIE) == NULL)
+        if (krb5int_find_pa_data(kdc_context,
+                                 inner_pa, KRB5_PADATA_FX_COOKIE) == NULL)
             retval = kdc_preauth_get_cookie(state, &cookie);
     }
     if (cookie != NULL)
@@ -464,6 +479,8 @@ kdc_fast_handle_reply_key(struct kdc_request_state *state,
                           krb5_keyblock **out_key)
 {
     krb5_error_code retval = 0;
+    kdc_realm_t *kdc_active_realm = state->realm_data;
+
     if (state->armor_key)
         retval = krb5_c_fx_cf2_simple(kdc_context,
                                       state->strengthen_key, "strengthenkey",
@@ -481,6 +498,7 @@ kdc_preauth_get_cookie(struct kdc_request_state *state,
 {
     char *contents;
     krb5_pa_data *pa = NULL;
+
     /* In our current implementation, the only purpose served by
      * returning a cookie is to indicate that a conversation should
      * continue on error.  Thus, the cookie can have a constant
diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c
index 5ca3676..19998d8 100644
--- a/src/kdc/kdc_preauth.c
+++ b/src/kdc/kdc_preauth.c
@@ -269,23 +269,23 @@ cleanup:
 /* Make a list of realm names.  The caller should free the list container but
  * not the list elements (which are aliases into kdc_realmlist). */
 static krb5_error_code
-get_realm_names(const char ***list_out)
+get_realm_names(struct server_handle *handle, const char ***list_out)
 {
     const char **list;
     int i;
 
-    list = calloc(kdc_numrealms + 1, sizeof(*list));
+    list = calloc(handle->kdc_numrealms + 1, sizeof(*list));
     if (list == NULL)
         return ENOMEM;
-    for (i = 0; i < kdc_numrealms; i++)
-        list[i] = kdc_realmlist[i]->realm_name;
+    for (i = 0; i < handle->kdc_numrealms; i++)
+        list[i] = handle->kdc_realmlist[i]->realm_name;
     list[i] = NULL;
     *list_out = list;
     return 0;
 }
 
 void
-load_preauth_plugins(krb5_context context)
+load_preauth_plugins(struct server_handle *handle, krb5_context context)
 {
     krb5_error_code ret;
     struct krb5_kdcpreauth_vtable_st *vtables = NULL, *vt;
@@ -303,7 +303,7 @@ load_preauth_plugins(krb5_context context)
     if (preauth_systems == NULL)
         goto cleanup;
 
-    if (get_realm_names(&realm_names))
+    if (get_realm_names(handle, &realm_names))
         goto cleanup;
 
     /* Add the static system to the list first.  No static systems require
@@ -718,6 +718,7 @@ hint_list_finish(struct hint_state *state, krb5_error_code code)
 {
     kdc_hint_respond_fn oldrespond = state->respond;
     void *oldarg = state->arg;
+    kdc_realm_t *kdc_active_realm = state->realm;
 
     if (!code) {
         if (state->pa_data[0] == 0) {
@@ -746,7 +747,6 @@ finish_get_edata(void *arg, krb5_error_code code, krb5_pa_data *pa)
 {
     struct hint_state *state = arg;
 
-    kdc_active_realm = state->realm;
     if (code == 0) {
         if (pa == NULL) {
             /* Include an empty value of the current type. */
@@ -765,6 +765,7 @@ static void
 hint_list_next(struct hint_state *state)
 {
     preauth_system *ap = state->ap;
+    kdc_realm_t *kdc_active_realm = state->realm;
 
     if (ap->type == -1) {
         hint_list_finish(state, 0);
@@ -810,7 +811,7 @@ get_preauth_hint_list(krb5_kdc_req *request, krb5_kdcpreauth_rock rock,
     state->arg = arg;
     state->request = request;
     state->rock = rock;
-    state->realm = kdc_active_realm;
+    state->realm = rock->rstate->realm_data;
     state->e_data_out = e_data_out;
 
     /* Allocate two extra entries for the cookie and the terminator. */
@@ -986,7 +987,6 @@ finish_verify_padata(void *arg, krb5_error_code code,
     krb5_boolean typed_e_data_flag;
 
     assert(state);
-    kdc_active_realm = state->realm; /* Restore the realm. */
     *state->modreq_ptr = modreq;
 
     if (code) {
@@ -1135,7 +1135,7 @@ check_padata(krb5_context context, krb5_kdcpreauth_rock rock,
     state->padata_context = padata_context;
     state->e_data_out = e_data;
     state->typed_e_data_out = typed_e_data;
-    state->realm = kdc_active_realm;
+    state->realm = rock->rstate->realm_data;
 
 #ifdef DEBUG
     krb5_klog_syslog (LOG_DEBUG, "checking padata");
@@ -1663,7 +1663,7 @@ return_enc_padata(krb5_context context, krb5_data *req_pkt,
         if (code)
             return code;
     }
-    code = kdc_handle_protected_negotiation(req_pkt, request, reply_key,
+    code = kdc_handle_protected_negotiation(context, req_pkt, request, reply_key,
                                             &reply_encpart->enc_padata);
     if (code)
         goto cleanup;
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
index 4f6ce6f..773d8cf 100644
--- a/src/kdc/kdc_util.c
+++ b/src/kdc/kdc_util.c
@@ -68,12 +68,14 @@ const int vague_errors = 1;
 const int vague_errors = 0;
 #endif
 
-static krb5_error_code kdc_rd_ap_req(krb5_ap_req *apreq,
+static krb5_error_code kdc_rd_ap_req(kdc_realm_t *kdc_active_realm,
+                                     krb5_ap_req *apreq,
                                      krb5_auth_context auth_context,
                                      krb5_db_entry **server,
                                      krb5_keyblock **tgskey,
                                      krb5_ticket **ticket);
-static krb5_error_code find_server_key(krb5_db_entry *, krb5_enctype,
+static krb5_error_code find_server_key(krb5_context,
+                                       krb5_db_entry *, krb5_enctype,
                                        krb5_kvno, krb5_keyblock **,
                                        krb5_kvno *);
 
@@ -82,7 +84,8 @@ static krb5_error_code find_server_key(krb5_db_entry *, krb5_enctype,
  * The replacement should be freed with krb5_free_authdata().
  */
 krb5_error_code
-concat_authorization_data(krb5_authdata **first, krb5_authdata **second,
+concat_authorization_data(krb5_context context,
+                          krb5_authdata **first, krb5_authdata **second,
                           krb5_authdata ***output)
 {
     register int i, j;
@@ -106,7 +109,7 @@ concat_authorization_data(krb5_authdata **first, krb5_authdata **second,
             /* now walk & copy */
             retdata[i] = (krb5_authdata *)malloc(sizeof(*retdata[i]));
             if (!retdata[i]) {
-                krb5_free_authdata(kdc_context, retdata);
+                krb5_free_authdata(context, retdata);
                 return ENOMEM;
             }
             *retdata[i] = **ptr;
@@ -114,7 +117,7 @@ concat_authorization_data(krb5_authdata **first, krb5_authdata **second,
                   (krb5_octet *)malloc(retdata[i]->length))) {
                 free(retdata[i]);
                 retdata[i] = 0;
-                krb5_free_authdata(kdc_context, retdata);
+                krb5_free_authdata(context, retdata);
                 return ENOMEM;
             }
             memcpy(retdata[i]->contents, (*ptr)->contents, retdata[i]->length);
@@ -127,13 +130,7 @@ concat_authorization_data(krb5_authdata **first, krb5_authdata **second,
 }
 
 krb5_boolean
-realm_compare(krb5_const_principal princ1, krb5_const_principal princ2)
-{
-    return krb5_realm_compare(kdc_context, princ1, princ2);
-}
-
-krb5_boolean
-is_local_principal(krb5_const_principal princ1)
+is_local_principal(kdc_realm_t *kdc_active_realm, krb5_const_principal princ1)
 {
     return krb5_realm_compare(kdc_context, princ1, tgs_server);
 }
@@ -197,14 +194,9 @@ comp_cksum(krb5_context kcontext, krb5_data *source, krb5_ticket *ticket,
     return(0);
 }
 
-krb5_pa_data *
-find_pa_data(krb5_pa_data **padata, krb5_preauthtype pa_type)
-{
-    return krb5int_find_pa_data(kdc_context, padata, pa_type);
-}
-
 krb5_error_code
-kdc_process_tgs_req(krb5_kdc_req *request, const krb5_fulladdr *from,
+kdc_process_tgs_req(kdc_realm_t *kdc_active_realm,
+                    krb5_kdc_req *request, const krb5_fulladdr *from,
                     krb5_data *pkt, krb5_ticket **ticket,
                     krb5_db_entry **krbtgt_ptr,
                     krb5_keyblock **tgskey,
@@ -226,7 +218,8 @@ kdc_process_tgs_req(krb5_kdc_req *request, const krb5_fulladdr *from,
     *krbtgt_ptr = NULL;
     *tgskey = NULL;
 
-    tmppa = find_pa_data(request->padata, KRB5_PADATA_AP_REQ);
+    tmppa = krb5int_find_pa_data(kdc_context,
+                                 request->padata, KRB5_PADATA_AP_REQ);
     if (!tmppa)
         return KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
 
@@ -252,7 +245,8 @@ kdc_process_tgs_req(krb5_kdc_req *request, const krb5_fulladdr *from,
 
        we set a flag here for checking below.
     */
-    foreign_server = !is_local_principal(apreq->ticket->server);
+    foreign_server = !is_local_principal(kdc_active_realm,
+                                         apreq->ticket->server);
 
     if ((retval = krb5_auth_con_init(kdc_context, &auth_context)))
         goto cleanup;
@@ -265,7 +259,8 @@ kdc_process_tgs_req(krb5_kdc_req *request, const krb5_fulladdr *from,
                                          from->address)) )
         goto cleanup_auth_context;
 
-    retval = kdc_rd_ap_req(apreq, auth_context, &krbtgt, tgskey, ticket);
+    retval = kdc_rd_ap_req(kdc_active_realm,
+                           apreq, auth_context, &krbtgt, tgskey, ticket);
     if (retval)
         goto cleanup_auth_context;
 
@@ -308,8 +303,10 @@ kdc_process_tgs_req(krb5_kdc_req *request, const krb5_fulladdr *from,
 
     /* make sure the client is of proper lineage (see above) */
     if (foreign_server &&
-        !find_pa_data(request->padata, KRB5_PADATA_FOR_USER)) {
-        if (is_local_principal((*ticket)->enc_part2->client)) {
+        !krb5int_find_pa_data(kdc_context,
+                              request->padata, KRB5_PADATA_FOR_USER)) {
+        if (is_local_principal(kdc_active_realm,
+                               (*ticket)->enc_part2->client)) {
             /* someone in a foreign realm claiming to be local */
             krb5_klog_syslog(LOG_INFO, _("PROCESS_TGS: failed lineage check"));
             retval = KRB5KDC_ERR_POLICY;
@@ -369,7 +366,8 @@ cleanup:
  */
 static
 krb5_error_code
-kdc_rd_ap_req(krb5_ap_req *apreq, krb5_auth_context auth_context,
+kdc_rd_ap_req(kdc_realm_t *kdc_active_realm,
+              krb5_ap_req *apreq, krb5_auth_context auth_context,
               krb5_db_entry **server, krb5_keyblock **tgskey,
               krb5_ticket **ticket)
 {
@@ -391,7 +389,8 @@ kdc_rd_ap_req(krb5_ap_req *apreq, krb5_auth_context auth_context,
         match_enctype = 0;
     }
 
-    retval = kdc_get_server_key(apreq->ticket, 0, match_enctype, server, NULL,
+    retval = kdc_get_server_key(kdc_context,
+                                apreq->ticket, 0, match_enctype, server, NULL,
                                 NULL);
     if (retval)
         return retval;
@@ -400,7 +399,8 @@ kdc_rd_ap_req(krb5_ap_req *apreq, krb5_auth_context auth_context,
     kvno = apreq->ticket->enc_part.kvno;
     do {
         krb5_free_keyblock(kdc_context, *tgskey);
-        retval = find_server_key(*server, search_enctype, kvno, tgskey, &kvno);
+        retval = find_server_key(kdc_context,
+                                 *server, search_enctype, kvno, tgskey, &kvno);
         if (retval)
             continue;
 
@@ -429,7 +429,8 @@ kdc_rd_ap_req(krb5_ap_req *apreq, krb5_auth_context auth_context,
  * This is also used by do_tgs_req() for u2u auth.
  */
 krb5_error_code
-kdc_get_server_key(krb5_ticket *ticket, unsigned int flags,
+kdc_get_server_key(krb5_context context,
+                   krb5_ticket *ticket, unsigned int flags,
                    krb5_boolean match_enctype, krb5_db_entry **server_ptr,
                    krb5_keyblock **key, krb5_kvno *kvno)
 {
@@ -445,11 +446,11 @@ kdc_get_server_key(krb5_ticket *ticket, unsigned int flags,
 
     *server_ptr = NULL;
 
-    retval = krb5_db_get_principal(kdc_context, ticket->server, flags,
+    retval = krb5_db_get_principal(context, ticket->server, flags,
                                    &server);
     if (retval == KRB5_KDB_NOENTRY) {
         char *sname;
-        if (!krb5_unparse_name(kdc_context, ticket->server, &sname)) {
+        if (!krb5_unparse_name(context, ticket->server, &sname)) {
             limit_string(sname);
             krb5_klog_syslog(LOG_ERR,
                              _("TGS_REQ: UNKNOWN SERVER: server='%s'"), sname);
@@ -465,7 +466,8 @@ kdc_get_server_key(krb5_ticket *ticket, unsigned int flags,
     }
 
     if (key) {
-        retval = find_server_key(server, search_enctype, search_kvno, key, kvno);
+        retval = find_server_key(context, server, search_enctype, search_kvno,
+                                 key, kvno);
         if (retval)
             goto errout;
     }
@@ -474,7 +476,7 @@ kdc_get_server_key(krb5_ticket *ticket, unsigned int flags,
     return 0;
 
 errout:
-    krb5_db_free_principal(kdc_context, server);
+    krb5_db_free_principal(context, server);
     return retval;
 }
 
@@ -484,7 +486,8 @@ errout:
  */
 static
 krb5_error_code
-find_server_key(krb5_db_entry *server, krb5_enctype enctype, krb5_kvno kvno,
+find_server_key(krb5_context context,
+                krb5_db_entry *server, krb5_enctype enctype, krb5_kvno kvno,
                 krb5_keyblock **key_out, krb5_kvno *kvno_out)
 {
     krb5_error_code       retval;
@@ -492,7 +495,7 @@ find_server_key(krb5_db_entry *server, krb5_enctype enctype, krb5_kvno kvno,
     krb5_keyblock       * key;
 
     *key_out = NULL;
-    retval = krb5_dbe_find_enctype(kdc_context, server, enctype, -1,
+    retval = krb5_dbe_find_enctype(context, server, enctype, -1,
                                    kvno ? (krb5_int32)kvno : -1, &server_key);
     if (retval)
         return retval;
@@ -500,13 +503,13 @@ find_server_key(krb5_db_entry *server, krb5_enctype enctype, krb5_kvno kvno,
         return KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
     if ((key = (krb5_keyblock *)malloc(sizeof *key)) == NULL)
         return ENOMEM;
-    retval = krb5_dbe_decrypt_key_data(kdc_context, NULL, server_key,
+    retval = krb5_dbe_decrypt_key_data(context, NULL, server_key,
                                        key, NULL);
     if (retval)
         goto errout;
     if (enctype != -1) {
         krb5_boolean similar;
-        retval = krb5_c_enctype_compare(kdc_context, enctype, key->enctype,
+        retval = krb5_c_enctype_compare(context, enctype, key->enctype,
                                         &similar);
         if (retval)
             goto errout;
@@ -521,7 +524,7 @@ find_server_key(krb5_db_entry *server, krb5_enctype enctype, krb5_kvno kvno,
     if (kvno_out)
         *kvno_out = server_key->key_data_kvno;
 errout:
-    krb5_free_keyblock(kdc_context, key);
+    krb5_free_keyblock(context, key);
     return retval;
 }
 
@@ -940,14 +943,15 @@ errcode_to_protocol(krb5_error_code code)
 /* Return -1 if the AS or TGS request is disallowed due to KDC policy on
  * anonymous tickets. */
 static int
-check_anon(krb5_context context, krb5_principal client, krb5_principal server)
+check_anon(kdc_realm_t *kdc_active_realm,
+           krb5_principal client, krb5_principal server)
 {
     /* If restrict_anon is set, reject requests from anonymous to principals
      * other than the local TGT. */
     if (restrict_anon &&
-        krb5_principal_compare_any_realm(context, client,
+        krb5_principal_compare_any_realm(kdc_context, client,
                                          krb5_anonymous_principal()) &&
-        !krb5_principal_compare(context, server, tgs_server))
+        !krb5_principal_compare(kdc_context, server, tgs_server))
         return -1;
     return 0;
 }
@@ -962,7 +966,8 @@ check_anon(krb5_context context, krb5_principal client, krb5_principal server)
                             KDC_OPT_VALIDATE | KDC_OPT_RENEW |          \
                             KDC_OPT_ENC_TKT_IN_SKEY | KDC_OPT_CNAME_IN_ADDL_TKT)
 int
-validate_as_request(register krb5_kdc_req *request, krb5_db_entry client,
+validate_as_request(kdc_realm_t *kdc_active_realm,
+                    register krb5_kdc_req *request, krb5_db_entry client,
                     krb5_db_entry server, krb5_timestamp kdc_time,
                     const char **status, krb5_pa_data ***e_data)
 {
@@ -1071,7 +1076,7 @@ validate_as_request(register krb5_kdc_req *request, krb5_db_entry client,
         return(KDC_ERR_MUST_USE_USER2USER);
     }
 
-    if (check_anon(kdc_context, request->client, request->server) != 0) {
+    if (check_anon(kdc_active_realm, request->client, request->server) != 0) {
         *status = "ANONYMOUS NOT ALLOWED";
         return(KDC_ERR_POLICY);
     }
@@ -1265,7 +1270,8 @@ fetch_asn1_field(unsigned char *astream, unsigned int level,
                        KDC_OPT_VALIDATE)
 
 int
-validate_tgs_request(register krb5_kdc_req *request, krb5_db_entry server,
+validate_tgs_request(kdc_realm_t *kdc_active_realm,
+                     register krb5_kdc_req *request, krb5_db_entry server,
                      krb5_ticket *ticket, krb5_timestamp kdc_time,
                      const char **status, krb5_pa_data ***e_data)
 {
@@ -1498,7 +1504,7 @@ validate_tgs_request(register krb5_kdc_req *request, krb5_db_entry server,
         return KRB_ERR_GENERIC;
     }
 
-    if (check_anon(kdc_context, ticket->enc_part2->client,
+    if (check_anon(kdc_active_realm, ticket->enc_part2->client,
                    request->server) != 0) {
         *status = "ANONYMOUS NOT ALLOWED";
         return(KDC_ERR_POLICY);
@@ -1522,7 +1528,7 @@ validate_tgs_request(register krb5_kdc_req *request, krb5_db_entry server,
 
 /* Return true if we believe server can support enctype as a session key. */
 static krb5_boolean
-dbentry_supports_enctype(krb5_context context, krb5_db_entry *server,
+dbentry_supports_enctype(kdc_realm_t *kdc_active_realm, krb5_db_entry *server,
                          krb5_enctype enctype)
 {
     krb5_error_code     retval;
@@ -1533,11 +1539,12 @@ dbentry_supports_enctype(krb5_context context, krb5_db_entry *server,
     krb5_boolean        in_list;
 
     /* Look up the supported session key enctypes list in the KDB. */
-    retval = krb5_dbe_get_string(context, server, KRB5_KDB_SK_SESSION_ENCTYPES,
+    retval = krb5_dbe_get_string(kdc_context, server,
+                                 KRB5_KDB_SK_SESSION_ENCTYPES,
                                  &etypes_str);
     if (retval == 0 && etypes_str != NULL && *etypes_str != '\0') {
         /* Pass a fake profile key for tracing of unrecognized tokens. */
-        retval = krb5int_parse_enctype_list(context, "KDB-session_etypes",
+        retval = krb5int_parse_enctype_list(kdc_context, "KDB-session_etypes",
                                             etypes_str, default_enctypes,
                                             &etypes);
         if (retval == 0 && etypes != NULL && etypes[0]) {
@@ -1562,7 +1569,7 @@ dbentry_supports_enctype(krb5_context context, krb5_db_entry *server,
         return FALSE;
 
     /* Assume the server supports any enctype it has a long-term key for. */
-    return !krb5_dbe_find_enctype(context, server, enctype, -1, 0, &datap);
+    return !krb5_dbe_find_enctype(kdc_context, server, enctype, -1, 0, &datap);
 }
 
 /*
@@ -1571,7 +1578,7 @@ dbentry_supports_enctype(krb5_context context, krb5_db_entry *server,
  * requested, and what the KDC and the application server can support.
  */
 krb5_enctype
-select_session_keytype(krb5_context context, krb5_db_entry *server,
+select_session_keytype(kdc_realm_t *kdc_active_realm, krb5_db_entry *server,
                        int nktypes, krb5_enctype *ktype)
 {
     int         i;
@@ -1580,10 +1587,10 @@ select_session_keytype(krb5_context context, krb5_db_entry *server,
         if (!krb5_c_valid_enctype(ktype[i]))
             continue;
 
-        if (!krb5_is_permitted_enctype(context, ktype[i]))
+        if (!krb5_is_permitted_enctype(kdc_context, ktype[i]))
             continue;
 
-        if (dbentry_supports_enctype(context, server, ktype[i]))
+        if (dbentry_supports_enctype(kdc_active_realm, server, ktype[i]))
             return ktype[i];
     }
 
@@ -1765,7 +1772,7 @@ verify_for_user_checksum(krb5_context context,
  * Legacy protocol transition (Windows 2003 and above)
  */
 static krb5_error_code
-kdc_process_for_user(krb5_context context,
+kdc_process_for_user(kdc_realm_t *kdc_active_realm,
                      krb5_pa_data *pa_data,
                      krb5_keyblock *tgs_session,
                      krb5_pa_s4u_x509_user **s4u_x509_user,
@@ -1782,7 +1789,7 @@ kdc_process_for_user(krb5_context context,
     if (code)
         return code;
 
-    code = verify_for_user_checksum(context, tgs_session, for_user);
+    code = verify_for_user_checksum(kdc_context, tgs_session, for_user);
     if (code) {
         *status = "INVALID_S4U2SELF_CHECKSUM";
         krb5_free_pa_for_user(kdc_context, for_user);
@@ -1797,7 +1804,7 @@ kdc_process_for_user(krb5_context context,
 
     (*s4u_x509_user)->user_id.user = for_user->user;
     for_user->user = NULL;
-    krb5_free_pa_for_user(context, for_user);
+    krb5_free_pa_for_user(kdc_context, for_user);
 
     return 0;
 }
@@ -2008,7 +2015,7 @@ cleanup:
  * Protocol transition (S4U2Self)
  */
 krb5_error_code
-kdc_process_s4u2self_req(krb5_context context,
+kdc_process_s4u2self_req(kdc_realm_t *kdc_active_realm,
                          krb5_kdc_req *request,
                          krb5_const_principal client_princ,
                          const krb5_db_entry *server,
@@ -2026,9 +2033,10 @@ kdc_process_s4u2self_req(krb5_context context,
 
     *princ_ptr = NULL;
 
-    pa_data = find_pa_data(request->padata, KRB5_PADATA_S4U_X509_USER);
+    pa_data = krb5int_find_pa_data(kdc_context,
+                                   request->padata, KRB5_PADATA_S4U_X509_USER);
     if (pa_data != NULL) {
-        code = kdc_process_s4u_x509_user(context,
+        code = kdc_process_s4u_x509_user(kdc_context,
                                          request,
                                          pa_data,
                                          tgs_subkey,
@@ -2038,9 +2046,10 @@ kdc_process_s4u2self_req(krb5_context context,
         if (code != 0)
             return code;
     } else {
-        pa_data = find_pa_data(request->padata, KRB5_PADATA_FOR_USER);
+        pa_data = krb5int_find_pa_data(kdc_context,
+                                       request->padata, KRB5_PADATA_FOR_USER);
         if (pa_data != NULL) {
-            code = kdc_process_for_user(context,
+            code = kdc_process_for_user(kdc_active_realm,
                                         pa_data,
                                         tgs_session,
                                         s4u_x509_user,
@@ -2078,9 +2087,9 @@ kdc_process_s4u2self_req(krb5_context context,
      * the TGT and that we have a global name service.
      */
     flags = 0;
-    switch (krb5_princ_type(context, request->server)) {
+    switch (krb5_princ_type(kdc_context, request->server)) {
     case KRB5_NT_SRV_HST:                   /* (1) */
-        if (krb5_princ_size(context, request->server) == 2)
+        if (krb5_princ_size(kdc_context, request->server) == 2)
             flags |= KRB5_PRINCIPAL_COMPARE_IGNORE_REALM;
         break;
     case KRB5_NT_ENTERPRISE_PRINCIPAL:      /* (2) */
@@ -2090,7 +2099,7 @@ kdc_process_s4u2self_req(krb5_context context,
         break;
     }
 
-    if (!krb5_principal_compare_flags(context,
+    if (!krb5_principal_compare_flags(kdc_context,
                                       request->server,
                                       client_princ,
                                       flags)) {
@@ -2114,11 +2123,13 @@ kdc_process_s4u2self_req(krb5_context context,
     /*
      * Do not attempt to lookup principals in foreign realms.
      */
-    if (is_local_principal((*s4u_x509_user)->user_id.user)) {
+    if (is_local_principal(kdc_active_realm,
+                           (*s4u_x509_user)->user_id.user)) {
         krb5_db_entry no_server;
         krb5_pa_data **e_data = NULL;
 
-        code = krb5_db_get_principal(context, (*s4u_x509_user)->user_id.user,
+        code = krb5_db_get_principal(kdc_context,
+                                     (*s4u_x509_user)->user_id.user,
                                      KRB5_KDB_FLAG_INCLUDE_PAC, &princ);
         if (code == KRB5_KDB_NOENTRY) {
             *status = "UNKNOWN_S4U2SELF_PRINCIPAL";
@@ -2130,11 +2141,11 @@ kdc_process_s4u2self_req(krb5_context context,
 
         memset(&no_server, 0, sizeof(no_server));
 
-        code = validate_as_request(request, *princ,
+        code = validate_as_request(kdc_active_realm, request, *princ,
                                    no_server, kdc_time, status, &e_data);
         if (code) {
-            krb5_db_free_principal(context, princ);
-            krb5_free_pa_data(context, e_data);
+            krb5_db_free_principal(kdc_context, princ);
+            krb5_free_pa_data(kdc_context, e_data);
             return code;
         }
 
@@ -2161,7 +2172,7 @@ check_allowed_to_delegate_to(krb5_context context, krb5_const_principal client,
 }
 
 krb5_error_code
-kdc_process_s4u2proxy_req(krb5_context context,
+kdc_process_s4u2proxy_req(kdc_realm_t *kdc_active_realm,
                           krb5_kdc_req *request,
                           const krb5_enc_tkt_part *t2enc,
                           const krb5_db_entry *server,
@@ -2206,7 +2217,7 @@ kdc_process_s4u2proxy_req(krb5_context context,
 }
 
 krb5_error_code
-kdc_check_transited_list(krb5_context context,
+kdc_check_transited_list(kdc_realm_t *kdc_active_realm,
                          const krb5_data *trans,
                          const krb5_data *realm1,
                          const krb5_data *realm2)
@@ -2219,7 +2230,7 @@ kdc_check_transited_list(krb5_context context,
         return code;
 
     /* Check against the KDB module. */
-    code = krb5_db_check_transited_realms(context, trans, realm1, realm2);
+    code = krb5_db_check_transited_realms(kdc_context, trans, realm1, realm2);
     if (code == KRB5_PLUGIN_OP_NOTSUPP)
         code = 0;
     return code;
@@ -2258,7 +2269,7 @@ validate_transit_path(krb5_context context,
 /* Someday, pass local address/port as well.  */
 /* Currently no info about name canonicalization is logged.  */
 void
-log_as_req(const krb5_fulladdr *from,
+log_as_req(krb5_context context, const krb5_fulladdr *from,
            krb5_kdc_req *request, krb5_kdc_rep *reply,
            krb5_db_entry *client, const char *cname,
            krb5_db_entry *server, const char *sname,
@@ -2293,7 +2304,7 @@ log_as_req(const krb5_fulladdr *from,
                          ktypestr, fromstring, status,
                          cname2, sname2, emsg ? ", " : "", emsg ? emsg : "");
     }
-    krb5_db_audit_as_req(kdc_context, request, client, server, authtime,
+    krb5_db_audit_as_req(context, request, client, server, authtime,
                          errcode);
 #if 0
     /* Sun (OpenSolaris) version would probably something like this.
@@ -2369,10 +2380,10 @@ log_tgs_req(const krb5_fulladdr *from,
 }
 
 void
-log_tgs_alt_tgt(krb5_principal p)
+log_tgs_alt_tgt(krb5_context context, krb5_principal p)
 {
     char *sname;
-    if (krb5_unparse_name(kdc_context, p, &sname)) {
+    if (krb5_unparse_name(context, p, &sname)) {
         krb5_klog_syslog(LOG_INFO,
                          _("TGS_REQ: issuing alternate <un-unparseable> TGT"));
     } else {
@@ -2444,7 +2455,7 @@ add_pa_data_element(krb5_context context,
 }
 
 void
-kdc_get_ticket_endtime(krb5_context context,
+kdc_get_ticket_endtime(kdc_realm_t *kdc_active_realm,
                        krb5_timestamp starttime,
                        krb5_timestamp endtime,
                        krb5_timestamp till,
@@ -2480,7 +2491,8 @@ kdc_get_ticket_endtime(krb5_context context,
  * @param index in/out index into @c out_enc_padata for next item
  */
 krb5_error_code
-kdc_handle_protected_negotiation(krb5_data *req_pkt, krb5_kdc_req *request,
+kdc_handle_protected_negotiation(krb5_context context,
+                                 krb5_data *req_pkt, krb5_kdc_req *request,
                                  const krb5_keyblock *reply_key,
                                  krb5_pa_data ***out_enc_padata)
 {
@@ -2488,14 +2500,14 @@ kdc_handle_protected_negotiation(krb5_data *req_pkt, krb5_kdc_req *request,
     krb5_checksum checksum;
     krb5_data *out = NULL;
     krb5_pa_data pa, *pa_in;
-    pa_in = krb5int_find_pa_data(kdc_context, request->padata,
+    pa_in = krb5int_find_pa_data(context, request->padata,
                                  KRB5_ENCPADATA_REQ_ENC_PA_REP);
     if (pa_in == NULL)
         return 0;
     pa.magic = KV5M_PA_DATA;
     pa.pa_type = KRB5_ENCPADATA_REQ_ENC_PA_REP;
     memset(&checksum, 0, sizeof(checksum));
-    retval = krb5_c_make_checksum(kdc_context,0, reply_key,
+    retval = krb5_c_make_checksum(context,0, reply_key,
                                   KRB5_KEYUSAGE_AS_REQ, req_pkt, &checksum);
     if (retval != 0)
         goto cleanup;
@@ -2504,7 +2516,7 @@ kdc_handle_protected_negotiation(krb5_data *req_pkt, krb5_kdc_req *request,
         goto cleanup;
     pa.contents = (krb5_octet *) out->data;
     pa.length = out->length;
-    retval = add_pa_data_element(kdc_context, &pa, out_enc_padata, FALSE);
+    retval = add_pa_data_element(context, &pa, out_enc_padata, FALSE);
     if (retval)
         goto cleanup;
     out->data = NULL;
@@ -2512,12 +2524,12 @@ kdc_handle_protected_negotiation(krb5_data *req_pkt, krb5_kdc_req *request,
     pa.pa_type = KRB5_PADATA_FX_FAST;
     pa.length = 0;
     pa.contents = NULL;
-    retval = add_pa_data_element(kdc_context, &pa, out_enc_padata, FALSE);
+    retval = add_pa_data_element(context, &pa, out_enc_padata, FALSE);
 cleanup:
     if (checksum.contents)
-        krb5_free_checksum_contents(kdc_context, &checksum);
+        krb5_free_checksum_contents(context, &checksum);
     if (out != NULL)
-        krb5_free_data(kdc_context, out);
+        krb5_free_data(context, out);
     return retval;
 }
 
@@ -2590,12 +2602,14 @@ make_toolong_error (void *handle, krb5_data **out)
     krb5_error errpkt;
     krb5_error_code retval;
     krb5_data *scratch;
+    struct server_handle *h = handle;
 
-    retval = krb5_us_timeofday(kdc_context, &errpkt.stime, &errpkt.susec);
+    retval = krb5_us_timeofday(h->kdc_err_context,
+                               &errpkt.stime, &errpkt.susec);
     if (retval)
         return retval;
     errpkt.error = KRB_ERR_FIELD_TOOLONG;
-    errpkt.server = tgs_server;
+    errpkt.server = h->kdc_realmlist[0]->realm_tgsprinc;
     errpkt.client = NULL;
     errpkt.cusec = 0;
     errpkt.ctime = 0;
@@ -2606,7 +2620,7 @@ make_toolong_error (void *handle, krb5_data **out)
     scratch = malloc(sizeof(*scratch));
     if (scratch == NULL)
         return ENOMEM;
-    retval = krb5_mk_error(kdc_context, &errpkt, scratch);
+    retval = krb5_mk_error(h->kdc_err_context, &errpkt, scratch);
     if (retval) {
         free(scratch);
         return retval;
@@ -2616,15 +2630,11 @@ make_toolong_error (void *handle, krb5_data **out)
     return 0;
 }
 
-krb5_context get_context(void *handle)
-{
-    return kdc_context;
-}
-
-void reset_for_hangup()
+void reset_for_hangup(void *ctx)
 {
     int k;
+    struct server_handle *h = ctx;
 
-    for (k = 0; k < kdc_numrealms; k++)
-        krb5_db_refresh_config(kdc_realmlist[k]->realm_context);
+    for (k = 0; k < h->kdc_numrealms; k++)
+        krb5_db_refresh_config(h->kdc_realmlist[k]->realm_context);
 }
diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h
index 0cd7989..2f215a7 100644
--- a/src/kdc/kdc_util.h
+++ b/src/kdc/kdc_util.h
@@ -32,10 +32,12 @@
 
 #include "kdb.h"
 #include "net-server.h"
+#include "realm_data.h"
+#include "reqstate.h"
 
 krb5_error_code check_hot_list (krb5_ticket *);
-krb5_boolean realm_compare (krb5_const_principal, krb5_const_principal);
-krb5_boolean is_local_principal(krb5_const_principal princ1);
+krb5_boolean is_local_principal(kdc_realm_t *kdc_active_realm,
+                                krb5_const_principal princ1);
 krb5_boolean krb5_is_tgs_principal (krb5_const_principal);
 krb5_boolean is_cross_tgs_principal(krb5_const_principal);
 krb5_error_code
@@ -49,7 +51,8 @@ compress_transited (krb5_data *,
                     krb5_principal,
                     krb5_data *);
 krb5_error_code
-concat_authorization_data (krb5_authdata **,
+concat_authorization_data (krb5_context,
+                           krb5_authdata **,
                            krb5_authdata **,
                            krb5_authdata ***);
 krb5_error_code
@@ -58,7 +61,7 @@ fetch_last_req_info (krb5_db_entry *, krb5_last_req_entry ***);
 krb5_error_code
 kdc_convert_key (krb5_keyblock *, krb5_keyblock *, int);
 krb5_error_code
-kdc_process_tgs_req (krb5_kdc_req *,
+kdc_process_tgs_req (kdc_realm_t *, krb5_kdc_req *,
                      const krb5_fulladdr *,
                      krb5_data *,
                      krb5_ticket **,
@@ -67,12 +70,12 @@ kdc_process_tgs_req (krb5_kdc_req *,
                      krb5_pa_data **pa_tgs_req);
 
 krb5_error_code
-kdc_get_server_key (krb5_ticket *, unsigned int,
+kdc_get_server_key (krb5_context, krb5_ticket *, unsigned int,
                     krb5_boolean match_enctype,
                     krb5_db_entry **, krb5_keyblock **, krb5_kvno *);
 
 int
-validate_as_request (krb5_kdc_req *, krb5_db_entry,
+validate_as_request (kdc_realm_t *, krb5_kdc_req *, krb5_db_entry,
                      krb5_db_entry, krb5_timestamp,
                      const char **, krb5_pa_data ***);
 
@@ -82,7 +85,7 @@ validate_forwardable(krb5_kdc_req *, krb5_db_entry,
                      const char **);
 
 int
-validate_tgs_request (krb5_kdc_req *, krb5_db_entry,
+validate_tgs_request (kdc_realm_t *, krb5_kdc_req *, krb5_db_entry,
                       krb5_ticket *, krb5_timestamp,
                       const char **, krb5_pa_data ***);
 
@@ -90,7 +93,7 @@ int
 fetch_asn1_field (unsigned char *, unsigned int, unsigned int, krb5_data *);
 
 krb5_enctype
-select_session_keytype (krb5_context context,
+select_session_keytype (kdc_realm_t *kdc_active_realm,
                         krb5_db_entry *server,
                         int nktypes,
                         krb5_enctype *ktypes);
@@ -106,12 +109,12 @@ rep_etypes2str(char *s, size_t len, krb5_kdc_rep *rep);
 /* do_as_req.c */
 void
 process_as_req (krb5_kdc_req *, krb5_data *,
-                const krb5_fulladdr *,
+                const krb5_fulladdr *, kdc_realm_t *,
                 verto_ctx *, loop_respond_fn, void *);
 
 /* do_tgs_req.c */
 krb5_error_code
-process_tgs_req (krb5_data *,
+process_tgs_req (struct server_handle *, krb5_data *,
                  const krb5_fulladdr *,
                  krb5_data ** );
 /* dispatch.c */
@@ -125,8 +128,6 @@ dispatch (void *,
           loop_respond_fn,
           void *);
 
-krb5_error_code
-setup_server_realm (krb5_principal);
 void
 kdc_err(krb5_context call_context, errcode_t code, const char *fmt, ...)
 #if !defined(__cplusplus) && (__GNUC__ > 2)
@@ -159,7 +160,7 @@ get_preauth_hint_list(krb5_kdc_req *request,
                       krb5_kdcpreauth_rock rock, krb5_pa_data ***e_data_out,
                       kdc_hint_respond_fn respond, void *arg);
 void
-load_preauth_plugins(krb5_context context);
+load_preauth_plugins(struct server_handle * handle, krb5_context context);
 void
 unload_preauth_plugins(krb5_context context);
 
@@ -180,9 +181,6 @@ return_padata(krb5_context context, krb5_kdcpreauth_rock rock,
 void
 free_padata_context(krb5_context context, void *padata_context);
 
-krb5_pa_data *
-find_pa_data (krb5_pa_data **padata, krb5_preauthtype pa_type);
-
 krb5_error_code
 add_pa_data_element (krb5_context context,
                      krb5_pa_data *padata,
@@ -222,13 +220,13 @@ handle_authdata (krb5_context context,
 
 /* replay.c */
 krb5_error_code kdc_init_lookaside(krb5_context context);
-krb5_boolean kdc_check_lookaside (krb5_data *, krb5_data **);
-void kdc_insert_lookaside (krb5_data *, krb5_data *);
+krb5_boolean kdc_check_lookaside (krb5_context, krb5_data *, krb5_data **);
+void kdc_insert_lookaside (krb5_context, krb5_data *, krb5_data *);
 void kdc_remove_lookaside (krb5_context kcontext, krb5_data *);
 void kdc_free_lookaside(krb5_context);
 
 /* kdc_util.c */
-void reset_for_hangup(void);
+void reset_for_hangup(void *);
 
 krb5_boolean
 include_pac_p(krb5_context context, krb5_kdc_req *request);
@@ -242,7 +240,7 @@ return_enc_padata(krb5_context context,
                   krb5_boolean is_referral);
 
 krb5_error_code
-kdc_process_s4u2self_req (krb5_context context,
+kdc_process_s4u2self_req (kdc_realm_t *kdc_active_realm,
                           krb5_kdc_req *request,
                           krb5_const_principal client_princ,
                           const krb5_db_entry *server,
@@ -262,7 +260,7 @@ kdc_make_s4u2self_rep (krb5_context context,
                        krb5_enc_kdc_rep_part *reply_encpart);
 
 krb5_error_code
-kdc_process_s4u2proxy_req (krb5_context context,
+kdc_process_s4u2proxy_req (kdc_realm_t *kdc_active_realm,
                            krb5_kdc_req *request,
                            const krb5_enc_tkt_part *t2enc,
                            const krb5_db_entry *server,
@@ -271,7 +269,7 @@ kdc_process_s4u2proxy_req (krb5_context context,
                            const char **status);
 
 krb5_error_code
-kdc_check_transited_list (krb5_context context,
+kdc_check_transited_list (kdc_realm_t *kdc_active_realm,
                           const krb5_data *trans,
                           const krb5_data *realm1,
                           const krb5_data *realm2);
@@ -296,7 +294,7 @@ validate_transit_path(krb5_context context,
                       krb5_db_entry *server,
                       krb5_db_entry *krbtgt);
 void
-kdc_get_ticket_endtime(krb5_context context,
+kdc_get_ticket_endtime(kdc_realm_t *kdc_active_realm,
                        krb5_timestamp now,
                        krb5_timestamp endtime,
                        krb5_timestamp till,
@@ -305,7 +303,7 @@ kdc_get_ticket_endtime(krb5_context context,
                        krb5_timestamp *out_endtime);
 
 void
-log_as_req(const krb5_fulladdr *from,
+log_as_req(krb5_context context, const krb5_fulladdr *from,
            krb5_kdc_req *request, krb5_kdc_rep *reply,
            krb5_db_entry *client, const char *cname,
            krb5_db_entry *server, const char *sname,
@@ -319,20 +317,7 @@ log_tgs_req(const krb5_fulladdr *from,
             unsigned int c_flags, const char *s4u_name,
             const char *status, krb5_error_code errcode, const char *emsg);
 void
-log_tgs_alt_tgt(krb5_principal p);
-
-/*Request state*/
-
-struct kdc_request_state {
-    krb5_keyblock *armor_key;
-    krb5_keyblock *strengthen_key;
-    krb5_pa_data *cookie;
-    krb5_int32 fast_options;
-    krb5_int32 fast_internal_flags;
-};
-
-krb5_error_code kdc_make_rstate(struct kdc_request_state **out);
-void kdc_free_rstate (struct kdc_request_state *s);
+log_tgs_alt_tgt(krb5_context context, krb5_principal p);
 
 /* FAST*/
 enum krb5_fast_kdc_flags {
@@ -374,7 +359,8 @@ krb5_error_code kdc_fast_handle_reply_key(struct kdc_request_state *state,
 krb5_error_code kdc_preauth_get_cookie(struct kdc_request_state *state,
                                        krb5_pa_data **cookie);
 krb5_error_code
-kdc_handle_protected_negotiation( krb5_data *req_pkt, krb5_kdc_req *request,
+kdc_handle_protected_negotiation( krb5_context context,
+                                  krb5_data *req_pkt, krb5_kdc_req *request,
                                   const krb5_keyblock *reply_key,
                                   krb5_pa_data ***out_enc_padata);
 krb5_error_code
diff --git a/src/kdc/main.c b/src/kdc/main.c
index 5b5673c..0e9e87e 100644
--- a/src/kdc/main.c
+++ b/src/kdc/main.c
@@ -68,10 +68,15 @@ static volatile int sighup_received = 0;
 
 #define KRB5_KDC_MAX_REALMS     32
 
-static krb5_context kdc_err_context;
 static const char *kdc_progname;
 
 /*
+ * Static server_handle for this file.  Other code will get access to
+ * it through the application handle that net-server.c uses.
+ */
+static struct server_handle shandle;
+
+/*
  * We use krb5_klog_init to set up a com_err callback to log error
  * messages.  The callback also pulls the error message out of the
  * context we pass to krb5_klog_init; however, we use realm-specific
@@ -87,7 +92,7 @@ kdc_err(krb5_context call_context, errcode_t code, const char *fmt, ...)
     va_list ap;
 
     if (call_context)
-        krb5_copy_error_message(kdc_err_context, call_context);
+        krb5_copy_error_message(shandle.kdc_err_context, call_context);
     va_start(ap, fmt);
     com_err_va(kdc_progname, code, fmt, ap);
     va_end(ap);
@@ -97,9 +102,12 @@ kdc_err(krb5_context call_context, errcode_t code, const char *fmt, ...)
  * Find the realm entry for a given realm.
  */
 kdc_realm_t *
-find_realm_data(char *rname, krb5_ui_4 rsize)
+find_realm_data(struct server_handle *handle, char *rname, krb5_ui_4 rsize)
 {
     int i;
+    kdc_realm_t **kdc_realmlist = handle->kdc_realmlist;
+    int kdc_numrealms = handle->kdc_numrealms;
+
     for (i=0; i<kdc_numrealms; i++) {
         if ((rsize == strlen(kdc_realmlist[i]->realm_name)) &&
             !strncmp(rname, kdc_realmlist[i]->realm_name, rsize))
@@ -108,23 +116,24 @@ find_realm_data(char *rname, krb5_ui_4 rsize)
     return((kdc_realm_t *) NULL);
 }
 
-krb5_error_code
-setup_server_realm(krb5_principal sprinc)
+kdc_realm_t *
+setup_server_realm(struct server_handle *handle, krb5_principal sprinc)
 {
     krb5_error_code     kret;
     kdc_realm_t         *newrealm;
+    kdc_realm_t **kdc_realmlist = handle->kdc_realmlist;
+    int kdc_numrealms = handle->kdc_numrealms;
 
     kret = 0;
     if (kdc_numrealms > 1) {
-        if (!(newrealm = find_realm_data(sprinc->realm.data,
+        if (!(newrealm = find_realm_data(handle, sprinc->realm.data,
                                          (krb5_ui_4) sprinc->realm.length)))
-            kret = ENOENT;
+            return NULL;
         else
-            kdc_active_realm = newrealm;
+            return newrealm;
     }
     else
-        kdc_active_realm = kdc_realmlist[0];
-    return(kret);
+        return kdc_realmlist[0];
 }
 
 static void
@@ -558,7 +567,7 @@ create_workers(verto_ctx *ctx, int num)
                                  _("Unable to reinitialize main loop"));
                 return ENOMEM;
             }
-            retval = loop_setup_signals(ctx, NULL, reset_for_hangup);
+            retval = loop_setup_signals(ctx, &shandle, reset_for_hangup);
             if (retval) {
                 krb5_klog_syslog(LOG_ERR, _("Unable to initialize signal "
                                             "handlers in pid %d"), pid);
@@ -626,7 +635,8 @@ create_workers(verto_ctx *ctx, int num)
 static krb5_error_code
 setup_sam(void)
 {
-    return krb5_c_make_random_key(kdc_context, ENCTYPE_DES_CBC_MD5, &psr_key);
+    krb5_context ctx = shandle.kdc_err_context;
+    return krb5_c_make_random_key(ctx, ENCTYPE_DES_CBC_MD5, &psr_key);
 }
 
 static void
@@ -736,7 +746,7 @@ initialize_realms(krb5_context kcontext, int argc, char **argv)
             break;
 
         case 'r':                       /* realm name for db */
-            if (!find_realm_data(optarg, (krb5_ui_4) strlen(optarg))) {
+            if (!find_realm_data(&shandle, optarg, (krb5_ui_4) strlen(optarg))) {
                 if ((rdatap = (kdc_realm_t *) malloc(sizeof(kdc_realm_t)))) {
                     if ((retval = init_realm(rdatap, optarg, mkey_name,
                                              menctype, default_udp_ports,
@@ -748,8 +758,8 @@ initialize_realms(krb5_context kcontext, int argc, char **argv)
                                 argv[0], optarg);
                         exit(1);
                     }
-                    kdc_realmlist[kdc_numrealms] = rdatap;
-                    kdc_numrealms++;
+                    shandle.kdc_realmlist[shandle.kdc_numrealms] = rdatap;
+                    shandle.kdc_numrealms++;
                     free(db_args), db_args=NULL, db_args_size = 0;
                 }
                 else
@@ -844,7 +854,7 @@ initialize_realms(krb5_context kcontext, int argc, char **argv)
     /*
      * Check to see if we processed any realms.
      */
-    if (kdc_numrealms == 0) {
+    if (shandle.kdc_numrealms == 0) {
         /* no realm specified, use default realm */
         if ((retval = krb5_get_default_realm(kcontext, &lrealm))) {
             com_err(argv[0], retval,
@@ -863,14 +873,12 @@ initialize_realms(krb5_context kcontext, int argc, char **argv)
                                   "file for details\n"), argv[0], lrealm);
                 exit(1);
             }
-            kdc_realmlist[0] = rdatap;
-            kdc_numrealms++;
+            shandle.kdc_realmlist[0] = rdatap;
+            shandle.kdc_numrealms++;
         }
         krb5_free_default_realm(kcontext, lrealm);
     }
 
-    /* Ensure that this is set for our first request. */
-    kdc_active_realm = kdc_realmlist[0];
     if (default_udp_ports)
         free(default_udp_ports);
     if (default_tcp_ports)
@@ -907,11 +915,11 @@ finish_realms()
 {
     int i;
 
-    for (i = 0; i < kdc_numrealms; i++) {
-        finish_realm(kdc_realmlist[i]);
-        kdc_realmlist[i] = 0;
+    for (i = 0; i < shandle.kdc_numrealms; i++) {
+        finish_realm(shandle.kdc_realmlist[i]);
+        shandle.kdc_realmlist[i] = 0;
     }
-    kdc_numrealms = 0;
+    shandle.kdc_numrealms = 0;
 }
 
 /*
@@ -952,12 +960,13 @@ int main(int argc, char **argv)
     if (strrchr(argv[0], '/'))
         argv[0] = strrchr(argv[0], '/')+1;
 
-    if (!(kdc_realmlist = (kdc_realm_t **) malloc(sizeof(kdc_realm_t *) *
-                                                  KRB5_KDC_MAX_REALMS))) {
+    shandle.kdc_realmlist = malloc(sizeof(kdc_realm_t *) *
+                                   KRB5_KDC_MAX_REALMS);
+    if (shandle.kdc_realmlist == NULL) {
         fprintf(stderr, _("%s: cannot get memory for realm list\n"), argv[0]);
         exit(1);
     }
-    memset(kdc_realmlist, 0,
+    memset(shandle.kdc_realmlist, 0,
            (size_t) (sizeof(kdc_realm_t *) * KRB5_KDC_MAX_REALMS));
 
     /*
@@ -972,7 +981,7 @@ int main(int argc, char **argv)
         exit(1);
     }
     krb5_klog_init(kcontext, "kdc", argv[0], 1);
-    kdc_err_context = kcontext;
+    shandle.kdc_err_context = kcontext;
     kdc_progname = argv[0];
     /* N.B.: After this point, com_err sends output to the KDC log
        file, and not to stderr.  We use the kdc_err wrapper around
@@ -1002,7 +1011,7 @@ int main(int argc, char **argv)
         return 1;
     }
 
-    load_preauth_plugins(kcontext);
+    load_preauth_plugins(&shandle, kcontext);
     load_authdata_plugins(kcontext);
 
     retval = setup_sam();
@@ -1013,8 +1022,8 @@ int main(int argc, char **argv)
     }
 
     /* Handle each realm's ports */
-    for (i=0; i<kdc_numrealms; i++) {
-        char *cp = kdc_realmlist[i]->realm_ports;
+    for (i=0; i< shandle.kdc_numrealms; i++) {
+        char *cp = shandle.kdc_realmlist[i]->realm_ports;
         int port;
         while (cp && *cp) {
             if (*cp == ',' || isspace((int) *cp)) {
@@ -1029,7 +1038,7 @@ int main(int argc, char **argv)
                 goto net_init_error;
         }
 
-        cp = kdc_realmlist[i]->realm_tcp_ports;
+        cp = shandle.kdc_realmlist[i]->realm_tcp_ports;
         while (cp && *cp) {
             if (*cp == ',' || isspace((int) *cp)) {
                 cp++;
@@ -1051,20 +1060,20 @@ int main(int argc, char **argv)
      * platform has pktinfo support and doesn't need reconfigs.
      */
     if (workers == 0) {
-        retval = loop_setup_routing_socket(ctx, NULL, kdc_progname);
+        retval = loop_setup_routing_socket(ctx, &shandle, kdc_progname);
         if (retval) {
             kdc_err(kcontext, retval, _("while initializing routing socket"));
             finish_realms();
             return 1;
         }
-        retval = loop_setup_signals(ctx, NULL, reset_for_hangup);
+        retval = loop_setup_signals(ctx, &shandle, reset_for_hangup);
         if (retval) {
             kdc_err(kcontext, retval, _("while initializing signal handlers"));
             finish_realms();
             return 1;
         }
     }
-    if ((retval = loop_setup_network(ctx, NULL, kdc_progname))) {
+    if ((retval = loop_setup_network(ctx, &shandle, kdc_progname))) {
     net_init_error:
         kdc_err(kcontext, retval, _("while initializing network"));
         finish_realms();
@@ -1102,10 +1111,10 @@ int main(int argc, char **argv)
     krb5_klog_syslog(LOG_INFO, _("shutting down"));
     unload_preauth_plugins(kcontext);
     unload_authdata_plugins(kcontext);
-    krb5_klog_close(kdc_context);
+    krb5_klog_close(kcontext);
     finish_realms();
-    if (kdc_realmlist)
-        free(kdc_realmlist);
+    if (shandle.kdc_realmlist)
+        free(shandle.kdc_realmlist);
 #ifndef NOCACHE
     kdc_free_lookaside(kcontext);
 #endif
diff --git a/src/kdc/realm_data.h b/src/kdc/realm_data.h
new file mode 100644
index 0000000..0387c28
--- /dev/null
+++ b/src/kdc/realm_data.h
@@ -0,0 +1,107 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* kdc/realm_data.h */
+/*
+ * Copyright (C) 2012 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   the documentation and/or other materials provided with the
+ *   distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef REALM_DATA_H
+#define REALM_DATA_H
+
+typedef struct __kdc_realm_data {
+    /*
+     * General Kerberos per-realm data.
+     */
+    char *              realm_name;     /* Realm name                       */
+/* XXX the real context should go away once the db_context is done.
+ * The db_context is then associated with the realm keytab using
+ * krb5_ktkdb_resolv(). There should be nothing in the context which
+ * cannot span multiple realms -- proven */
+    krb5_context        realm_context;  /* Context to be used for realm     */
+    krb5_keytab         realm_keytab;   /* keytab to be used for this realm */
+    char *              realm_profile;  /* Profile file for this realm      */
+    char *              realm_host_based_services; /* do referral processing for these services
+                                                    * If '*' - allow all referrals */
+    char *              realm_no_host_referral; /* no referral for these services.
+                                                 * If '*' - disallow all referrals and
+                                                 * ignore realm_host_based_services */
+    /*
+     * Database per-realm data.
+     */
+    char *              realm_stash;    /* Stash file name for realm        */
+    char *              realm_mpname;   /* Master principal name for realm  */
+    krb5_principal      realm_mprinc;   /* Master principal for realm       */
+    /*
+     * Note realm_mkey is mkey read from stash or keyboard and may not be the
+     * latest.
+     */
+    krb5_keyblock       realm_mkey;     /* Master key for this realm        */
+    /*
+     * TGS per-realm data.
+     */
+    krb5_principal      realm_tgsprinc; /* TGS principal for this realm     */
+    /*
+     * Other per-realm data.
+     */
+    char                *realm_ports;   /* Per-realm KDC UDP port */
+    char                *realm_tcp_ports; /* Per-realm KDC TCP port */
+    /*
+     * Per-realm parameters.
+     */
+    krb5_deltat         realm_maxlife;  /* Maximum ticket life for realm    */
+    krb5_deltat         realm_maxrlife; /* Maximum renewable life for realm */
+    krb5_boolean        realm_reject_bad_transit; /* Accept unverifiable transited_realm ? */
+    krb5_boolean        realm_restrict_anon;  /* Anon to local TGT only */
+    krb5_boolean        realm_assume_des_crc_sess;  /* Assume princs support des-cbc-crc for session keys */
+} kdc_realm_t;
+
+struct server_handle {
+    kdc_realm_t **kdc_realmlist;
+    int kdc_numrealms;
+    krb5_context kdc_err_context;
+};
+
+kdc_realm_t *find_realm_data(struct server_handle *, char *, krb5_ui_4);
+kdc_realm_t *setup_server_realm(struct server_handle *, krb5_principal);
+
+/*
+ * These macros used to refer to a global pointer to the active realm state
+ * structure for a request.  They now refer to a local variable that must be
+ * properly declared in each function that uses these macros.
+ */
+#define kdc_context                     kdc_active_realm->realm_context
+#define max_life_for_realm              kdc_active_realm->realm_maxlife
+#define max_renewable_life_for_realm    kdc_active_realm->realm_maxrlife
+#define master_keyblock                 kdc_active_realm->realm_mkey
+#define master_princ                    kdc_active_realm->realm_mprinc
+#define tgs_server                      kdc_active_realm->realm_tgsprinc
+#define reject_bad_transit              kdc_active_realm->realm_reject_bad_transit
+#define restrict_anon                   kdc_active_realm->realm_restrict_anon
+#define assume_des_crc_sess             kdc_active_realm->realm_assume_des_crc_sess
+
+#endif  /* REALM_DATA_H */
diff --git a/src/kdc/replay.c b/src/kdc/replay.c
index 2df9cc6..3eee6e8 100644
--- a/src/kdc/replay.c
+++ b/src/kdc/replay.c
@@ -157,13 +157,14 @@ kdc_remove_lookaside(krb5_context kcontext, krb5_data *req_packet)
 
     e = find_entry(req_packet);
     if (e != NULL)
-        discard_entry(kdc_context, e);
+        discard_entry(kcontext, e);
 }
 
 /* Return true and fill in reply_packet_out if req_packet is in the lookaside
  * cache; otherwise return false.  Also discard old entries in the cache. */
 krb5_boolean
-kdc_check_lookaside(krb5_data *req_packet, krb5_data **reply_packet_out)
+kdc_check_lookaside(krb5_context kcontext, krb5_data *req_packet,
+                    krb5_data **reply_packet_out)
 {
     struct entry *e;
 
@@ -176,21 +177,22 @@ kdc_check_lookaside(krb5_data *req_packet, krb5_data **reply_packet_out)
 
     e->num_hits++;
     hits++;
-    return (krb5_copy_data(kdc_context, &e->reply_packet,
+    return (krb5_copy_data(kcontext, &e->reply_packet,
                            reply_packet_out) == 0);
 }
 
 /* Insert a request and reply into the lookaside cache.  Assumes it's not
  * already there, and can fail silently on memory exhaustion. */
 void
-kdc_insert_lookaside(krb5_data *req_packet, krb5_data *reply_packet)
+kdc_insert_lookaside(krb5_context kcontext, krb5_data *req_packet,
+                     krb5_data *reply_packet)
 {
     struct entry *e, *next;
     krb5_timestamp timenow;
     krb5_ui_4 hash = murmurhash3(req_packet);
     size_t esize = entry_size(req_packet, reply_packet);
 
-    if (krb5_timeofday(kdc_context, &timenow))
+    if (krb5_timeofday(kcontext, &timenow))
         return;
 
     /* Purge stale entries and limit the total size of the entries. */
@@ -198,7 +200,7 @@ kdc_insert_lookaside(krb5_data *req_packet, krb5_data *reply_packet)
         if (!STALE(e, timenow) && total_size + esize <= LOOKASIDE_MAX_SIZE)
             break;
         max_hits_per_entry = max(max_hits_per_entry, e->num_hits);
-        discard_entry(kdc_context, e);
+        discard_entry(kcontext, e);
     }
 
     /* Create a new entry for this request and reply. */
@@ -206,14 +208,14 @@ kdc_insert_lookaside(krb5_data *req_packet, krb5_data *reply_packet)
     if (e == NULL)
         return;
     e->timein = timenow;
-    if (krb5int_copy_data_contents(kdc_context, req_packet, &e->req_packet)) {
+    if (krb5int_copy_data_contents(kcontext, req_packet, &e->req_packet)) {
         free(e);
         return;
     }
     if (reply_packet != NULL &&
-        krb5int_copy_data_contents(kdc_context, reply_packet,
+        krb5int_copy_data_contents(kcontext, reply_packet,
                                    &e->reply_packet)) {
-        krb5_free_data_contents(kdc_context, &e->req_packet);
+        krb5_free_data_contents(kcontext, &e->req_packet);
         free(e);
         return;
     }
diff --git a/src/kdc/reqstate.h b/src/kdc/reqstate.h
new file mode 100644
index 0000000..58dd616
--- /dev/null
+++ b/src/kdc/reqstate.h
@@ -0,0 +1,53 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* kdc/reqstate.h */
+/*
+ * Copyright (C) 2012 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   the documentation and/or other materials provided with the
+ *   distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef REQSTATE_H
+#define REQSTATE_H
+
+#include "realm_data.h"
+
+/* Request state */
+
+struct kdc_request_state {
+    krb5_keyblock *armor_key;
+    krb5_keyblock *strengthen_key;
+    krb5_pa_data *cookie;
+    krb5_int32 fast_options;
+    krb5_int32 fast_internal_flags;
+    kdc_realm_t *realm_data;
+};
+
+krb5_error_code kdc_make_rstate(kdc_realm_t *active_realm,
+                                struct kdc_request_state **out);
+void kdc_free_rstate(struct kdc_request_state *s);
+
+#endif  /* REQSTATE_H */
diff --git a/src/kdc/rtest.c b/src/kdc/rtest.c
index 446001c..6852284 100644
--- a/src/kdc/rtest.c
+++ b/src/kdc/rtest.c
@@ -109,4 +109,9 @@ main(int argc, char **argv)
 }
 
 void krb5_klog_syslog(void) {}
-kdc_realm_t *find_realm_data (char *rname, krb5_ui_4 rsize) { return 0; }
+kdc_realm_t *
+find_realm_data(struct server_handle *handle,
+                char *rname, krb5_ui_4 rsize)
+{
+    return 0;
+}
diff --git a/src/lib/apputils/net-server.c b/src/lib/apputils/net-server.c
index 1f8a8f9..3aa6fde 100644
--- a/src/lib/apputils/net-server.c
+++ b/src/lib/apputils/net-server.c
@@ -277,7 +277,7 @@ do_break(verto_ctx *ctx, verto_ev *ev)
 
 struct sighup_context {
     void *handle;
-    void (*reset)();
+    void (*reset)(void *);
 };
 
 static void
@@ -288,7 +288,7 @@ do_reset(verto_ctx *ctx, verto_ev *ev)
     krb5_klog_syslog(LOG_DEBUG, _("Got signal to reset"));
     krb5_klog_reopen(get_context(sc->handle));
     if (sc->reset)
-        sc->reset();
+        sc->reset(sc->handle);
 }
 
 static void


More information about the cvs-krb5 mailing list