From c3c440d42b99d1370cf090c2e855955146eb4a7a Mon Sep 17 00:00:00 2001 From: Zhanna Tsitkov Date: Mon, 26 Jan 2009 16:20:41 +0000 Subject: [PATCH] Check asprintf return codes. Styling git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@21795 dc483132-0cff-0310-8789-dd5450dbe970 --- src/kdc/do_tgs_req.c | 1103 +++++++++++++++++++++--------------------- src/kdc/main.c | 103 ++-- 2 files changed, 617 insertions(+), 589 deletions(-) diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c index 5a349c864..2e86d3d54 100644 --- a/src/kdc/do_tgs_req.c +++ b/src/kdc/do_tgs_req.c @@ -72,19 +72,19 @@ #include "adm_proto.h" static void find_alternate_tgs (krb5_kdc_req *, krb5_db_entry *, - krb5_boolean *, int *); + krb5_boolean *, int *); static krb5_error_code prepare_error_tgs (krb5_kdc_req *, krb5_ticket *, - int, krb5_principal, - krb5_data **, const char *); + int, krb5_principal, + krb5_data **, const char *); -static krb5_boolean +static krb5_int32 is_substr ( char *, krb5_data *); /*ARGSUSED*/ krb5_error_code process_tgs_req(krb5_data *pkt, const krb5_fulladdr *from, - krb5_data **response) +krb5_data **response) { krb5_keyblock * subkey = 0; krb5_kdc_req *request = 0; @@ -107,17 +107,17 @@ process_tgs_req(krb5_data *pkt, const krb5_fulladdr *from, char *cname = 0, *sname = 0, *altcname = 0; krb5_last_req_entry *nolrarray[2], nolrentry; krb5_enctype useenctype; - int errcode, errcode2; + int errcode, errcode2; register int i; size_t len; int firstpass = 1; - const char *status = 0; + const char *status = 0; krb5_enc_tkt_part *header_enc_tkt = NULL; /* ticket granting or evidence ticket */ krb5_db_entry client, krbtgt; int c_nprincs = 0, k_nprincs = 0; - krb5_pa_for_user *for_user = NULL; /* protocol transition request */ - krb5_authdata **kdc_issued_auth_data = NULL; /* auth data issued by KDC */ - unsigned int c_flags = 0, s_flags = 0; /* client/server KDB flags */ + krb5_pa_for_user *for_user = NULL; /* protocol transition request */ + krb5_authdata **kdc_issued_auth_data = NULL; /* auth data issued by KDC */ + unsigned int c_flags = 0, s_flags = 0; /* client/server KDB flags */ char *s4u_name = NULL; krb5_boolean is_referral, db_ref_done = FALSE; const char *emsg = NULL; @@ -125,41 +125,42 @@ process_tgs_req(krb5_data *pkt, const krb5_fulladdr *from, krb5_data *comp1 = NULL, *comp2 = NULL; krb5_data *tgs_1 =NULL, *server_1 = NULL; krb5_principal krbtgt_princ; + krb5_int32 host_based_srv_listed, no_host_referral_listed; session_key.contents = NULL; retval = decode_krb5_tgs_req(pkt, &request); if (retval) - return retval; + return retval; /* * 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; + krb5_free_kdc_req(kdc_context, request); + return retval; } errcode = kdc_process_tgs_req(request, from, pkt, &header_ticket, - &krbtgt, &k_nprincs, &subkey); + &krbtgt, &k_nprincs, &subkey); if (header_ticket && header_ticket->enc_part2 && - (errcode2 = krb5_unparse_name(kdc_context, - header_ticket->enc_part2->client, - &cname))) { - status = "UNPARSING CLIENT"; - errcode = errcode2; - goto cleanup; + (errcode2 = krb5_unparse_name(kdc_context, + header_ticket->enc_part2->client, + &cname))) { + status = "UNPARSING CLIENT"; + errcode = errcode2; + goto cleanup; } limit_string(cname); if (errcode) { - status = "PROCESS_TGS"; - goto cleanup; + status = "PROCESS_TGS"; + goto cleanup; } if (!header_ticket) { - errcode = KRB5_NO_TKT_SUPPLIED; /* XXX? */ - status="UNEXPECTED NULL in header_ticket"; - goto cleanup; + errcode = KRB5_NO_TKT_SUPPLIED; /* XXX? */ + status="UNEXPECTED NULL in header_ticket"; + goto cleanup; } /* @@ -180,8 +181,8 @@ process_tgs_req(krb5_data *pkt, const krb5_fulladdr *from, header? */ if (isflagset(request->kdc_options, KDC_OPT_CANONICALIZE)) { - setflag(c_flags, KRB5_KDB_FLAG_CANONICALIZE); - setflag(s_flags, KRB5_KDB_FLAG_CANONICALIZE); + setflag(c_flags, KRB5_KDB_FLAG_CANONICALIZE); + setflag(s_flags, KRB5_KDB_FLAG_CANONICALIZE); } db_ref_done = FALSE; @@ -189,32 +190,32 @@ process_tgs_req(krb5_data *pkt, const krb5_fulladdr *from, ref_tgt_again: nprincs = 1; if ((errcode = krb5_unparse_name(kdc_context, request->server, &sname))) { - status = "UNPARSING SERVER"; - goto cleanup; + status = "UNPARSING SERVER"; + goto cleanup; } limit_string(sname); errcode = krb5_db_get_principal_ext(kdc_context, - request->server, - s_flags, - &server, - &nprincs, - &more); + request->server, + s_flags, + &server, + &nprincs, + &more); if (errcode) { - status = "LOOKING_UP_SERVER"; - nprincs = 0; - goto cleanup; + status = "LOOKING_UP_SERVER"; + nprincs = 0; + goto cleanup; } tgt_again: if (more) { - status = "NON_UNIQUE_PRINCIPAL"; - errcode = KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE; - goto cleanup; + status = "NON_UNIQUE_PRINCIPAL"; + errcode = KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE; + goto cleanup; } else if (nprincs != 1) { - /* - * might be a request for a TGT for some other realm; we - * should do our best to find such a TGS in this db - */ + /* + * might be a request for a TGT for some other realm; we + * should do our best to find such a TGS in this db + */ if (firstpass ) { if ( krb5_is_tgs_principal(request->server) == TRUE) { /* Principal is a name of krb ticket service */ @@ -238,43 +239,62 @@ tgt_again: } else if ( db_ref_done == FALSE) { /* By now we know that server principal name is unknown <== nprincs!=1 from get_principal - * If CANONICALIZE flag is set in the request (1) - * If req is not U2U authn. req (2) - * the requested server princ. has exactly two components (3) + * If CANONICALIZE flag is set in the request + * If req is not U2U authn. req + * the requested server princ. has exactly two components * either - * the name type is NT-SRV-HST (4.a) + * the name type is NT-SRV-HST * or name type is NT-UNKNOWN and - * the 1st component is listed in conf file under host_based_services (4.b) - * the 1st component is not in a list in conf under "no_host_referral" (5) - * the 2d component looks like fully-qualified domain name (FQDN) (6) + * the 1st component is listed in conf file under host_based_services + * the 1st component is not in a list in conf under "no_host_referral" + * the 2d component looks like fully-qualified domain name (FQDN) * If all of these conditions are satisfied - try mapping the FQDN and * re-process the request as if client had asked for cross-realm TGT. */ - if (isflagset(request->kdc_options, KDC_OPT_CANONICALIZE) == TRUE && /* (1) */ - !isflagset(request->kdc_options, KDC_OPT_ENC_TKT_IN_SKEY) && /* (2) */ - krb5_princ_size(kdc_context, request->server) == 2) { /* (3) */ + if (isflagset(request->kdc_options, KDC_OPT_CANONICALIZE) == TRUE && + !isflagset(request->kdc_options, KDC_OPT_ENC_TKT_IN_SKEY) && + krb5_princ_size(kdc_context, request->server) == 2) { comp1 = krb5_princ_component(kdc_context, request->server, 0); comp2 = krb5_princ_component(kdc_context, request->server, 1); - if ((krb5_princ_type(kdc_context, request->server) == KRB5_NT_SRV_HST || /* (4.a) */ - (krb5_princ_type(kdc_context, request->server) == KRB5_NT_UNKNOWN && /* (4.b) */ - (is_substr(kdc_active_realm->realm_host_based_services, comp1)==TRUE || - strchr(kdc_active_realm->realm_host_based_services, '*')))) && - (kdc_active_realm->realm_no_host_referral == NULL || - (!strchr(kdc_active_realm->realm_host_based_services, '*') && - is_substr(kdc_active_realm->realm_no_host_referral,comp1)==FALSE))) { /* (5) */ - - for ( len=0; len < comp2->length; len++) { - if ( comp2->data[len] == '.' ) break; + host_based_srv_listed = FALSE; + no_host_referral_listed = TRUE; + if (kdc_active_realm->realm_host_based_services != NULL) { + host_based_srv_listed = + is_substr(kdc_active_realm->realm_host_based_services, comp1); + if (host_based_srv_listed == ENOMEM) { + retval = ENOMEM; + goto cleanup; } - if ( len == comp2->length) /* (6) */ + } + if (kdc_active_realm->realm_no_host_referral != NULL) { + no_host_referral_listed = + is_substr(kdc_active_realm->realm_no_host_referral,comp1); + if (no_host_referral_listed == ENOMEM) { + retval = ENOMEM; + goto cleanup; + } + } + + if ((krb5_princ_type(kdc_context, request->server) == KRB5_NT_SRV_HST || + (krb5_princ_type(kdc_context, request->server) == KRB5_NT_UNKNOWN && + kdc_active_realm->realm_host_based_services != NULL && + (host_based_srv_listed == TRUE || + strchr(kdc_active_realm->realm_host_based_services, '*')))) && + (kdc_active_realm->realm_no_host_referral == NULL || + (!strchr(kdc_active_realm->realm_host_based_services, '*') && + no_host_referral_listed == FALSE))) { + + for (len=0; len < comp2->length; len++) { + if (comp2->data[len] == '.') break; + } + if (len == comp2->length) goto cleanup; - /* try mapping FQDN or the containing domains */ temp_buf = calloc(1, comp2->length+1); - if ( !temp_buf){ + if (!temp_buf){ retval = ENOMEM; goto cleanup; } @@ -304,12 +324,13 @@ tgt_again: (*request->server).realm.data, "krbtgt", realms[0], (char *)0); - for (cpp = realms; *cpp; cpp++) free(*cpp); + for (cpp = realms; *cpp; cpp++) free(*cpp); krb5_free_principal(kdc_context, request->server); retval = krb5_copy_principal(kdc_context, krbtgt_princ, &(request->server)); - if ( retval == 0 ) { + if (retval == 0) { db_ref_done = TRUE; + if (sname != NULL) free(sname); goto ref_tgt_again; } } @@ -317,40 +338,39 @@ tgt_again: } } - - krb5_db_free_principal(kdc_context, &server, nprincs); - status = "UNKNOWN_SERVER"; - errcode = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; - goto cleanup; + krb5_db_free_principal(kdc_context, &server, nprincs); + status = "UNKNOWN_SERVER"; + errcode = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; + goto cleanup; } if ((errcode = krb5_timeofday(kdc_context, &kdc_time))) { - status = "TIME_OF_DAY"; - goto cleanup; + status = "TIME_OF_DAY"; + goto cleanup; } if ((retval = validate_tgs_request(request, server, header_ticket, - kdc_time, &status))) { - if (!status) - status = "UNKNOWN_REASON"; - errcode = retval + ERROR_TABLE_BASE_krb5; - goto cleanup; + kdc_time, &status))) { + if (!status) + status = "UNKNOWN_REASON"; + errcode = retval + ERROR_TABLE_BASE_krb5; + goto cleanup; } if (!is_local_principal(header_enc_tkt->client)) - setflag(c_flags, KRB5_KDB_FLAG_CROSS_REALM); + 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); + !krb5_principal_compare(kdc_context, tgs_server, server.princ); /* Check for protocol transition */ errcode = kdc_process_s4u2self_req(kdc_context, request, header_enc_tkt->client, - &server, header_enc_tkt->session, kdc_time, - &for_user, &client, &c_nprincs, &status); + &server, header_enc_tkt->session, kdc_time, + &for_user, &client, &c_nprincs, &status); if (errcode) - goto cleanup; + goto cleanup; if (for_user != NULL) - setflag(c_flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION); + setflag(c_flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION); /* * We pick the session keytype here.... @@ -365,114 +385,114 @@ tgt_again: */ useenctype = 0; if (isflagset(request->kdc_options, KDC_OPT_ENC_TKT_IN_SKEY | - KDC_OPT_CNAME_IN_ADDL_TKT)) { - krb5_keyblock * st_sealing_key; - krb5_kvno st_srv_kvno; - krb5_enctype etype; - krb5_db_entry st_client; - int st_nprincs = 0; - - /* - * Get the key for the second ticket, and decrypt it. - */ - if ((errcode = kdc_get_server_key(request->second_ticket[st_idx], - c_flags, - TRUE, /* match_enctype */ - &st_client, - &st_nprincs, - &st_sealing_key, - &st_srv_kvno))) { - status = "2ND_TKT_SERVER"; - goto cleanup; - } - errcode = krb5_decrypt_tkt_part(kdc_context, st_sealing_key, - request->second_ticket[st_idx]); - krb5_free_keyblock(kdc_context, st_sealing_key); - if (errcode) { - status = "2ND_TKT_DECRYPT"; - krb5_db_free_principal(kdc_context, &st_client, st_nprincs); - goto cleanup; - } - - etype = request->second_ticket[st_idx]->enc_part2->session->enctype; - if (!krb5_c_valid_enctype(etype)) { - status = "BAD_ETYPE_IN_2ND_TKT"; - errcode = KRB5KDC_ERR_ETYPE_NOSUPP; - krb5_db_free_principal(kdc_context, &st_client, st_nprincs); - goto cleanup; - } - - for (i = 0; i < request->nktypes; i++) { - if (request->ktype[i] == etype) { - useenctype = etype; - break; - } - } - - 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, - request, - request->second_ticket[st_idx]->enc_part2, - &st_client, - header_ticket->enc_part2->client, - request->server, - &status); - if (errcode) - goto cleanup; - - setflag(c_flags, KRB5_KDB_FLAG_CONSTRAINED_DELEGATION); - - assert(krb5_is_tgs_principal(header_ticket->server)); - - /* From now on, use evidence ticket as header ticket */ - header_enc_tkt = request->second_ticket[st_idx]->enc_part2; - - assert(c_nprincs == 0); /* assured by kdc_process_s4u2self_req() */ - - client = st_client; - c_nprincs = st_nprincs; - } else { - /* "client" is not used for user2user */ - krb5_db_free_principal(kdc_context, &st_client, st_nprincs); - } + KDC_OPT_CNAME_IN_ADDL_TKT)) { + krb5_keyblock * st_sealing_key; + krb5_kvno st_srv_kvno; + krb5_enctype etype; + krb5_db_entry st_client; + int st_nprincs = 0; + + /* + * Get the key for the second ticket, and decrypt it. + */ + if ((errcode = kdc_get_server_key(request->second_ticket[st_idx], + c_flags, + TRUE, /* match_enctype */ + &st_client, + &st_nprincs, + &st_sealing_key, + &st_srv_kvno))) { + status = "2ND_TKT_SERVER"; + goto cleanup; + } + errcode = krb5_decrypt_tkt_part(kdc_context, st_sealing_key, + request->second_ticket[st_idx]); + krb5_free_keyblock(kdc_context, st_sealing_key); + if (errcode) { + status = "2ND_TKT_DECRYPT"; + krb5_db_free_principal(kdc_context, &st_client, st_nprincs); + goto cleanup; + } + + etype = request->second_ticket[st_idx]->enc_part2->session->enctype; + if (!krb5_c_valid_enctype(etype)) { + status = "BAD_ETYPE_IN_2ND_TKT"; + errcode = KRB5KDC_ERR_ETYPE_NOSUPP; + krb5_db_free_principal(kdc_context, &st_client, st_nprincs); + goto cleanup; + } + + for (i = 0; i < request->nktypes; i++) { + if (request->ktype[i] == etype) { + useenctype = etype; + break; + } + } + + 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, + request, + request->second_ticket[st_idx]->enc_part2, + &st_client, + header_ticket->enc_part2->client, + request->server, + &status); + if (errcode) + goto cleanup; + + setflag(c_flags, KRB5_KDB_FLAG_CONSTRAINED_DELEGATION); + + assert(krb5_is_tgs_principal(header_ticket->server)); + + /* From now on, use evidence ticket as header ticket */ + header_enc_tkt = request->second_ticket[st_idx]->enc_part2; + + assert(c_nprincs == 0); /* assured by kdc_process_s4u2self_req() */ + + client = st_client; + c_nprincs = st_nprincs; + } else { + /* "client" is not used for user2user */ + krb5_db_free_principal(kdc_context, &st_client, st_nprincs); + } } /* * Select the keytype for the ticket session key. */ if ((useenctype == 0) && - (useenctype = select_session_keytype(kdc_context, &server, - request->nktypes, - request->ktype)) == 0) { - /* unsupported ktype */ - status = "BAD_ENCRYPTION_TYPE"; - errcode = KRB5KDC_ERR_ETYPE_NOSUPP; - goto cleanup; + (useenctype = select_session_keytype(kdc_context, &server, + request->nktypes, + request->ktype)) == 0) { + /* unsupported ktype */ + status = "BAD_ENCRYPTION_TYPE"; + errcode = KRB5KDC_ERR_ETYPE_NOSUPP; + goto cleanup; } errcode = krb5_c_make_random_key(kdc_context, useenctype, &session_key); if (errcode) { - /* random key failed */ - status = "RANDOM_KEY_FAILED"; - goto cleanup; + /* random key failed */ + status = "RANDOM_KEY_FAILED"; + goto cleanup; } authtime = header_enc_tkt->times.authtime; if (is_referral) - ticket_reply.server = server.princ; + ticket_reply.server = server.princ; else - ticket_reply.server = request->server; /* XXX careful for realm... */ + ticket_reply.server = request->server; /* XXX careful for realm... */ enc_tkt_reply.flags = 0; enc_tkt_reply.times.starttime = 0; if (isflagset(server.attributes, KRB5_KDB_OK_AS_DELEGATE) && - !is_referral) { - /* Ensure that we are not returning a referral */ - setflag(enc_tkt_reply.flags, TKT_FLG_OK_AS_DELEGATE); + !is_referral) { + /* Ensure that we are not returning a referral */ + setflag(enc_tkt_reply.flags, TKT_FLG_OK_AS_DELEGATE); } /* @@ -480,13 +500,13 @@ tgt_again: * authtime's value. */ if (!(header_enc_tkt->times.starttime)) - header_enc_tkt->times.starttime = header_enc_tkt->times.authtime; + header_enc_tkt->times.starttime = header_enc_tkt->times.authtime; /* don't use new addresses unless forwarded, see below */ enc_tkt_reply.caddrs = header_enc_tkt->caddrs; /* noaddrarray[0] = 0; */ - reply_encpart.caddrs = 0; /* optional...don't put it in */ + reply_encpart.caddrs = 0;/* optional...don't put it in */ reply_encpart.enc_padata = NULL; /* It should be noted that local policy may affect the */ @@ -494,105 +514,105 @@ tgt_again: /* realms may refuse to issue renewable tickets */ if (isflagset(request->kdc_options, KDC_OPT_FORWARDABLE)) - setflag(enc_tkt_reply.flags, TKT_FLG_FORWARDABLE); + setflag(enc_tkt_reply.flags, TKT_FLG_FORWARDABLE); if (isflagset(c_flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION)) { - if (!krb5_is_tgs_principal(server.princ) && - is_local_principal(server.princ)) { - if (isflagset(server.attributes, KRB5_KDB_OK_TO_AUTH_AS_DELEGATE)) - setflag(enc_tkt_reply.flags, TKT_FLG_FORWARDABLE); - else - clear(enc_tkt_reply.flags, TKT_FLG_FORWARDABLE); - } - if (isflagset(client.attributes, KRB5_KDB_DISALLOW_FORWARDABLE)) - clear(enc_tkt_reply.flags, TKT_FLG_FORWARDABLE); + if (!krb5_is_tgs_principal(server.princ) && + is_local_principal(server.princ)) { + if (isflagset(server.attributes, KRB5_KDB_OK_TO_AUTH_AS_DELEGATE)) + setflag(enc_tkt_reply.flags, TKT_FLG_FORWARDABLE); + else + clear(enc_tkt_reply.flags, TKT_FLG_FORWARDABLE); + } + if (isflagset(client.attributes, KRB5_KDB_DISALLOW_FORWARDABLE)) + clear(enc_tkt_reply.flags, TKT_FLG_FORWARDABLE); } if (isflagset(request->kdc_options, KDC_OPT_FORWARDED)) { - setflag(enc_tkt_reply.flags, TKT_FLG_FORWARDED); + setflag(enc_tkt_reply.flags, TKT_FLG_FORWARDED); - /* include new addresses in ticket & reply */ + /* include new addresses in ticket & reply */ - enc_tkt_reply.caddrs = request->addresses; - reply_encpart.caddrs = request->addresses; - } + enc_tkt_reply.caddrs = request->addresses; + reply_encpart.caddrs = request->addresses; + } if (isflagset(header_enc_tkt->flags, TKT_FLG_FORWARDED)) - setflag(enc_tkt_reply.flags, TKT_FLG_FORWARDED); + setflag(enc_tkt_reply.flags, TKT_FLG_FORWARDED); if (isflagset(request->kdc_options, KDC_OPT_PROXIABLE)) - setflag(enc_tkt_reply.flags, TKT_FLG_PROXIABLE); + setflag(enc_tkt_reply.flags, TKT_FLG_PROXIABLE); if (isflagset(request->kdc_options, KDC_OPT_PROXY)) { - setflag(enc_tkt_reply.flags, TKT_FLG_PROXY); + setflag(enc_tkt_reply.flags, TKT_FLG_PROXY); - /* include new addresses in ticket & reply */ + /* include new addresses in ticket & reply */ - enc_tkt_reply.caddrs = request->addresses; - reply_encpart.caddrs = request->addresses; + enc_tkt_reply.caddrs = request->addresses; + reply_encpart.caddrs = request->addresses; } if (isflagset(request->kdc_options, KDC_OPT_ALLOW_POSTDATE)) - setflag(enc_tkt_reply.flags, TKT_FLG_MAY_POSTDATE); + setflag(enc_tkt_reply.flags, TKT_FLG_MAY_POSTDATE); if (isflagset(request->kdc_options, KDC_OPT_POSTDATED)) { - setflag(enc_tkt_reply.flags, TKT_FLG_POSTDATED); - setflag(enc_tkt_reply.flags, TKT_FLG_INVALID); - enc_tkt_reply.times.starttime = request->from; + setflag(enc_tkt_reply.flags, TKT_FLG_POSTDATED); + setflag(enc_tkt_reply.flags, TKT_FLG_INVALID); + enc_tkt_reply.times.starttime = request->from; } else - enc_tkt_reply.times.starttime = kdc_time; + enc_tkt_reply.times.starttime = kdc_time; if (isflagset(request->kdc_options, KDC_OPT_VALIDATE)) { - assert(isflagset(c_flags, KRB5_KDB_FLAGS_S4U) == 0); - /* BEWARE of allocation hanging off of ticket & enc_part2, it belongs - to the caller */ - ticket_reply = *(header_ticket); - enc_tkt_reply = *(header_ticket->enc_part2); - clear(enc_tkt_reply.flags, TKT_FLG_INVALID); + assert(isflagset(c_flags, KRB5_KDB_FLAGS_S4U) == 0); + /* BEWARE of allocation hanging off of ticket & enc_part2, it belongs + to the caller */ + ticket_reply = *(header_ticket); + enc_tkt_reply = *(header_ticket->enc_part2); + clear(enc_tkt_reply.flags, TKT_FLG_INVALID); } if (isflagset(request->kdc_options, KDC_OPT_RENEW)) { - krb5_deltat old_life; + krb5_deltat old_life; - assert(isflagset(c_flags, KRB5_KDB_FLAGS_S4U) == 0); - /* BEWARE of allocation hanging off of ticket & enc_part2, it belongs - to the caller */ - ticket_reply = *(header_ticket); - enc_tkt_reply = *(header_ticket->enc_part2); + assert(isflagset(c_flags, KRB5_KDB_FLAGS_S4U) == 0); + /* BEWARE of allocation hanging off of ticket & enc_part2, it belongs + to the caller */ + ticket_reply = *(header_ticket); + enc_tkt_reply = *(header_ticket->enc_part2); - old_life = enc_tkt_reply.times.endtime - enc_tkt_reply.times.starttime; + old_life = enc_tkt_reply.times.endtime - enc_tkt_reply.times.starttime; - enc_tkt_reply.times.starttime = kdc_time; - enc_tkt_reply.times.endtime = - min(header_ticket->enc_part2->times.renew_till, - kdc_time + old_life); + enc_tkt_reply.times.starttime = kdc_time; + enc_tkt_reply.times.endtime = + min(header_ticket->enc_part2->times.renew_till, + kdc_time + old_life); } else { - /* not a renew request */ - enc_tkt_reply.times.starttime = kdc_time; - until = (request->till == 0) ? kdc_infinity : request->till; - enc_tkt_reply.times.endtime = - min(until, min(enc_tkt_reply.times.starttime + server.max_life, - min(enc_tkt_reply.times.starttime + max_life_for_realm, - header_enc_tkt->times.endtime))); - if (isflagset(request->kdc_options, KDC_OPT_RENEWABLE_OK) && - (enc_tkt_reply.times.endtime < request->till) && - isflagset(header_enc_tkt->flags, TKT_FLG_RENEWABLE)) { - setflag(request->kdc_options, KDC_OPT_RENEWABLE); - request->rtime = - min(request->till, header_enc_tkt->times.renew_till); - } + /* not a renew request */ + enc_tkt_reply.times.starttime = kdc_time; + until = (request->till == 0) ? kdc_infinity : request->till; + enc_tkt_reply.times.endtime = + min(until, min(enc_tkt_reply.times.starttime + server.max_life, + min(enc_tkt_reply.times.starttime + max_life_for_realm, + header_enc_tkt->times.endtime))); + if (isflagset(request->kdc_options, KDC_OPT_RENEWABLE_OK) && + (enc_tkt_reply.times.endtime < request->till) && + isflagset(header_enc_tkt->flags, TKT_FLG_RENEWABLE)) { + setflag(request->kdc_options, KDC_OPT_RENEWABLE); + request->rtime = + min(request->till, header_enc_tkt->times.renew_till); + } } rtime = (request->rtime == 0) ? kdc_infinity : request->rtime; if (isflagset(request->kdc_options, KDC_OPT_RENEWABLE)) { - /* already checked above in policy check to reject request for a - renewable ticket using a non-renewable ticket */ - setflag(enc_tkt_reply.flags, TKT_FLG_RENEWABLE); - enc_tkt_reply.times.renew_till = - min(rtime, - min(header_enc_tkt->times.renew_till, - enc_tkt_reply.times.starttime + - min(server.max_renewable_life, - max_renewable_life_for_realm))); + /* already checked above in policy check to reject request for a + renewable ticket using a non-renewable ticket */ + setflag(enc_tkt_reply.flags, TKT_FLG_RENEWABLE); + enc_tkt_reply.times.renew_till = + min(rtime, + min(header_enc_tkt->times.renew_till, + enc_tkt_reply.times.starttime + + min(server.max_renewable_life, + max_renewable_life_for_realm))); } else { - enc_tkt_reply.times.renew_till = 0; + enc_tkt_reply.times.renew_till = 0; } /* @@ -604,137 +624,137 @@ tgt_again: * Propagate the preauthentication flags through to the returned ticket. */ if (isflagset(header_enc_tkt->flags, TKT_FLG_PRE_AUTH)) - setflag(enc_tkt_reply.flags, TKT_FLG_PRE_AUTH); + setflag(enc_tkt_reply.flags, TKT_FLG_PRE_AUTH); if (isflagset(header_enc_tkt->flags, TKT_FLG_HW_AUTH)) - setflag(enc_tkt_reply.flags, TKT_FLG_HW_AUTH); + setflag(enc_tkt_reply.flags, TKT_FLG_HW_AUTH); /* starttime is optional, and treated as authtime if not present. so we can nuke it if it matches */ if (enc_tkt_reply.times.starttime == enc_tkt_reply.times.authtime) - enc_tkt_reply.times.starttime = 0; + enc_tkt_reply.times.starttime = 0; if (isflagset(c_flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION)) { - errcode = krb5_unparse_name(kdc_context, for_user->user, &s4u_name); + errcode = krb5_unparse_name(kdc_context, for_user->user, &s4u_name); } else if (isflagset(c_flags, KRB5_KDB_FLAG_CONSTRAINED_DELEGATION)) { - errcode = krb5_unparse_name(kdc_context, header_enc_tkt->client, &s4u_name); + errcode = krb5_unparse_name(kdc_context, header_enc_tkt->client, &s4u_name); } else { - errcode = 0; + errcode = 0; } if (errcode) { - status = "UNPARSING S4U CLIENT"; - goto cleanup; + status = "UNPARSING S4U CLIENT"; + goto cleanup; } if (isflagset(request->kdc_options, KDC_OPT_ENC_TKT_IN_SKEY)) { - krb5_enc_tkt_part *t2enc = request->second_ticket[st_idx]->enc_part2; - encrypting_key = *(t2enc->session); + krb5_enc_tkt_part *t2enc = request->second_ticket[st_idx]->enc_part2; + encrypting_key = *(t2enc->session); } else { - /* - * Find the server key - */ - if ((errcode = krb5_dbe_find_enctype(kdc_context, &server, - -1, /* ignore keytype */ - -1, /* Ignore salttype */ - 0, /* Get highest kvno */ - &server_key))) { - status = "FINDING_SERVER_KEY"; - goto cleanup; - } - /* convert server.key into a real key (it may be encrypted - * in the database) */ - if ((errcode = krb5_dbekd_decrypt_key_data(kdc_context, - &master_keyblock, - server_key, &encrypting_key, - NULL))) { - status = "DECRYPT_SERVER_KEY"; - goto cleanup; - } + /* + * Find the server key + */ + if ((errcode = krb5_dbe_find_enctype(kdc_context, &server, + -1, /* ignore keytype */ + -1, /* Ignore salttype */ + 0,/* Get highest kvno */ + &server_key))) { + status = "FINDING_SERVER_KEY"; + goto cleanup; + } + /* convert server.key into a real key (it may be encrypted + * in the database) */ + if ((errcode = krb5_dbekd_decrypt_key_data(kdc_context, + &master_keyblock, + server_key, &encrypting_key, + NULL))) { + status = "DECRYPT_SERVER_KEY"; + goto cleanup; + } } if (isflagset(c_flags, KRB5_KDB_FLAG_CONSTRAINED_DELEGATION)) { - /* - * Don't allow authorization data to be disabled if constrained - * delegation is requested. We don't want to deny the server - * the ability to validate that delegation was used. - */ - clear(server.attributes, KRB5_KDB_NO_AUTH_DATA_REQUIRED); + /* + * Don't allow authorization data to be disabled if constrained + * delegation is requested. We don't want to deny the server + * the ability to validate that delegation was used. + */ + clear(server.attributes, KRB5_KDB_NO_AUTH_DATA_REQUIRED); } if (isflagset(server.attributes, KRB5_KDB_NO_AUTH_DATA_REQUIRED) == 0) { - /* - * If we are not doing protocol transition/constrained delegation - * and there was no authorization data included, try to lookup - * the client principal as it may be mapped to a local account. - * - * Always validate authorization data for constrained delegation - * because we must validate the KDC signatures. - */ - if (!isflagset(c_flags, KRB5_KDB_FLAGS_S4U) && - header_enc_tkt->authorization_data == NULL) { - - /* Generate authorization data so we can include it in ticket */ - setflag(c_flags, KRB5_KDB_FLAG_INCLUDE_PAC); - /* Map principals from foreign (possibly non-AD) realms */ - setflag(c_flags, KRB5_KDB_FLAG_MAP_PRINCIPALS); - - assert(c_nprincs == 0); /* should not have been looked up already */ - - c_nprincs = 1; - errcode = krb5_db_get_principal_ext(kdc_context, - header_enc_tkt->client, - c_flags, - &client, - &c_nprincs, - &more); - /* - * We can ignore errors because the principal may be a - * valid cross-realm principal for which we have no local - * mapping. But we do want to check that at most one entry - * was returned. - */ - if (errcode == 0 && (more || c_nprincs > 1)) { - errcode = KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE; - goto cleanup; - } else if (errcode) { - c_nprincs = 0; - } - } + /* + * If we are not doing protocol transition/constrained delegation + * and there was no authorization data included, try to lookup + * the client principal as it may be mapped to a local account. + * + * Always validate authorization data for constrained delegation + * because we must validate the KDC signatures. + */ + if (!isflagset(c_flags, KRB5_KDB_FLAGS_S4U) && + header_enc_tkt->authorization_data == NULL) { + + /* Generate authorization data so we can include it in ticket */ + setflag(c_flags, KRB5_KDB_FLAG_INCLUDE_PAC); + /* Map principals from foreign (possibly non-AD) realms */ + setflag(c_flags, KRB5_KDB_FLAG_MAP_PRINCIPALS); + + assert(c_nprincs == 0); /* should not have been looked up already */ + + c_nprincs = 1; + errcode = krb5_db_get_principal_ext(kdc_context, + header_enc_tkt->client, + c_flags, + &client, + &c_nprincs, + &more); + /* + * We can ignore errors because the principal may be a + * valid cross-realm principal for which we have no local + * mapping. But we do want to check that at most one entry + * was returned. + */ + if (errcode == 0 && (more || c_nprincs > 1)) { + errcode = KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE; + goto cleanup; + } else if (errcode) { + c_nprincs = 0; + } + } } enc_tkt_reply.authorization_data = NULL; if (isflagset(c_flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION) && - is_local_principal(header_enc_tkt->client)) - enc_tkt_reply.client = for_user->user; + is_local_principal(header_enc_tkt->client)) + enc_tkt_reply.client = for_user->user; else - enc_tkt_reply.client = header_enc_tkt->client; + enc_tkt_reply.client = header_enc_tkt->client; errcode = handle_authdata(kdc_context, - c_flags, - (c_nprincs != 0) ? &client : NULL, - &server, - (k_nprincs != 0) ? &krbtgt : NULL, - subkey != NULL ? subkey : - header_ticket->enc_part2->session, - &encrypting_key, /* U2U or server key */ - pkt, - request, - for_user ? for_user->user : NULL, - header_enc_tkt, - &enc_tkt_reply); + c_flags, + (c_nprincs != 0) ? &client : NULL, + &server, + (k_nprincs != 0) ? &krbtgt : NULL, + subkey != NULL ? subkey : + header_ticket->enc_part2->session, + &encrypting_key, /* U2U or server key */ + pkt, + request, + for_user ? for_user->user : NULL, + header_enc_tkt, + &enc_tkt_reply); if (errcode) { - krb5_klog_syslog(LOG_INFO, "TGS_REQ : handle_authdata (%d)", errcode); - status = "HANDLE_AUTHDATA"; - goto cleanup; + krb5_klog_syslog(LOG_INFO, "TGS_REQ : handle_authdata (%d)", errcode); + status = "HANDLE_AUTHDATA"; + goto cleanup; } if (is_referral && isflagset(s_flags, KRB5_KDB_FLAG_CANONICALIZE)) { - errcode = return_svr_referral_data(kdc_context, - &server, &reply_encpart); - if (errcode) { - status = "KDC_RETURN_ENC_PADATA"; - goto cleanup; - } + errcode = return_svr_referral_data(kdc_context, + &server, &reply_encpart); + if (errcode) { + status = "KDC_RETURN_ENC_PADATA"; + goto cleanup; + } } enc_tkt_reply.session = &session_key; @@ -751,87 +771,87 @@ tgt_again: /* 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)) { - /* tgt issued by local realm or issued by realm of client */ - enc_tkt_reply.transited = header_enc_tkt->transited; + realm_compare(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 { - /* tgt issued by some other realm and not the realm of the client */ - /* assemble new transited field into allocated storage */ - if (header_enc_tkt->transited.tr_type != - KRB5_DOMAIN_X500_COMPRESS) { - status = "BAD_TRTYPE"; - errcode = KRB5KDC_ERR_TRTYPE_NOSUPP; - goto cleanup; - } - enc_tkt_transited.tr_type = KRB5_DOMAIN_X500_COMPRESS; - enc_tkt_transited.magic = 0; - enc_tkt_transited.tr_contents.magic = 0; - enc_tkt_transited.tr_contents.data = 0; - enc_tkt_transited.tr_contents.length = 0; - enc_tkt_reply.transited = enc_tkt_transited; - if ((errcode = - add_to_transited(&header_enc_tkt->transited.tr_contents, - &enc_tkt_reply.transited.tr_contents, - header_ticket->server, - enc_tkt_reply.client, - request->server))) { - status = "ADD_TR_FAIL"; - goto cleanup; - } - newtransited = 1; + /* tgt issued by some other realm and not the realm of the client */ + /* assemble new transited field into allocated storage */ + if (header_enc_tkt->transited.tr_type != + KRB5_DOMAIN_X500_COMPRESS) { + status = "BAD_TRTYPE"; + errcode = KRB5KDC_ERR_TRTYPE_NOSUPP; + goto cleanup; + } + enc_tkt_transited.tr_type = KRB5_DOMAIN_X500_COMPRESS; + enc_tkt_transited.magic = 0; + enc_tkt_transited.tr_contents.magic = 0; + enc_tkt_transited.tr_contents.data = 0; + enc_tkt_transited.tr_contents.length = 0; + enc_tkt_reply.transited = enc_tkt_transited; + if ((errcode = + add_to_transited(&header_enc_tkt->transited.tr_contents, + &enc_tkt_reply.transited.tr_contents, + header_ticket->server, + enc_tkt_reply.client, + request->server))) { + status = "ADD_TR_FAIL"; + goto cleanup; + } + newtransited = 1; } if (isflagset(c_flags, KRB5_KDB_FLAG_CROSS_REALM)) { - errcode = validate_transit_path(kdc_context, header_enc_tkt->client, - &server, - (k_nprincs != 0) ? &krbtgt : NULL); - if (errcode) { - status = "NON_TRANSITIVE"; - goto cleanup; - } + errcode = validate_transit_path(kdc_context, header_enc_tkt->client, + &server, + (k_nprincs != 0) ? &krbtgt : NULL); + if (errcode) { + status = "NON_TRANSITIVE"; + goto cleanup; + } } if (!isflagset (request->kdc_options, KDC_OPT_DISABLE_TRANSITED_CHECK)) { - unsigned int tlen; - char *tdots; - - errcode = kdc_check_transited_list (kdc_context, - &enc_tkt_reply.transited.tr_contents, - krb5_princ_realm (kdc_context, header_enc_tkt->client), - krb5_princ_realm (kdc_context, request->server)); - tlen = enc_tkt_reply.transited.tr_contents.length; - tdots = tlen > 125 ? "..." : ""; - tlen = tlen > 125 ? 125 : tlen; - - if (errcode == 0) { - setflag (enc_tkt_reply.flags, TKT_FLG_TRANSIT_POLICY_CHECKED); - } else if (errcode == KRB5KRB_AP_ERR_ILL_CR_TKT) - krb5_klog_syslog (LOG_INFO, - "bad realm transit path from '%s' to '%s' " - "via '%.*s%s'", - cname ? cname : "", - sname ? sname : "", - tlen, - enc_tkt_reply.transited.tr_contents.data, - tdots); - else { - emsg = krb5_get_error_message(kdc_context, errcode); - krb5_klog_syslog (LOG_ERR, - "unexpected error checking transit from " - "'%s' to '%s' via '%.*s%s': %s", - cname ? cname : "", - sname ? sname : "", - tlen, - enc_tkt_reply.transited.tr_contents.data, - tdots, emsg); - krb5_free_error_message(kdc_context, emsg); - emsg = NULL; - } + unsigned int tlen; + char *tdots; + + errcode = kdc_check_transited_list (kdc_context, + &enc_tkt_reply.transited.tr_contents, + krb5_princ_realm (kdc_context, header_enc_tkt->client), + krb5_princ_realm (kdc_context, request->server)); + tlen = enc_tkt_reply.transited.tr_contents.length; + tdots = tlen > 125 ? "..." : ""; + tlen = tlen > 125 ? 125 : tlen; + + if (errcode == 0) { + setflag (enc_tkt_reply.flags, TKT_FLG_TRANSIT_POLICY_CHECKED); + } else if (errcode == KRB5KRB_AP_ERR_ILL_CR_TKT) + krb5_klog_syslog (LOG_INFO, + "bad realm transit path from '%s' to '%s' " + "via '%.*s%s'", + cname ? cname : "", + sname ? sname : "", + tlen, + enc_tkt_reply.transited.tr_contents.data, + tdots); + else { + emsg = krb5_get_error_message(kdc_context, errcode); + krb5_klog_syslog (LOG_ERR, + "unexpected error checking transit from " + "'%s' to '%s' via '%.*s%s': %s", + cname ? cname : "", + sname ? sname : "", + tlen, + enc_tkt_reply.transited.tr_contents.data, + tdots, emsg); + krb5_free_error_message(kdc_context, emsg); + emsg = NULL; + } } else - krb5_klog_syslog (LOG_INFO, "not checking transit path"); + krb5_klog_syslog (LOG_INFO, "not checking transit path"); if (reject_bad_transit - && !isflagset (enc_tkt_reply.flags, TKT_FLG_TRANSIT_POLICY_CHECKED)) { - errcode = KRB5KDC_ERR_POLICY; - status = "BAD_TRANSIT"; - goto cleanup; + && !isflagset (enc_tkt_reply.flags, TKT_FLG_TRANSIT_POLICY_CHECKED)) { + errcode = KRB5KDC_ERR_POLICY; + status = "BAD_TRANSIT"; + goto cleanup; } ticket_reply.enc_part2 = &enc_tkt_reply; @@ -843,44 +863,44 @@ tgt_again: * the second ticket. */ if (isflagset(request->kdc_options, KDC_OPT_ENC_TKT_IN_SKEY)) { - /* - * Make sure the client for the second ticket matches - * requested server. - */ - krb5_enc_tkt_part *t2enc = request->second_ticket[st_idx]->enc_part2; - krb5_principal client2 = t2enc->client; - if (!krb5_principal_compare(kdc_context, request->server, client2)) { - if ((errcode = krb5_unparse_name(kdc_context, client2, &altcname))) - altcname = 0; - if (altcname != NULL) - limit_string(altcname); - - errcode = KRB5KDC_ERR_SERVER_NOMATCH; - status = "2ND_TKT_MISMATCH"; - goto cleanup; - } - - ticket_reply.enc_part.kvno = 0; - ticket_reply.enc_part.enctype = t2enc->session->enctype; - st_idx++; + /* + * Make sure the client for the second ticket matches + * requested server. + */ + krb5_enc_tkt_part *t2enc = request->second_ticket[st_idx]->enc_part2; + krb5_principal client2 = t2enc->client; + if (!krb5_principal_compare(kdc_context, request->server, client2)) { + if ((errcode = krb5_unparse_name(kdc_context, client2, &altcname))) + altcname = 0; + if (altcname != NULL) + limit_string(altcname); + + errcode = KRB5KDC_ERR_SERVER_NOMATCH; + status = "2ND_TKT_MISMATCH"; + goto cleanup; + } + + ticket_reply.enc_part.kvno = 0; + ticket_reply.enc_part.enctype = t2enc->session->enctype; + st_idx++; } else { - ticket_reply.enc_part.kvno = server_key->key_data_kvno; + ticket_reply.enc_part.kvno = server_key->key_data_kvno; } errcode = krb5_encrypt_tkt_part(kdc_context, &encrypting_key, - &ticket_reply); + &ticket_reply); if (!isflagset(request->kdc_options, KDC_OPT_ENC_TKT_IN_SKEY)) - krb5_free_keyblock_contents(kdc_context, &encrypting_key); + krb5_free_keyblock_contents(kdc_context, &encrypting_key); if (errcode) { - status = "TKT_ENCRYPT"; - goto cleanup; + status = "TKT_ENCRYPT"; + goto cleanup; } /* Start assembling the response */ reply.msg_type = KRB5_TGS_REP; - reply.padata = 0; /* always */ + reply.padata = 0;/* always */ reply.client = enc_tkt_reply.client; - reply.enc_part.kvno = 0; /* We are using the session key */ + reply.enc_part.kvno = 0;/* We are using the session key */ reply.ticket = &ticket_reply; reply_encpart.session = &session_key; @@ -894,14 +914,14 @@ tgt_again: /* starttime is optional, and treated as authtime if not present. so we can nuke it if it matches */ if (enc_tkt_reply.times.starttime == enc_tkt_reply.times.authtime) - enc_tkt_reply.times.starttime = 0; + enc_tkt_reply.times.starttime = 0; nolrentry.lr_type = KRB5_LRQ_NONE; nolrentry.value = 0; nolrarray[0] = &nolrentry; nolrarray[1] = 0; - reply_encpart.last_req = nolrarray; /* not available for TGS reqs */ - reply_encpart.key_exp = 0; /* ditto */ + reply_encpart.last_req = nolrarray; /* not available for TGS reqs */ + reply_encpart.key_exp = 0;/* ditto */ reply_encpart.flags = enc_tkt_reply.flags; reply_encpart.server = ticket_reply.server; @@ -909,83 +929,83 @@ tgt_again: in the AP_REQ */ reply.enc_part.enctype = subkey ? subkey->enctype : - header_ticket->enc_part2->session->enctype; + header_ticket->enc_part2->session->enctype; errcode = krb5_encode_kdc_rep(kdc_context, KRB5_TGS_REP, &reply_encpart, - subkey ? 1 : 0, - subkey ? subkey : - header_ticket->enc_part2->session, - &reply, response); + subkey ? 1 : 0, + subkey ? subkey : + header_ticket->enc_part2->session, + &reply, response); if (errcode) { - status = "ENCODE_KDC_REP"; + status = "ENCODE_KDC_REP"; } else { - status = "ISSUE"; + status = "ISSUE"; } memset(ticket_reply.enc_part.ciphertext.data, 0, - ticket_reply.enc_part.ciphertext.length); + ticket_reply.enc_part.ciphertext.length); free(ticket_reply.enc_part.ciphertext.data); /* these parts are left on as a courtesy from krb5_encode_kdc_rep so we can use them in raw form if needed. But, we don't... */ memset(reply.enc_part.ciphertext.data, 0, - reply.enc_part.ciphertext.length); + reply.enc_part.ciphertext.length); free(reply.enc_part.ciphertext.data); cleanup: assert(status != NULL); if (errcode) - emsg = krb5_get_error_message (kdc_context, errcode); + emsg = krb5_get_error_message (kdc_context, errcode); log_tgs_req(from, request, &reply, cname, sname, altcname, authtime, - c_flags, s4u_name, status, errcode, emsg); + c_flags, s4u_name, status, errcode, emsg); if (errcode) { - krb5_free_error_message (kdc_context, emsg); - emsg = NULL; + krb5_free_error_message (kdc_context, emsg); + emsg = NULL; } if (errcode) { int got_err = 0; - if (status == 0) { - status = krb5_get_error_message (kdc_context, errcode); - got_err = 1; - } - errcode -= ERROR_TABLE_BASE_krb5; - if (errcode < 0 || errcode > 128) - errcode = KRB_ERR_GENERIC; - - retval = prepare_error_tgs(request, header_ticket, errcode, - nprincs ? server.princ : NULL, - response, status); - if (got_err) { - krb5_free_error_message (kdc_context, status); - status = 0; - } + if (status == 0) { + status = krb5_get_error_message (kdc_context, errcode); + got_err = 1; + } + errcode -= ERROR_TABLE_BASE_krb5; + if (errcode < 0 || errcode > 128) + errcode = KRB_ERR_GENERIC; + + retval = prepare_error_tgs(request, header_ticket, errcode, + nprincs ? server.princ : NULL, + response, status); + if (got_err) { + krb5_free_error_message (kdc_context, status); + status = 0; + } } if (header_ticket != NULL) - krb5_free_ticket(kdc_context, header_ticket); + krb5_free_ticket(kdc_context, header_ticket); if (request != NULL) - krb5_free_kdc_req(kdc_context, request); + krb5_free_kdc_req(kdc_context, request); if (cname != NULL) - free(cname); + free(cname); if (sname != NULL) - free(sname); + free(sname); if (nprincs != 0) - krb5_db_free_principal(kdc_context, &server, 1); + krb5_db_free_principal(kdc_context, &server, 1); if (session_key.contents != NULL) - krb5_free_keyblock_contents(kdc_context, &session_key); + krb5_free_keyblock_contents(kdc_context, &session_key); if (newtransited) - free(enc_tkt_reply.transited.tr_contents.data); + free(enc_tkt_reply.transited.tr_contents.data); if (k_nprincs) - krb5_db_free_principal(kdc_context, &krbtgt, k_nprincs); + krb5_db_free_principal(kdc_context, &krbtgt, k_nprincs); if (c_nprincs) - krb5_db_free_principal(kdc_context, &client, c_nprincs); + krb5_db_free_principal(kdc_context, &client, c_nprincs); if (for_user != NULL) - krb5_free_pa_for_user(kdc_context, for_user); + krb5_free_pa_for_user(kdc_context, for_user); if (kdc_issued_auth_data != NULL) - krb5_free_authdata(kdc_context, kdc_issued_auth_data); + krb5_free_authdata(kdc_context, kdc_issued_auth_data); if (s4u_name != NULL) - free(s4u_name); + free(s4u_name); if (subkey != NULL) - krb5_free_keyblock(kdc_context, subkey); + krb5_free_keyblock(kdc_context, subkey); return retval; } @@ -993,7 +1013,7 @@ cleanup: static krb5_error_code prepare_error_tgs (krb5_kdc_req *request, krb5_ticket *ticket, int error, krb5_principal canon_server, - krb5_data **response, const char *status) + krb5_data **response, const char *status) { krb5_error errpkt; krb5_error_code retval; @@ -1003,21 +1023,21 @@ prepare_error_tgs (krb5_kdc_req *request, krb5_ticket *ticket, int error, errpkt.cusec = 0; if ((retval = krb5_us_timeofday(kdc_context, &errpkt.stime, - &errpkt.susec))) - return(retval); + &errpkt.susec))) + return(retval); errpkt.error = error; errpkt.server = request->server; if (ticket && ticket->enc_part2) - errpkt.client = ticket->enc_part2->client; + errpkt.client = ticket->enc_part2->client; else - errpkt.client = NULL; + errpkt.client = NULL; errpkt.text.length = strlen(status) + 1; if (!(errpkt.text.data = strdup(status))) - return ENOMEM; + return ENOMEM; if (!(scratch = (krb5_data *)malloc(sizeof(*scratch)))) { - free(errpkt.text.data); - return ENOMEM; + free(errpkt.text.data); + return ENOMEM; } errpkt.e_data.length = 0; errpkt.e_data.data = NULL; @@ -1025,9 +1045,9 @@ prepare_error_tgs (krb5_kdc_req *request, krb5_ticket *ticket, int error, retval = krb5_mk_error(kdc_context, &errpkt, scratch); free(errpkt.text.data); if (retval) - free(scratch); + free(scratch); else - *response = scratch; + *response = scratch; return retval; } @@ -1039,7 +1059,7 @@ prepare_error_tgs (krb5_kdc_req *request, krb5_ticket *ticket, int error, */ static void find_alternate_tgs(krb5_kdc_req *request, krb5_db_entry *server, - krb5_boolean *more, int *nprincs) + krb5_boolean *more, int *nprincs) { krb5_error_code retval; krb5_principal *plist, *pl2; @@ -1055,10 +1075,10 @@ find_alternate_tgs(krb5_kdc_req *request, krb5_db_entry *server, * the principal. */ if ((retval = krb5_walk_realm_tree(kdc_context, - krb5_princ_realm(kdc_context, request->server), - krb5_princ_component(kdc_context, request->server, 1), - &plist, KRB5_REALM_BRANCH_CHAR))) - return; + krb5_princ_realm(kdc_context, request->server), + krb5_princ_component(kdc_context, request->server, 1), + &plist, KRB5_REALM_BRANCH_CHAR))) + return; /* move to the end */ for (pl2 = plist; *pl2; pl2++); @@ -1066,43 +1086,43 @@ find_alternate_tgs(krb5_kdc_req *request, krb5_db_entry *server, /* the first entry in this array is for krbtgt/local@local, so we ignore it */ while (--pl2 > plist) { - *nprincs = 1; - tmp = *krb5_princ_realm(kdc_context, *pl2); - krb5_princ_set_realm(kdc_context, *pl2, - krb5_princ_realm(kdc_context, tgs_server)); - retval = get_principal(kdc_context, *pl2, server, nprincs, more); - krb5_princ_set_realm(kdc_context, *pl2, &tmp); - if (retval) { - *nprincs = 0; - *more = FALSE; - krb5_free_realm_tree(kdc_context, plist); - return; - } - if (*more) { - krb5_db_free_principal(kdc_context, server, *nprincs); - continue; - } else if (*nprincs == 1) { - /* Found it! */ - krb5_principal tmpprinc; - - tmp = *krb5_princ_realm(kdc_context, *pl2); - krb5_princ_set_realm(kdc_context, *pl2, - krb5_princ_realm(kdc_context, tgs_server)); - if ((retval = krb5_copy_principal(kdc_context, *pl2, &tmpprinc))) { - krb5_db_free_principal(kdc_context, server, *nprincs); - krb5_princ_set_realm(kdc_context, *pl2, &tmp); - continue; - } - krb5_princ_set_realm(kdc_context, *pl2, &tmp); - - krb5_free_principal(kdc_context, request->server); - request->server = tmpprinc; - log_tgs_alt_tgt(request->server); - krb5_free_realm_tree(kdc_context, plist); - return; - } - krb5_db_free_principal(kdc_context, server, *nprincs); - continue; + *nprincs = 1; + tmp = *krb5_princ_realm(kdc_context, *pl2); + krb5_princ_set_realm(kdc_context, *pl2, + krb5_princ_realm(kdc_context, tgs_server)); + retval = get_principal(kdc_context, *pl2, server, nprincs, more); + krb5_princ_set_realm(kdc_context, *pl2, &tmp); + if (retval) { + *nprincs = 0; + *more = FALSE; + krb5_free_realm_tree(kdc_context, plist); + return; + } + if (*more) { + krb5_db_free_principal(kdc_context, server, *nprincs); + continue; + } else if (*nprincs == 1) { + /* Found it! */ + krb5_principal tmpprinc; + + tmp = *krb5_princ_realm(kdc_context, *pl2); + krb5_princ_set_realm(kdc_context, *pl2, + krb5_princ_realm(kdc_context, tgs_server)); + if ((retval = krb5_copy_principal(kdc_context, *pl2, &tmpprinc))) { + krb5_db_free_principal(kdc_context, server, *nprincs); + krb5_princ_set_realm(kdc_context, *pl2, &tmp); + continue; + } + krb5_princ_set_realm(kdc_context, *pl2, &tmp); + + krb5_free_principal(kdc_context, request->server); + request->server = tmpprinc; + log_tgs_alt_tgt(request->server); + krb5_free_realm_tree(kdc_context, plist); + return; + } + krb5_db_free_principal(kdc_context, server, *nprincs); + continue; } *nprincs = 0; @@ -1113,7 +1133,7 @@ find_alternate_tgs(krb5_kdc_req *request, krb5_db_entry *server, /* is_substr - verfies if d1 contains d2->data with head/trail-ing whitespaces */ -static krb5_boolean +static krb5_int32 is_substr ( char *d1, krb5_data *d2) { krb5_boolean ret = FALSE; @@ -1121,8 +1141,9 @@ is_substr ( char *d1, krb5_data *d2) if ( d1 && d2 && d2->data && (d2->length+2 <= strlen(d1))){ if ((new_d2 = calloc(1,d2->length+1))) { strncpy(new_d2,d2->data,d2->length); - asprintf( &d2_formated, "%c%s%c", ' ', new_d2, ' '); - if ( d2_formated != 0 && strstr( d1, d2_formated) != NULL) + if (asprintf( &d2_formated, "%c%s%c", ' ', new_d2, ' ') < 0) + ret = ENOMEM; + else if (d2_formated != 0 && strstr(d1, d2_formated) != NULL) ret = TRUE; free(new_d2); free(d2_formated); @@ -1131,5 +1152,3 @@ is_substr ( char *d1, krb5_data *d2) return ret; } - - diff --git a/src/kdc/main.c b/src/kdc/main.c index ee5d5907b..7d260f296 100644 --- a/src/kdc/main.c +++ b/src/kdc/main.c @@ -166,71 +166,84 @@ finish_realm(kdc_realm_t *rdp) free(rdp); } -static void +static krb5_error_code handle_referrals(krb5_realm_params *rparams, char *no_refrls, char *host_based_srvcs, kdc_realm_t *rdp ) { int i = 0; - if ( no_refrls == NULL || ( strchr(no_refrls,'*'))==0) { - if ( no_refrls!=0 ){ + krb5_error_code retval = 0; + if (no_refrls == NULL || strchr(no_refrls, '*') == NULL) { + if (no_refrls != NULL){ if (rparams && rparams->realm_no_host_referral) { - asprintf(&(rdp->realm_no_host_referral), "%s%s%s%s%s", - " ", no_refrls," ",rparams->realm_no_host_referral, " "); + if (asprintf(&(rdp->realm_no_host_referral), "%s%s%s%s%s", + " ", no_refrls," ",rparams->realm_no_host_referral, " ") < 0) + retval = ENOMEM; } else { - asprintf(&(rdp->realm_no_host_referral),"%s%s%s", " ", no_refrls," "); + if(asprintf(&(rdp->realm_no_host_referral),"%s%s%s", " ", no_refrls, " ") < 0) + retval = ENOMEM; } } else { if (rparams && rparams->realm_no_host_referral) { - asprintf(&(rdp->realm_no_host_referral),"%s%s%s", " ", rparams->realm_no_host_referral," "); + if (asprintf(&(rdp->realm_no_host_referral),"%s%s%s", " ", + rparams->realm_no_host_referral, " ") < 0) + retval = ENOMEM; } else - rdp->realm_no_host_referral = 0; + rdp->realm_no_host_referral = NULL; } - if ( rdp->realm_no_host_referral && - strlen(rdp->realm_no_host_referral)>1 && strchr(rdp->realm_no_host_referral, '*')!=0) { - rdp->realm_no_host_referral = strdup("*"); + if (rdp->realm_no_host_referral && + strlen(rdp->realm_no_host_referral) > 1 && strchr(rdp->realm_no_host_referral, '*') != NULL) { + rdp->realm_no_host_referral = strdup("*"); } else { /* only if no_host_referral != "*" */ - if ( (host_based_srvcs !=0 && strchr(host_based_srvcs,'*')!=0) || - (rparams && rparams->realm_host_based_services && strchr(rparams->realm_host_based_services,'*')!=0)) { - asprintf(&(rdp->realm_host_based_services),"%s", "*"); + if ((host_based_srvcs != NULL && strchr(host_based_srvcs,'*') != NULL) || + (rparams && rparams->realm_host_based_services && + strchr(rparams->realm_host_based_services,'*') != NULL)) { + if (asprintf(&(rdp->realm_host_based_services),"%s", "*") < 0) + retval = ENOMEM; } else { - if ( host_based_srvcs !=0) { + if (host_based_srvcs != NULL) { if (rparams && rparams->realm_host_based_services) { - asprintf(&(rdp->realm_host_based_services),"%s%s%s%s%s", - " ", host_based_srvcs," ",rparams->realm_host_based_services," "); + if (asprintf(&(rdp->realm_host_based_services),"%s%s%s%s%s", + " ", host_based_srvcs," ",rparams->realm_host_based_services," ") < 0) + retval = ENOMEM; } else - asprintf(&(rdp->realm_host_based_services),"%s%s%s", " ", host_based_srvcs," "); + if (asprintf(&(rdp->realm_host_based_services),"%s%s%s", " ", + host_based_srvcs, " ") < 0) + retval = ENOMEM; } else { if (rparams && rparams->realm_host_based_services) { - asprintf(&(rdp->realm_host_based_services),"%s%s%s"," ", rparams->realm_host_based_services," "); + if (asprintf(&(rdp->realm_host_based_services),"%s%s%s", " ", + rparams->realm_host_based_services, " ") < 0) + retval = ENOMEM; } else - rdp->realm_host_based_services = 0; + rdp->realm_host_based_services = NULL; } } /* Walk realm_host_based_services and realm_no_host_referral and replace all ',' with whitespace */ i = 0; - while ( rdp && rdp->realm_host_based_services && (rdp->realm_host_based_services)[i] != 0){ - if (( rdp->realm_host_based_services)[i]==',' ) - ( rdp->realm_host_based_services)[i]=' '; + while (rdp && rdp->realm_host_based_services && (rdp->realm_host_based_services)[i] != 0){ + if ((rdp->realm_host_based_services)[i] == ',') + (rdp->realm_host_based_services)[i] = ' '; i++; } i = 0; - while ( rdp && rdp->realm_no_host_referral && ( rdp->realm_no_host_referral)[i] != 0){ - if (( rdp->realm_no_host_referral)[i]==',' ) - ( rdp->realm_no_host_referral)[i]=' '; + while (rdp && rdp->realm_no_host_referral && ( rdp->realm_no_host_referral)[i] != 0){ + if ((rdp->realm_no_host_referral)[i] == ',') + (rdp->realm_no_host_referral)[i] = ' '; i++; } } } else { - if ( no_refrls != NULL && strchr(no_refrls,'*') !=0 ) - asprintf(&(rdp->realm_no_host_referral),"%s", "* "); - else - rdp->realm_no_host_referral = 0; + if (no_refrls != NULL && strchr(no_refrls,'*') != NULL) { + if (asprintf(&(rdp->realm_no_host_referral),"%s", "*") < 0) + retval = ENOMEM; + } else + rdp->realm_no_host_referral = NULL; } - return; + return retval; } /* * Initialize a realm control structure from the alternate profile or from @@ -320,7 +333,9 @@ init_realm(char *progname, kdc_realm_t *rdp, char *realm, rparams->realm_max_rlife : KRB5_KDB_MAX_RLIFE; /* Handle KDC referrals */ - handle_referrals(rparams, no_refrls, host_based_srvcs, rdp ); + kret = handle_referrals(rparams, no_refrls, host_based_srvcs, rdp); + if (kret == ENOMEM) + goto whoops; if (rparams) krb5_free_realm_params(rdp->realm_context, rparams); @@ -511,8 +526,8 @@ initialize_realms(krb5_context kcontext, int argc, char **argv) krb5_pointer aprof; const char *hierarchy[3]; char **db_args = NULL; - char *no_refrls = 0; - char *host_based_srvcs = 0; + char *no_refrls = NULL; + char *host_based_srvcs = NULL; int db_args_size = 0; extern char *optarg; @@ -531,20 +546,17 @@ initialize_realms(krb5_context kcontext, int argc, char **argv) max_dgram_reply_size = MAX_DGRAM_SIZE; /* The service name "*" means any service. */ hierarchy[1] = "no_host_referral"; - if (krb5_aprof_get_string_all(aprof, hierarchy, &no_refrls)){ - no_refrls = 0; - } else { - if ( strlen(no_refrls) && strchr(no_refrls, '*')) { + if (!krb5_aprof_get_string_all(aprof, hierarchy, &no_refrls)){ + if (no_refrls != NULL && strlen(no_refrls) && strchr(no_refrls, '*')) { no_refrls = strdup("*"); } } - if ( no_refrls == 0 || strchr(no_refrls, '*')==0) { + if (no_refrls == 0 || strchr(no_refrls, '*') == NULL) { hierarchy[1] = "host_based_services"; - if (krb5_aprof_get_string_all(aprof, hierarchy, &host_based_srvcs)) - host_based_srvcs = 0; - else - if ( strchr( host_based_srvcs, '*')) { - host_based_srvcs = strdup("*"); + if (!krb5_aprof_get_string_all(aprof, hierarchy, &host_based_srvcs)) { + if (strchr(host_based_srvcs, '*')) { + host_based_srvcs = strdup("*"); + } } } @@ -844,6 +856,3 @@ int main(int argc, char **argv) return errout; } - - - -- 2.26.2