Eliminate the need for the domain_realm mapping table on the client side by implement...
authorZhanna Tsitkov <tsitkova@mit.edu>
Fri, 23 Jan 2009 19:59:50 +0000 (19:59 +0000)
committerZhanna Tsitkov <tsitkova@mit.edu>
Fri, 23 Jan 2009 19:59:50 +0000 (19:59 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@21792 dc483132-0cff-0310-8789-dd5450dbe970

src/include/adm.h
src/include/adm_proto.h
src/include/k5-int.h
src/kdc/do_tgs_req.c
src/kdc/extern.h
src/kdc/main.c
src/lib/kadm5/admin.h
src/lib/kadm5/alt_prof.c
src/lib/kadm5/srv/libkadm5srv.exports
src/lib/krb5/libkrb5.exports
src/lib/krb5/os/def_realm.c

index 34c195fa24cfdbf01a096df0a8db15da10ba697b..15b42d9ab802b65a7bc7e8eb78c146199c39916b 100644 (file)
@@ -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;
index 04e6a47916fa5bd5338e48034c2ca6fac3d010a5..9d7002027b43e3029e86c4b013b3e3c007c5b8b1 100644 (file)
@@ -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 **,
index f3da373bc2ad48356e51fde149ae6a65aedc8fb5..063c30310811cd6fd55bce84aaf9aa1375fc85f0 100644 (file)
@@ -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 {
index 9c96734e6abff7847e1c2f7d796dd765b958056d..5a349c86421d5428b5d8ef22a126529bfb765e26 100644 (file)
@@ -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;
+}
+
+
+
index 0da6b14fbb54383207f7d4853a4f0548a88358f4..20cc4bc049a61dd1c86debbad06f0b7e08a0a76a 100644 (file)
@@ -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.
      */
index 247826d4f5841d9a2c73bf4dded2d35112920665..ee5d5907b0bfcb3ffd41ece552231cda9dbc4eab 100644 (file)
@@ -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);
index b2d05ad68adadf5289f65241ccf0d2fd2cead8df..cdf2f4dc8d9df90bd7b6311818547240331096d3 100644 (file)
@@ -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;
index 45f748d0f93366c1af1372987e84819898a1c76b..477866b2194b73ffad6017bb5960dad7efbd8bc6 100644 (file)
@@ -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);
index 120558016cc428878fc03a65d0ecb61303669a07..d0a45bac94985aa95550d94ad1a9f5b1d1f7135b 100644 (file)
@@ -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
index 4a6581fe12d6ba471eebfc3c2e43e5bb072a171a..9651f30bc486b6a23c00d9fe14270ccd8e7eaf0a 100644 (file)
@@ -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
index 13a025d9bbf49cfcbdf0211e0ee0e65976df6b88..327a63c8d9aab1500e3db8a169d3f093ac22e8cb 100644 (file)
@@ -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;
+}
+
+