From: Tom Yu Date: Sat, 8 Sep 2012 00:18:41 +0000 (-0400) Subject: Eliminate some KDC globals X-Git-Tag: krb5-1.11-alpha1~58 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0a2f14f752c32a24200363cc6b6ae64a92f81379;p=thirdparty%2Fkrb5.git 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. --- diff --git a/src/kdc/dispatch.c b/src/kdc/dispatch.c index e3f43bc248..68c67f4d55 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 #include #include 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 4ca712dd48..79da300d22 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 8a6d93cec0..c45fe87c30 100644 --- a/src/kdc/do_tgs_req.c +++ b/src/kdc/do_tgs_req.c @@ -69,19 +69,21 @@ #include 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 7307bfcf55..fe627494b8 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 c601e5702b..7dc658f632 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 f3e037d535..1ce27d689b 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 5ca36769d1..19998d8501 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 4f6ce6f30b..773d8cf172 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 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 0cd7989fcc..2f215a7413 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 5b5673c477..0e9e87eb68 100644 --- a/src/kdc/main.c +++ b/src/kdc/main.c @@ -68,9 +68,14 @@ 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 @@ -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; irealm_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; irealm_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 0000000000..0387c28ae6 --- /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 2df9cc6073..3eee6e8d4f 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 0000000000..58dd616b53 --- /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 446001c0a8..685228411d 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 1f8a8f97ae..3aa6fdeeb0 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