svn rev #24547: trunk/ doc/ src/include/ src/kdc/ src/lib/kadm5/ src/tests/ src/util/

ghudson@MIT.EDU ghudson at MIT.EDU
Wed Dec 1 15:01:46 EST 2010


http://src.mit.edu/fisheye/changelog/krb5/?cs=24547
Commit By: ghudson
Log Message:
ticket: 6829
subject: Implement restrict_anonymous_to_tgt realm flag
target_version: 1.9
tags: pullup

Implement a new realm flag to reject ticket requests from anonymous
principals to any principal other than the local TGT.  Allows FAST to
be deployed using anonymous tickets as armor in realms where the set
of authenticatable users must be constrained.



Changed Files:
U   trunk/doc/admin.texinfo
U   trunk/src/include/adm.h
U   trunk/src/include/k5-int.h
U   trunk/src/kdc/extern.h
U   trunk/src/kdc/kdc_util.c
U   trunk/src/kdc/main.c
U   trunk/src/lib/kadm5/admin.h
U   trunk/src/lib/kadm5/alt_prof.c
U   trunk/src/tests/t_anonpkinit.py
U   trunk/src/util/k5test.py
Modified: trunk/doc/admin.texinfo
===================================================================
--- trunk/doc/admin.texinfo	2010-12-01 02:16:37 UTC (rev 24546)
+++ trunk/doc/admin.texinfo	2010-12-01 20:01:46 UTC (rev 24547)
@@ -1562,8 +1562,12 @@
 current implementation has little protection against denial-of-service
 attacks), the standard port number assigned for Kerberos TCP traffic
 is port 88.
-- at end table
 
+ at itemx restrict_anonymous_to_kdc
+This flag determines the default value of restrict_anonymous_to_kdc for
+realms.  The default value is @code{false}.
+ at end table
+
 @node realms (kdc.conf), pkinit kdc options, kdcdefaults, kdc.conf
 @subsection [realms]
 
@@ -1742,6 +1746,15 @@
 
 This option defaults to @code{true}.
 
+ at itemx restrict_anonymous_to_tgt
+A boolean value (@code{true}, @code{false}).  If set to @code{true}, the
+KDC will reject ticket requests from anonymous principals to service
+principals other than the realm's ticket-granting service.  This option
+allows anonymous PKINIT to be enabled for use as FAST armor tickets
+without allowing anonymous authentication to services.  By default, the
+value of restrict_anonymous_to_tgt as specified in the [kdcdefaults]
+section is used.
+
 @end table
 
 @node pkinit kdc options, Sample kdc.conf File, realms (kdc.conf), kdc.conf

Modified: trunk/src/include/adm.h
===================================================================
--- trunk/src/include/adm.h	2010-12-01 02:16:37 UTC (rev 24546)
+++ trunk/src/include/adm.h	2010-12-01 20:01:46 UTC (rev 24547)
@@ -210,6 +210,7 @@
     krb5_flags          realm_flags;
     krb5_key_salt_tuple *realm_keysalts;
     unsigned int        realm_reject_bad_transit:1;
+    unsigned int        realm_restrict_anon:1;
     unsigned int        realm_kadmind_port_valid:1;
     unsigned int        realm_enctype_valid:1;
     unsigned int        realm_max_life_valid:1;
@@ -217,6 +218,7 @@
     unsigned int        realm_expiration_valid:1;
     unsigned int        realm_flags_valid:1;
     unsigned int        realm_reject_bad_transit_valid:1;
+    unsigned int        realm_restrict_anon_valid:1;
     krb5_int32          realm_num_keysalts;
 } krb5_realm_params;
 #endif  /* KRB5_ADM_H__ */

Modified: trunk/src/include/k5-int.h
===================================================================
--- trunk/src/include/k5-int.h	2010-12-01 02:16:37 UTC (rev 24546)
+++ trunk/src/include/k5-int.h	2010-12-01 20:01:46 UTC (rev 24547)
@@ -263,6 +263,7 @@
 #define KRB5_CONF_REALM_TRY_DOMAINS           "realm_try_domains"
 #define KRB5_CONF_REJECT_BAD_TRANSIT          "reject_bad_transit"
 #define KRB5_CONF_RENEW_LIFETIME              "renew_lifetime"
+#define KRB5_CONF_RESTRICT_ANONYMOUS_TO_TGT   "restrict_anonymous_to_tgt"
 #define KRB5_CONF_SAFE_CHECKSUM_TYPE          "safe_checksum_type"
 #define KRB5_CONF_SUPPORTED_ENCTYPES          "supported_enctypes"
 #define KRB5_CONF_TICKET_LIFETIME             "ticket_lifetime"

Modified: trunk/src/kdc/extern.h
===================================================================
--- trunk/src/kdc/extern.h	2010-12-01 02:16:37 UTC (rev 24546)
+++ trunk/src/kdc/extern.h	2010-12-01 20:01:46 UTC (rev 24547)
@@ -74,6 +74,7 @@
     krb5_deltat         realm_maxlife;  /* Maximum ticket life for realm    */
     krb5_deltat         realm_maxrlife; /* Maximum renewable life for realm */
     krb5_boolean        realm_reject_bad_transit; /* Accept unverifiable transited_realm ? */
+    krb5_boolean        realm_restrict_anon;  /* Anon to local TGT only */
 } kdc_realm_t;
 
 extern kdc_realm_t      **kdc_realmlist;
@@ -95,6 +96,7 @@
 #define master_princ                    kdc_active_realm->realm_mprinc
 #define tgs_server                      kdc_active_realm->realm_tgsprinc
 #define reject_bad_transit              kdc_active_realm->realm_reject_bad_transit
+#define restrict_anon                   kdc_active_realm->realm_restrict_anon
 
 /* various externs for KDC */
 extern krb5_data        empty_string;   /* an empty string */

Modified: trunk/src/kdc/kdc_util.c
===================================================================
--- trunk/src/kdc/kdc_util.c	2010-12-01 02:16:37 UTC (rev 24546)
+++ trunk/src/kdc/kdc_util.c	2010-12-01 20:01:46 UTC (rev 24547)
@@ -838,6 +838,21 @@
     return (protcode >= 0 && protcode <= 128) ? protcode : KRB_ERR_GENERIC;
 }
 
+/* Return -1 if the AS or TGS request is disallowed due to KDC policy on
+ * anonymous tickets. */
+static int
+check_anon(krb5_context context, krb5_principal client, krb5_principal server)
+{
+    /* If restrict_anon is set, reject requests from anonymous to principals
+     * other than the local TGT. */
+    if (restrict_anon &&
+        krb5_principal_compare_any_realm(context, client,
+                                         krb5_anonymous_principal()) &&
+        !krb5_principal_compare(context, server, tgs_server))
+        return -1;
+    return 0;
+}
+
 /*
  * Routines that validate a AS request; checks a lot of things.  :-)
  *
@@ -957,6 +972,11 @@
         return(KDC_ERR_MUST_USE_USER2USER);
     }
 
+    if (check_anon(kdc_context, request->client, request->server) != 0) {
+        *status = "ANONYMOUS NOT ALLOWED";
+        return(KDC_ERR_POLICY);
+    }
+
     /* Perform KDB module policy checks. */
     ret = krb5_db_check_policy_as(kdc_context, request, &client, &server,
                                   kdc_time, status, e_data);
@@ -1379,6 +1399,12 @@
         return KRB_ERR_GENERIC;
     }
 
+    if (check_anon(kdc_context, ticket->enc_part2->client,
+                   request->server) != 0) {
+        *status = "ANONYMOUS NOT ALLOWED";
+        return(KDC_ERR_POLICY);
+    }
+
     /* Perform KDB module policy checks. */
     ret = krb5_db_check_policy_tgs(kdc_context, request, &server,
                                    ticket, status, e_data);

Modified: trunk/src/kdc/main.c
===================================================================
--- trunk/src/kdc/main.c	2010-12-01 02:16:37 UTC (rev 24546)
+++ trunk/src/kdc/main.c	2010-12-01 20:01:46 UTC (rev 24547)
@@ -279,8 +279,8 @@
 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, char **db_args, char *no_refrls,
-           char *host_based_srvcs)
+           krb5_boolean def_manual, krb5_boolean def_restrict_anon,
+           char **db_args, char *no_refrls, char *host_based_srvcs)
 {
     krb5_error_code     kret;
     krb5_boolean        manual;
@@ -356,6 +356,11 @@
     } else
         manual = def_manual;
 
+    if (rparams && rparams->realm_restrict_anon_valid)
+        rdp->realm_restrict_anon = rparams->realm_restrict_anon;
+    else
+        rdp->realm_restrict_anon = def_restrict_anon;
+
     /* Handle master key type */
     if (rparams && rparams->realm_enctype_valid)
         rdp->realm_mkey.enctype = (krb5_enctype) rparams->realm_enctype;
@@ -655,6 +660,7 @@
     krb5_enctype        menctype = ENCTYPE_UNKNOWN;
     kdc_realm_t         *rdatap = NULL;
     krb5_boolean        manual = FALSE;
+    krb5_boolean        def_restrict_anon;
     char                *default_udp_ports = 0;
     char                *default_tcp_ports = 0;
     krb5_pointer        aprof;
@@ -678,6 +684,9 @@
         hierarchy[1] = KRB5_CONF_MAX_DGRAM_REPLY_SIZE;
         if (krb5_aprof_get_int32(aprof, hierarchy, TRUE, &max_dgram_reply_size))
             max_dgram_reply_size = MAX_DGRAM_SIZE;
+        hierarchy[1] = KRB5_CONF_RESTRICT_ANONYMOUS_TO_TGT;
+        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;
@@ -736,7 +745,8 @@
                 if ((rdatap = (kdc_realm_t *) malloc(sizeof(kdc_realm_t)))) {
                     if ((retval = init_realm(rdatap, optarg, mkey_name,
                                              menctype, default_udp_ports,
-                                             default_tcp_ports, manual, db_args,
+                                             default_tcp_ports, manual,
+                                             def_restrict_anon, db_args,
                                              no_refrls, host_based_srvcs))) {
                         fprintf(stderr,
                                 "%s: cannot initialize realm %s - see log file for details\n",
@@ -848,8 +858,8 @@
         if ((rdatap = (kdc_realm_t *) malloc(sizeof(kdc_realm_t)))) {
             if ((retval = init_realm(rdatap, lrealm, mkey_name, menctype,
                                      default_udp_ports, default_tcp_ports,
-                                     manual, db_args, no_refrls,
-                                     host_based_srvcs))) {
+                                     manual, def_restrict_anon, 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	2010-12-01 02:16:37 UTC (rev 24546)
+++ trunk/src/lib/kadm5/admin.h	2010-12-01 20:01:46 UTC (rev 24547)
@@ -291,6 +291,7 @@
     krb5_flags          realm_flags;
     krb5_key_salt_tuple *realm_keysalts;
     unsigned int        realm_reject_bad_transit:1;
+    unsigned int        realm_restrict_anon:1;
     unsigned int        realm_kadmind_port_valid:1;
     unsigned int        realm_enctype_valid:1;
     unsigned int        realm_max_life_valid:1;
@@ -298,6 +299,7 @@
     unsigned int        realm_expiration_valid:1;
     unsigned int        realm_flags_valid:1;
     unsigned int        realm_reject_bad_transit_valid:1;
+    unsigned int        realm_restrict_anon_valid:1;
     krb5_int32          realm_num_keysalts;
 } krb5_realm_params;
 

Modified: trunk/src/lib/kadm5/alt_prof.c
===================================================================
--- trunk/src/lib/kadm5/alt_prof.c	2010-12-01 02:16:37 UTC (rev 24546)
+++ trunk/src/lib/kadm5/alt_prof.c	2010-12-01 20:01:46 UTC (rev 24547)
@@ -1058,6 +1058,12 @@
         rparams->realm_reject_bad_transit_valid = 1;
     }
 
+    hierarchy[2] = KRB5_CONF_RESTRICT_ANONYMOUS_TO_TGT;
+    if (!krb5_aprof_get_boolean(aprofile, hierarchy, TRUE, &bvalue)) {
+        rparams->realm_restrict_anon = bvalue;
+        rparams->realm_restrict_anon_valid = 1;
+    }
+
     hierarchy[2] = KRB5_CONF_NO_HOST_REFERRAL;
     if (!krb5_aprof_get_string_all(aprofile, hierarchy, &no_refrls))
         rparams->realm_no_host_referral = no_refrls;

Modified: trunk/src/tests/t_anonpkinit.py
===================================================================
--- trunk/src/tests/t_anonpkinit.py	2010-12-01 02:16:37 UTC (rev 24546)
+++ trunk/src/tests/t_anonpkinit.py	2010-12-01 20:01:46 UTC (rev 24547)
@@ -25,10 +25,23 @@
     }
 }
 
-realm = K5Realm(krb5_conf=pkinit_krb5_conf, create_user=False,
-                create_host=False)
+restrictive_kdc_conf = {
+    'all': { 'realms' : { '$realm' : {
+                'restrict_anonymous_to_tgt' : 'true' } } } }
+
+# In the basic test, anonymous is not restricted, so kvno should succeed.
+realm = K5Realm(krb5_conf=pkinit_krb5_conf, create_user=False)
 realm.addprinc('WELLKNOWN/ANONYMOUS')
 realm.kinit('@%s' % realm.realm, flags=['-n'])
 realm.klist('WELLKNOWN/ANONYMOUS at WELLKNOWN:ANONYMOUS')
+realm.run_as_client([kvno, realm.host_princ])
+realm.stop()
 
+# Now try again with anonymous restricted; kvno should fail.
+realm = K5Realm(krb5_conf=pkinit_krb5_conf, kdc_conf=restrictive_kdc_conf,
+                create_user=False)
+realm.addprinc('WELLKNOWN/ANONYMOUS')
+realm.kinit('@%s' % realm.realm, flags=['-n'])
+realm.run_as_client([kvno, realm.host_princ], expected_code=1)
+
 success('Anonymous PKINIT.')

Modified: trunk/src/util/k5test.py
===================================================================
--- trunk/src/util/k5test.py	2010-12-01 02:16:37 UTC (rev 24546)
+++ trunk/src/util/k5test.py	2010-12-01 20:01:46 UTC (rev 24547)
@@ -181,6 +181,7 @@
   - ktutil
   - kinit
   - klist
+  - kvno
   - kdestroy
   - kpasswd
   - t_inetd
@@ -1054,6 +1055,7 @@
 ktutil = os.path.join(buildtop, 'kadmin', 'ktutil', 'ktutil')
 kinit = os.path.join(buildtop, 'clients', 'kinit', 'kinit')
 klist = os.path.join(buildtop, 'clients', 'klist', 'klist')
+kvno = os.path.join(buildtop, 'clients', 'kvno', 'kvno')
 kdestroy = os.path.join(buildtop, 'clients', 'kdestroy', 'kdestroy')
 kpasswd = os.path.join(buildtop, 'clients', 'kpasswd', 'kpasswd')
 t_inetd = os.path.join(buildtop, 'tests', 'dejagnu', 't_inetd')




More information about the cvs-krb5 mailing list