diff --git a/kdc/kerberos5.c b/kdc/kerberos5.c index f11b2984b..f869038a9 100644 --- a/kdc/kerberos5.c +++ b/kdc/kerberos5.c @@ -116,6 +116,22 @@ is_default_salt_p(const krb5_salt *default_salt, const Key *key) return TRUE; } + +static krb5_boolean +is_anon_request_p(kdc_request_t r) +{ + KDC_REQ_BODY *b = &r->req.req_body; + + /* + * Some versions of heimdal use bit 14 instead of 16 for + * request_anonymous, as indicated in the anonymous draft prior to + * version 11. Bit 14 is assigned to S4U2Proxy, but all S4U2Proxy + * requests will have a second ticket; don't consider those anonymous + */ + return b->kdc_options.request_anonymous || + (b->kdc_options.cname_in_addl_tkt && !b->additional_tickets); +} + /* * return the first appropriate key of `princ' in `ret_key'. Look for * all the etypes in (`etypes', `len'), stopping as soon as we find @@ -437,7 +453,6 @@ static krb5_error_code pa_enc_chal_validate(kdc_request_t r, const PA_DATA *pa) { krb5_data pepper1, pepper2, ts_data; - KDC_REQ_BODY *b = &r->req.req_body; int invalidPassword = 0; EncryptedData enc_data; krb5_enctype aenctype; @@ -448,7 +463,7 @@ pa_enc_chal_validate(kdc_request_t r, const PA_DATA *pa) heim_assert(r->armor_crypto != NULL, "ENC-CHAL called for non FAST"); - if (_kdc_is_anon_request(b)) { + if (is_anon_request_p(r)) { ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; kdc_log(r->context, r->config, 0, "ENC-CHALL doesn't support anon"); return ret; @@ -1537,6 +1552,24 @@ _kdc_check_addresses(krb5_context context, return result; } +/* + * + */ +krb5_error_code +_kdc_check_anon_policy (krb5_context context, + krb5_kdc_configuration *config, + hdb_entry_ex *client, + hdb_entry_ex *server) +{ + if (!config->allow_anonymous){ + kdc_log(context, config, 0, + "Request for anonymous ticket denied by local policy"); + return KRB5KDC_ERR_POLICY; + } + + return 0; +} + /* * */ @@ -1760,12 +1793,11 @@ _kdc_as_rep(kdc_request_t r, * */ - if (_kdc_is_anonymous(context, r->client_princ)) { - if (!_kdc_is_anon_request(b)) { - kdc_log(context, config, 0, "Anonymous client w/o anonymous flag"); - ret = KRB5KDC_ERR_BADOPTION; - goto out; - } + if (_kdc_is_anonymous(context, r->client_princ) && + !is_anon_request_p(r)) { + kdc_log(context, config, 0, "Anonymous client w/o anonymous flag"); + ret = KRB5KDC_ERR_BADOPTION; + goto out; } /* @@ -1936,7 +1968,7 @@ _kdc_as_rep(kdc_request_t r, * send requre preauth is its required or anon is requested, * anon is today only allowed via preauth mechanisms. */ - if (require_preauth_p(r) || _kdc_is_anon_request(b)) { + if (require_preauth_p(r) || is_anon_request_p(r)) { ret = KRB5KDC_ERR_PREAUTH_REQUIRED; _kdc_set_e_text(r, "Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ"); goto out; @@ -1969,6 +2001,16 @@ _kdc_as_rep(kdc_request_t r, if(ret) goto out; + if (is_anon_request_p(r)) { + ret = _kdc_check_anon_policy(context, config, r->client, r->server); + if (ret) { + _kdc_set_e_text(r, "Anonymous ticket requests are disabled"); + goto out; + } + + r->et.flags.anonymous = 1; + } + /* * Select the best encryption type for the KDC with out regard to * the client since the client never needs to read that data. @@ -1980,8 +2022,7 @@ _kdc_as_rep(kdc_request_t r, if(ret) goto out; - if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey - || (_kdc_is_anon_request(b) && !config->allow_anonymous)) { + if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey) { ret = KRB5KDC_ERR_BADOPTION; _kdc_set_e_text(r, "Bad KDC options"); goto out; @@ -2003,7 +2044,7 @@ _kdc_as_rep(kdc_request_t r, ret = copy_Realm(&r->client_princ->realm, &rep.crealm); if (ret) goto out; - if (_kdc_is_anon_request(b)) + if (r->et.flags.anonymous) ret = _kdc_make_anonymous_principalname(&rep.cname); else if (f.canonicalize || r->client->entry.flags.force_canonicalize) ret = _krb5_principal2principalname(&rep.cname, r->client->entry.principal); @@ -2120,9 +2161,6 @@ _kdc_as_rep(kdc_request_t r, } } - if (_kdc_is_anon_request(b)) - r->et.flags.anonymous = 1; - if(b->addresses){ ALLOC(r->et.caddr); copy_HostAddresses(b->addresses, r->et.caddr); @@ -2235,7 +2273,7 @@ _kdc_as_rep(kdc_request_t r, } /* Add the PAC */ - if (send_pac_p(context, req) && !_kdc_is_anon_request(b)) { + if (send_pac_p(context, req) && !r->et.flags.anonymous) { generate_pac(r, skey); } @@ -2430,14 +2468,3 @@ _kdc_tkt_add_if_relevant_ad(krb5_context context, return 0; } - -krb5_boolean -_kdc_is_anon_request(const KDC_REQ_BODY *b) -{ - /* some versions of heimdal use bit 14 instead of 16 for - request_anonymous, as indicated in the anonymous draft prior to - version 11. Bit 14 is assigned to S4U2Proxy, but all S4U2Proxy - requests will have a second ticket; don't consider those anonymous */ - return (b->kdc_options.request_anonymous || - (b->kdc_options.cname_in_addl_tkt && !b->additional_tickets)); -} diff --git a/kdc/krb5tgs.c b/kdc/krb5tgs.c index 1333ad3bf..7ef05ecfa 100644 --- a/kdc/krb5tgs.c +++ b/kdc/krb5tgs.c @@ -506,15 +506,8 @@ check_tgs_flags(krb5_context context, * anonymous KDC option SHOULD be set, but it is not required. * Treat an anonymous TGT as if the anonymous flag was set. */ - if (tgt->flags.anonymous || f.request_anonymous) { - if (!config->allow_anonymous){ - kdc_log(context, config, 0, - "Request for anonymous ticket"); - return KRB5KDC_ERR_BADOPTION; - } - + if (tgt->flags.anonymous || f.request_anonymous) et->flags.anonymous = 1; - } return 0; } @@ -2352,6 +2345,13 @@ server_lookup: goto out; } + /* check local and per-principal anonymous ticket issuance policy */ + if (tgt->flags.anonymous || b->kdc_options.request_anonymous) { + ret = _kdc_check_anon_policy(context, config, client, server); + if (ret) + goto out; + } + /* * If this is an referral, add server referral data to the * auth_data reply .