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;
/* 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 session_key;

View File

@@ -278,6 +278,69 @@ _kdc_log_timestamp(krb5_context context,
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
make_pa_enc_challange(krb5_context context, METHOD_DATA *md,
krb5_crypto crypto)
@@ -620,13 +683,19 @@ struct kdc_patypes {
static const struct kdc_patypes pat[] = {
#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
{ KRB5_PADATA_PK_AS_REQ, "PK-INIT(ietf)", 0 },
{ KRB5_PADATA_PK_AS_REQ_WIN, "PK-INIT(win2k)", 0 },
{ KRB5_PADATA_PK_AS_REQ, "PK-INIT(ietf)", 0, NULL },
{ KRB5_PADATA_PK_AS_REQ_WIN, "PK-INIT(win2k)", 0, NULL },
#endif
{ KRB5_PADATA_PA_PK_OCSP_RESPONSE , "OCSP", 0 },
{ KRB5_PADATA_PA_PK_OCSP_RESPONSE , "OCSP", 0, NULL },
{
KRB5_PADATA_ENC_TIMESTAMP , "ENC-TS",
PA_ANNOUNCE,
@@ -637,10 +706,10 @@ static const struct kdc_patypes pat[] = {
PA_ANNOUNCE | PA_REQ_FAST,
pa_enc_chal_validate
},
{ KRB5_PADATA_REQ_ENC_PA_REP , "REQ-ENC-PA-REP", 0 },
{ KRB5_PADATA_FX_FAST, "FX-FAST", PA_ANNOUNCE },
{ KRB5_PADATA_FX_ERROR, "FX-ERROR", 0 },
{ KRB5_PADATA_FX_COOKIE, "FX-COOKIE", 0 }
{ KRB5_PADATA_REQ_ENC_PA_REP , "REQ-ENC-PA-REP", 0, NULL },
{ KRB5_PADATA_FX_FAST, "FX-FAST", PA_ANNOUNCE, NULL },
{ KRB5_PADATA_FX_ERROR, "FX-ERROR", 0, NULL },
{ KRB5_PADATA_FX_COOKIE, "FX-COOKIE", 0, NULL }
};
static void
@@ -1658,15 +1727,12 @@ _kdc_as_rep(kdc_request_t r,
KDC_REQ_BODY *b = NULL;
AS_REP rep;
KDCOptions f;
krb5_enctype setype, sessionetype;
krb5_enctype setype;
EncTicketPart et;
EncKDCRepPart ek;
krb5_error_code ret = 0;
Key *ckey, *skey;
int flags = 0;
#ifdef PKINIT
pk_client_params *pkp = NULL;
#endif
METHOD_DATA error_method;
memset(&rep, 0, sizeof(rep));
@@ -1675,10 +1741,6 @@ _kdc_as_rep(kdc_request_t r,
error_method.len = 0;
error_method.val = NULL;
ALLOC(rep.padata);
rep.padata->len = 0;
rep.padata->val = NULL;
/*
* 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
* decrypt.
*/
ret = _kdc_find_etype(context, config->as_use_strongest_session_key, FALSE,
client, b->etype.val, b->etype.len, &sessionetype,
NULL);
@@ -1841,58 +1904,8 @@ _kdc_as_rep(kdc_request_t r,
if (found_pa) {
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)
goto use_pa;
/* 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);
}
#if PKINIT
if (pkp) {
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;
/*
* Check and session and reply keys
*/
} else
#endif
{
ret = krb5_generate_random_keyblock(context, sessionetype, &et.key);
if (r->session_key.keytype == ETYPE_NULL) {
ret = krb5_generate_random_keyblock(context, r->sessionetype, &r->session_key);
if (ret)
goto out;
}
@@ -2200,11 +2199,18 @@ _kdc_as_rep(kdc_request_t r,
goto out;
}
ret = copy_EncryptionKey(&et.key, &ek.key);
ret = copy_EncryptionKey(&r->session_key, &et.key);
if (ret)
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) {
PA_ClientCanonicalized canon;
krb5_data data;
@@ -2250,15 +2256,22 @@ _kdc_as_rep(kdc_request_t r,
pa.padata_type = KRB5_PADATA_CLIENT_CANONICALIZED;
pa.padata_value = data;
ret = add_METHOD_DATA(rep.padata, &pa);
ret = add_METHOD_DATA(&r->outpadata, &pa);
free(data.data);
if (ret)
goto out;
}
if (rep.padata->len == 0) {
free(rep.padata);
rep.padata = NULL;
if (r->outpadata.len) {
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 */
@@ -2355,10 +2368,6 @@ out:
goto out2;
}
out2:
#ifdef PKINIT
if (pkp)
_kdc_pk_free_client_param(context, pkp);
#endif
free_EncTicketPart(&et);
free_EncKDCRepPart(&ek);