From: Zhanna Tsitkov Date: Fri, 23 Jan 2009 19:59:50 +0000 (+0000) Subject: Eliminate the need for the domain_realm mapping table on the client side by implement... X-Git-Tag: krb5-1.7-alpha1~39 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=f26dadeaae22b6843375ce1dd4e21b6ad2d3e099;p=krb5.git Eliminate the need for the domain_realm mapping table on the client side by implementing minimal referral support in the KDC git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@21792 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/include/adm.h b/src/include/adm.h index 34c195fa2..15b42d9ab 100644 --- a/src/include/adm.h +++ b/src/include/adm.h @@ -1,7 +1,7 @@ /* * include/krb5/adm.h * - * Copyright 1995,2001 by the Massachusetts Institute of Technology. + * Copyright 1995,2001,2009 by the Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may @@ -200,6 +200,8 @@ typedef struct __krb5_realm_params { char * realm_kdc_ports; char * realm_kdc_tcp_ports; char * realm_acl_file; + char * realm_host_based_services; + char * realm_no_host_referral; krb5_int32 realm_kadmind_port; krb5_enctype realm_enctype; krb5_deltat realm_max_life; diff --git a/src/include/adm_proto.h b/src/include/adm_proto.h index 04e6a4791..9d7002027 100644 --- a/src/include/adm_proto.h +++ b/src/include/adm_proto.h @@ -1,7 +1,7 @@ /* * include/krb5/adm_proto.h * - * Copyright 1995, 2007 by the Massachusetts Institute of Technology. + * Copyright 1995, 2007,2008,2009 by the Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may @@ -83,6 +83,8 @@ krb5_error_code krb5_aprof_get_deltat krb5_deltat *); krb5_error_code krb5_aprof_get_string (krb5_pointer, const char **, krb5_boolean, char **); +krb5_error_code krb5_aprof_get_string_all + (krb5_pointer, const char **, char **); krb5_error_code krb5_aprof_get_int32 (krb5_pointer, const char **, diff --git a/src/include/k5-int.h b/src/include/k5-int.h index f3da373bc..063c30310 100644 --- a/src/include/k5-int.h +++ b/src/include/k5-int.h @@ -527,6 +527,9 @@ krb5_error_code os_get_default_config_files krb5_error_code krb5_os_hostaddr (krb5_context, const char *, krb5_address ***); +krb5_error_code krb5int_get_domain_realm_mapping + (krb5_context , const char *, char ***); + /* N.B.: You need to include fake-addrinfo.h *before* k5-int.h if you're going to use this structure. */ struct addrlist { diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c index 9c96734e6..5a349c864 100644 --- a/src/kdc/do_tgs_req.c +++ b/src/kdc/do_tgs_req.c @@ -71,7 +71,6 @@ #include "extern.h" #include "adm_proto.h" - static void find_alternate_tgs (krb5_kdc_req *, krb5_db_entry *, krb5_boolean *, int *); @@ -79,6 +78,9 @@ static krb5_error_code prepare_error_tgs (krb5_kdc_req *, krb5_ticket *, int, krb5_principal, krb5_data **, const char *); +static krb5_boolean +is_substr ( char *, krb5_data *); + /*ARGSUSED*/ krb5_error_code process_tgs_req(krb5_data *pkt, const krb5_fulladdr *from, @@ -104,10 +106,10 @@ process_tgs_req(krb5_data *pkt, const krb5_fulladdr *from, krb5_key_data *server_key; char *cname = 0, *sname = 0, *altcname = 0; krb5_last_req_entry *nolrarray[2], nolrentry; -/* krb5_address *noaddrarray[1]; */ krb5_enctype useenctype; int errcode, errcode2; register int i; + size_t len; int firstpass = 1; const char *status = 0; krb5_enc_tkt_part *header_enc_tkt = NULL; /* ticket granting or evidence ticket */ @@ -117,8 +119,12 @@ process_tgs_req(krb5_data *pkt, const krb5_fulladdr *from, 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; + krb5_boolean is_referral, db_ref_done = FALSE; const char *emsg = NULL; + char **realms, **cpp, *temp_buf=NULL; + krb5_data *comp1 = NULL, *comp2 = NULL; + krb5_data *tgs_1 =NULL, *server_1 = NULL; + krb5_principal krbtgt_princ; session_key.contents = NULL; @@ -133,14 +139,6 @@ process_tgs_req(krb5_data *pkt, const krb5_fulladdr *from, krb5_free_kdc_req(kdc_context, request); return retval; } - - if ((errcode = krb5_unparse_name(kdc_context, request->server, &sname))) { - status = "UNPARSING SERVER"; - goto cleanup; - } - limit_string(sname); - - /* errcode = kdc_process_tgs_req(request, from, pkt, &req_authdat); */ errcode = kdc_process_tgs_req(request, from, pkt, &header_ticket, &krbtgt, &k_nprincs, &subkey); if (header_ticket && header_ticket->enc_part2 && @@ -181,12 +179,21 @@ process_tgs_req(krb5_data *pkt, const krb5_fulladdr *from, /* XXX make sure server here has the proper realm...taken from AP_REQ header? */ - nprincs = 1; if (isflagset(request->kdc_options, KDC_OPT_CANONICALIZE)) { setflag(c_flags, KRB5_KDB_FLAG_CANONICALIZE); setflag(s_flags, KRB5_KDB_FLAG_CANONICALIZE); } + db_ref_done = FALSE; + +ref_tgt_again: + nprincs = 1; + if ((errcode = krb5_unparse_name(kdc_context, request->server, &sname))) { + status = "UNPARSING SERVER"; + goto cleanup; + } + limit_string(sname); + errcode = krb5_db_get_principal_ext(kdc_context, request->server, s_flags, @@ -208,21 +215,109 @@ tgt_again: * 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 && krb5_is_tgs_principal(request->server) == TRUE) { - if (krb5_princ_size(kdc_context, request->server) == 2) { - krb5_data *server_1 = - krb5_princ_component(kdc_context, request->server, 1); - krb5_data *tgs_1 = - krb5_princ_component(kdc_context, tgs_server, 1); - - if (!tgs_1 || !data_eq(*server_1, *tgs_1)) { - krb5_db_free_principal(kdc_context, &server, nprincs); - find_alternate_tgs(request, &server, &more, &nprincs); - firstpass = 0; - goto tgt_again; - } - } - } + if (firstpass ) { + + if ( krb5_is_tgs_principal(request->server) == TRUE) { /* Principal is a name of krb ticket service */ + if (krb5_princ_size(kdc_context, request->server) == 2) { + + server_1 = krb5_princ_component(kdc_context, request->server, 1); + tgs_1 = krb5_princ_component(kdc_context, tgs_server, 1); + + if (!tgs_1 || !data_eq(*server_1, *tgs_1)) { + krb5_db_free_principal(kdc_context, &server, nprincs); + find_alternate_tgs(request, &server, &more, &nprincs); + firstpass = 0; + goto tgt_again; + } + } + krb5_db_free_principal(kdc_context, &server, nprincs); + status = "UNKNOWN_SERVER"; + errcode = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; + goto cleanup; + + } 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) + * either + * the name type is NT-SRV-HST (4.a) + * 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) + * 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) */ + + 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; + } + if ( len == comp2->length) /* (6) */ + goto cleanup; + + /* try mapping FQDN or the containing domains */ + temp_buf = calloc(1, comp2->length+1); + if ( !temp_buf){ + retval = ENOMEM; + goto cleanup; + } + strncpy(temp_buf, comp2->data,comp2->length); + retval = krb5int_get_domain_realm_mapping(kdc_context, temp_buf, &realms); + free(temp_buf); + if (retval) { + /* no match found */ + com_err("krb5_get_domain_realm_mapping", retval, 0); + goto cleanup; + } + if (realms == 0) { + printf(" (null)\n"); + goto cleanup; + } + if (realms[0] == 0) { + printf(" (none)\n"); + free(realms); + 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); + krb5_free_principal(kdc_context, request->server); + + retval = krb5_copy_principal(kdc_context, krbtgt_princ, &(request->server)); + if ( retval == 0 ) { + db_ref_done = TRUE; + goto ref_tgt_again; + } + } + } + } + } + + krb5_db_free_principal(kdc_context, &server, nprincs); status = "UNKNOWN_SERVER"; errcode = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; @@ -1015,3 +1110,26 @@ find_alternate_tgs(krb5_kdc_req *request, krb5_db_entry *server, krb5_free_realm_tree(kdc_context, plist); return; } + +/* is_substr - verfies if d1 contains d2->data with head/trail-ing whitespaces + */ +static krb5_boolean +is_substr ( char *d1, krb5_data *d2) +{ + krb5_boolean ret = FALSE; + char *new_d2 = 0, *d2_formated = 0; + 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) + ret = TRUE; + free(new_d2); + free(d2_formated); + } + } + return ret; +} + + + diff --git a/src/kdc/extern.h b/src/kdc/extern.h index 0da6b14fb..20cc4bc04 100644 --- a/src/kdc/extern.h +++ b/src/kdc/extern.h @@ -1,7 +1,7 @@ /* * kdc/extern.h * - * Copyright 1990,2001,2007 by the Massachusetts Institute of Technology. + * Copyright 1990,2001,2007,2009 by the Massachusetts Institute of Technology. * * Export of this software from the United States of America may * require a specific license from the United States Government. @@ -41,6 +41,11 @@ typedef struct __kdc_realm_data { 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. */ diff --git a/src/kdc/main.c b/src/kdc/main.c index 247826d4f..ee5d5907b 100644 --- a/src/kdc/main.c +++ b/src/kdc/main.c @@ -1,7 +1,7 @@ /* * kdc/main.c * - * Copyright 1990,2001,2008 by the Massachusetts Institute of Technology. + * Copyright 1990,2001,2008,2009 by the Massachusetts Institute of Technology. * * Export of this software from the United States of America may * require a specific license from the United States Government. @@ -146,6 +146,10 @@ finish_realm(kdc_realm_t *rdp) free(rdp->realm_tcp_ports); if (rdp->realm_keytab) krb5_kt_close(rdp->realm_context, rdp->realm_keytab); + if (rdp->realm_host_based_services) + free(rdp->realm_host_based_services); + if (rdp->realm_no_host_referral) + free(rdp->realm_no_host_referral); if (rdp->realm_context) { if (rdp->realm_mprinc) krb5_free_principal(rdp->realm_context, rdp->realm_mprinc); @@ -162,6 +166,72 @@ finish_realm(kdc_realm_t *rdp) free(rdp); } +static void +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 ){ + 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, " "); + } else { + asprintf(&(rdp->realm_no_host_referral),"%s%s%s", " ", no_refrls," "); + } + } else { + if (rparams && rparams->realm_no_host_referral) { + asprintf(&(rdp->realm_no_host_referral),"%s%s%s", " ", rparams->realm_no_host_referral," "); + } else + rdp->realm_no_host_referral = 0; + } + + 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("*"); + } 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", "*"); + } else { + if ( host_based_srvcs !=0) { + 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," "); + } else + asprintf(&(rdp->realm_host_based_services),"%s%s%s", " ", host_based_srvcs," "); + } else { + if (rparams && rparams->realm_host_based_services) { + asprintf(&(rdp->realm_host_based_services),"%s%s%s"," ", rparams->realm_host_based_services," "); + } else + rdp->realm_host_based_services = 0; + } + } + + /* 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]=' '; + 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]=' '; + i++; + } + } + } else { + if ( no_refrls != NULL && strchr(no_refrls,'*') !=0 ) + asprintf(&(rdp->realm_no_host_referral),"%s", "* "); + else + rdp->realm_no_host_referral = 0; + } + + return; +} /* * Initialize a realm control structure from the alternate profile or from * the specified defaults. @@ -172,7 +242,8 @@ finish_realm(kdc_realm_t *rdp) static krb5_error_code init_realm(char *progname, kdc_realm_t *rdp, char *realm, char *def_mpname, krb5_enctype def_enctype, char *def_udp_ports, - char *def_tcp_ports, krb5_boolean def_manual, char **db_args) + char *def_tcp_ports, krb5_boolean def_manual, char **db_args, + char *no_refrls, char *host_based_srvcs) { krb5_error_code kret; krb5_boolean manual; @@ -239,7 +310,7 @@ init_realm(char *progname, kdc_realm_t *rdp, char *realm, rdp->realm_reject_bad_transit = rparams->realm_reject_bad_transit; else rdp->realm_reject_bad_transit = 1; - + /* Handle ticket maximum life */ rdp->realm_maxlife = (rparams && rparams->realm_max_life_valid) ? rparams->realm_max_life : KRB5_KDB_MAX_LIFE; @@ -248,6 +319,9 @@ init_realm(char *progname, kdc_realm_t *rdp, char *realm, rdp->realm_maxrlife = (rparams && rparams->realm_max_rlife_valid) ? rparams->realm_max_rlife : KRB5_KDB_MAX_RLIFE; + /* Handle KDC referrals */ + handle_referrals(rparams, no_refrls, host_based_srvcs, rdp ); + if (rparams) krb5_free_realm_params(rdp->realm_context, rparams); @@ -437,6 +511,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; int db_args_size = 0; extern char *optarg; @@ -453,11 +529,30 @@ initialize_realms(krb5_context kcontext, int argc, char **argv) hierarchy[1] = "kdc_max_dgram_reply_size"; if (krb5_aprof_get_int32(aprof, hierarchy, TRUE, &max_dgram_reply_size)) 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, '*')) { + no_refrls = strdup("*"); + } + } + if ( no_refrls == 0 || strchr(no_refrls, '*')==0) { + 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("*"); + } + } /* aprof_init can return 0 with aprof == NULL */ if (aprof) krb5_aprof_finish(aprof); } + if (default_udp_ports == 0) default_udp_ports = strdup(DEFAULT_KDC_UDP_PORTLIST); if (default_tcp_ports == 0) @@ -491,7 +586,8 @@ initialize_realms(krb5_context kcontext, int argc, char **argv) if ((retval = init_realm(argv[0], rdatap, optarg, mkey_name, menctype, default_udp_ports, - default_tcp_ports, manual, db_args))) { + default_tcp_ports, manual, db_args, + no_refrls, host_based_srvcs))) { fprintf(stderr,"%s: cannot initialize realm %s - see log file for details\n", argv[0], optarg); exit(1); @@ -588,7 +684,8 @@ initialize_realms(krb5_context kcontext, int argc, char **argv) if ((rdatap = (kdc_realm_t *) malloc(sizeof(kdc_realm_t)))) { if ((retval = init_realm(argv[0], rdatap, lrealm, mkey_name, menctype, default_udp_ports, - default_tcp_ports, manual, db_args))) { + default_tcp_ports, manual, db_args, + no_refrls, host_based_srvcs))) { fprintf(stderr,"%s: cannot initialize realm %s - see log file for details\n", argv[0], lrealm); exit(1); diff --git a/src/lib/kadm5/admin.h b/src/lib/kadm5/admin.h index b2d05ad68..cdf2f4dc8 100644 --- a/src/lib/kadm5/admin.h +++ b/src/lib/kadm5/admin.h @@ -283,6 +283,8 @@ typedef struct __krb5_realm_params { char * realm_kdc_ports; char * realm_kdc_tcp_ports; char * realm_acl_file; + char * realm_host_based_services; + char * realm_no_host_referral; krb5_int32 realm_kadmind_port; krb5_enctype realm_enctype; krb5_deltat realm_max_life; diff --git a/src/lib/kadm5/alt_prof.c b/src/lib/kadm5/alt_prof.c index 45f748d0f..477866b21 100644 --- a/src/lib/kadm5/alt_prof.c +++ b/src/lib/kadm5/alt_prof.c @@ -1,7 +1,7 @@ /* * lib/kadm/alt_prof.c * - * Copyright 1995,2001,2008 by the Massachusetts Institute of Technology. + * Copyright 1995,2001,2008,2009 by the Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may @@ -273,6 +273,59 @@ krb5_aprof_get_string(acontext, hierarchy, uselast, stringp) return(kret); } +/* + * krb5_aprof_get_string_all() - When the attr identified by "hierarchy" is specified multiple times, + * collect all its string values from the alternate profile. + * + * Parameters: + * acontext - opaque context for alternate profile. + * hierarchy - hierarchy of value to retrieve. + * stringp - Returned string value. + * + * Returns: + * error codes from profile_get_values() or ENOMEM + * Caller is responsible for deallocating stringp buffer + */ +krb5_error_code +krb5_aprof_get_string_all(acontext, hierarchy, stringp) + krb5_pointer acontext; + const char **hierarchy; + char **stringp; +{ + krb5_error_code kret=0; + char **values; + int lastidx; + char *tmp; + size_t buf_size=0; + + if (!(kret = krb5_aprof_getvals(acontext, hierarchy, &values))) { + for (lastidx=0; values[lastidx]; lastidx++); + lastidx--; + + buf_size = strlen(values[0])+2; + for (lastidx=1; values[lastidx]; lastidx++){ + buf_size += strlen(values[lastidx]+1); + } + } + if (buf_size > 0) { + *stringp = calloc(1,buf_size); + if (stringp == NULL){ + profile_free_list(values); + return ENOMEM; + } + tmp=*stringp; + strcpy(tmp,values[0]); + for (lastidx=1; values[lastidx]; lastidx++){ + tmp = strcat(tmp, " "); + tmp = strcat(tmp, values[lastidx]); + } + /* Free the string storage */ + profile_free_list(values); + } + return(kret); +} + + /* * krb5_aprof_get_int32() - Get a 32-bit integer value from the alternate * profile. @@ -866,6 +919,10 @@ krb5_read_realm_params(kcontext, realm, rparamp) char *kdcprofile = 0; char *kdcenv = 0; + char *no_refrls = 0; + char *host_based_srvcs = 0; + + krb5_error_code kret; @@ -971,6 +1028,26 @@ krb5_read_realm_params(kcontext, realm, rparamp) rparams->realm_reject_bad_transit_valid = 1; } + hierarchy[2] = "no_host_referral"; + if (!krb5_aprof_get_string_all(aprofile, hierarchy, &no_refrls)) { + + if (strchr(no_refrls, '*')) + no_refrls = strdup("*"); + rparams->realm_no_host_referral = no_refrls; + } else + no_refrls = 0; + + if (no_refrls == 0 || strlen(no_refrls) == 0 || strncmp(no_refrls, "*",1) != 0) { + hierarchy[2] = "host_based_services"; + if (!krb5_aprof_get_string_all(aprofile, hierarchy, &host_based_srvcs)){ + if (strchr(host_based_srvcs, '*')) + host_based_srvcs = strdup("*"); + rparams->realm_host_based_services = host_based_srvcs; + } else + host_based_srvcs = 0; + } + + /* Get the value for the default principal flags */ hierarchy[2] = "default_principal_flags"; if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { @@ -1039,6 +1116,8 @@ krb5_free_realm_params(kcontext, rparams) krb5_xfree(rparams->realm_kdc_ports); krb5_xfree(rparams->realm_kdc_tcp_ports); krb5_xfree(rparams->realm_acl_file); + krb5_xfree(rparams->realm_no_host_referral); + krb5_xfree(rparams->realm_host_based_services); krb5_xfree(rparams); } return(0); diff --git a/src/lib/kadm5/srv/libkadm5srv.exports b/src/lib/kadm5/srv/libkadm5srv.exports index 120558016..d0a45bac9 100644 --- a/src/lib/kadm5/srv/libkadm5srv.exports +++ b/src/lib/kadm5/srv/libkadm5srv.exports @@ -67,6 +67,7 @@ krb5_aprof_get_boolean krb5_aprof_get_deltat krb5_aprof_get_int32 krb5_aprof_get_string +krb5_aprof_get_string_all krb5_aprof_getvals krb5_aprof_init krb5_copy_key_data_contents diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports index 4a6581fe1..9651f30bc 100644 --- a/src/lib/krb5/libkrb5.exports +++ b/src/lib/krb5/libkrb5.exports @@ -362,6 +362,7 @@ krb5_os_free_context krb5_os_hostaddr krb5_os_init_context krb5_os_localaddr +krb5int_get_domain_realm_mapping krb5_overridekeyname krb5_pac_add_buffer krb5_pac_free diff --git a/src/lib/krb5/os/def_realm.c b/src/lib/krb5/os/def_realm.c index 13a025d9b..327a63c8d 100644 --- a/src/lib/krb5/os/def_realm.c +++ b/src/lib/krb5/os/def_realm.c @@ -1,7 +1,7 @@ /* * lib/krb5/os/def_realm.c * - * Copyright 1990,1991 by the Massachusetts Institute of Technology. + * Copyright 1990,1991,2009 by the Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may @@ -187,3 +187,73 @@ krb5_free_default_realm(krb5_context context, char *lrealm) { free (lrealm); } +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]; + +#ifdef DEBUG_REFERRALS + printf("krb5int_get_domain_realm_mapping(host:%s) called\n",host); +#endif + /* 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 ) { +#ifdef DEBUG_REFERRALS + printf(" trying to look up %s in the domain_realm map\n",cp); +#endif + retval = profile_get_string(context->profile, "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, '.'); + } + } +#ifdef DEBUG_REFERRALS + printf(" done searching the domain_realm map\n"); +#endif + if (temp_realm!=(char*)NULL) { +#ifdef DEBUG_REFERRALS + printf(" temp_realm is %s\n",temp_realm); +#endif + realm = strdup(temp_realm); + profile_release_string(temp_realm); + if (!realm) { + return ENOMEM; + } + } + if (!(retrealms = (char **)calloc(2, sizeof(*retrealms)))) { + if (realm != (char *)NULL) + free(realm); + return ENOMEM; + } + + retrealms[0] = realm; + retrealms[1] = 0; + + *realmsp = retrealms; + + return 0; +} + +