summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGreg Hudson <ghudson@mit.edu>2010-12-01 20:01:46 +0000
committerGreg Hudson <ghudson@mit.edu>2010-12-01 20:01:46 +0000
commit9479352bf9c570659ebdc40561ac81a7eb292b08 (patch)
tree3a4fc5078619402e8aba1386d2a99f58a207efc2 /src
parentcdd631f3ec5c02f9c2983f459f944577a5a0c3e2 (diff)
downloadkrb5-9479352bf9c570659ebdc40561ac81a7eb292b08.tar.gz
krb5-9479352bf9c570659ebdc40561ac81a7eb292b08.tar.xz
krb5-9479352bf9c570659ebdc40561ac81a7eb292b08.zip
Implement restrict_anonymous_to_tgt realm flag
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. ticket: 6829 target_version: 1.9 tags: pullup git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@24547 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src')
-rw-r--r--src/include/adm.h2
-rw-r--r--src/include/k5-int.h1
-rw-r--r--src/kdc/extern.h2
-rw-r--r--src/kdc/kdc_util.c26
-rw-r--r--src/kdc/main.c20
-rw-r--r--src/lib/kadm5/admin.h2
-rw-r--r--src/lib/kadm5/alt_prof.c6
-rw-r--r--src/tests/t_anonpkinit.py17
-rw-r--r--src/util/k5test.py2
9 files changed, 71 insertions, 7 deletions
diff --git a/src/include/adm.h b/src/include/adm.h
index 68f3c7a897..c23cd89e34 100644
--- a/src/include/adm.h
+++ b/src/include/adm.h
@@ -210,6 +210,7 @@ typedef struct __krb5_realm_params {
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 @@ typedef struct __krb5_realm_params {
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__ */
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
index 9a81d3bbcc..ac46b46006 100644
--- a/src/include/k5-int.h
+++ b/src/include/k5-int.h
@@ -263,6 +263,7 @@ typedef INT64_TYPE krb5_int64;
#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"
diff --git a/src/kdc/extern.h b/src/kdc/extern.h
index 24bad20a50..236e5ccd9c 100644
--- a/src/kdc/extern.h
+++ b/src/kdc/extern.h
@@ -74,6 +74,7 @@ typedef struct __kdc_realm_data {
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 @@ kdc_realm_t *find_realm_data (char *, krb5_ui_4);
#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 */
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
index 691ece06c9..62fea6fdb6 100644
--- a/src/kdc/kdc_util.c
+++ b/src/kdc/kdc_util.c
@@ -838,6 +838,21 @@ errcode_to_protocol(krb5_error_code code)
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 @@ validate_as_request(register krb5_kdc_req *request, krb5_db_entry client,
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 @@ validate_tgs_request(register krb5_kdc_req *request, krb5_db_entry server,
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);
diff --git a/src/kdc/main.c b/src/kdc/main.c
index 5b90bd5926..57cd226fb0 100644
--- a/src/kdc/main.c
+++ b/src/kdc/main.c
@@ -279,8 +279,8 @@ handle_referral_params(krb5_realm_params *rparams,
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 @@ init_realm(kdc_realm_t *rdp, char *realm, char *def_mpname,
} 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 @@ initialize_realms(krb5_context kcontext, int argc, char **argv)
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 @@ initialize_realms(krb5_context kcontext, int argc, char **argv)
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 @@ initialize_realms(krb5_context kcontext, int argc, char **argv)
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 @@ initialize_realms(krb5_context kcontext, int argc, char **argv)
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);
diff --git a/src/lib/kadm5/admin.h b/src/lib/kadm5/admin.h
index 99837033be..8b59c6b5bb 100644
--- a/src/lib/kadm5/admin.h
+++ b/src/lib/kadm5/admin.h
@@ -291,6 +291,7 @@ typedef struct __krb5_realm_params {
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 @@ typedef struct __krb5_realm_params {
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;
diff --git a/src/lib/kadm5/alt_prof.c b/src/lib/kadm5/alt_prof.c
index 6a79655126..cdd732113a 100644
--- a/src/lib/kadm5/alt_prof.c
+++ b/src/lib/kadm5/alt_prof.c
@@ -1058,6 +1058,12 @@ krb5_read_realm_params(kcontext, realm, rparamp)
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;
diff --git a/src/tests/t_anonpkinit.py b/src/tests/t_anonpkinit.py
index 0149a671b1..ddb96919b4 100644
--- a/src/tests/t_anonpkinit.py
+++ b/src/tests/t_anonpkinit.py
@@ -25,10 +25,23 @@ pkinit_krb5_conf = {
}
}
-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@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.')
diff --git a/src/util/k5test.py b/src/util/k5test.py
index a710eee3ae..a032d78b5b 100644
--- a/src/util/k5test.py
+++ b/src/util/k5test.py
@@ -181,6 +181,7 @@ Scripts may use the following functions and variables:
- ktutil
- kinit
- klist
+ - kvno
- kdestroy
- kpasswd
- t_inetd
@@ -1054,6 +1055,7 @@ kdb5_util = os.path.join(buildtop, 'kadmin', 'dbutil', 'kdb5_util')
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')