svn rev #21792: trunk/src/ include/ kdc/ lib/kadm5/ lib/kadm5/srv/ lib/krb5/ ...

tsitkova@MIT.EDU tsitkova at MIT.EDU
Fri Jan 23 14:59:53 EST 2009


http://src.mit.edu/fisheye/changelog/krb5/?cs=21792
Commit By: tsitkova
Log Message:
Eliminate the need for the domain_realm mapping table on the client side by implementing minimal referral support in the KDC.




Changed Files:
U   trunk/src/include/adm.h
U   trunk/src/include/adm_proto.h
U   trunk/src/include/k5-int.h
U   trunk/src/kdc/do_tgs_req.c
U   trunk/src/kdc/extern.h
U   trunk/src/kdc/main.c
U   trunk/src/lib/kadm5/admin.h
U   trunk/src/lib/kadm5/alt_prof.c
U   trunk/src/lib/kadm5/srv/libkadm5srv.exports
U   trunk/src/lib/krb5/libkrb5.exports
U   trunk/src/lib/krb5/os/def_realm.c
Modified: trunk/src/include/adm.h
===================================================================
--- trunk/src/include/adm.h	2009-01-23 19:57:08 UTC (rev 21791)
+++ trunk/src/include/adm.h	2009-01-23 19:59:50 UTC (rev 21792)
@@ -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 @@
     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;

Modified: trunk/src/include/adm_proto.h
===================================================================
--- trunk/src/include/adm_proto.h	2009-01-23 19:57:08 UTC (rev 21791)
+++ trunk/src/include/adm_proto.h	2009-01-23 19:59:50 UTC (rev 21792)
@@ -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_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 **,

Modified: trunk/src/include/k5-int.h
===================================================================
--- trunk/src/include/k5-int.h	2009-01-23 19:57:08 UTC (rev 21791)
+++ trunk/src/include/k5-int.h	2009-01-23 19:59:50 UTC (rev 21792)
@@ -527,6 +527,9 @@
 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 {

Modified: trunk/src/kdc/do_tgs_req.c
===================================================================
--- trunk/src/kdc/do_tgs_req.c	2009-01-23 19:57:08 UTC (rev 21791)
+++ trunk/src/kdc/do_tgs_req.c	2009-01-23 19:59:50 UTC (rev 21792)
@@ -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 @@
 					  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 @@
     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 @@
     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 @@
 	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 @@
     /* 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 @@
 	 * 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 (firstpass ) {
 
-		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 ( 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 at 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 @@
     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;
+}
+
+
+

Modified: trunk/src/kdc/extern.h
===================================================================
--- trunk/src/kdc/extern.h	2009-01-23 19:57:08 UTC (rev 21791)
+++ trunk/src/kdc/extern.h	2009-01-23 19:59:50 UTC (rev 21792)
@@ -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 @@
     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.
      */

Modified: trunk/src/kdc/main.c
===================================================================
--- trunk/src/kdc/main.c	2009-01-23 19:57:08 UTC (rev 21791)
+++ trunk/src/kdc/main.c	2009-01-23 19:59:50 UTC (rev 21792)
@@ -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 @@
 	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 @@
     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 @@
 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 @@
 	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 @@
     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 @@
     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 @@
 	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 @@
 		    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 @@
 	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);

Modified: trunk/src/lib/kadm5/admin.h
===================================================================
--- trunk/src/lib/kadm5/admin.h	2009-01-23 19:57:08 UTC (rev 21791)
+++ trunk/src/lib/kadm5/admin.h	2009-01-23 19:59:50 UTC (rev 21792)
@@ -283,6 +283,8 @@
     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;

Modified: trunk/src/lib/kadm5/alt_prof.c
===================================================================
--- trunk/src/lib/kadm5/alt_prof.c	2009-01-23 19:57:08 UTC (rev 21791)
+++ trunk/src/lib/kadm5/alt_prof.c	2009-01-23 19:59:50 UTC (rev 21792)
@@ -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
@@ -274,6 +274,59 @@
 }
 
 /*
+ * 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,7 +919,11 @@
 
     char		*kdcprofile = 0;
     char		*kdcenv = 0;
+    char                *no_refrls = 0;
+    char                *host_based_srvcs = 0;
+         
 
+
     krb5_error_code	kret;
 
     filename = (kdcprofile) ? kdcprofile : DEFAULT_KDC_PROFILE;
@@ -971,6 +1028,26 @@
 	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_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);

Modified: trunk/src/lib/kadm5/srv/libkadm5srv.exports
===================================================================
--- trunk/src/lib/kadm5/srv/libkadm5srv.exports	2009-01-23 19:57:08 UTC (rev 21791)
+++ trunk/src/lib/kadm5/srv/libkadm5srv.exports	2009-01-23 19:59:50 UTC (rev 21792)
@@ -67,6 +67,7 @@
 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

Modified: trunk/src/lib/krb5/libkrb5.exports
===================================================================
--- trunk/src/lib/krb5/libkrb5.exports	2009-01-23 19:57:08 UTC (rev 21791)
+++ trunk/src/lib/krb5/libkrb5.exports	2009-01-23 19:59:50 UTC (rev 21792)
@@ -362,6 +362,7 @@
 krb5_os_hostaddr
 krb5_os_init_context
 krb5_os_localaddr
+krb5int_get_domain_realm_mapping
 krb5_overridekeyname
 krb5_pac_add_buffer
 krb5_pac_free

Modified: trunk/src/lib/krb5/os/def_realm.c
===================================================================
--- trunk/src/lib/krb5/os/def_realm.c	2009-01-23 19:57:08 UTC (rev 21791)
+++ trunk/src/lib/krb5/os/def_realm.c	2009-01-23 19:59:50 UTC (rev 21792)
@@ -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 @@
 {
 	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;
+}
+
+




More information about the cvs-krb5 mailing list