krb5 commit: Simplify KDC host referral code

Greg Hudson ghudson at MIT.EDU
Fri Jan 11 13:37:43 EST 2013


https://github.com/krb5/krb5/commit/c53ea7bef444d7c151c46224b7a0600b9539496f
commit c53ea7bef444d7c151c46224b7a0600b9539496f
Author: Greg Hudson <ghudson at mit.edu>
Date:   Fri Jan 11 13:26:37 2013 -0500

    Simplify KDC host referral code
    
    Remove some unnecessary optimizations to reduce code complexity.  Get
    rid of krb5_match_config_pattern in favor of a simpler helper function
    in do_tgs_req_c.  Get rid of KRB5_CONF_ASTERISK and just use "*"
    instead.  Use a helper function to combine [kdcdefaults] and realm
    subsection values of variables, and don't bother adding leading and
    trailing spaces.  Consistently use the names "hostbased" and
    "no_referral" to refer to variable values (with a "realm_" prefix for
    structures which currently use it).

 src/include/adm_proto.h                   |    1 -
 src/include/k5-int.h                      |    1 -
 src/kdc/do_tgs_req.c                      |   36 +++++---
 src/kdc/main.c                            |  127 +++++++++--------------------
 src/kdc/realm_data.h                      |    7 +-
 src/lib/kadm5/admin.h                     |    4 +-
 src/lib/kadm5/alt_prof.c                  |   57 +++-----------
 src/lib/kadm5/srv/libkadm5srv_mit.exports |    1 -
 8 files changed, 77 insertions(+), 157 deletions(-)

diff --git a/src/include/adm_proto.h b/src/include/adm_proto.h
index e9cbab6..daca5a1 100644
--- a/src/include/adm_proto.h
+++ b/src/include/adm_proto.h
@@ -79,7 +79,6 @@ krb5_error_code krb5_aprof_finish(krb5_pointer);
 krb5_error_code krb5_read_realm_params(krb5_context, char *,
                                        krb5_realm_params **);
 krb5_error_code krb5_free_realm_params(krb5_context, krb5_realm_params *);
-krb5_boolean krb5_match_config_pattern(const char *, const char *);
 
 /* str_conv.c */
 krb5_error_code krb5_string_to_flags(char *, const char *, const char *,
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
index fef1ddb..9da1b63 100644
--- a/src/include/k5-int.h
+++ b/src/include/k5-int.h
@@ -275,7 +275,6 @@ typedef INT64_TYPE krb5_int64;
 #define KRB5_CONF_VERIFY_AP_REQ_NOFAIL        "verify_ap_req_nofail"
 #define KRB5_CONF_V4_INSTANCE_CONVERT         "v4_instance_convert"
 #define KRB5_CONF_V4_REALM                    "v4_realm"
-#define KRB5_CONF_ASTERISK                    "*"
 
 /* Cache configuration variables */
 #define KRB5_CC_CONF_FAST_AVAIL                  "fast_avail"
diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c
index 1d56566..1e73313 100644
--- a/src/kdc/do_tgs_req.c
+++ b/src/kdc/do_tgs_req.c
@@ -1063,6 +1063,24 @@ cleanup:
     return retval;
 }
 
+/* Return true if item is an element of the space/comma-separated list. */
+static krb5_boolean
+in_list(const char *list, const char *item)
+{
+    const char *p;
+    int len = strlen(item);
+
+    if (list == NULL)
+        return FALSE;
+    for (p = strstr(list, item); p != NULL; p = strstr(p + 1, item)) {
+        if ((p == list || isspace((unsigned char)p[-1]) || p[-1] == ',') &&
+            (p[len] == '\0' || isspace((unsigned char)p[len]) ||
+             p[len] == ','))
+                return TRUE;
+    }
+    return FALSE;
+}
+
 /*
  * Check whether the request satisfies the conditions for generating a referral
  * TGT.  The caller checks whether the hostname component looks like a FQDN.
@@ -1072,8 +1090,8 @@ is_referral_req(kdc_realm_t *kdc_active_realm, krb5_kdc_req *request)
 {
     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;
+    char *hostbased = kdc_active_realm->realm_hostbased;
+    char *no_referral = kdc_active_realm->realm_no_referral;
 
     if (!(request->kdc_options & KDC_OPT_CANONICALIZE))
         return FALSE;
@@ -1090,22 +1108,14 @@ is_referral_req(kdc_realm_t *kdc_active_realm, krb5_kdc_req *request)
     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;
-        } else
+        if (!in_list(hostbased, stype) && !in_list(hostbased, "*"))
             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 (krb5_match_config_pattern(nonref_services, KRB5_CONF_ASTERISK))
-                goto cleanup;
-        }
+        if (in_list(no_referral, stype) || in_list(no_referral, "*"))
+            goto cleanup;
         ret = TRUE;
         break;
     default:
diff --git a/src/kdc/main.c b/src/kdc/main.c
index 51792fb..a5605f8 100644
--- a/src/kdc/main.c
+++ b/src/kdc/main.c
@@ -151,10 +151,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_hostbased)
+        free(rdp->realm_hostbased);
+    if (rdp->realm_no_referral)
+        free(rdp->realm_no_referral);
     if (rdp->realm_context) {
         if (rdp->realm_mprinc)
             krb5_free_principal(rdp->realm_context, rdp->realm_mprinc);
@@ -172,75 +172,24 @@ finish_realm(kdc_realm_t *rdp)
     free(rdp);
 }
 
+/* Set *val_out to an allocated string containing val1 and/or val2, separated
+ * by a space if both are set, or NULL if neither is set. */
 static krb5_error_code
-handle_referral_params(krb5_realm_params *rparams,
-                       char *no_refrls, char *host_based_srvcs,
-                       kdc_realm_t *rdp )
+combine(const char *val1, const char *val2, char **val_out)
 {
-    krb5_error_code retval = 0;
-    if (no_refrls && krb5_match_config_pattern(no_refrls, KRB5_CONF_ASTERISK) == TRUE) {
-        rdp->realm_no_host_referral = strdup(KRB5_CONF_ASTERISK);
-        if (!rdp->realm_no_host_referral)
-            retval = ENOMEM;
-    } else {
-        if (rparams && rparams->realm_no_host_referral) {
-            if (krb5_match_config_pattern(rparams->realm_no_host_referral,
-                                          KRB5_CONF_ASTERISK) == TRUE) {
-                rdp->realm_no_host_referral = strdup(KRB5_CONF_ASTERISK);
-                if (!rdp->realm_no_host_referral)
-                    retval = ENOMEM;
-            } else if (no_refrls) {
-                if (asprintf(&(rdp->realm_no_host_referral),
-                             "%s%s%s%s%s", " ", no_refrls," ",
-                             rparams->realm_no_host_referral, " ") < 0)
-                    retval = ENOMEM;
-            } else if (asprintf(&(rdp->realm_no_host_referral),"%s%s%s", " ",
-                                rparams->realm_no_host_referral, " ") < 0)
-                retval = ENOMEM;
-        } else if( no_refrls != NULL) {
-            if ( asprintf(&(rdp->realm_no_host_referral),
-                          "%s%s%s", " ", no_refrls, " ") < 0)
-                retval = ENOMEM;
-        } else
-            rdp->realm_no_host_referral = NULL;
-    }
-
-    if (rdp->realm_no_host_referral &&
-        krb5_match_config_pattern(rdp->realm_no_host_referral,
-                                  KRB5_CONF_ASTERISK) == TRUE) {
-        rdp->realm_host_based_services = NULL;
-        return 0;
-    }
-
-    if (host_based_srvcs &&
-        (krb5_match_config_pattern(host_based_srvcs, KRB5_CONF_ASTERISK) == TRUE)) {
-        rdp->realm_host_based_services = strdup(KRB5_CONF_ASTERISK);
-        if (!rdp->realm_host_based_services)
-            retval = ENOMEM;
+    if (val1 == NULL && val2 == NULL) {
+        *val_out = NULL;
+    } else if (val1 != NULL && val2 != NULL) {
+        if (asprintf(val_out, "%s %s", val1, val2) < 0) {
+            *val_out = NULL;
+            return ENOMEM;
+        }
     } else {
-        if (rparams && rparams->realm_host_based_services) {
-            if (krb5_match_config_pattern(rparams->realm_host_based_services,
-                                          KRB5_CONF_ASTERISK) == TRUE) {
-                rdp->realm_host_based_services = strdup(KRB5_CONF_ASTERISK);
-                if (!rdp->realm_host_based_services)
-                    retval = ENOMEM;
-            } else if (host_based_srvcs) {
-                if (asprintf(&(rdp->realm_host_based_services), "%s%s%s%s%s",
-                             " ", host_based_srvcs," ",
-                             rparams->realm_host_based_services, " ") < 0)
-                    retval = ENOMEM;
-            } else if (asprintf(&(rdp->realm_host_based_services),"%s%s%s", " ",
-                                rparams->realm_host_based_services, " ") < 0)
-                retval = ENOMEM;
-        } else if (host_based_srvcs) {
-            if (asprintf(&(rdp->realm_host_based_services),"%s%s%s", " ",
-                         host_based_srvcs, " ") < 0)
-                retval = ENOMEM;
-        } else
-            rdp->realm_host_based_services = NULL;
+        *val_out = strdup((val1 != NULL) ? val1 : val2);
+        if (*val_out == NULL)
+            return ENOMEM;
     }
-
-    return retval;
+    return 0;
 }
 
 /*
@@ -254,7 +203,7 @@ static krb5_error_code
 init_realm(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, krb5_boolean def_restrict_anon,
-           char **db_args, char *no_refrls, char *host_based_srvcs)
+           char **db_args, char *no_referral, char *hostbased)
 {
     krb5_error_code     kret;
     krb5_boolean        manual;
@@ -368,8 +317,13 @@ init_realm(kdc_realm_t *rdp, char *realm, char *def_mpname,
         rparams->realm_max_rlife : KRB5_KDB_MAX_RLIFE;
 
     /* Handle KDC referrals */
-    kret = handle_referral_params(rparams, no_refrls, host_based_srvcs, rdp);
-    if (kret == ENOMEM)
+    kret = combine(no_referral, rparams->realm_no_referral,
+                   &rdp->realm_no_referral);
+    if (kret)
+        goto whoops;
+
+    kret = combine(hostbased, rparams->realm_hostbased, &rdp->realm_hostbased);
+    if (kret)
         goto whoops;
 
     if (rparams)
@@ -673,8 +627,8 @@ initialize_realms(krb5_context kcontext, int argc, char **argv)
     char                *default_tcp_ports = 0;
     krb5_pointer        aprof;
     const char          *hierarchy[3];
-    char                *no_refrls = NULL;
-    char                *host_based_srvcs = NULL;
+    char                *no_referral = NULL;
+    char                *hostbased = NULL;
     int                  db_args_size = 0;
     char                **db_args = NULL;
 
@@ -696,14 +650,11 @@ initialize_realms(krb5_context kcontext, int argc, char **argv)
         if (krb5_aprof_get_boolean(aprof, hierarchy, TRUE, &def_restrict_anon))
             def_restrict_anon = FALSE;
         hierarchy[1] = KRB5_CONF_NO_HOST_REFERRAL;
-        if (krb5_aprof_get_string_all(aprof, hierarchy, &no_refrls))
-            no_refrls = 0;
-        if (!no_refrls ||
-            krb5_match_config_pattern(no_refrls, KRB5_CONF_ASTERISK) == FALSE) {
-            hierarchy[1] = KRB5_CONF_HOST_BASED_SERVICES;
-            if (krb5_aprof_get_string_all(aprof, hierarchy, &host_based_srvcs))
-                host_based_srvcs = 0;
-        }
+        if (krb5_aprof_get_string_all(aprof, hierarchy, &no_referral))
+            no_referral = 0;
+        hierarchy[1] = KRB5_CONF_HOST_BASED_SERVICES;
+        if (krb5_aprof_get_string_all(aprof, hierarchy, &hostbased))
+            hostbased = 0;
 
         krb5_aprof_finish(aprof);
     }
@@ -753,7 +704,7 @@ initialize_realms(krb5_context kcontext, int argc, char **argv)
                                              menctype, default_udp_ports,
                                              default_tcp_ports, manual,
                                              def_restrict_anon, db_args,
-                                             no_refrls, host_based_srvcs))) {
+                                             no_referral, hostbased))) {
                         fprintf(stderr, _("%s: cannot initialize realm %s - "
                                           "see log file for details\n"),
                                 argv[0], optarg);
@@ -869,7 +820,7 @@ initialize_realms(krb5_context kcontext, int argc, char **argv)
             if ((retval = init_realm(rdatap, lrealm, mkey_name, menctype,
                                      default_udp_ports, default_tcp_ports,
                                      manual, def_restrict_anon, db_args,
-                                     no_refrls, host_based_srvcs))) {
+                                     no_referral, hostbased))) {
                 fprintf(stderr, _("%s: cannot initialize realm %s - see log "
                                   "file for details\n"), argv[0], lrealm);
                 exit(1);
@@ -888,10 +839,10 @@ initialize_realms(krb5_context kcontext, int argc, char **argv)
         free(db_args);
     if (db_name)
         free(db_name);
-    if (host_based_srvcs)
-        free(host_based_srvcs);
-    if (no_refrls)
-        free(no_refrls);
+    if (hostbased)
+        free(hostbased);
+    if (no_referral)
+        free(no_referral);
 
     return;
 }
diff --git a/src/kdc/realm_data.h b/src/kdc/realm_data.h
index 0387c28..1593c44 100644
--- a/src/kdc/realm_data.h
+++ b/src/kdc/realm_data.h
@@ -45,11 +45,8 @@ 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 */
+    char *              realm_hostbased; /* referral services for NT-UNKNOWN */
+    char *              realm_no_referral; /* non-referral services         */
     /*
      * Database per-realm data.
      */
diff --git a/src/lib/kadm5/admin.h b/src/lib/kadm5/admin.h
index fd8d654..1af7ac2 100644
--- a/src/lib/kadm5/admin.h
+++ b/src/lib/kadm5/admin.h
@@ -294,8 +294,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;
+    char *              realm_hostbased;
+    char *              realm_no_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 2a587e4..4b6bf80 100644
--- a/src/lib/kadm5/alt_prof.c
+++ b/src/lib/kadm5/alt_prof.c
@@ -37,7 +37,6 @@
 #include <ctype.h>
 #include <kdb_log.h>
 
-krb5_boolean krb5_match_config_pattern(const char *, const char*);
 static krb5_key_salt_tuple *copy_key_salt_tuple(ksalt, len)
     krb5_key_salt_tuple *ksalt;
     krb5_int32 len;
@@ -938,12 +937,9 @@ 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;
+    char                *no_referral = 0;
+    char                *hostbased = 0;
+    krb5_error_code      kret;
 
     filename = (kdcprofile) ? kdcprofile : DEFAULT_KDC_PROFILE;
     envname = (kdcenv) ? kdcenv : KDC_PROFILE_ENV;
@@ -1057,18 +1053,12 @@ krb5_read_realm_params(kcontext, realm, rparamp)
     }
 
     hierarchy[2] = KRB5_CONF_NO_HOST_REFERRAL;
-    if (!krb5_aprof_get_string_all(aprofile, hierarchy, &no_refrls))
-        rparams->realm_no_host_referral = no_refrls;
-    else
-        no_refrls = 0;
-
-    if (!no_refrls || krb5_match_config_pattern(no_refrls, KRB5_CONF_ASTERISK) == FALSE) {
-        hierarchy[2] = KRB5_CONF_HOST_BASED_SERVICES;
-        if (!krb5_aprof_get_string_all(aprofile, hierarchy, &host_based_srvcs))
-            rparams->realm_host_based_services = host_based_srvcs;
-        else
-            host_based_srvcs = 0;
-    }
+    if (!krb5_aprof_get_string_all(aprofile, hierarchy, &no_referral))
+        rparams->realm_no_referral = no_referral;
+
+    hierarchy[2] = KRB5_CONF_HOST_BASED_SERVICES;
+    if (!krb5_aprof_get_string_all(aprofile, hierarchy, &hostbased))
+        rparams->realm_hostbased = hostbased;
 
     /* Get the value for the default principal flags */
     hierarchy[2] = KRB5_CONF_DEFAULT_PRINCIPAL_FLAGS;
@@ -1137,34 +1127,9 @@ krb5_free_realm_params(kcontext, rparams)
         free(rparams->realm_kdc_ports);
         free(rparams->realm_kdc_tcp_ports);
         free(rparams->realm_acl_file);
-        free(rparams->realm_no_host_referral);
-        free(rparams->realm_host_based_services);
+        free(rparams->realm_no_referral);
+        free(rparams->realm_hostbased);
         free(rparams);
     }
     return(0);
 }
-/*
- * match_config_pattern -
- *       returns TRUE is the pattern is found in the attr's list of values.
- *       Otherwise - FALSE.
- *       In conf file the values are separates by commas or whitespaces.
- */
-krb5_boolean
-krb5_match_config_pattern(const char *string, const char *pattern)
-{
-    const char *ptr;
-    char next = '\0';
-    int len = strlen(pattern);
-
-    for (ptr = strstr(string,pattern); ptr != 0; ptr = strstr(ptr+len,pattern)) {
-        if (ptr == string
-            || isspace((unsigned char)*(ptr-1))
-            || *(ptr-1) ==',') {
-            next = *(ptr + len);
-            if (next == '\0' || isspace((unsigned char)next) || next ==',') {
-                return TRUE;
-            }
-        }
-    }
-    return FALSE;
-}
diff --git a/src/lib/kadm5/srv/libkadm5srv_mit.exports b/src/lib/kadm5/srv/libkadm5srv_mit.exports
index 358b9c6..0788ac1 100644
--- a/src/lib/kadm5/srv/libkadm5srv_mit.exports
+++ b/src/lib/kadm5/srv/libkadm5srv_mit.exports
@@ -80,7 +80,6 @@ krb5_klog_syslog
 krb5_read_realm_params
 krb5_string_to_flags
 krb5_string_to_keysalts
-krb5_match_config_pattern
 master_db
 master_princ
 osa_free_princ_ent


More information about the cvs-krb5 mailing list