summaryrefslogtreecommitdiff
path: root/source4/heimdal/kdc/pkinit.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/heimdal/kdc/pkinit.c')
-rwxr-xr-xsource4/heimdal/kdc/pkinit.c285
1 files changed, 84 insertions, 201 deletions
diff --git a/source4/heimdal/kdc/pkinit.c b/source4/heimdal/kdc/pkinit.c
index 985c7c15e4..83c379825c 100755
--- a/source4/heimdal/kdc/pkinit.c
+++ b/source4/heimdal/kdc/pkinit.c
@@ -33,7 +33,7 @@
#include "kdc_locl.h"
-RCSID("$Id: pkinit.c,v 1.43 2005/09/21 00:40:32 lha Exp $");
+RCSID("$Id: pkinit.c,v 1.49 2005/10/21 17:14:19 lha Exp $");
#ifdef PKINIT
@@ -65,7 +65,6 @@ struct krb5_pk_cert {
enum pkinit_type {
PKINIT_COMPAT_WIN2K = 1,
- PKINIT_COMPAT_19 = 2,
PKINIT_COMPAT_27 = 3
};
@@ -76,6 +75,7 @@ struct pk_client_params {
unsigned nonce;
DH *dh;
EncryptionKey reply_key;
+ char *dh_group_name;
};
struct pk_principal_mapping {
@@ -111,6 +111,7 @@ struct pk_principal_mapping {
static struct krb5_pk_identity *kdc_identity;
static struct pk_principal_mapping principal_mappings;
+static struct krb5_dh_moduli **moduli;
/*
*
@@ -134,49 +135,6 @@ pk_check_pkauthenticator_win2k(krb5_context context,
}
static krb5_error_code
-pk_check_pkauthenticator_19(krb5_context context,
- PKAuthenticator_19 *a,
- KDC_REQ *req)
-{
- u_char *buf = NULL;
- size_t buf_size;
- krb5_error_code ret;
- size_t len;
- krb5_timestamp now;
-
- krb5_timeofday (context, &now);
-
- /* XXX cusec */
- if (a->ctime == 0 || abs(a->ctime - now) > context->max_skew) {
- krb5_clear_error_string(context);
- return KRB5KRB_AP_ERR_SKEW;
- }
-
- if (a->paChecksum.cksumtype != CKSUMTYPE_RSA_MD5 &&
- a->paChecksum.cksumtype != CKSUMTYPE_SHA1)
- {
- krb5_clear_error_string(context);
- ret = KRB5KRB_ERR_GENERIC;
- }
-
- ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, &req->req_body, &len, ret);
- if (ret) {
- krb5_clear_error_string(context);
- return ret;
- }
- if (buf_size != len)
- krb5_abortx(context, "Internal error in ASN.1 encoder");
-
- ret = krb5_verify_checksum(context, NULL, 0, buf, len,
- &a->paChecksum);
- if (ret)
- krb5_clear_error_string(context);
-
- free(buf);
- return ret;
-}
-
-static krb5_error_code
pk_check_pkauthenticator(krb5_context context,
PKAuthenticator *a,
KDC_REQ *req)
@@ -281,35 +239,23 @@ _kdc_pk_free_client_param(krb5_context context,
if (client_params->dh_public_key)
BN_free(client_params->dh_public_key);
krb5_free_keyblock_contents(context, &client_params->reply_key);
+ if (client_params->dh_group_name)
+ free(client_params->dh_group_name);
memset(client_params, 0, sizeof(*client_params));
free(client_params);
}
static krb5_error_code
-check_dh_params(DH *dh)
-{
- /* XXX check the DH parameters come from 1st or 2nd Oeakley Group */
- return 0;
-}
-
-static krb5_error_code
generate_dh_keyblock(krb5_context context, pk_client_params *client_params,
krb5_enctype enctype, krb5_keyblock *reply_key)
{
unsigned char *dh_gen_key = NULL;
krb5_keyblock key;
- int dh_gen_keylen;
krb5_error_code ret;
+ size_t dh_gen_keylen, size;
memset(&key, 0, sizeof(key));
- dh_gen_key = malloc(DH_size(client_params->dh));
- if (dh_gen_key == NULL) {
- krb5_set_error_string(context, "malloc: out of memory");
- ret = ENOMEM;
- goto out;
- }
-
if (!DH_generate_key(client_params->dh)) {
krb5_set_error_string(context, "Can't generate Diffie-Hellman "
"keys (%s)",
@@ -323,7 +269,20 @@ generate_dh_keyblock(krb5_context context, pk_client_params *client_params,
goto out;
}
- dh_gen_keylen = DH_compute_key(dh_gen_key,
+ dh_gen_keylen = DH_size(client_params->dh);
+ size = BN_num_bytes(client_params->dh->p);
+ if (size < dh_gen_keylen)
+ size = dh_gen_keylen;
+
+ dh_gen_key = malloc(size);
+ if (dh_gen_key == NULL) {
+ krb5_set_error_string(context, "malloc: out of memory");
+ ret = ENOMEM;
+ goto out;
+ }
+ memset(dh_gen_key, 0, size - dh_gen_keylen);
+
+ dh_gen_keylen = DH_compute_key(dh_gen_key + (size - dh_gen_keylen),
client_params->dh_public_key,
client_params->dh);
if (dh_gen_keylen == -1) {
@@ -363,7 +322,9 @@ integer_to_BN(krb5_context context, const char *field, heim_integer *f)
}
static krb5_error_code
-get_dh_param(krb5_context context, SubjectPublicKeyInfo *dh_key_info,
+get_dh_param(krb5_context context,
+ krb5_kdc_configuration *config,
+ SubjectPublicKeyInfo *dh_key_info,
pk_client_params *client_params)
{
DomainParameters dhparam;
@@ -395,6 +356,20 @@ get_dh_param(krb5_context context, SubjectPublicKeyInfo *dh_key_info,
goto out;
}
+ if ((dh_key_info->subjectPublicKey.length % 8) != 0) {
+ ret = KRB5_BADMSGTYPE;
+ krb5_set_error_string(context, "PKINIT: subjectPublicKey not aligned "
+ "to 8 bit boundary");
+ goto out;
+ }
+
+
+ ret = _krb5_dh_group_ok(context, config->pkinit_dh_min_bits,
+ &dhparam.p, &dhparam.g, &dhparam.q, moduli,
+ &client_params->dh_group_name);
+ if (ret)
+ goto out;
+
dh = DH_new();
if (dh == NULL) {
krb5_set_error_string(context, "Cannot create DH structure (%s)",
@@ -415,22 +390,29 @@ get_dh_param(krb5_context context, SubjectPublicKeyInfo *dh_key_info,
{
heim_integer glue;
- glue.data = dh_key_info->subjectPublicKey.data;
- glue.length = dh_key_info->subjectPublicKey.length;
+ size_t size;
+
+ ret = decode_DHPublicKey(dh_key_info->subjectPublicKey.data,
+ dh_key_info->subjectPublicKey.length / 8,
+ &glue,
+ &size);
+ if (ret) {
+ krb5_clear_error_string(context);
+ return ret;
+ }
client_params->dh_public_key = integer_to_BN(context,
"subjectPublicKey",
&glue);
- if (client_params->dh_public_key == NULL) {
- krb5_clear_error_string(context);
+ free_heim_integer(&glue);
+ if (client_params->dh_public_key == NULL)
goto out;
- }
}
if (DH_check(dh, &dhret) != 1) {
krb5_set_error_string(context, "PKINIT DH data not ok: %s",
ERR_error_string(ERR_get_error(), NULL));
- ret = KRB5_KDC_ERR_KEY_SIZE;
+ ret = KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED;
goto out;
}
@@ -525,13 +507,12 @@ _kdc_pk_rd_padata(krb5_context context,
return 0;
}
- client_params = malloc(sizeof(*client_params));
+ client_params = calloc(1, sizeof(*client_params));
if (client_params == NULL) {
krb5_clear_error_string(context);
ret = ENOMEM;
goto out;
}
- memset(client_params, 0, sizeof(*client_params));
if (pa->padata_type == KRB5_PADATA_PK_AS_REQ_WIN) {
PA_PK_AS_REQ_Win2k r;
@@ -586,51 +567,6 @@ _kdc_pk_rd_padata(krb5_context context,
free_ContentInfo(&info);
- } else if (pa->padata_type == KRB5_PADATA_PK_AS_REQ_19) {
- PA_PK_AS_REQ_19 r;
-
- type = "PK-INIT-19";
- pa_contentType = oid_id_pkauthdata();
-
- ret = decode_PA_PK_AS_REQ_19(pa->padata_value.data,
- pa->padata_value.length,
- &r,
- NULL);
- if (ret) {
- krb5_set_error_string(context, "Can't decode "
- "PK-AS-REQ-19: %d", ret);
- goto out;
- }
-
- if (heim_oid_cmp(&r.signedAuthPack.contentType,
- oid_id_pkcs7_signedData()))
- {
- krb5_set_error_string(context, "PK-AS-REQ-19 invalid content "
- "type oid");
- free_PA_PK_AS_REQ_19(&r);
- ret = KRB5KRB_ERR_GENERIC;
- goto out;
- }
-
- if (r.signedAuthPack.content == NULL) {
- krb5_set_error_string(context, "PK-AS-REQ-19 no signed auth pack");
- free_PA_PK_AS_REQ_19(&r);
- ret = KRB5KRB_ERR_GENERIC;
- goto out;
- }
-
- signed_content.data = malloc(r.signedAuthPack.content->length);
- if (signed_content.data == NULL) {
- ret = ENOMEM;
- free_PA_PK_AS_REQ_19(&r);
- krb5_set_error_string(context, "PK-AS-REQ-19 out of memory");
- goto out;
- }
- signed_content.length = r.signedAuthPack.content->length;
- memcpy(signed_content.data, r.signedAuthPack.content->data,
- signed_content.length);
-
- free_PA_PK_AS_REQ_19(&r);
} else if (pa->padata_type == KRB5_PADATA_PK_AS_REQ) {
PA_PK_AS_REQ r;
ContentInfo info;
@@ -701,12 +637,14 @@ _kdc_pk_rd_padata(krb5_context context,
if (ret)
goto out;
+#if 0
/* Signature is correct, now verify the signed message */
if (heim_oid_cmp(&eContentType, pa_contentType)) {
krb5_set_error_string(context, "got wrong oid for pkauthdata");
ret = KRB5_BADMSGTYPE;
goto out;
}
+#endif
if (pa->padata_type == KRB5_PADATA_PK_AS_REQ_WIN) {
AuthPack_Win2k ap;
@@ -738,37 +676,6 @@ _kdc_pk_rd_padata(krb5_context context,
}
free_AuthPack_Win2k(&ap);
- } else if (pa->padata_type == KRB5_PADATA_PK_AS_REQ_19) {
- AuthPack_19 ap;
-
- ret = decode_AuthPack_19(eContent.data,
- eContent.length,
- &ap,
- NULL);
- if (ret) {
- krb5_set_error_string(context, "can't decode AuthPack: %d", ret);
- free_AuthPack_19(&ap);
- goto out;
- }
-
- ret = pk_check_pkauthenticator_19(context,
- &ap.pkAuthenticator,
- req);
- if (ret) {
- free_AuthPack_19(&ap);
- goto out;
- }
-
- client_params->type = PKINIT_COMPAT_19;
- client_params->nonce = ap.pkAuthenticator.nonce;
-
- if (ap.clientPublicValue) {
- krb5_set_error_string(context, "PK-INIT, no support for DH");
- ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
- free_AuthPack_19(&ap);
- goto out;
- }
- free_AuthPack_19(&ap);
} else if (pa->padata_type == KRB5_PADATA_PK_AS_REQ) {
AuthPack ap;
@@ -794,7 +701,8 @@ _kdc_pk_rd_padata(krb5_context context,
client_params->nonce = ap.pkAuthenticator.nonce;
if (ap.clientPublicValue) {
- ret = get_dh_param(context, ap.clientPublicValue, client_params);
+ ret = get_dh_param(context, config,
+ ap.clientPublicValue, client_params);
if (ret) {
free_AuthPack(&ap);
goto out;
@@ -924,9 +832,8 @@ pk_mk_pa_reply_enckey(krb5_context context,
enc_alg->parameters->length = params.length;
switch (client_params->type) {
- case PKINIT_COMPAT_WIN2K:
- case PKINIT_COMPAT_19: {
- ReplyKeyPack_19 kp;
+ case PKINIT_COMPAT_WIN2K: {
+ ReplyKeyPack_Win2k kp;
memset(&kp, 0, sizeof(kp));
ret = copy_EncryptionKey(reply_key, &kp.replyKey);
@@ -936,10 +843,10 @@ pk_mk_pa_reply_enckey(krb5_context context,
}
kp.nonce = client_params->nonce;
- ASN1_MALLOC_ENCODE(ReplyKeyPack_19,
+ ASN1_MALLOC_ENCODE(ReplyKeyPack_Win2k,
buf.data, buf.length,
&kp, &size,ret);
- free_ReplyKeyPack_19(&kp);
+ free_ReplyKeyPack_Win2k(&kp);
}
case PKINIT_COMPAT_27: {
krb5_crypto ascrypto;
@@ -1249,6 +1156,7 @@ _kdc_pk_mk_pa_reply(krb5_context context,
if (client_params->type == PKINIT_COMPAT_27) {
PA_PK_AS_REP rep;
+ const char *type, *other = "";
memset(&rep, 0, sizeof(rep));
@@ -1257,6 +1165,8 @@ _kdc_pk_mk_pa_reply(krb5_context context,
if (client_params->dh == NULL) {
ContentInfo info;
+ type = "enckey";
+
rep.element = choice_PA_PK_AS_REP_encKeyPack;
krb5_generate_random_keyblock(context, enctype,
@@ -1287,11 +1197,11 @@ _kdc_pk_mk_pa_reply(krb5_context context,
} else {
ContentInfo info;
- rep.element = choice_PA_PK_AS_REP_dhInfo;
+ type = "dh";
+ if (client_params->dh_group_name)
+ other = client_params->dh_group_name;
- ret = check_dh_params(client_params->dh);
- if (ret)
- return ret;
+ rep.element = choice_PA_PK_AS_REP_dhInfo;
ret = generate_dh_keyblock(context, client_params, enctype,
&client_params->reply_key);
@@ -1332,41 +1242,8 @@ _kdc_pk_mk_pa_reply(krb5_context context,
if (len != size)
krb5_abortx(context, "Internal ASN.1 encoder error");
- } else if (client_params->type == PKINIT_COMPAT_19) {
- PA_PK_AS_REP_19 rep;
-
- pa_type = KRB5_PADATA_PK_AS_REP_19;
-
- memset(&rep, 0, sizeof(rep));
+ kdc_log(context, config, 0, "PK-INIT using %s %s", type, other);
- if (client_params->dh == NULL) {
- rep.element = choice_PA_PK_AS_REP_19_encKeyPack;
- krb5_generate_random_keyblock(context, enctype,
- &client_params->reply_key);
- ret = pk_mk_pa_reply_enckey(context,
- client_params,
- req,
- req_buffer,
- &client_params->reply_key,
- &rep.u.encKeyPack);
- } else {
- krb5_set_error_string(context, "DH -19 not implemented");
- ret = KRB5KRB_ERR_GENERIC;
- }
- if (ret) {
- free_PA_PK_AS_REP_19(&rep);
- goto out;
- }
-
- ASN1_MALLOC_ENCODE(PA_PK_AS_REP_19, buf, len, &rep, &size, ret);
- free_PA_PK_AS_REP_19(&rep);
- if (ret) {
- krb5_set_error_string(context,
- "encode PA-PK-AS-REP-19 failed %d", ret);
- goto out;
- }
- if (len != size)
- krb5_abortx(context, "Internal ASN.1 encoder error");
} else if (client_params->type == PKINIT_COMPAT_WIN2K) {
PA_PK_AS_REP_Win2k rep;
@@ -1557,7 +1434,7 @@ _kdc_pk_check_client(krb5_context context,
free(*subject_name);
*subject_name = NULL;
krb5_set_error_string(context, "PKINIT no matching principals");
- return KRB5_KDC_ERROR_CLIENT_NAME_MISMATCH;
+ return KRB5_KDC_ERR_CLIENT_NAME_MISMATCH;
}
static krb5_error_code
@@ -1598,12 +1475,19 @@ _kdc_pk_initialize(krb5_context context,
const char *user_id,
const char *x509_anchors)
{
- const char *mapping_file;
+ const char *file;
krb5_error_code ret;
char buf[1024];
unsigned long lineno = 0;
FILE *f;
+ file = krb5_config_get_string(context, NULL,
+ "libdefaults", "moduli", NULL);
+
+ ret = _krb5_parse_moduli(context, file, &moduli);
+ if (ret)
+ krb5_err(context, 1, ret, "PKINIT: failed to load modidi file");
+
principal_mappings.len = 0;
principal_mappings.val = NULL;
@@ -1620,16 +1504,15 @@ _kdc_pk_initialize(krb5_context context,
return ret;
}
- mapping_file = krb5_config_get_string_default(context,
- NULL,
- HDB_DB_DIR "/pki-mapping",
- "kdc",
- "pki-mappings-file",
- NULL);
- f = fopen(mapping_file, "r");
+ file = krb5_config_get_string_default(context,
+ NULL,
+ HDB_DB_DIR "/pki-mapping",
+ "kdc",
+ "pki-mappings-file",
+ NULL);
+ f = fopen(file, "r");
if (f == NULL) {
- krb5_warnx(context, "PKINIT: failed to load mappings file %s",
- mapping_file);
+ krb5_warnx(context, "PKINIT: failed to load mappings file %s", file);
return 0;
}