summaryrefslogtreecommitdiffstats
path: root/src/kdc
diff options
context:
space:
mode:
authorTom Yu <tlyu@mit.edu>2012-09-07 20:18:41 -0400
committerTom Yu <tlyu@mit.edu>2012-10-15 19:41:14 -0400
commit0a2f14f752c32a24200363cc6b6ae64a92f81379 (patch)
tree707f1dce91dfbe42df0eead38b33cbf7728d9703 /src/kdc
parent1a3f548db030b764f46820c342fb2abb226dc43b (diff)
downloadkrb5-0a2f14f752c32a24200363cc6b6ae64a92f81379.tar.gz
krb5-0a2f14f752c32a24200363cc6b6ae64a92f81379.tar.xz
krb5-0a2f14f752c32a24200363cc6b6ae64a92f81379.zip
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.
Diffstat (limited to 'src/kdc')
-rw-r--r--src/kdc/dispatch.c48
-rw-r--r--src/kdc/do_as_req.c34
-rw-r--r--src/kdc/do_tgs_req.c74
-rw-r--r--src/kdc/extern.c2
-rw-r--r--src/kdc/extern.h68
-rw-r--r--src/kdc/fast_util.c32
-rw-r--r--src/kdc/kdc_preauth.c22
-rw-r--r--src/kdc/kdc_util.c196
-rw-r--r--src/kdc/kdc_util.h64
-rw-r--r--src/kdc/main.c85
-rw-r--r--src/kdc/realm_data.h107
-rw-r--r--src/kdc/replay.c20
-rw-r--r--src/kdc/reqstate.h53
-rw-r--r--src/kdc/rtest.c7
14 files changed, 487 insertions, 325 deletions
diff --git a/src/kdc/dispatch.c b/src/kdc/dispatch.c
index e3f43bc24..68c67f4d5 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 4ca712dd4..79da300d2 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 8a6d93cec..c45fe87c3 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 7307bfcf5..fe627494b 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 c601e5702..7dc658f63 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 f3e037d53..1ce27d689 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 5ca36769d..19998d850 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 4f6ce6f30..773d8cf17 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 0cd7989fc..2f215a741 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 5b5673c47..0e9e87eb6 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 000000000..0387c28ae
--- /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 2df9cc607..3eee6e8d4 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 000000000..58dd616b5
--- /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 446001c0a..685228411 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;
+}