diff options
author | Tom Yu <tlyu@mit.edu> | 2012-09-21 20:49:29 -0400 |
---|---|---|
committer | Tom Yu <tlyu@mit.edu> | 2012-10-15 19:41:16 -0400 |
commit | 2b03bb01e37faee55b9e60c90cc8076549de0d6d (patch) | |
tree | 1e6e8c8d1c3b93f4f14514c7b9f3a414c934f0c4 /src/kdc | |
parent | 3b8b18d6a87f5d2b4f255ee2e7d34ae6b48b4bf6 (diff) | |
download | krb5-2b03bb01e37faee55b9e60c90cc8076549de0d6d.tar.gz krb5-2b03bb01e37faee55b9e60c90cc8076549de0d6d.tar.xz krb5-2b03bb01e37faee55b9e60c90cc8076549de0d6d.zip |
Clean up domain->realm referrals
Clean up domain->realm referrals by breaking prep_reprocess_tgs_req()
into smaller functions. Give the resulting functions more descriptive
names. Also delete an unnecessary and almost exact copy of
krb5_get_host_realm().
Diffstat (limited to 'src/kdc')
-rw-r--r-- | src/kdc/do_tgs_req.c | 172 | ||||
-rw-r--r-- | src/kdc/kdc_transit.c | 2 | ||||
-rw-r--r-- | src/kdc/kdc_util.c | 59 | ||||
-rw-r--r-- | src/kdc/kdc_util.h | 2 |
4 files changed, 91 insertions, 144 deletions
diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c index 52d456ea50..cb9e142f75 100644 --- a/src/kdc/do_tgs_req.c +++ b/src/kdc/do_tgs_req.c @@ -77,7 +77,7 @@ 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(kdc_realm_t *, krb5_kdc_req *, krb5_principal *); +find_referral_tgs(kdc_realm_t *, krb5_kdc_req *, krb5_principal *); static krb5_error_code db_get_svc_princ(krb5_context, krb5_principal, krb5_flags, @@ -1065,94 +1065,99 @@ cleanup: return retval; } -static krb5_int32 -prep_reprocess_req(kdc_realm_t *kdc_active_realm, krb5_kdc_req *request, - krb5_principal *krbtgt_princ) +/* + * Check whether the request satisfies the conditions for generating a referral + * TGT. The caller checks whether the hostname component looks like a FQDN. + */ +static krb5_boolean +is_referral_req(kdc_realm_t *kdc_active_realm, krb5_kdc_req *request) { - krb5_error_code retval = KRB5KRB_AP_ERR_BADMATCH; - char **realms, **cpp, *temp_buf=NULL; - krb5_data *comp1 = NULL, *comp2 = NULL; - char *comp1_str = NULL; - - /* By now we know that server principal name is unknown. - * 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 - * or name type is NT-UNKNOWN and - * 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) && - !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); - - comp1_str = calloc(1,comp1->length+1); - if (!comp1_str) { - retval = ENOMEM; - goto cleanup; - } - strlcpy(comp1_str,comp1->data,comp1->length+1); - - if ((krb5_princ_type(kdc_context, request->server) == KRB5_NT_SRV_HST || - krb5_princ_type(kdc_context, request->server) == KRB5_NT_SRV_INST || - (krb5_princ_type(kdc_context, request->server) == KRB5_NT_UNKNOWN && - kdc_active_realm->realm_host_based_services != NULL && - (krb5_match_config_pattern(kdc_active_realm->realm_host_based_services, - comp1_str) == TRUE || - krb5_match_config_pattern(kdc_active_realm->realm_host_based_services, - KRB5_CONF_ASTERISK) == TRUE))) && - (kdc_active_realm->realm_no_host_referral == NULL || - (krb5_match_config_pattern(kdc_active_realm->realm_no_host_referral, - KRB5_CONF_ASTERISK) == FALSE && - krb5_match_config_pattern(kdc_active_realm->realm_no_host_referral, - comp1_str) == FALSE))) { - - if (memchr(comp2->data, '.', comp2->length) == NULL) - goto cleanup; - temp_buf = calloc(1, comp2->length+1); - if (!temp_buf) { - retval = ENOMEM; + krb5_boolean ret = FALSE; + char *stype = NULL; + char *ref_services = kdc_active_realm->realm_host_based_services; + char *nonref_services = kdc_active_realm->realm_no_host_referral; + + if (!(request->kdc_options & KDC_OPT_CANONICALIZE)) + return FALSE; + + if (request->kdc_options & KDC_OPT_ENC_TKT_IN_SKEY) + return FALSE; + + if (krb5_princ_size(kdc_context, request->server) != 2) + return FALSE; + + stype = data2string(krb5_princ_component(kdc_context, request->server, 0)); + if (stype == NULL) + return FALSE; + switch (krb5_princ_type(kdc_context, request->server)) { + case KRB5_NT_UNKNOWN: + /* Allow referrals for NT-UNKNOWN principals, if configured. */ + if (kdc_active_realm->realm_host_based_services != NULL) { + if (!krb5_match_config_pattern(ref_services, stype) && + !krb5_match_config_pattern(ref_services, KRB5_CONF_ASTERISK)) goto cleanup; - } - strlcpy(temp_buf, comp2->data,comp2->length+1); - retval = krb5int_get_domain_realm_mapping(kdc_context, temp_buf, &realms); - free(temp_buf); - if (retval) { - /* no match found */ - kdc_err(kdc_context, retval, "unable to find realm of host"); - goto cleanup; - } - if (realms == 0) { - retval = KRB5KRB_AP_ERR_BADMATCH; + } else + goto cleanup; + /* FALLTHROUGH */ + case KRB5_NT_SRV_HST: + case KRB5_NT_SRV_INST: + /* Deny referrals for specific service types, if configured. */ + if (kdc_active_realm->realm_no_host_referral != NULL) { + if (krb5_match_config_pattern(nonref_services, stype)) goto cleanup; - } - if (realms[0] == 0) { - free(realms); - retval = KRB5KRB_AP_ERR_BADMATCH; + if (krb5_match_config_pattern(nonref_services, KRB5_CONF_ASTERISK)) goto cleanup; - } - /* Modify request. - * Construct cross-realm tgt : krbtgt/REMOTE_REALM@LOCAL_REALM - * and use it as a principal in this req. - */ - retval = krb5_build_principal(kdc_context, krbtgt_princ, - (*request->server).realm.length, - (*request->server).realm.data, - "krbtgt", realms[0], (char *)0); - for (cpp = realms; *cpp; cpp++) - free(*cpp); } + ret = TRUE; + break; + default: + goto cleanup; + } +cleanup: + free(stype); + return ret; +} + +/* + * Find a remote realm TGS principal for an unknown host-based service + * principal. + */ +static krb5_int32 +find_referral_tgs(kdc_realm_t *kdc_active_realm, krb5_kdc_req *request, + krb5_principal *krbtgt_princ) +{ + krb5_error_code retval = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; + char **realms = NULL, *hostname = NULL; + krb5_data srealm = request->server->realm; + + if (!is_referral_req(kdc_active_realm, request)) + goto cleanup; + + hostname = data2string(krb5_princ_component(kdc_context, + request->server, 1)); + if (hostname == NULL) { + retval = ENOMEM; + goto cleanup; + } + /* If the hostname doesn't contain a '.', it's not a FQDN. */ + if (strchr(hostname, '.') == NULL) + goto cleanup; + retval = krb5_get_host_realm(kdc_context, hostname, &realms); + if (retval) { + /* no match found */ + kdc_err(kdc_context, retval, "unable to find realm of host"); + goto cleanup; + } + if (realms == NULL || realms[0] == '\0') { + retval = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; + goto cleanup; } + retval = krb5_build_principal(kdc_context, krbtgt_princ, + srealm.length, srealm.data, + "krbtgt", realms[0], (char *)0); cleanup: - free(comp1_str); + krb5_free_host_realm(kdc_context, realms); + free(hostname); return retval; } @@ -1186,8 +1191,7 @@ search_sprinc(kdc_realm_t *kdc_active_realm, krb5_kdc_req *req, goto cleanup; if (!is_cross_tgs_principal(req->server)) { - /* domain->realm referral */ - ret = prep_reprocess_req(kdc_active_realm, req, &reftgs); + ret = find_referral_tgs(kdc_active_realm, req, &reftgs); if (ret != 0) goto cleanup; ret = db_get_svc_princ(kdc_context, reftgs, flags, server, status); diff --git a/src/kdc/kdc_transit.c b/src/kdc/kdc_transit.c index 88b4616b27..9947761450 100644 --- a/src/kdc/kdc_transit.c +++ b/src/kdc/kdc_transit.c @@ -129,7 +129,7 @@ subrealm(char *r1, char *r2) * names. */ -static char * +char * data2string (krb5_data *d) { char *s; diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c index 10ed38314d..387a76cf3c 100644 --- a/src/kdc/kdc_util.c +++ b/src/kdc/kdc_util.c @@ -1881,65 +1881,6 @@ cleanup: return retval; } - -krb5_error_code -krb5int_get_domain_realm_mapping(krb5_context context, - const char *host, char ***realmsp) -{ - char **retrealms; - char *realm, *cp, *temp_realm; - krb5_error_code retval; - char temp_host[MAX_DNS_NAMELEN+1]; - - /* do sanity check and lower-case */ - retval = krb5int_clean_hostname(context, host, temp_host, sizeof temp_host); - if (retval) - return retval; - /* - Search for the best match for the host or domain. - Example: Given a host a.b.c.d, try to match on: - 1) a.b.c.d 2) .b.c.d. 3) b.c.d 4) .c.d 5) c.d 6) .d 7) d - */ - - cp = temp_host; - realm = (char *)NULL; - temp_realm = 0; - while (cp ) { - retval = profile_get_string(context->profile, KRB5_CONF_DOMAIN_REALM, cp, - 0, (char *)NULL, &temp_realm); - if (retval) - return retval; - if (temp_realm != (char *)NULL) - break; /* Match found */ - - /* Setup for another test */ - if (*cp == '.') { - cp++; - } else { - cp = strchr(cp, '.'); - } - } - if (temp_realm != (char*)NULL) { - realm = strdup(temp_realm); - profile_release_string(temp_realm); - if (!realm) { - return ENOMEM; - } - } - retrealms = (char **)calloc(2, sizeof(*retrealms)); - if (!retrealms) { - if (realm != (char *)NULL) - free(realm); - return ENOMEM; - } - - retrealms[0] = realm; - retrealms[1] = 0; - - *realmsp = retrealms; - return 0; -} - /* * Although the KDC doesn't call this function directly, * process_tcp_connection_read() in net-server.c does call it. diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h index b89bd99c73..8a5c66a911 100644 --- a/src/kdc/kdc_util.h +++ b/src/kdc/kdc_util.h @@ -400,4 +400,6 @@ int check_anon(kdc_realm_t *kdc_active_realm, krb5_principal client, krb5_principal server); int errcode_to_protocol(krb5_error_code code); +char *data2string(krb5_data *d); + #endif /* __KRB5_KDC_UTIL__ */ |