From 63557427e0a1cd3d23c0942ab58bcae7c2e35534 Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Thu, 2 May 2019 17:05:25 +1000 Subject: [PATCH] kdc: allow anonymous AS requests with long-term keys RFC8062 section 4.1 allows clients with long-term KDC keys to set the anonymous flag; in this case their identity is authenticated but the returned ticket contains the anonymous principal name as the client name. kdc: allow authenticated anonymous PKINIT The KDC PKINIT code conflated the checks for authenticated and unauthenticated anonymous by only looking at the anonymous KDC request option. --- kdc/kerberos5.c | 20 +++++--------------- kdc/pkinit.c | 10 ++++++---- 2 files changed, 11 insertions(+), 19 deletions(-) diff --git a/kdc/kerberos5.c b/kdc/kerberos5.c index 614731ad2..bf68743b5 100644 --- a/kdc/kerberos5.c +++ b/kdc/kerberos5.c @@ -597,12 +597,6 @@ pa_enc_ts_validate(kdc_request_t r, const PA_DATA *pa) Key *pa_key; char *str; - if (_kdc_is_anon_request(&r->req.req_body)) { - ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; - _kdc_set_e_text(r, "ENC-TS doesn't support anon"); - goto out; - } - ret = decode_EncryptedData(pa->padata_value.data, pa->padata_value.length, &enc_data, @@ -1774,16 +1768,10 @@ _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 ticket w/o anonymous flag"); + kdc_log(context, config, 0, "Anonymous client w/o anonymous flag"); ret = KRB5KDC_ERR_BADOPTION; goto out; } - } else if (_kdc_is_anon_request(b)) { - kdc_log(context, config, 0, - "Request for a anonymous ticket with non " - "anonymous client name: %s", r->client_name); - ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; - goto out; } /* @@ -2013,7 +2001,7 @@ _kdc_as_rep(kdc_request_t r, rep.msg_type = krb_as_rep; if (_kdc_is_anonymous(context, r->client_princ)) { - Realm anon_realm=KRB5_ANON_REALM; + Realm anon_realm = KRB5_ANON_REALM; ret = copy_Realm(&anon_realm, &rep.crealm); } else if (f.canonicalize || r->client->entry.flags.force_canonicalize) ret = copy_Realm(&r->client->entry.principal->realm, &rep.crealm); @@ -2021,7 +2009,9 @@ _kdc_as_rep(kdc_request_t r, ret = copy_Realm(&r->client_princ->realm, &rep.crealm); if (ret) goto out; - if (f.canonicalize || r->client->entry.flags.force_canonicalize) + if (_kdc_is_anon_request(b)) + 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); else ret = _krb5_principal2principalname(&rep.cname, r->client_princ); diff --git a/kdc/pkinit.c b/kdc/pkinit.c index 182055074..dbe833f07 100644 --- a/kdc/pkinit.c +++ b/kdc/pkinit.c @@ -477,7 +477,7 @@ _kdc_pk_rd_padata(krb5_context context, type = "PK-INIT-Win2k"; - if (_kdc_is_anon_request(&req->req_body)) { + if (_kdc_is_anonymous(context, client->entry.principal)) { ret = KRB5_KDC_ERR_PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED; krb5_set_error_message(context, ret, "Anon not supported in RSA mode"); @@ -623,7 +623,7 @@ _kdc_pk_rd_padata(krb5_context context, hx509_certs signer_certs; int flags = HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH; /* BTMM */ - if (_kdc_is_anon_request(&req->req_body)) + if (_kdc_is_anonymous(context, client->entry.principal)) flags |= HX509_CMS_VS_ALLOW_ZERO_SIGNER; ret = hx509_cms_verify_signed(context->hx509ctx, @@ -708,7 +708,7 @@ _kdc_pk_rd_padata(krb5_context context, goto out; } - if (_kdc_is_anon_request(&req->req_body) && + if (_kdc_is_anonymous(context, client->entry.principal) && ap.clientPublicValue == NULL) { free_AuthPack(&ap); ret = KRB5_KDC_ERR_PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED; @@ -1676,8 +1676,10 @@ _kdc_pk_check_client(krb5_context context, size_t i; if (cp->cert == NULL) { + if (!_kdc_is_anonymous(context, client->entry.principal)) + return KRB5KDC_ERR_BADOPTION; - *subject_name = strdup("anonymous client client"); + *subject_name = strdup(""); if (*subject_name == NULL) return ENOMEM; return 0;