summaryrefslogtreecommitdiff
path: root/source4/heimdal/lib/krb5/pkinit.c
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2006-11-07 06:59:56 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 14:25:03 -0500
commit3c1e780ec7e16dc6667402bbc65708bf9a5c062f (patch)
tree2102bb577ea9f00751b8c869b0a5c756fc2ae8e5 /source4/heimdal/lib/krb5/pkinit.c
parent8b91594e0936bbaedf5430406fcf8df3ea406c10 (diff)
downloadsamba-3c1e780ec7e16dc6667402bbc65708bf9a5c062f.tar.gz
samba-3c1e780ec7e16dc6667402bbc65708bf9a5c062f.tar.bz2
samba-3c1e780ec7e16dc6667402bbc65708bf9a5c062f.zip
r19604: This is a massive commit, and I appologise in advance for it's size.
This merges Samba4 with lorikeet-heimdal, which itself has been tracking Heimdal CVS for the past couple of weeks. This is such a big change because Heimdal reorganised it's internal structures, with the mechglue merge, and because many of our 'wishes' have been granted: we now have DCE_STYLE GSSAPI, send_to_kdc hooks and many other features merged into the mainline code. We have adapted to upstream's choice of API in these cases. In gensec_gssapi and gensec_krb5, we either expect a valid PAC, or NO PAC. This matches windows behavour. We also have an option to require the PAC to be present (which allows us to automate the testing of this code). This also includes a restructure of how the kerberos dependencies are handled, due to the fallout of the merge. Andrew Bartlett (This used to be commit 4826f1735197c2a471d771495e6d4c1051b4c471)
Diffstat (limited to 'source4/heimdal/lib/krb5/pkinit.c')
-rwxr-xr-xsource4/heimdal/lib/krb5/pkinit.c157
1 files changed, 102 insertions, 55 deletions
diff --git a/source4/heimdal/lib/krb5/pkinit.c b/source4/heimdal/lib/krb5/pkinit.c
index 00f7b4ebd9..f519b5ad08 100755
--- a/source4/heimdal/lib/krb5/pkinit.c
+++ b/source4/heimdal/lib/krb5/pkinit.c
@@ -33,7 +33,7 @@
#include "krb5_locl.h"
-RCSID("$Id: pkinit.c,v 1.99 2006/05/07 12:32:38 lha Exp $");
+RCSID("$Id: pkinit.c,v 1.110 2006/10/14 09:52:50 lha Exp $");
struct krb5_dh_moduli {
char *name;
@@ -69,7 +69,7 @@ struct krb5_pk_identity {
hx509_certs certs;
hx509_certs anchors;
hx509_certs certpool;
- hx509_revoke_ctx revoke;
+ hx509_revoke_ctx revokectx;
};
struct krb5_pk_cert {
@@ -344,8 +344,8 @@ build_auth_pack(krb5_context context,
ALLOC(a->clientPublicValue, 1);
if (a->clientPublicValue == NULL)
return ENOMEM;
- ret = copy_oid(oid_id_dhpublicnumber(),
- &a->clientPublicValue->algorithm.algorithm);
+ ret = der_copy_oid(oid_id_dhpublicnumber(),
+ &a->clientPublicValue->algorithm.algorithm);
if (ret)
return ret;
@@ -392,7 +392,7 @@ build_auth_pack(krb5_context context,
ASN1_MALLOC_ENCODE(DHPublicKey, dhbuf.data, dhbuf.length,
&dh_pub_key, &size, ret);
- free_heim_integer(&dh_pub_key);
+ der_free_heim_integer(&dh_pub_key);
if (ret)
return ret;
if (size != dhbuf.length)
@@ -413,7 +413,7 @@ _krb5_pk_mk_ContentInfo(krb5_context context,
{
krb5_error_code ret;
- ret = copy_oid(oid, &content_info->contentType);
+ ret = der_copy_oid(oid, &content_info->contentType);
if (ret)
return ret;
ALLOC(content_info->content, 1);
@@ -672,8 +672,16 @@ _krb5_pk_verify_sign(krb5_context context,
contentType,
content,
&signer_certs);
- if (ret)
+ if (ret) {
+ char *s = hx509_get_error_string(id->hx509ctx, ret);
+ if (s) {
+ krb5_set_error_string(context,
+ "CMS verify signed failed with %s", s);
+ free(s);
+ } else
+ krb5_clear_error_string(context);
return ret;
+ }
*signer = calloc(1, sizeof(**signer));
if (*signer == NULL) {
@@ -833,7 +841,9 @@ pk_verify_host(krb5_context context,
oid_id_pkinit_san(),
&list);
if (ret) {
- krb5_clear_error_string(context);
+ krb5_set_error_string(context, "Failed to find the PK-INIT "
+ "subjectAltName in the KDC certificate");
+
return ret;
}
@@ -845,7 +855,9 @@ pk_verify_host(krb5_context context,
&r,
NULL);
if (ret) {
- krb5_clear_error_string(context);
+ krb5_set_error_string(context, "Failed to decode the PK-INIT "
+ "subjectAltName in the KDC certificate");
+
break;
}
@@ -856,7 +868,7 @@ pk_verify_host(krb5_context context,
{
krb5_set_error_string(context, "KDC have wrong realm name in "
"the certificate");
- ret = EINVAL;
+ ret = KRB5_KDC_ERR_INVALID_CERTIFICATE;
}
free_KRB5PrincipalName(&r);
@@ -875,7 +887,8 @@ pk_verify_host(krb5_context context,
hi->ai->ai_addr, hi->ai->ai_addrlen);
if (ret)
- krb5_set_error_string(context, "Address mismatch in the KDC certificate");
+ krb5_set_error_string(context, "Address mismatch in "
+ "the KDC certificate");
}
return ret;
}
@@ -901,7 +914,7 @@ pk_rd_pa_reply_enckey(krb5_context context,
krb5_data content;
heim_oid contentType = { 0, NULL };
- if (heim_oid_cmp(oid_id_pkcs7_envelopedData(), &rep->contentType)) {
+ if (der_heim_oid_cmp(oid_id_pkcs7_envelopedData(), &rep->contentType)) {
krb5_set_error_string(context, "PKINIT: Invalid content type");
return EINVAL;
}
@@ -913,8 +926,10 @@ pk_rd_pa_reply_enckey(krb5_context context,
ret = hx509_cms_unenvelope(ctx->id->hx509ctx,
ctx->id->certs,
+ HX509_CMS_UE_DONT_REQUIRE_KU_ENCIPHERMENT,
rep->content->data,
rep->content->length,
+ NULL,
&contentType,
&content);
if (ret)
@@ -935,7 +950,7 @@ pk_rd_pa_reply_enckey(krb5_context context,
goto out;
}
- if (heim_oid_cmp(&ci.contentType, oid_id_pkcs7_signedData())) {
+ if (der_heim_oid_cmp(&ci.contentType, oid_id_pkcs7_signedData())) {
ret = EINVAL; /* XXX */
krb5_set_error_string(context, "PKINIT: Invalid content type");
goto out;
@@ -964,19 +979,18 @@ pk_rd_pa_reply_enckey(krb5_context context,
/* make sure that it is the kdc's certificate */
ret = pk_verify_host(context, realm, hi, ctx, host);
if (ret) {
- krb5_set_error_string(context, "PKINIT: failed verify host: %d", ret);
goto out;
}
#if 0
if (type == COMPAT_WIN2K) {
- if (heim_oid_cmp(&contentType, oid_id_pkcs7_data()) != 0) {
+ if (der_heim_oid_cmp(&contentType, oid_id_pkcs7_data()) != 0) {
krb5_set_error_string(context, "PKINIT: reply key, wrong oid");
ret = KRB5KRB_AP_ERR_MSG_TYPE;
goto out;
}
} else {
- if (heim_oid_cmp(&contentType, oid_id_pkrkeydata()) != 0) {
+ if (der_heim_oid_cmp(&contentType, oid_id_pkrkeydata()) != 0) {
krb5_set_error_string(context, "PKINIT: reply key, wrong oid");
ret = KRB5KRB_AP_ERR_MSG_TYPE;
goto out;
@@ -1002,7 +1016,7 @@ pk_rd_pa_reply_enckey(krb5_context context,
out:
if (host)
_krb5_pk_cert_free(host);
- free_oid(&contentType);
+ der_free_oid(&contentType);
krb5_data_free(&content);
return ret;
@@ -1034,7 +1048,7 @@ pk_rd_pa_reply_dh(krb5_context context,
krb5_data_zero(&content);
memset(&kdc_dh_info, 0, sizeof(kdc_dh_info));
- if (heim_oid_cmp(oid_id_pkcs7_signedData(), &rep->contentType)) {
+ if (der_heim_oid_cmp(oid_id_pkcs7_signedData(), &rep->contentType)) {
krb5_set_error_string(context, "PKINIT: Invalid content type");
return EINVAL;
}
@@ -1059,7 +1073,7 @@ pk_rd_pa_reply_dh(krb5_context context,
if (ret)
goto out;
- if (heim_oid_cmp(&contentType, oid_id_pkdhkeydata())) {
+ if (der_heim_oid_cmp(&contentType, oid_id_pkdhkeydata())) {
krb5_set_error_string(context, "pkinit - dh reply contains wrong oid");
ret = KRB5KRB_AP_ERR_MSG_TYPE;
goto out;
@@ -1324,20 +1338,28 @@ hx_pass_prompter(void *data, const hx509_prompt *prompter)
password_data.data = prompter->reply.data;
password_data.length = prompter->reply.length;
- prompt.prompt = "Enter your private key passphrase: ";
- prompt.hidden = 1;
+
+ prompt.prompt = prompter->prompt;
+ prompt.hidden = hx509_prompt_hidden(prompter->type);
prompt.reply = &password_data;
- if (prompter->hidden)
+
+ switch (prompter->type) {
+ case HX509_PROMPT_TYPE_INFO:
+ prompt.type = KRB5_PROMPT_TYPE_INFO;
+ break;
+ case HX509_PROMPT_TYPE_PASSWORD:
+ case HX509_PROMPT_TYPE_QUESTION:
+ default:
prompt.type = KRB5_PROMPT_TYPE_PASSWORD;
- else
- prompt.type = KRB5_PROMPT_TYPE_PREAUTH; /* XXX */
+ break;
+ }
ret = (*p->prompter)(p->context, p->prompter_data, NULL, NULL, 1, &prompt);
if (ret) {
memset (prompter->reply.data, 0, prompter->reply.length);
- return 0;
+ return 1;
}
- return strlen(prompter->reply.data);
+ return 0;
}
@@ -1354,8 +1376,8 @@ _krb5_pk_load_id(krb5_context context,
struct krb5_pk_identity **ret_id,
const char *user_id,
const char *anchor_id,
- char * const *chain,
- char * const *revoke,
+ char * const *chain_list,
+ char * const *revoke_list,
krb5_prompter_fct prompter,
void *prompter_data,
char *password)
@@ -1392,7 +1414,7 @@ _krb5_pk_load_id(krb5_context context,
goto out;
ret = hx509_lock_init(id->hx509ctx, &lock);
- if (password)
+ if (password && password[0])
hx509_lock_add_password(lock, password);
if (prompter) {
@@ -1405,7 +1427,7 @@ _krb5_pk_load_id(krb5_context context,
goto out;
}
- ret = hx509_certs_init(id->hx509ctx, user_id, 0, NULL, &id->certs);
+ ret = hx509_certs_init(id->hx509ctx, user_id, 0, lock, &id->certs);
if (ret)
goto out;
@@ -1418,33 +1440,36 @@ _krb5_pk_load_id(krb5_context context,
if (ret)
goto out;
- while (chain && *chain) {
- ret = hx509_certs_append(id->hx509ctx, id->certpool, NULL, *chain);
+ while (chain_list && *chain_list) {
+ ret = hx509_certs_append(id->hx509ctx, id->certpool,
+ NULL, *chain_list);
if (ret) {
krb5_set_error_string(context,
"pkinit failed to load chain %s",
- *chain);
+ *chain_list);
goto out;
}
- chain++;
+ chain_list++;
}
- if (revoke) {
- ret = hx509_revoke_init(id->hx509ctx, &id->revoke);
+ if (revoke_list) {
+ ret = hx509_revoke_init(id->hx509ctx, &id->revokectx);
if (ret) {
krb5_set_error_string(context, "revoke failed to init");
goto out;
}
- while (*revoke) {
- ret = hx509_revoke_add_crl(id->hx509ctx, id->revoke, *revoke);
+ while (*revoke_list) {
+ ret = hx509_revoke_add_crl(id->hx509ctx,
+ id->revokectx,
+ *revoke_list);
if (ret) {
krb5_set_error_string(context,
"pkinit failed to load revoke %s",
- *revoke);
+ *revoke_list);
goto out;
}
- revoke++;
+ revoke_list++;
}
} else
hx509_context_set_missing_revoke(id->hx509ctx, 1);
@@ -1454,7 +1479,7 @@ _krb5_pk_load_id(krb5_context context,
goto out;
hx509_verify_attach_anchors(id->verify_ctx, id->anchors);
- hx509_verify_attach_revoke(id->verify_ctx, id->revoke);
+ hx509_verify_attach_revoke(id->verify_ctx, id->revokectx);
out:
if (ret) {
@@ -1462,7 +1487,7 @@ out:
hx509_certs_free(&id->certs);
hx509_certs_free(&id->anchors);
hx509_certs_free(&id->certpool);
- hx509_revoke_free(&id->revoke);
+ hx509_revoke_free(&id->revokectx);
hx509_context_free(&id->hx509ctx);
free(id);
} else
@@ -1588,9 +1613,9 @@ _krb5_parse_moduli_line(krb5_context context,
return 0;
out:
free(m1->name);
- free_heim_integer(&m1->p);
- free_heim_integer(&m1->g);
- free_heim_integer(&m1->q);
+ der_free_heim_integer(&m1->p);
+ der_free_heim_integer(&m1->g);
+ der_free_heim_integer(&m1->q);
free(m1);
return ret;
}
@@ -1601,9 +1626,9 @@ _krb5_free_moduli(struct krb5_dh_moduli **moduli)
int i;
for (i = 0; moduli[i] != NULL; i++) {
free(moduli[i]->name);
- free_heim_integer(&moduli[i]->p);
- free_heim_integer(&moduli[i]->g);
- free_heim_integer(&moduli[i]->q);
+ der_free_heim_integer(&moduli[i]->p);
+ der_free_heim_integer(&moduli[i]->g);
+ der_free_heim_integer(&moduli[i]->q);
free(moduli[i]);
}
free(moduli);
@@ -1712,9 +1737,9 @@ _krb5_dh_group_ok(krb5_context context, unsigned long bits,
*name = NULL;
for (i = 0; moduli[i] != NULL; i++) {
- if (heim_integer_cmp(&moduli[i]->g, g) == 0 &&
- heim_integer_cmp(&moduli[i]->p, p) == 0 &&
- (q == NULL || heim_integer_cmp(&moduli[i]->q, q) == 0))
+ if (der_heim_integer_cmp(&moduli[i]->g, g) == 0 &&
+ der_heim_integer_cmp(&moduli[i]->p, p) == 0 &&
+ (q == NULL || der_heim_integer_cmp(&moduli[i]->q, q) == 0))
{
if (bits && bits > moduli[i]->bits) {
krb5_set_error_string(context, "PKINIT: DH group parameter %s "
@@ -1769,8 +1794,8 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context,
krb5_principal principal,
const char *user_id,
const char *x509_anchors,
- char * const * chain,
- char * const * revoke,
+ char * const * pool,
+ char * const * pki_revoke,
int flags,
krb5_prompter_fct prompter,
void *prompter_data,
@@ -1778,6 +1803,7 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context,
{
#ifdef PKINIT
krb5_error_code ret;
+ char *anchors = NULL;
if (opt->opt_private == NULL) {
krb5_set_error_string(context, "PKINIT: on non extendable opt");
@@ -1797,12 +1823,33 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context,
opt->opt_private->pk_init_ctx->require_eku = 1;
opt->opt_private->pk_init_ctx->require_krbtgt_otherName = 1;
+
+ /* XXX implement krb5_appdefault_strings */
+ if (pool == NULL)
+ pool = krb5_config_get_strings(context, NULL,
+ "appdefaults",
+ "pkinit-pool",
+ NULL);
+
+ if (pki_revoke == NULL)
+ pki_revoke = krb5_config_get_strings(context, NULL,
+ "appdefaults",
+ "pkinit-revoke",
+ NULL);
+
+ if (x509_anchors == NULL) {
+ krb5_appdefault_string(context, "kinit",
+ krb5_principal_get_realm(context, principal),
+ "pkinit-anchors", NULL, &anchors);
+ x509_anchors = anchors;
+ }
+
ret = _krb5_pk_load_id(context,
&opt->opt_private->pk_init_ctx->id,
user_id,
x509_anchors,
- chain,
- revoke,
+ pool,
+ pki_revoke,
prompter,
prompter_data,
password);