handle BTMM, more logging
This commit is contained in:
@@ -3,6 +3,8 @@
|
|||||||
* (Royal Institute of Technology, Stockholm, Sweden).
|
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
|
* Portions Copyright (c) 2009 Apple Inc. All rights reserved.
|
||||||
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
* are met:
|
* are met:
|
||||||
@@ -180,18 +182,26 @@ static krb5_error_code
|
|||||||
find_cert(krb5_context context, struct krb5_pk_identity *id,
|
find_cert(krb5_context context, struct krb5_pk_identity *id,
|
||||||
hx509_query *q, hx509_cert *cert)
|
hx509_query *q, hx509_cert *cert)
|
||||||
{
|
{
|
||||||
struct certfind cf[3] = {
|
struct certfind cf[4] = {
|
||||||
|
{ "MobileMe EKU" },
|
||||||
{ "PKINIT EKU" },
|
{ "PKINIT EKU" },
|
||||||
{ "MS EKU" },
|
{ "MS EKU" },
|
||||||
{ "any (or no)" }
|
{ "any (or no)" }
|
||||||
};
|
};
|
||||||
int i, ret;
|
int i, ret, start = 1;
|
||||||
|
unsigned oids[] = { 1, 2, 840, 113635, 100, 3, 2, 1 };
|
||||||
|
const heim_oid mobileMe = { sizeof(oids)/sizeof(oids[0]), oids };
|
||||||
|
|
||||||
cf[0].oid = &asn1_oid_id_pkekuoid;
|
|
||||||
cf[1].oid = &asn1_oid_id_pkinit_ms_eku;
|
|
||||||
cf[2].oid = NULL;
|
|
||||||
|
|
||||||
for (i = 0; i < sizeof(cf)/sizeof(cf[0]); i++) {
|
if (id->flags & PKINIT_BTMM)
|
||||||
|
start = 0;
|
||||||
|
|
||||||
|
cf[0].oid = &mobileMe;
|
||||||
|
cf[1].oid = &asn1_oid_id_pkekuoid;
|
||||||
|
cf[2].oid = &asn1_oid_id_pkinit_ms_eku;
|
||||||
|
cf[3].oid = NULL;
|
||||||
|
|
||||||
|
for (i = start; i < sizeof(cf)/sizeof(cf[0]); i++) {
|
||||||
ret = hx509_query_match_eku(q, cf[i].oid);
|
ret = hx509_query_match_eku(q, cf[i].oid);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pk_copy_error(context, context->hx509ctx, ret,
|
pk_copy_error(context, context->hx509ctx, ret,
|
||||||
@@ -344,7 +354,7 @@ build_edi(krb5_context context,
|
|||||||
hx509_certs certs,
|
hx509_certs certs,
|
||||||
ExternalPrincipalIdentifiers *ids)
|
ExternalPrincipalIdentifiers *ids)
|
||||||
{
|
{
|
||||||
return hx509_certs_iter(hx509ctx, certs, cert2epi, ids);
|
return hx509_certs_iter_f(hx509ctx, certs, cert2epi, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
static krb5_error_code
|
static krb5_error_code
|
||||||
@@ -800,6 +810,8 @@ pk_mk_padata(krb5_context context,
|
|||||||
krb5_error_code KRB5_LIB_FUNCTION
|
krb5_error_code KRB5_LIB_FUNCTION
|
||||||
_krb5_pk_mk_padata(krb5_context context,
|
_krb5_pk_mk_padata(krb5_context context,
|
||||||
void *c,
|
void *c,
|
||||||
|
int ic_flags,
|
||||||
|
int win2k,
|
||||||
const KDC_REQ_BODY *req_body,
|
const KDC_REQ_BODY *req_body,
|
||||||
unsigned nonce,
|
unsigned nonce,
|
||||||
METHOD_DATA *md)
|
METHOD_DATA *md)
|
||||||
@@ -814,7 +826,7 @@ _krb5_pk_mk_padata(krb5_context context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
win2k_compat = krb5_config_get_bool_default(context, NULL,
|
win2k_compat = krb5_config_get_bool_default(context, NULL,
|
||||||
FALSE,
|
win2k,
|
||||||
"realms",
|
"realms",
|
||||||
req_body->realm,
|
req_body->realm,
|
||||||
"pkinit_win2k",
|
"pkinit_win2k",
|
||||||
@@ -823,7 +835,7 @@ _krb5_pk_mk_padata(krb5_context context,
|
|||||||
if (win2k_compat) {
|
if (win2k_compat) {
|
||||||
ctx->require_binding =
|
ctx->require_binding =
|
||||||
krb5_config_get_bool_default(context, NULL,
|
krb5_config_get_bool_default(context, NULL,
|
||||||
FALSE,
|
TRUE,
|
||||||
"realms",
|
"realms",
|
||||||
req_body->realm,
|
req_body->realm,
|
||||||
"pkinit_win2k_require_binding",
|
"pkinit_win2k_require_binding",
|
||||||
@@ -839,6 +851,11 @@ _krb5_pk_mk_padata(krb5_context context,
|
|||||||
req_body->realm,
|
req_body->realm,
|
||||||
"pkinit_require_eku",
|
"pkinit_require_eku",
|
||||||
NULL);
|
NULL);
|
||||||
|
if (ic_flags & KRB5_INIT_CREDS_NO_C_NO_EKU_CHECK)
|
||||||
|
ctx->require_eku = 0;
|
||||||
|
if (ctx->id->flags & PKINIT_BTMM)
|
||||||
|
ctx->require_eku = 0;
|
||||||
|
|
||||||
ctx->require_krbtgt_otherName =
|
ctx->require_krbtgt_otherName =
|
||||||
krb5_config_get_bool_default(context, NULL,
|
krb5_config_get_bool_default(context, NULL,
|
||||||
TRUE,
|
TRUE,
|
||||||
@@ -876,13 +893,20 @@ pk_verify_sign(krb5_context context,
|
|||||||
struct krb5_pk_cert **signer)
|
struct krb5_pk_cert **signer)
|
||||||
{
|
{
|
||||||
hx509_certs signer_certs;
|
hx509_certs signer_certs;
|
||||||
int ret;
|
int ret, flags = 0;
|
||||||
|
|
||||||
|
/* BTMM is broken in Leo and SnowLeo */
|
||||||
|
if (id->flags & PKINIT_BTMM) {
|
||||||
|
flags |= HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH;
|
||||||
|
flags |= HX509_CMS_VS_NO_KU_CHECK;
|
||||||
|
flags |= HX509_CMS_VS_NO_VALIDATE;
|
||||||
|
}
|
||||||
|
|
||||||
*signer = NULL;
|
*signer = NULL;
|
||||||
|
|
||||||
ret = hx509_cms_verify_signed(context->hx509ctx,
|
ret = hx509_cms_verify_signed(context->hx509ctx,
|
||||||
id->verify_ctx,
|
id->verify_ctx,
|
||||||
HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH|HX509_CMS_VS_NO_KU_CHECK,
|
flags,
|
||||||
data,
|
data,
|
||||||
length,
|
length,
|
||||||
NULL,
|
NULL,
|
||||||
@@ -1549,9 +1573,11 @@ _krb5_pk_rd_pa_reply(krb5_context context,
|
|||||||
|
|
||||||
switch (rep.element) {
|
switch (rep.element) {
|
||||||
case choice_PA_PK_AS_REP_dhInfo:
|
case choice_PA_PK_AS_REP_dhInfo:
|
||||||
|
_krb5_debug(context, 5, "krb5_get_init_creds: using pkinit dh");
|
||||||
os = rep.u.dhInfo.dhSignedData;
|
os = rep.u.dhInfo.dhSignedData;
|
||||||
break;
|
break;
|
||||||
case choice_PA_PK_AS_REP_encKeyPack:
|
case choice_PA_PK_AS_REP_encKeyPack:
|
||||||
|
_krb5_debug(context, 5, "krb5_get_init_creds: using kinit enc reply key");
|
||||||
os = rep.u.encKeyPack;
|
os = rep.u.encKeyPack;
|
||||||
break;
|
break;
|
||||||
default: {
|
default: {
|
||||||
@@ -1559,6 +1585,8 @@ _krb5_pk_rd_pa_reply(krb5_context context,
|
|||||||
free_PA_PK_AS_REP(&rep);
|
free_PA_PK_AS_REP(&rep);
|
||||||
memset(&rep, 0, sizeof(rep));
|
memset(&rep, 0, sizeof(rep));
|
||||||
|
|
||||||
|
_krb5_debug(context, 5, "krb5_get_init_creds: using BTMM kinit enc reply key");
|
||||||
|
|
||||||
ret = decode_PA_PK_AS_REP_BTMM(pa->padata_value.data,
|
ret = decode_PA_PK_AS_REP_BTMM(pa->padata_value.data,
|
||||||
pa->padata_value.length,
|
pa->padata_value.length,
|
||||||
&btmm,
|
&btmm,
|
||||||
@@ -1727,6 +1755,7 @@ hx_pass_prompter(void *data, const hx509_prompt *prompter)
|
|||||||
|
|
||||||
static krb5_error_code
|
static krb5_error_code
|
||||||
_krb5_pk_set_user_id(krb5_context context,
|
_krb5_pk_set_user_id(krb5_context context,
|
||||||
|
krb5_principal principal,
|
||||||
krb5_pk_init_ctx ctx,
|
krb5_pk_init_ctx ctx,
|
||||||
struct hx509_certs_data *certs)
|
struct hx509_certs_data *certs)
|
||||||
{
|
{
|
||||||
@@ -1754,9 +1783,46 @@ _krb5_pk_set_user_id(krb5_context context,
|
|||||||
hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
|
hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
|
||||||
hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE);
|
hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE);
|
||||||
|
|
||||||
|
if (principal && strncmp("LKDC:SHA1.", krb5_principal_get_realm(context, principal), 9) == 0) {
|
||||||
|
ctx->id->flags |= PKINIT_BTMM;
|
||||||
|
}
|
||||||
|
|
||||||
ret = find_cert(context, ctx->id, q, &ctx->id->cert);
|
ret = find_cert(context, ctx->id, q, &ctx->id->cert);
|
||||||
hx509_query_free(context->hx509ctx, q);
|
hx509_query_free(context->hx509ctx, q);
|
||||||
|
|
||||||
|
if (ret == 0 && _krb5_have_debug(context, 2)) {
|
||||||
|
hx509_name name;
|
||||||
|
char *str, *sn;
|
||||||
|
heim_integer i;
|
||||||
|
|
||||||
|
ret = hx509_cert_get_subject(ctx->id->cert, &name);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = hx509_name_to_string(name, &str);
|
||||||
|
hx509_name_free(&name);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = hx509_cert_get_serialnumber(ctx->id->cert, &i);
|
||||||
|
if (ret) {
|
||||||
|
free(str);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = der_print_hex_heim_integer(&i, &sn);
|
||||||
|
der_free_heim_integer(&i);
|
||||||
|
if (ret) {
|
||||||
|
free(name);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
_krb5_debug(context, 2, "using cert: subject: %s sn: %s", str, sn);
|
||||||
|
free(str);
|
||||||
|
free(sn);
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2344,6 +2410,7 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context,
|
|||||||
|
|
||||||
if (opt->opt_private->pk_init_ctx->id->certs) {
|
if (opt->opt_private->pk_init_ctx->id->certs) {
|
||||||
_krb5_pk_set_user_id(context,
|
_krb5_pk_set_user_id(context,
|
||||||
|
principal,
|
||||||
opt->opt_private->pk_init_ctx,
|
opt->opt_private->pk_init_ctx,
|
||||||
opt->opt_private->pk_init_ctx->id->certs);
|
opt->opt_private->pk_init_ctx->id->certs);
|
||||||
} else
|
} else
|
||||||
@@ -2404,7 +2471,7 @@ _krb5_get_init_creds_opt_set_pkinit_user_certs(krb5_context context,
|
|||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
_krb5_pk_set_user_id(context, opt->opt_private->pk_init_ctx, certs);
|
_krb5_pk_set_user_id(context, NULL, opt->opt_private->pk_init_ctx, certs);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
#else
|
||||||
@@ -2480,7 +2547,7 @@ _krb5_pk_enterprise_cert(krb5_context context,
|
|||||||
*res = NULL;
|
*res = NULL;
|
||||||
|
|
||||||
if (user_id == NULL) {
|
if (user_id == NULL) {
|
||||||
krb5_clear_error_message(context);
|
krb5_set_error_message(context, ENOENT, "no user id");
|
||||||
return ENOENT;
|
return ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2488,14 +2555,14 @@ _krb5_pk_enterprise_cert(krb5_context context,
|
|||||||
if (ret) {
|
if (ret) {
|
||||||
pk_copy_error(context, context->hx509ctx, ret,
|
pk_copy_error(context, context->hx509ctx, ret,
|
||||||
"Failed to init cert certs");
|
"Failed to init cert certs");
|
||||||
return ret;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = hx509_query_alloc(context->hx509ctx, &q);
|
ret = hx509_query_alloc(context->hx509ctx, &q);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
krb5_set_error_message(context, ret, "out of memory");
|
krb5_set_error_message(context, ret, "out of memory");
|
||||||
hx509_certs_free(&certs);
|
hx509_certs_free(&certs);
|
||||||
return ret;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
|
hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
|
||||||
|
Reference in New Issue
Block a user