move PKINIT to a preauth mech too

This commit is contained in:
Love Hornquist Astrand
2011-05-11 23:17:48 -07:00
committed by Love Hörnquist Åstrand
parent 07342aa138
commit 68bd6f63e8
2 changed files with 106 additions and 97 deletions

View File

@@ -66,7 +66,7 @@ struct kdc_request_desc {
EncKDCRepPart ek; EncKDCRepPart ek;
/* PA methods can affect both the reply key and the session key (pkinit) */ /* PA methods can affect both the reply key and the session key (pkinit) */
krb5_keyblock sessionetype; krb5_enctype sessionetype;
krb5_keyblock reply_key; krb5_keyblock reply_key;
krb5_keyblock session_key; krb5_keyblock session_key;

View File

@@ -278,6 +278,69 @@ _kdc_log_timestamp(krb5_context context,
type, authtime_str, starttime_str, endtime_str, renewtime_str); type, authtime_str, starttime_str, endtime_str, renewtime_str);
} }
/*
*
*/
#ifdef PKINIT
static krb5_error_code
pa_pkinit_validate(kdc_request_t r, const PA_DATA *pa)
{
char *client_cert = NULL;
krb5_error_code ret;
pk_client_params *pkp = NULL;
ret = _kdc_pk_rd_padata(r->context, r->config, &r->req, pa, r->client, &pkp);
if (ret || pkp == NULL) {
ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
kdc_log(r->context, r->config, 5,
"Failed to decode PKINIT PA-DATA -- %s",
r->client_name);
goto out;
}
ret = _kdc_pk_check_client(r->context,
r->config,
r->clientdb,
r->client,
pkp,
&client_cert);
if (ret) {
_kdc_set_e_text(r, "PKINIT certificate not allowed to "
"impersonate principal");
goto out;
}
kdc_log(r->context, r->config, 0,
"PKINIT pre-authentication succeeded -- %s using %s",
r->client_name, client_cert);
free(client_cert);
ret = _kdc_pk_mk_pa_reply(r->context, r->config, pkp, r->client,
r->sessionetype, &r->req, &r->request,
&r->reply_key, &r->session_key, &r->outpadata);
if (ret) {
_kdc_set_e_text(r, "Failed to build PK-INIT reply");
goto out;
}
#if 0
ret = _kdc_add_inital_verified_cas(r->context, r->config,
pkp, &r->et);
#endif
out:
if (pkp)
_kdc_pk_free_client_param(r->context, pkp);
return ret;
}
#endif /* PKINIT */
/*
*
*/
static krb5_error_code static krb5_error_code
make_pa_enc_challange(krb5_context context, METHOD_DATA *md, make_pa_enc_challange(krb5_context context, METHOD_DATA *md,
krb5_crypto crypto) krb5_crypto crypto)
@@ -620,13 +683,19 @@ struct kdc_patypes {
static const struct kdc_patypes pat[] = { static const struct kdc_patypes pat[] = {
#ifdef PKINIT #ifdef PKINIT
{ KRB5_PADATA_PK_AS_REQ, "PK-INIT(ietf)", PA_ANNOUNCE }, {
{ KRB5_PADATA_PK_AS_REQ_WIN, "PK-INIT(win2k)", PA_ANNOUNCE }, KRB5_PADATA_PK_AS_REQ, "PK-INIT(ietf)", PA_ANNOUNCE,
pa_pkinit_validate
},
{
KRB5_PADATA_PK_AS_REQ_WIN, "PK-INIT(win2k)", PA_ANNOUNCE,
pa_pkinit_validate
},
#else #else
{ KRB5_PADATA_PK_AS_REQ, "PK-INIT(ietf)", 0 }, { KRB5_PADATA_PK_AS_REQ, "PK-INIT(ietf)", 0, NULL },
{ KRB5_PADATA_PK_AS_REQ_WIN, "PK-INIT(win2k)", 0 }, { KRB5_PADATA_PK_AS_REQ_WIN, "PK-INIT(win2k)", 0, NULL },
#endif #endif
{ KRB5_PADATA_PA_PK_OCSP_RESPONSE , "OCSP", 0 }, { KRB5_PADATA_PA_PK_OCSP_RESPONSE , "OCSP", 0, NULL },
{ {
KRB5_PADATA_ENC_TIMESTAMP , "ENC-TS", KRB5_PADATA_ENC_TIMESTAMP , "ENC-TS",
PA_ANNOUNCE, PA_ANNOUNCE,
@@ -637,10 +706,10 @@ static const struct kdc_patypes pat[] = {
PA_ANNOUNCE | PA_REQ_FAST, PA_ANNOUNCE | PA_REQ_FAST,
pa_enc_chal_validate pa_enc_chal_validate
}, },
{ KRB5_PADATA_REQ_ENC_PA_REP , "REQ-ENC-PA-REP", 0 }, { KRB5_PADATA_REQ_ENC_PA_REP , "REQ-ENC-PA-REP", 0, NULL },
{ KRB5_PADATA_FX_FAST, "FX-FAST", PA_ANNOUNCE }, { KRB5_PADATA_FX_FAST, "FX-FAST", PA_ANNOUNCE, NULL },
{ KRB5_PADATA_FX_ERROR, "FX-ERROR", 0 }, { KRB5_PADATA_FX_ERROR, "FX-ERROR", 0, NULL },
{ KRB5_PADATA_FX_COOKIE, "FX-COOKIE", 0 } { KRB5_PADATA_FX_COOKIE, "FX-COOKIE", 0, NULL }
}; };
static void static void
@@ -1658,15 +1727,12 @@ _kdc_as_rep(kdc_request_t r,
KDC_REQ_BODY *b = NULL; KDC_REQ_BODY *b = NULL;
AS_REP rep; AS_REP rep;
KDCOptions f; KDCOptions f;
krb5_enctype setype, sessionetype; krb5_enctype setype;
EncTicketPart et; EncTicketPart et;
EncKDCRepPart ek; EncKDCRepPart ek;
krb5_error_code ret = 0; krb5_error_code ret = 0;
Key *ckey, *skey; Key *ckey, *skey;
int flags = 0; int flags = 0;
#ifdef PKINIT
pk_client_params *pkp = NULL;
#endif
METHOD_DATA error_method; METHOD_DATA error_method;
memset(&rep, 0, sizeof(rep)); memset(&rep, 0, sizeof(rep));
@@ -1675,10 +1741,6 @@ _kdc_as_rep(kdc_request_t r,
error_method.len = 0; error_method.len = 0;
error_method.val = NULL; error_method.val = NULL;
ALLOC(rep.padata);
rep.padata->len = 0;
rep.padata->val = NULL;
/* /*
* Look for FAST armor and unwrap * Look for FAST armor and unwrap
*/ */
@@ -1794,6 +1856,7 @@ _kdc_as_rep(kdc_request_t r,
* enctype that an older version of a KDC in the same realm can't * enctype that an older version of a KDC in the same realm can't
* decrypt. * decrypt.
*/ */
ret = _kdc_find_etype(context, config->as_use_strongest_session_key, FALSE, ret = _kdc_find_etype(context, config->as_use_strongest_session_key, FALSE,
client, b->etype.val, b->etype.len, &sessionetype, client, b->etype.val, b->etype.len, &sessionetype,
NULL); NULL);
@@ -1841,58 +1904,8 @@ _kdc_as_rep(kdc_request_t r,
if (found_pa) { if (found_pa) {
et.flags.pre_authent = 1; et.flags.pre_authent = 1;
goto preauth_done;
} }
#ifdef PKINIT
kdc_log(context, config, 5,
"Looking for PKINIT pa-data -- %s", r->client_name);
_kdc_set_e_text(r, "No PKINIT PA found");
i = 0;
pa = _kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_REQ);
if (pa == NULL) {
i = 0;
pa = _kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_REQ_WIN);
}
if (pa) {
char *client_cert = NULL;
ret = _kdc_pk_rd_padata(context, config, req, pa, r->client, &pkp);
if (ret) {
ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
kdc_log(context, config, 5,
"Failed to decode PKINIT PA-DATA -- %s",
r->client_name);
goto out;
}
if (ret == 0 && pkp == NULL)
goto out;
ret = _kdc_pk_check_client(context,
config,
r->clientdb,
r->client,
pkp,
&client_cert);
if (ret) {
_kdc_set_e_text(r, "PKINIT certificate not allowed to "
"impersonate principal");
_kdc_pk_free_client_param(context, pkp);
pkp = NULL;
goto out;
}
found_pa = 1;
et.flags.pre_authent = 1;
kdc_log(context, config, 0,
"PKINIT pre-authentication succeeded -- %s using %s",
r->client_name, client_cert);
free(client_cert);
}
preauth_done:
#endif
if(found_pa == 0 && config->require_preauth) if(found_pa == 0 && config->require_preauth)
goto use_pa; goto use_pa;
/* We come here if we found a pa-enc-timestamp, but if there /* We come here if we found a pa-enc-timestamp, but if there
@@ -2170,26 +2183,12 @@ _kdc_as_rep(kdc_request_t r,
copy_HostAddresses(et.caddr, ek.caddr); copy_HostAddresses(et.caddr, ek.caddr);
} }
#if PKINIT /*
if (pkp) { * Check and session and reply keys
ret = _kdc_pk_mk_pa_reply(context, config, pkp, r->client, */
sessionetype, req, req_buffer,
&r->reply_key, &et.key, rep.padata);
if (ret) {
_kdc_set_e_text(r, "Failed to build PK-INIT reply");
goto out;
}
ret = _kdc_add_inital_verified_cas(context,
config,
pkp,
&et);
if (ret)
goto out;
} else if (r->session_key.keytype == ETYPE_NULL) {
#endif ret = krb5_generate_random_keyblock(context, r->sessionetype, &r->session_key);
{
ret = krb5_generate_random_keyblock(context, sessionetype, &et.key);
if (ret) if (ret)
goto out; goto out;
} }
@@ -2200,11 +2199,18 @@ _kdc_as_rep(kdc_request_t r,
goto out; goto out;
} }
ret = copy_EncryptionKey(&et.key, &ek.key); ret = copy_EncryptionKey(&r->session_key, &et.key);
if (ret) if (ret)
goto out; goto out;
/* Add signing of alias referral */ ret = copy_EncryptionKey(&r->session_key, &ek.key);
if (ret)
goto out;
/*
* Add signing of alias referral
*/
if (f.canonicalize) { if (f.canonicalize) {
PA_ClientCanonicalized canon; PA_ClientCanonicalized canon;
krb5_data data; krb5_data data;
@@ -2250,15 +2256,22 @@ _kdc_as_rep(kdc_request_t r,
pa.padata_type = KRB5_PADATA_CLIENT_CANONICALIZED; pa.padata_type = KRB5_PADATA_CLIENT_CANONICALIZED;
pa.padata_value = data; pa.padata_value = data;
ret = add_METHOD_DATA(rep.padata, &pa); ret = add_METHOD_DATA(&r->outpadata, &pa);
free(data.data); free(data.data);
if (ret) if (ret)
goto out; goto out;
} }
if (rep.padata->len == 0) { if (r->outpadata.len) {
free(rep.padata);
rep.padata = NULL; ALLOC(rep.padata);
if (rep.padata == NULL) {
ret = ENOMEM;
goto out;
}
ret = copy_METHOD_DATA(&r->outpadata, rep.padata);
if (ret)
goto out;
} }
/* Add the PAC */ /* Add the PAC */
@@ -2355,10 +2368,6 @@ out:
goto out2; goto out2;
} }
out2: out2:
#ifdef PKINIT
if (pkp)
_kdc_pk_free_client_param(context, pkp);
#endif
free_EncTicketPart(&et); free_EncTicketPart(&et);
free_EncKDCRepPart(&ek); free_EncKDCRepPart(&ek);