summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/heimdal/kdc/kdc.h5
-rw-r--r--source4/heimdal/kdc/kerberos5.c15
-rwxr-xr-xsource4/heimdal/kdc/pkinit.c285
-rw-r--r--source4/heimdal/lib/asn1/der.h5
-rw-r--r--source4/heimdal/lib/gssapi/acquire_cred.c20
-rw-r--r--source4/heimdal/lib/gssapi/display_status.c42
-rw-r--r--source4/heimdal/lib/gssapi/gssapi_locl.h8
-rw-r--r--source4/heimdal/lib/gssapi/init_sec_context.c19
-rw-r--r--source4/heimdal/lib/hdb/hdb.c14
-rw-r--r--source4/heimdal/lib/krb5/acache.c110
-rw-r--r--source4/heimdal/lib/krb5/cache.c215
-rw-r--r--source4/heimdal/lib/krb5/init_creds.c36
-rw-r--r--source4/heimdal/lib/krb5/init_creds_pw.c32
-rw-r--r--source4/heimdal/lib/krb5/keytab_keyfile.c75
-rw-r--r--source4/heimdal/lib/krb5/krb5-private.h42
-rw-r--r--source4/heimdal/lib/krb5/krb5-protos.h36
-rw-r--r--source4/heimdal/lib/krb5/krb5.h9
-rw-r--r--source4/heimdal/lib/krb5/krb5_locl.h5
-rw-r--r--source4/heimdal/lib/krb5/krbhst.c33
-rw-r--r--source4/heimdal/lib/krb5/mcache.c89
-rwxr-xr-xsource4/heimdal/lib/krb5/pkinit.c789
-rw-r--r--source4/heimdal/lib/krb5/rd_cred.c53
-rw-r--r--source4/heimdal/lib/roken/roken-common.h6
-rw-r--r--source4/heimdal/lib/roken/roken.h11
24 files changed, 1264 insertions, 690 deletions
diff --git a/source4/heimdal/kdc/kdc.h b/source4/heimdal/kdc/kdc.h
index f186983cef..3d25729d4e 100644
--- a/source4/heimdal/kdc/kdc.h
+++ b/source4/heimdal/kdc/kdc.h
@@ -35,7 +35,7 @@
*/
/*
- * $Id: kdc.h,v 1.4 2005/06/30 01:50:42 lha Exp $
+ * $Id: kdc.h,v 1.5 2005/10/21 17:11:21 lha Exp $
*/
#ifndef __KDC_H__
@@ -74,6 +74,9 @@ typedef struct krb5_kdc_configuration {
krb5_boolean enable_pkinit_princ_in_cert;
krb5_log_facility *logf;
+
+ int pkinit_dh_min_bits;
+
} krb5_kdc_configuration;
#include <kdc-protos.h>
diff --git a/source4/heimdal/kdc/kerberos5.c b/source4/heimdal/kdc/kerberos5.c
index 3191ab19b7..fdc60761f3 100644
--- a/source4/heimdal/kdc/kerberos5.c
+++ b/source4/heimdal/kdc/kerberos5.c
@@ -855,11 +855,6 @@ _kdc_as_rep(krb5_context context,
;
if (pa == NULL) {
i = 0;
- if((pa = find_padata(req, &i, KRB5_PADATA_PK_AS_REQ_19)))
- ;
- }
- if (pa == NULL) {
- i = 0;
if((pa = find_padata(req, &i, KRB5_PADATA_PK_AS_REQ_WIN)))
;
}
@@ -887,12 +882,14 @@ _kdc_as_rep(krb5_context context,
e_text = "PKINIT certificate not allowed to "
"impersonate principal";
_kdc_pk_free_client_param(context, pkp);
+
+ kdc_log(context, config, 0, "%s", e_text);
pkp = NULL;
goto ts_enc;
}
found_pa = 1;
et.flags.pre_authent = 1;
- kdc_log(context, config, 2,
+ kdc_log(context, config, 0,
"PKINIT pre-authentication succeeded -- %s using %s",
client_name, client_cert);
free(client_cert);
@@ -1057,12 +1054,6 @@ _kdc_as_rep(krb5_context context,
pa->padata_type = KRB5_PADATA_PK_AS_REQ;
pa->padata_value.length = 0;
pa->padata_value.data = NULL;
-
- ret = realloc_method_data(&method_data);
- pa = &method_data.val[method_data.len-1];
- pa->padata_type = KRB5_PADATA_PK_AS_REQ_19;
- pa->padata_value.length = 0;
- pa->padata_value.data = NULL;
#endif
/* XXX check ret */
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;
}
diff --git a/source4/heimdal/lib/asn1/der.h b/source4/heimdal/lib/asn1/der.h
index a66a3908c6..1f89f875f5 100644
--- a/source4/heimdal/lib/asn1/der.h
+++ b/source4/heimdal/lib/asn1/der.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-/* $Id: der.h,v 1.29 2005/07/12 06:27:19 lha Exp $ */
+/* $Id: der.h,v 1.30 2005/10/07 03:48:00 lha Exp $ */
#ifndef __DER_H__
#define __DER_H__
@@ -240,4 +240,7 @@ int der_get_type_num(const char *);
const char * der_get_tag_name(unsigned);
int der_get_tag_num(const char *);
+int der_parse_hex_heim_integer(const char *, heim_integer *);
+int der_print_hex_heim_integer(const heim_integer *, char **);
+
#endif /* __DER_H__ */
diff --git a/source4/heimdal/lib/gssapi/acquire_cred.c b/source4/heimdal/lib/gssapi/acquire_cred.c
index 6ded413626..23c2603352 100644
--- a/source4/heimdal/lib/gssapi/acquire_cred.c
+++ b/source4/heimdal/lib/gssapi/acquire_cred.c
@@ -33,7 +33,7 @@
#include "gssapi_locl.h"
-RCSID("$Id: acquire_cred.c,v 1.22 2005/01/05 02:32:26 lukeh Exp $");
+RCSID("$Id: acquire_cred.c,v 1.23 2005/10/21 12:44:08 lha Exp $");
static krb5_error_code
get_keytab(krb5_context context, krb5_keytab *keytab)
@@ -83,9 +83,23 @@ static OM_uint32 acquire_initiator_cred
ret = GSS_S_FAILURE;
memset(&cred, 0, sizeof(cred));
+ /* If we have a preferred principal, lets try to find it in all
+ * caches, otherwise, fall back to default cache. Ignore
+ * errors. */
+ if (ccache == NULL && handle->principal) {
+ kret = krb5_cc_cache_match (gssapi_krb5_context,
+ handle->principal,
+ NULL,
+ &ccache);
+ if (kret) {
+ ccache = NULL;
+ } else {
+ made_ccache = TRUE;
+ }
+ }
if (ccache == NULL) {
- kret = krb5_cc_default(context, &ccache);
- if (kret)
+ kret = krb5_cc_default(gssapi_krb5_context, &ccache);
+ if (kret)
goto end;
made_ccache = TRUE;
}
diff --git a/source4/heimdal/lib/gssapi/display_status.c b/source4/heimdal/lib/gssapi/display_status.c
index 6e9456aa2e..0aa88bb57c 100644
--- a/source4/heimdal/lib/gssapi/display_status.c
+++ b/source4/heimdal/lib/gssapi/display_status.c
@@ -33,7 +33,7 @@
#include "gssapi_locl.h"
-RCSID("$Id: display_status.c,v 1.13 2005/08/23 08:30:55 lha Exp $");
+RCSID("$Id: display_status.c,v 1.14 2005/10/12 07:23:03 lha Exp $");
static const char *
calling_error(OM_uint32 v)
@@ -112,25 +112,47 @@ supplementary_error(OM_uint32 v)
}
void
-gssapi_krb5_set_error_string (void)
+gssapi_krb5_clear_status (void)
{
struct gssapi_thr_context *ctx = gssapi_get_thread_context(1);
- char *e;
+ if (ctx == NULL)
+ return;
+ HEIMDAL_MUTEX_lock(&ctx->mutex);
+ if (ctx->error_string)
+ free(ctx->error_string);
+ ctx->error_string = NULL;
+ HEIMDAL_MUTEX_unlock(&ctx->mutex);
+}
+
+void
+gssapi_krb5_set_status (const char *fmt, ...)
+{
+ struct gssapi_thr_context *ctx = gssapi_get_thread_context(1);
+ va_list args;
if (ctx == NULL)
return;
HEIMDAL_MUTEX_lock(&ctx->mutex);
+ va_start(args, fmt);
if (ctx->error_string)
free(ctx->error_string);
+ /* ignore failures, will use status code instead */
+ vasprintf(&ctx->error_string, fmt, args);
+ va_end(args);
+ HEIMDAL_MUTEX_unlock(&ctx->mutex);
+}
+
+void
+gssapi_krb5_set_error_string (void)
+{
+ char *e;
+
e = krb5_get_error_string(gssapi_krb5_context);
- if (e == NULL)
- ctx->error_string = NULL;
- else {
- /* ignore failures, will use status code instead */
- ctx->error_string = strdup(e);
+ if (e) {
+ gssapi_krb5_set_status("%s", e);
krb5_free_error_string(gssapi_krb5_context, e);
- }
- HEIMDAL_MUTEX_unlock(&ctx->mutex);
+ } else
+ gssapi_krb5_clear_status();
}
char *
diff --git a/source4/heimdal/lib/gssapi/gssapi_locl.h b/source4/heimdal/lib/gssapi/gssapi_locl.h
index 47a37e4657..a25e2fdcc9 100644
--- a/source4/heimdal/lib/gssapi/gssapi_locl.h
+++ b/source4/heimdal/lib/gssapi/gssapi_locl.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-/* $Id: gssapi_locl.h,v 1.40 2005/06/16 20:34:03 lha Exp $ */
+/* $Id: gssapi_locl.h,v 1.41 2005/10/12 15:20:37 lha Exp $ */
#ifndef GSSAPI_LOCL_H
#define GSSAPI_LOCL_H
@@ -246,6 +246,12 @@ int
gss_oid_equal(const gss_OID a, const gss_OID b);
void
+gssapi_krb5_clear_status (void);
+
+void
+gssapi_krb5_set_status (const char *fmt, ...);
+
+void
gssapi_krb5_set_error_string (void);
char *
diff --git a/source4/heimdal/lib/gssapi/init_sec_context.c b/source4/heimdal/lib/gssapi/init_sec_context.c
index 5c6c6a0f8e..93e8d44c86 100644
--- a/source4/heimdal/lib/gssapi/init_sec_context.c
+++ b/source4/heimdal/lib/gssapi/init_sec_context.c
@@ -33,7 +33,7 @@
#include "gssapi_locl.h"
-RCSID("$Id: init_sec_context.c,v 1.59 2005/08/11 10:47:25 lha Exp $");
+RCSID("$Id: init_sec_context.c,v 1.60 2005/10/12 07:25:18 lha Exp $");
/*
* copy the addresses from `input_chan_bindings' (if any) to
@@ -848,16 +848,23 @@ spnego_reply
ret = der_match_tag_and_length((const char *)indata.data,
indata.length,
ASN1_C_CONTEXT, CONS, 1, &len, &taglen);
- if (ret)
- return ret;
+ if (ret) {
+ gssapi_krb5_set_status("Failed to decode NegToken choice");
+ *minor_status = ret;
+ return GSS_S_FAILURE;
+ }
- if(len > indata.length - taglen)
- return ASN1_OVERRUN;
+ if(len > indata.length - taglen) {
+ gssapi_krb5_set_status("Buffer overrun in NegToken choice");
+ *minor_status = ASN1_OVERRUN;
+ return GSS_S_FAILURE;
+ }
ret = decode_NegTokenTarg((const char *)indata.data + taglen,
len, &targ, NULL);
if (ret) {
- *minor_status = ENOMEM;
+ gssapi_krb5_set_status("Failed to decode NegTokenTarg");
+ *minor_status = ret;
return GSS_S_FAILURE;
}
diff --git a/source4/heimdal/lib/hdb/hdb.c b/source4/heimdal/lib/hdb/hdb.c
index 8233eb6ac7..c66579fab0 100644
--- a/source4/heimdal/lib/hdb/hdb.c
+++ b/source4/heimdal/lib/hdb/hdb.c
@@ -33,7 +33,7 @@
#include "hdb_locl.h"
-RCSID("$Id: hdb.c,v 1.55 2005/08/19 13:07:03 lha Exp $");
+RCSID("$Id: hdb.c,v 1.56 2005/10/19 13:51:40 lha Exp $");
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
@@ -170,7 +170,7 @@ hdb_check_db_format(krb5_context context, HDB *db)
{
krb5_data tag;
krb5_data version;
- krb5_error_code ret;
+ krb5_error_code ret, ret2;
unsigned ver;
int foo;
@@ -181,9 +181,11 @@ hdb_check_db_format(krb5_context context, HDB *db)
tag.data = HDB_DB_FORMAT_ENTRY;
tag.length = strlen(tag.data);
ret = (*db->hdb__get)(context, db, tag, &version);
- db->hdb_unlock(context, db);
+ ret2 = db->hdb_unlock(context, db);
if(ret)
return ret;
+ if (ret2)
+ return ret2;
foo = sscanf(version.data, "%u", &ver);
krb5_data_free (&version);
if (foo != 1)
@@ -196,7 +198,7 @@ hdb_check_db_format(krb5_context context, HDB *db)
krb5_error_code
hdb_init_db(krb5_context context, HDB *db)
{
- krb5_error_code ret;
+ krb5_error_code ret, ret2;
krb5_data tag;
krb5_data version;
char ver[32];
@@ -215,10 +217,10 @@ hdb_init_db(krb5_context context, HDB *db)
version.data = ver;
version.length = strlen(version.data) + 1; /* zero terminated */
ret = (*db->hdb__put)(context, db, 0, tag, version);
- ret = db->hdb_unlock(context, db);
+ ret2 = db->hdb_unlock(context, db);
if (ret)
return ret;
- return ret;
+ return ret2;
}
#ifdef HAVE_DLOPEN
diff --git a/source4/heimdal/lib/krb5/acache.c b/source4/heimdal/lib/krb5/acache.c
index 75f5315c71..7cf2c65d89 100644
--- a/source4/heimdal/lib/krb5/acache.c
+++ b/source4/heimdal/lib/krb5/acache.c
@@ -37,7 +37,7 @@
#include <dlfcn.h>
#endif
-RCSID("$Id: acache.c,v 1.11 2005/06/16 19:32:44 lha Exp $");
+RCSID("$Id: acache.c,v 1.14 2005/10/03 08:44:18 lha Exp $");
/* XXX should we fetch these for each open ? */
static HEIMDAL_MUTEX acc_mutex = HEIMDAL_MUTEX_INITIALIZER;
@@ -67,7 +67,7 @@ static const struct {
{ ccErrContextNotFound, KRB5_CC_NOTFOUND },
{ ccIteratorEnd, KRB5_CC_END },
{ ccErrNoMem, KRB5_CC_NOMEM },
- { ccErrServerUnavailable, KRB5_CC_BADNAME },
+ { ccErrServerUnavailable, KRB5_CC_NOSUPP },
{ ccNoError, 0 }
};
@@ -110,7 +110,7 @@ init_ccapi(krb5_context context)
if (cc_handle == NULL) {
HEIMDAL_MUTEX_unlock(&acc_mutex);
krb5_set_error_string(context, "Failed to load %s", lib);
- return ccErrServerUnavailable;
+ return KRB5_CC_NOSUPP;
}
init_func = dlsym(cc_handle, "cc_initialize");
@@ -119,14 +119,14 @@ init_ccapi(krb5_context context)
krb5_set_error_string(context, "Failed to find cc_initialize"
"in %s: %s", lib, dlerror());
dlclose(cc_handle);
- return ccErrServerUnavailable;
+ return KRB5_CC_NOSUPP;
}
return 0;
#else
HEIMDAL_MUTEX_unlock(&acc_mutex);
krb5_set_error_string(context, "no support for shared object");
- return ccErrServerUnavailable;
+ return KRB5_CC_NOSUPP;
#endif
}
@@ -633,8 +633,10 @@ acc_get_first (krb5_context context,
int32_t error;
error = (*a->ccache->func->new_credentials_iterator)(a->ccache, &iter);
- if (error)
+ if (error) {
+ krb5_clear_error_string(context);
return ENOENT;
+ }
*cursor = iter;
return 0;
}
@@ -761,6 +763,97 @@ acc_get_version(krb5_context context,
return 0;
}
+struct cache_iter {
+ cc_context_t context;
+ cc_ccache_iterator_t iter;
+};
+
+static krb5_error_code
+acc_get_cache_first(krb5_context context, krb5_cc_cursor *cursor)
+{
+ struct cache_iter *iter;
+ krb5_error_code ret;
+ cc_int32 error;
+
+ ret = init_ccapi(context);
+ if (ret)
+ return ret;
+
+ iter = calloc(1, sizeof(*iter));
+ if (iter == NULL) {
+ krb5_set_error_string(context, "malloc - out of memory");
+ return ENOMEM;
+ }
+
+ error = (*init_func)(&iter->context, ccapi_version_3, NULL, NULL);
+ if (error) {
+ free(iter);
+ return translate_cc_error(context, error);
+ }
+
+ error = (*iter->context->func->new_ccache_iterator)(iter->context,
+ &iter->iter);
+ if (error) {
+ free(iter);
+ krb5_clear_error_string(context);
+ return ENOENT;
+ }
+ *cursor = iter;
+ return 0;
+}
+
+static krb5_error_code
+acc_get_cache_next(krb5_context context, krb5_cc_cursor cursor, krb5_ccache *id)
+{
+ struct cache_iter *iter = cursor;
+ cc_ccache_t cache;
+ krb5_acc *a;
+ krb5_error_code ret;
+ int32_t error;
+
+ error = (*iter->iter->func->next)(iter->iter, &cache);
+ if (error)
+ return translate_cc_error(context, error);
+
+ ret = _krb5_cc_allocate(context, &krb5_acc_ops, id);
+ if (ret) {
+ (*cache->func->release)(cache);
+ return ret;
+ }
+
+ ret = acc_alloc(context, id);
+ if (ret) {
+ (*cache->func->release)(cache);
+ free(*id);
+ return ret;
+ }
+
+ a = ACACHE(*id);
+ a->ccache = cache;
+
+ a->cache_name = get_cc_name(a->ccache);
+ if (a->cache_name == NULL) {
+ acc_close(context, *id);
+ *id = NULL;
+ krb5_set_error_string(context, "malloc: out of memory");
+ return ENOMEM;
+ }
+ return 0;
+}
+
+static krb5_error_code
+acc_end_cache_get(krb5_context context, krb5_cc_cursor cursor)
+{
+ struct cache_iter *iter = cursor;
+
+ (*iter->iter->func->release)(iter->iter);
+ iter->iter = NULL;
+ (*iter->context->func->release)(iter->context);
+ iter->context = NULL;
+ free(iter);
+ return 0;
+}
+
const krb5_cc_ops krb5_acc_ops = {
"API",
acc_get_name,
@@ -777,5 +870,8 @@ const krb5_cc_ops krb5_acc_ops = {
acc_end_get,
acc_remove_cred,
acc_set_flags,
- acc_get_version
+ acc_get_version,
+ acc_get_cache_first,
+ acc_get_cache_next,
+ acc_end_cache_get
};
diff --git a/source4/heimdal/lib/krb5/cache.c b/source4/heimdal/lib/krb5/cache.c
index f293a96ed9..ec956409a7 100644
--- a/source4/heimdal/lib/krb5/cache.c
+++ b/source4/heimdal/lib/krb5/cache.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2005 Kungliga Tekniska Högskolan
+ * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -33,7 +33,7 @@
#include "krb5_locl.h"
-RCSID("$Id: cache.c,v 1.71 2005/06/16 20:19:57 lha Exp $");
+RCSID("$Id: cache.c,v 1.73 2005/10/19 17:30:40 lha Exp $");
/*
* Add a new ccache type with operations `ops', overwriting any
@@ -77,6 +77,29 @@ krb5_cc_register(krb5_context context,
}
/*
+ * Allocate the memory for a `id' and the that function table to
+ * `ops'. Returns 0 or and error code.
+ */
+
+krb5_error_code
+_krb5_cc_allocate(krb5_context context,
+ const krb5_cc_ops *ops,
+ krb5_ccache *id)
+{
+ krb5_ccache p;
+
+ p = malloc (sizeof(*p));
+ if(p == NULL) {
+ krb5_set_error_string(context, "malloc: out of memory");
+ return KRB5_CC_NOMEM;
+ }
+ p->ops = ops;
+ *id = p;
+
+ return 0;
+}
+
+/*
* Allocate memory for a new ccache in `id' with operations `ops'
* and name `residual'.
* Return 0 or an error code.
@@ -89,18 +112,13 @@ allocate_ccache (krb5_context context,
krb5_ccache *id)
{
krb5_error_code ret;
- krb5_ccache p;
- p = malloc(sizeof(*p));
- if(p == NULL) {
- krb5_set_error_string(context, "malloc: out of memory");
- return KRB5_CC_NOMEM;
- }
- p->ops = ops;
- *id = p;
- ret = p->ops->resolve(context, id, residual);
+ ret = _krb5_cc_allocate(context, ops, id);
+ if (ret)
+ return ret;
+ ret = (*id)->ops->resolve(context, id, residual);
if(ret)
- free(p);
+ free(*id);
return ret;
}
@@ -145,16 +163,12 @@ krb5_cc_gen_new(krb5_context context,
const krb5_cc_ops *ops,
krb5_ccache *id)
{
- krb5_ccache p;
+ krb5_error_code ret;
- p = malloc (sizeof(*p));
- if (p == NULL) {
- krb5_set_error_string(context, "malloc: out of memory");
- return KRB5_CC_NOMEM;
- }
- p->ops = ops;
- *id = p;
- return p->ops->gen_new(context, id);
+ ret = _krb5_cc_allocate(context, ops, id);
+ if (ret)
+ return ret;
+ return (*id)->ops->gen_new(context, id);
}
/*
@@ -641,17 +655,172 @@ krb5_cc_clear_mcred(krb5_creds *mcred)
/*
* Get the cc ops that is registered in `context' to handle the
- * `prefix'. Returns NULL if ops not found.
+ * `prefix'. `prefix' can be a complete credential cache name or a
+ * prefix, the function will only use part up to the first colon (:)
+ * if there is one. Returns NULL if ops not found.
*/
const krb5_cc_ops *
krb5_cc_get_prefix_ops(krb5_context context, const char *prefix)
{
+ char *p, *p1;
int i;
+
+ p = strdup(prefix);
+ if (p == NULL) {
+ krb5_set_error_string(context, "malloc - out of memory");
+ return NULL;
+ }
+ p1 = strchr(p, ':');
+ if (p1)
+ *p1 = '\0';
for(i = 0; i < context->num_cc_ops && context->cc_ops[i].prefix; i++) {
- if(strcmp(context->cc_ops[i].prefix, prefix) == 0)
+ if(strcmp(context->cc_ops[i].prefix, p) == 0) {
+ free(p);
return &context->cc_ops[i];
+ }
}
+ free(p);
return NULL;
}
+
+struct krb5_cc_cache_cursor_data {
+ const krb5_cc_ops *ops;
+ krb5_cc_cursor cursor;
+};
+
+/*
+ * Start iterating over all caches of `type'. If `type' is NULL, the
+ * default type is * used. `cursor' is initialized to the beginning.
+ * Return 0 or an error code.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_cache_get_first (krb5_context context,
+ const char *type,
+ krb5_cc_cache_cursor *cursor)
+{
+ const krb5_cc_ops *ops;
+ krb5_error_code ret;
+
+ if (type == NULL)
+ type = krb5_cc_default_name(context);
+
+ ops = krb5_cc_get_prefix_ops(context, type);
+ if (ops == NULL) {
+ krb5_set_error_string(context, "Unknown type \"%s\" when iterating "
+ "trying to iterate the credential caches", type);
+ return KRB5_CC_UNKNOWN_TYPE;
+ }
+
+ if (ops->get_cache_first == NULL) {
+ krb5_set_error_string(context, "Credential cache type %s doesn't support "
+ "iterations over caches", ops->prefix);
+ return KRB5_CC_NOSUPP;
+ }
+
+ *cursor = calloc(1, sizeof(**cursor));
+ if (*cursor == NULL) {
+ krb5_set_error_string(context, "malloc - out of memory");
+ return ENOMEM;
+ }
+
+ (*cursor)->ops = ops;
+
+ ret = ops->get_cache_first(context, &(*cursor)->cursor);
+ if (ret) {
+ free(*cursor);
+ *cursor = NULL;
+ }
+ return ret;
+}
+
+/*
+ * Retrieve the next cache pointed to by (`cursor') in `id'
+ * and advance `cursor'.
+ * Return 0 or an error code.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_cache_next (krb5_context context,
+ krb5_cc_cache_cursor cursor,
+ krb5_ccache *id)
+{
+ return cursor->ops->get_cache_next(context, cursor->cursor, id);
+}
+
+/*
+ * Destroy the cursor `cursor'.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_cache_end_seq_get (krb5_context context,
+ krb5_cc_cache_cursor cursor)
+{
+ krb5_error_code ret;
+ ret = cursor->ops->end_cache_get(context, cursor->cursor);
+ cursor->ops = NULL;
+ free(cursor);
+ return ret;
+}
+
+/*
+ * Search for a matching credential cache of type `type' that have the
+ * `principal' as the default principal. If NULL is used for `type',
+ * the default type is used. On success, `id' needs to be freed with
+ * krb5_cc_close or krb5_cc_destroy. On failure, error code is
+ * returned and `id' is set to NULL.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_cache_match (krb5_context context,
+ krb5_principal client,
+ const char *type,
+ krb5_ccache *id)
+{
+ krb5_cc_cache_cursor cursor;
+ krb5_error_code ret;
+ krb5_ccache cache = NULL;
+
+ *id = NULL;
+
+ ret = krb5_cc_cache_get_first (context, type, &cursor);
+ if (ret)
+ return ret;
+
+ while ((ret = krb5_cc_cache_next (context, cursor, &cache)) == 0) {
+ krb5_principal principal;
+
+ ret = krb5_cc_get_principal(context, cache, &principal);
+ if (ret == 0) {
+ krb5_boolean match;
+
+ match = krb5_principal_compare(context, principal, client);
+ krb5_free_principal(context, principal);
+ if (match)
+ break;
+ }
+
+ krb5_cc_close(context, cache);
+ cache = NULL;
+ }
+
+ krb5_cc_cache_end_seq_get(context, cursor);
+
+ if (cache == NULL) {
+ char *str;
+
+ krb5_unparse_name(context, client, &str);
+
+ krb5_set_error_string(context, "Principal %s not found in a "
+ "credential cache", str ? str : "<out of memory>");
+ if (str)
+ free(str);
+ return KRB5_CC_NOTFOUND;
+ }
+ *id = cache;
+
+ return 0;
+}
+
diff --git a/source4/heimdal/lib/krb5/init_creds.c b/source4/heimdal/lib/krb5/init_creds.c
index 95c980d92c..51b8ebc392 100644
--- a/source4/heimdal/lib/krb5/init_creds.c
+++ b/source4/heimdal/lib/krb5/init_creds.c
@@ -33,14 +33,14 @@
#include "krb5_locl.h"
-RCSID("$Id: init_creds.c,v 1.20 2004/11/09 18:50:43 lha Exp $");
+RCSID("$Id: init_creds.c,v 1.21 2005/10/12 12:45:27 lha Exp $");
void KRB5_LIB_FUNCTION
krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt)
{
memset (opt, 0, sizeof(*opt));
opt->flags = 0;
- opt->private = NULL;
+ opt->opt_private = NULL;
}
krb5_error_code KRB5_LIB_FUNCTION
@@ -56,13 +56,13 @@ krb5_get_init_creds_opt_alloc(krb5_context context,
return ENOMEM;
}
krb5_get_init_creds_opt_init(o);
- o->private = calloc(1, sizeof(*o->private));
- if (o->private == NULL) {
+ o->opt_private = calloc(1, sizeof(*o->opt_private));
+ if (o->opt_private == NULL) {
krb5_set_error_string(context, "out of memory");
free(o);
return ENOMEM;
}
- o->private->refcount = 1;
+ o->opt_private->refcount = 1;
*opt = o;
return 0;
}
@@ -82,16 +82,16 @@ _krb5_get_init_creds_opt_copy(krb5_context context,
}
if (in)
*opt = *in;
- if(opt->private == NULL) {
- opt->private = calloc(1, sizeof(*opt->private));
- if (opt->private == NULL) {
+ if(opt->opt_private == NULL) {
+ opt->opt_private = calloc(1, sizeof(*opt->opt_private));
+ if (opt->opt_private == NULL) {
krb5_set_error_string(context, "out of memory");
free(opt);
return ENOMEM;
}
- opt->private->refcount = 1;
+ opt->opt_private->refcount = 1;
} else
- opt->private->refcount++;
+ opt->opt_private->refcount++;
*out = opt;
return 0;
}
@@ -99,13 +99,13 @@ _krb5_get_init_creds_opt_copy(krb5_context context,
void KRB5_LIB_FUNCTION
krb5_get_init_creds_opt_free(krb5_get_init_creds_opt *opt)
{
- if (opt->private == NULL)
+ if (opt->opt_private == NULL)
return;
- if (opt->private->refcount < 1) /* abort ? */
+ if (opt->opt_private->refcount < 1) /* abort ? */
return;
- if (--opt->private->refcount == 0) {
+ if (--opt->opt_private->refcount == 0) {
_krb5_get_init_creds_opt_free_pkinit(opt);
- free(opt->private);
+ free(opt->opt_private);
}
memset(opt, 0, sizeof(*opt));
free(opt);
@@ -293,7 +293,7 @@ require_ext_opt(krb5_context context,
krb5_get_init_creds_opt *opt,
const char *type)
{
- if (opt->private == NULL) {
+ if (opt->opt_private == NULL) {
krb5_set_error_string(context, "%s on non extendable opt", type);
return EINVAL;
}
@@ -310,8 +310,8 @@ krb5_get_init_creds_opt_set_pa_password(krb5_context context,
ret = require_ext_opt(context, opt, "init_creds_opt_set_pa_password");
if (ret)
return ret;
- opt->private->password = password;
- opt->private->key_proc = key_proc;
+ opt->opt_private->password = password;
+ opt->opt_private->key_proc = key_proc;
return 0;
}
@@ -324,7 +324,7 @@ krb5_get_init_creds_opt_set_pac_request(krb5_context context,
ret = require_ext_opt(context, opt, "init_creds_opt_set_pac_req");
if (ret)
return ret;
- opt->private->req_pac = req_pac ?
+ opt->opt_private->req_pac = req_pac ?
KRB5_PA_PAC_REQ_TRUE :
KRB5_PA_PAC_REQ_FALSE;
return 0;
diff --git a/source4/heimdal/lib/krb5/init_creds_pw.c b/source4/heimdal/lib/krb5/init_creds_pw.c
index 8fd5c4611f..3c694624bf 100644
--- a/source4/heimdal/lib/krb5/init_creds_pw.c
+++ b/source4/heimdal/lib/krb5/init_creds_pw.c
@@ -33,7 +33,7 @@
#include "krb5_locl.h"
-RCSID("$Id: init_creds_pw.c,v 1.88 2005/08/13 08:25:32 lha Exp $");
+RCSID("$Id: init_creds_pw.c,v 1.90 2005/10/12 12:45:11 lha Exp $");
typedef struct krb5_get_init_creds_ctx {
krb5_kdc_flags flags;
@@ -275,11 +275,11 @@ get_init_creds_common(krb5_context context,
options = &default_opt;
}
- if (options->private) {
- ctx->password = options->private->password;
- ctx->key_proc = options->private->key_proc;
- ctx->req_pac = options->private->req_pac;
- ctx->pk_init_ctx = options->private->pk_init_ctx;
+ if (options->opt_private) {
+ ctx->password = options->opt_private->password;
+ ctx->key_proc = options->opt_private->key_proc;
+ ctx->req_pac = options->opt_private->req_pac;
+ ctx->pk_init_ctx = options->opt_private->pk_init_ctx;
} else
ctx->req_pac = KRB5_PA_PAC_DONT_CARE;
@@ -1014,10 +1014,10 @@ pa_data_to_md_pkinit(krb5_context context,
return 0;
#ifdef PKINIT
return _krb5_pk_mk_padata(context,
- ctx->pk_init_ctx,
- &a->req_body,
- ctx->pk_nonce,
- md);
+ ctx->pk_init_ctx,
+ &a->req_body,
+ ctx->pk_nonce,
+ md);
#else
krb5_set_error_string(context, "no support for PKINIT compiled in");
return EINVAL;
@@ -1114,6 +1114,7 @@ process_pa_data_to_key(krb5_context context,
krb5_creds *creds,
AS_REQ *a,
krb5_kdc_rep *rep,
+ const krb5_krbhst_info *hi,
krb5_keyblock **key)
{
struct pa_info_data paid, *ppaid = NULL;
@@ -1158,6 +1159,7 @@ process_pa_data_to_key(krb5_context context,
ret = _krb5_pk_rd_pa_reply(context,
ctx->pk_init_ctx,
etype,
+ hi,
ctx->pk_nonce,
&ctx->req_buffer,
pa,
@@ -1194,6 +1196,8 @@ init_cred_loop(krb5_context context,
size_t len;
size_t size;
int send_to_kdc_flags = 0;
+ krb5_krbhst_info *hi = NULL;
+
memset(&md, 0, sizeof(md));
memset(&rep, 0, sizeof(rep));
@@ -1321,7 +1325,7 @@ init_cred_loop(krb5_context context,
krb5_keyblock *key = NULL;
ret = process_pa_data_to_key(context, ctx, creds,
- &ctx->as_req, &rep, &key);
+ &ctx->as_req, &rep, hi, &key);
if (ret)
goto out;
@@ -1462,8 +1466,8 @@ krb5_get_init_creds_password(krb5_context context,
return ret;
if (password == NULL &&
- options->private->password == NULL &&
- options->private->pk_init_ctx == NULL)
+ options->opt_private->password == NULL &&
+ options->opt_private->pk_init_ctx == NULL)
{
krb5_prompt prompt;
krb5_data password_data;
@@ -1491,7 +1495,7 @@ krb5_get_init_creds_password(krb5_context context,
password = password_data.data;
}
- if (options->private->password == NULL) {
+ if (options->opt_private->password == NULL) {
ret = krb5_get_init_creds_opt_set_pa_password(context, options,
password, NULL);
if (ret) {
diff --git a/source4/heimdal/lib/krb5/keytab_keyfile.c b/source4/heimdal/lib/krb5/keytab_keyfile.c
index b53fa36a03..5c94291e72 100644
--- a/source4/heimdal/lib/krb5/keytab_keyfile.c
+++ b/source4/heimdal/lib/krb5/keytab_keyfile.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan
+ * Copyright (c) 1997 - 2002, 2005 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -33,7 +33,7 @@
#include "krb5_locl.h"
-RCSID("$Id: keytab_keyfile.c,v 1.16 2005/01/08 22:57:18 lha Exp $");
+RCSID("$Id: keytab_keyfile.c,v 1.17 2005/09/30 11:20:53 lha Exp $");
/* afs keyfile operations --------------------------------------- */
@@ -288,9 +288,16 @@ akf_add_entry(krb5_context context,
krb5_storage *sp;
- if (entry->keyblock.keyvalue.length != 8
- || entry->keyblock.keytype != ETYPE_DES_CBC_MD5)
+ if (entry->keyblock.keyvalue.length != 8)
return 0;
+ switch(entry->keyblock.keytype) {
+ case ETYPE_DES_CBC_CRC:
+ case ETYPE_DES_CBC_MD4:
+ case ETYPE_DES_CBC_MD5:
+ break;
+ default:
+ return 0;
+ }
fd = open (d->filename, O_RDWR | O_BINARY);
if (fd < 0) {
@@ -329,50 +336,72 @@ akf_add_entry(krb5_context context,
return ret;
}
}
+
+ /*
+ * Make sure we don't add the entry twice, assumes the DES
+ * encryption types are all the same key.
+ */
+ if (len > 0) {
+ int32_t kvno;
+ int i;
+
+ for (i = 0; i < len; i++) {
+ ret = krb5_ret_int32(sp, &kvno);
+ if (ret) {
+ krb5_set_error_string (context, "Failed got get kvno ");
+ goto out;
+ }
+ if(krb5_storage_seek(sp, 8, SEEK_CUR) < 0) {
+ krb5_set_error_string (context, "seek: %s", strerror(ret));
+ goto out;
+ }
+ if (kvno == entry->vno) {
+ ret = 0;
+ goto out;
+ }
+ }
+ }
+
len++;
if(krb5_storage_seek(sp, 0, SEEK_SET) < 0) {
ret = errno;
- krb5_storage_free(sp);
- close(fd);
krb5_set_error_string (context, "seek: %s", strerror(ret));
- return ret;
+ goto out;
}
ret = krb5_store_int32(sp, len);
if(ret) {
- krb5_storage_free(sp);
- close(fd);
+ krb5_set_error_string(context, "keytab keyfile failed new length");
return ret;
}
-
if(krb5_storage_seek(sp, (len - 1) * (8 + 4), SEEK_CUR) < 0) {
ret = errno;
- krb5_storage_free(sp);
- close(fd);
- krb5_set_error_string (context, "seek: %s", strerror(ret));
- return ret;
+ krb5_set_error_string (context, "seek to end: %s", strerror(ret));
+ goto out;
}
ret = krb5_store_int32(sp, entry->vno);
if(ret) {
- krb5_storage_free(sp);
- close(fd);
- return ret;
+ krb5_set_error_string(context, "keytab keyfile failed store kvno");
+ goto out;
}
ret = krb5_storage_write(sp, entry->keyblock.keyvalue.data,
entry->keyblock.keyvalue.length);
if(ret != entry->keyblock.keyvalue.length) {
- krb5_storage_free(sp);
- close(fd);
- if(ret < 0)
- return errno;
- return ENOTTY;
+ if (ret < 0)
+ ret = errno;
+ else
+ ret = ENOTTY;
+ krb5_set_error_string(context, "keytab keyfile failed to add key");
+ goto out;
}
+ ret = 0;
+out:
krb5_storage_free(sp);
close (fd);
- return 0;
+ return ret;
}
const krb5_kt_ops krb5_akf_ops = {
diff --git a/source4/heimdal/lib/krb5/krb5-private.h b/source4/heimdal/lib/krb5/krb5-private.h
index ef47bd1e26..07d9329337 100644
--- a/source4/heimdal/lib/krb5/krb5-private.h
+++ b/source4/heimdal/lib/krb5/krb5-private.h
@@ -31,6 +31,12 @@ _krb5_aes_cts_encrypt (
unsigned char */*ivec*/,
const int /*encryptp*/);
+krb5_error_code
+_krb5_cc_allocate (
+ krb5_context /*context*/,
+ const krb5_cc_ops */*ops*/,
+ krb5_ccache */*id*/);
+
void
_krb5_crc_init_table (void);
@@ -41,6 +47,16 @@ _krb5_crc_update (
u_int32_t /*res*/);
krb5_error_code
+_krb5_dh_group_ok (
+ krb5_context /*context*/,
+ unsigned long /*bits*/,
+ heim_integer */*p*/,
+ heim_integer */*g*/,
+ heim_integer */*q*/,
+ struct krb5_dh_moduli **/*moduli*/,
+ char **/*name*/);
+
+krb5_error_code
_krb5_expand_default_cc_name (
krb5_context /*context*/,
const char */*str*/,
@@ -61,6 +77,9 @@ _krb5_extract_ticket (
krb5_decrypt_proc /*decrypt_proc*/,
krb5_const_pointer /*decryptarg*/);
+void
+_krb5_free_krbhst_info (krb5_krbhst_info */*hi*/);
+
krb5_error_code
_krb5_get_default_principal_local (
krb5_context /*context*/,
@@ -234,6 +253,12 @@ _krb5_krb_time_to_life (
time_t /*end*/);
krb5_error_code
+_krb5_krbhost_info_move (
+ krb5_context /*context*/,
+ krb5_krbhst_info */*from*/,
+ krb5_krbhst_info **/*to*/);
+
+krb5_error_code
_krb5_mk_req_internal (
krb5_context /*context*/,
krb5_auth_context */*auth_context*/,
@@ -257,6 +282,20 @@ _krb5_oid_to_enctype (
const heim_oid */*oid*/,
krb5_enctype */*etype*/);
+krb5_error_code
+_krb5_parse_moduli (
+ krb5_context /*context*/,
+ const char */*file*/,
+ struct krb5_dh_moduli ***/*moduli*/);
+
+krb5_error_code
+_krb5_parse_moduli_line (
+ krb5_context /*context*/,
+ const char */*file*/,
+ int /*lineno*/,
+ char */*p*/,
+ struct krb5_dh_moduli **/*m*/);
+
void KRB5_LIB_FUNCTION
_krb5_pk_cert_free (struct krb5_pk_cert */*cert*/);
@@ -308,6 +347,7 @@ _krb5_pk_rd_pa_reply (
krb5_context /*context*/,
void */*c*/,
krb5_enctype /*etype*/,
+ const krb5_krbhst_info */*hi*/,
unsigned /*nonce*/,
const krb5_data */*req_buffer*/,
PA_DATA */*pa*/,
@@ -316,7 +356,7 @@ _krb5_pk_rd_pa_reply (
krb5_error_code KRB5_LIB_FUNCTION
_krb5_pk_verify_sign (
krb5_context /*context*/,
- const char */*data*/,
+ const void */*data*/,
size_t /*length*/,
struct krb5_pk_identity */*id*/,
heim_oid */*contentType*/,
diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h
index 681ac4189b..a46f8b8f8f 100644
--- a/source4/heimdal/lib/krb5/krb5-protos.h
+++ b/source4/heimdal/lib/krb5/krb5-protos.h
@@ -535,6 +535,30 @@ krb5_c_verify_checksum (
const krb5_checksum */*cksum*/,
krb5_boolean */*valid*/);
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_cache_end_seq_get (
+ krb5_context /*context*/,
+ krb5_cc_cache_cursor /*cursor*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_cache_get_first (
+ krb5_context /*context*/,
+ const char */*type*/,
+ krb5_cc_cache_cursor */*cursor*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_cache_match (
+ krb5_context /*context*/,
+ krb5_principal /*client*/,
+ const char */*type*/,
+ krb5_ccache */*id*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_cache_next (
+ krb5_context /*context*/,
+ krb5_cc_cache_cursor /*cursor*/,
+ krb5_ccache */*id*/);
+
void KRB5_LIB_FUNCTION
krb5_cc_clear_mcred (krb5_creds */*mcred*/);
@@ -2867,6 +2891,13 @@ krb5_set_real_time (
krb5_timestamp /*sec*/,
int32_t /*usec*/);
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_set_send_recv_func (
+ krb5_context /*context*/,
+ krb5_send_and_recv_func_t /*func*/,
+ krb5_send_and_recv_close_func_t /*close_fn*/,
+ void */*data*/);
+
void KRB5_LIB_FUNCTION
krb5_set_use_admin_kdc (
krb5_context /*context*/,
@@ -3432,11 +3463,6 @@ krb5_write_safe_message (
krb5_error_code KRB5_LIB_FUNCTION
krb5_xfree (void */*ptr*/);
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_set_send_recv_func(krb5_context context,
- krb5_send_and_recv_func_t func,
- krb5_send_and_recv_close_func_t close_fn,
- void *data);
#ifdef __cplusplus
}
diff --git a/source4/heimdal/lib/krb5/krb5.h b/source4/heimdal/lib/krb5/krb5.h
index 800683ef0c..ef595d4d20 100644
--- a/source4/heimdal/lib/krb5/krb5.h
+++ b/source4/heimdal/lib/krb5/krb5.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-/* $Id: krb5.h,v 1.237 2005/07/09 14:47:21 lha Exp $ */
+/* $Id: krb5.h,v 1.239 2005/10/12 12:39:28 lha Exp $ */
#ifndef __KRB5_H__
#define __KRB5_H__
@@ -368,6 +368,8 @@ typedef struct krb5_creds {
krb5_ticket_flags flags;
} krb5_creds;
+typedef struct krb5_cc_cache_cursor_data *krb5_cc_cache_cursor;
+
typedef struct krb5_cc_ops {
const char *prefix;
const char* (*get_name)(krb5_context, krb5_ccache);
@@ -388,6 +390,9 @@ typedef struct krb5_cc_ops {
krb5_flags, krb5_creds*);
krb5_error_code (*set_flags)(krb5_context, krb5_ccache, krb5_flags);
int (*get_version)(krb5_context, krb5_ccache);
+ krb5_error_code (*get_cache_first)(krb5_context, krb5_cc_cursor *);
+ krb5_error_code (*get_cache_next)(krb5_context, krb5_cc_cursor, krb5_ccache *);
+ krb5_error_code (*end_cache_get)(krb5_context, krb5_cc_cursor);
} krb5_cc_ops;
struct krb5_log_facility;
@@ -659,7 +664,7 @@ typedef struct _krb5_get_init_creds_opt {
krb5_preauthtype *preauth_list;
int preauth_list_length;
krb5_data *salt;
- struct _krb5_get_init_creds_opt_private *private;
+ struct _krb5_get_init_creds_opt_private *opt_private;
} krb5_get_init_creds_opt;
#define KRB5_GET_INIT_CREDS_OPT_TKT_LIFE 0x0001
diff --git a/source4/heimdal/lib/krb5/krb5_locl.h b/source4/heimdal/lib/krb5/krb5_locl.h
index a64ccc586e..4a02677239 100644
--- a/source4/heimdal/lib/krb5/krb5_locl.h
+++ b/source4/heimdal/lib/krb5/krb5_locl.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-/* $Id: krb5_locl.h,v 1.81 2005/05/29 14:28:39 lha Exp $ */
+/* $Id: krb5_locl.h,v 1.83 2005/10/07 12:08:02 lha Exp $ */
#ifndef __KRB5_LOCL_H__
#define __KRB5_LOCL_H__
@@ -141,6 +141,7 @@ struct krb5_pk_identity;
struct krb5_pk_cert;
struct ContentInfo;
typedef struct krb5_pk_init_ctx_data *krb5_pk_init_ctx;
+struct krb5_dh_moduli;
/* v4 glue */
struct _krb5_krb_auth_data;
@@ -161,6 +162,8 @@ struct _krb5_krb_auth_data;
#define KEYTAB_DEFAULT "ANY:FILE:" SYSCONFDIR "/krb5.keytab,krb4:" SYSCONFDIR "/srvtab"
#define KEYTAB_DEFAULT_MODIFY "FILE:" SYSCONFDIR "/krb5.keytab"
+#define MODULI_FILE SYSCONFDIR "/krb5.moduli"
+
#ifndef O_BINARY
#define O_BINARY 0
#endif
diff --git a/source4/heimdal/lib/krb5/krbhst.c b/source4/heimdal/lib/krb5/krbhst.c
index 98e9cb3f09..ef9f5dbd60 100644
--- a/source4/heimdal/lib/krb5/krbhst.c
+++ b/source4/heimdal/lib/krb5/krbhst.c
@@ -34,7 +34,7 @@
#include "krb5_locl.h"
#include <resolve.h>
-RCSID("$Id: krbhst.c,v 1.52 2005/06/17 04:23:26 lha Exp $");
+RCSID("$Id: krbhst.c,v 1.53 2005/10/08 15:40:50 lha Exp $");
static int
string_to_proto(const char *string)
@@ -228,14 +228,37 @@ parse_hostspec(krb5_context context, struct krb5_krbhst_data *kd,
return hi;
}
-static void
-free_krbhst_info(krb5_krbhst_info *hi)
+void
+_krb5_free_krbhst_info(krb5_krbhst_info *hi)
{
if (hi->ai != NULL)
freeaddrinfo(hi->ai);
free(hi);
}
+krb5_error_code
+_krb5_krbhost_info_move(krb5_context context,
+ krb5_krbhst_info *from,
+ krb5_krbhst_info **to)
+{
+ /* trailing NUL is included in structure */
+ *to = calloc(1, sizeof(**to) + strlen(from->hostname));
+ if(*to == NULL) {
+ krb5_set_error_string(context, "malloc - out of memory");
+ return ENOMEM;
+ }
+
+ (*to)->proto = from->proto;
+ (*to)->port = from->port;
+ (*to)->def_port = from->def_port;
+ (*to)->ai = from->ai;
+ from->ai = NULL;
+ (*to)->next = NULL;
+ strcpy((*to)->hostname, from->hostname);
+ return 0;
+}
+
+
static void
append_host_hostinfo(struct krb5_krbhst_data *kd, struct krb5_krbhst_info *host)
{
@@ -245,7 +268,7 @@ append_host_hostinfo(struct krb5_krbhst_data *kd, struct krb5_krbhst_info *host)
if(h->proto == host->proto &&
h->port == host->port &&
strcmp(h->hostname, host->hostname) == 0) {
- free_krbhst_info(host);
+ _krb5_free_krbhst_info(host);
return;
}
*kd->end = host;
@@ -752,7 +775,7 @@ krb5_krbhst_free(krb5_context context, krb5_krbhst_handle handle)
for (h = handle->hosts; h != NULL; h = next) {
next = h->next;
- free_krbhst_info(h);
+ _krb5_free_krbhst_info(h);
}
free(handle->realm);
diff --git a/source4/heimdal/lib/krb5/mcache.c b/source4/heimdal/lib/krb5/mcache.c
index 0a65d53849..9588d936d5 100644
--- a/source4/heimdal/lib/krb5/mcache.c
+++ b/source4/heimdal/lib/krb5/mcache.c
@@ -33,7 +33,7 @@
#include "krb5_locl.h"
-RCSID("$Id: mcache.c,v 1.19 2004/04/25 19:25:35 joda Exp $");
+RCSID("$Id: mcache.c,v 1.20 2005/09/30 11:16:04 lha Exp $");
typedef struct krb5_mcache {
char *name;
@@ -162,20 +162,25 @@ mcc_initialize(krb5_context context,
&m->primary_principal);
}
-static krb5_error_code
-mcc_close(krb5_context context,
- krb5_ccache id)
+static int
+mcc_close_internal(krb5_mcache *m)
{
- krb5_mcache *m = MCACHE(id);
-
if (--m->refcnt != 0)
return 0;
if (MISDEAD(m)) {
free (m->name);
- krb5_data_free(&id->data);
+ return 1;
}
+ return 0;
+}
+static krb5_error_code
+mcc_close(krb5_context context,
+ krb5_ccache id)
+{
+ if (mcc_close_internal(MCACHE(id)))
+ krb5_data_free(&id->data);
return 0;
}
@@ -334,6 +339,70 @@ mcc_set_flags(krb5_context context,
return 0; /* XXX */
}
+struct mcache_iter {
+ krb5_mcache *cache;
+};
+
+static krb5_error_code
+mcc_get_cache_first(krb5_context context, krb5_cc_cursor *cursor)
+{
+ struct mcache_iter *iter;
+
+ iter = calloc(1, sizeof(*iter));
+ if (iter == NULL) {
+ krb5_set_error_string(context, "malloc - out of memory");
+ return ENOMEM;
+ }
+
+ HEIMDAL_MUTEX_lock(&mcc_mutex);
+ iter->cache = mcc_head;
+ if (iter->cache)
+ iter->cache->refcnt++;
+ HEIMDAL_MUTEX_unlock(&mcc_mutex);
+
+ *cursor = iter;
+ return 0;
+}
+
+static krb5_error_code
+mcc_get_cache_next(krb5_context context, krb5_cc_cursor cursor, krb5_ccache *id)
+{
+ struct mcache_iter *iter = cursor;
+ krb5_error_code ret;
+ krb5_mcache *m;
+
+ if (iter->cache == NULL)
+ return KRB5_CC_END;
+
+ HEIMDAL_MUTEX_lock(&mcc_mutex);
+ m = iter->cache;
+ if (m->next)
+ m->next->refcnt++;
+ iter->cache = m->next;
+ HEIMDAL_MUTEX_unlock(&mcc_mutex);
+
+ ret = _krb5_cc_allocate(context, &krb5_mcc_ops, id);
+ if (ret)
+ return ret;
+
+ (*id)->data.data = m;
+ (*id)->data.length = sizeof(*m);
+
+ return 0;
+}
+
+static krb5_error_code
+mcc_end_cache_get(krb5_context context, krb5_cc_cursor cursor)
+{
+ struct mcache_iter *iter = cursor;
+
+ if (iter->cache)
+ mcc_close_internal(iter->cache);
+ iter->cache = NULL;
+ free(iter);
+ return 0;
+}
+
const krb5_cc_ops krb5_mcc_ops = {
"MEMORY",
mcc_get_name,
@@ -349,5 +418,9 @@ const krb5_cc_ops krb5_mcc_ops = {
mcc_get_next,
mcc_end_get,
mcc_remove_cred,
- mcc_set_flags
+ mcc_set_flags,
+ NULL,
+ mcc_get_cache_first,
+ mcc_get_cache_next,
+ mcc_end_cache_get
};
diff --git a/source4/heimdal/lib/krb5/pkinit.c b/source4/heimdal/lib/krb5/pkinit.c
index 7ac1436f6e..0c5dfc44e9 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.62 2005/09/20 23:21:36 lha Exp $");
+RCSID("$Id: pkinit.c,v 1.75 2005/10/21 17:18:38 lha Exp $");
#ifdef PKINIT
@@ -57,12 +57,9 @@ RCSID("$Id: pkinit.c,v 1.62 2005/09/20 23:21:36 lha Exp $");
enum {
COMPAT_WIN2K = 1,
- COMPAT_19 = 2,
- COMPAT_27 = 3
+ COMPAT_IETF = 2
};
-
-
#define OPENSSL_ASN1_MALLOC_ENCODE(T, B, BL, S, R) \
{ \
unsigned char *p; \
@@ -107,12 +104,22 @@ struct krb5_pk_cert {
X509 *cert;
};
+struct krb5_dh_moduli {
+ char *name;
+ unsigned long bits;
+ heim_integer p;
+ heim_integer g;
+ heim_integer q;
+};
+
struct krb5_pk_init_ctx_data {
struct krb5_pk_identity *id;
DH *dh;
+ krb5_data *clientDHNonce;
+ struct krb5_dh_moduli **m;
+ int require_binding;
};
-
void KRB5_LIB_FUNCTION
_krb5_pk_cert_free(struct krb5_pk_cert *cert)
{
@@ -135,6 +142,20 @@ BN_to_integer(krb5_context context, BIGNUM *bn, heim_integer *integer)
return 0;
}
+static BIGNUM *
+integer_to_BN(krb5_context context, const char *field, const heim_integer *f)
+{
+ BIGNUM *bn;
+
+ bn = BN_bin2bn((const unsigned char *)f->data, f->length, NULL);
+ if (bn == NULL) {
+ krb5_set_error_string(context, "PKINIT: parsing BN failed %s", field);
+ return NULL;
+ }
+ bn->neg = f->negative;
+ return bn;
+}
+
/*
* UI ex_data has the callback_data as passed to Engine. This is far
* from being complete, we will only process one prompt
@@ -251,7 +272,8 @@ _krb5_pk_create_sign(krb5_context context,
krb5_data buf;
SignedData sd;
EVP_MD_CTX md;
- int len, i;
+ int i;
+ unsigned len;
size_t size;
X509_NAME *issuer_name;
@@ -444,74 +466,9 @@ _krb5_pk_create_sign(krb5_context context,
}
static krb5_error_code
-build_auth_pack_win2k(krb5_context context,
- unsigned nonce,
- const KDC_REQ_BODY *body,
- AuthPack_Win2k *a)
-{
- krb5_error_code ret;
- krb5_timestamp sec;
- int32_t usec;
-
- /* fill in PKAuthenticator */
- ret = copy_PrincipalName(body->sname, &a->pkAuthenticator.kdcName);
- if (ret)
- return ret;
- ret = copy_Realm(&body->realm, &a->pkAuthenticator.kdcRealm);
- if (ret)
- return ret;
-
- krb5_us_timeofday(context, &sec, &usec);
- a->pkAuthenticator.ctime = sec;
- a->pkAuthenticator.cusec = usec;
- a->pkAuthenticator.nonce = nonce;
-
- return 0;
-}
-
-static krb5_error_code
-build_auth_pack_19(krb5_context context,
- unsigned nonce,
- const KDC_REQ_BODY *body,
- AuthPack_19 *a)
-{
- size_t buf_size, len;
- krb5_cksumtype cksum;
- krb5_error_code ret;
- void *buf;
- krb5_timestamp sec;
- int32_t usec;
-
- krb5_clear_error_string(context);
-
- /* XXX some PACKETCABLE needs implemetations need md5 */
- cksum = CKSUMTYPE_RSA_MD5;
-
- krb5_us_timeofday(context, &sec, &usec);
- a->pkAuthenticator.ctime = sec;
- a->pkAuthenticator.nonce = nonce;
-
- ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, body, &len, ret);
- if (ret)
- return ret;
- if (buf_size != len)
- krb5_abortx(context, "internal error in ASN.1 encoder");
-
- ret = krb5_create_checksum(context,
- NULL,
- 0,
- cksum,
- buf,
- len,
- &a->pkAuthenticator.paChecksum);
- free(buf);
-
- return ret;
-}
-
-static krb5_error_code
build_auth_pack(krb5_context context,
unsigned nonce,
+ krb5_pk_init_ctx ctx,
DH *dh,
const KDC_REQ_BODY *body,
AuthPack *a)
@@ -545,18 +502,39 @@ build_auth_pack(krb5_context context,
len,
&checksum);
free(buf);
- if (ret == 0) {
- ret = krb5_data_copy(&a->pkAuthenticator.paChecksum,
- checksum.checksum.data, checksum.checksum.length);
- free_Checksum(&checksum);
- }
+ if (ret)
+ return ret;
- if (ret == 0 && dh) {
+ ret = krb5_data_copy(&a->pkAuthenticator.paChecksum,
+ checksum.checksum.data, checksum.checksum.length);
+ free_Checksum(&checksum);
+ if (ret)
+ return ret;
+
+ if (dh) {
DomainParameters dp;
heim_integer dh_pub_key;
krb5_data dhbuf;
size_t size;
+ if (1 /* support_cached_dh */) {
+ ALLOC(a->clientDHNonce, 1);
+ if (a->clientDHNonce == NULL) {
+ krb5_clear_error_string(context);
+ return ENOMEM;
+ }
+ ret = krb5_data_alloc(a->clientDHNonce, 40);
+ if (a->clientDHNonce == NULL) {
+ krb5_clear_error_string(context);
+ return ENOMEM;
+ }
+ memset(a->clientDHNonce->data, 0, a->clientDHNonce->length);
+ ret = krb5_copy_data(context, a->clientDHNonce,
+ &ctx->clientDHNonce);
+ if (ret)
+ return ret;
+ }
+
ALLOC(a->clientPublicValue, 1);
if (a->clientPublicValue == NULL)
return ENOMEM;
@@ -606,20 +584,11 @@ build_auth_pack(krb5_context context,
if (ret)
return ret;
- dhbuf.length = length_heim_integer(&dh_pub_key);
- dhbuf.data = malloc(dhbuf.length);
- if (dhbuf.data == NULL) {
- free_heim_integer(&dh_pub_key);
- krb5_set_error_string(context, "malloc: out of memory");
- return ret;
- }
- ret = der_put_heim_integer((char *)dhbuf.data + dhbuf.length - 1,
- dhbuf.length, &dh_pub_key, &size);
+ ASN1_MALLOC_ENCODE(DHPublicKey, dhbuf.data, dhbuf.length,
+ &dh_pub_key, &size, ret);
free_heim_integer(&dh_pub_key);
- if (ret) {
- free(dhbuf.data);
+ if (ret)
return ret;
- }
if (size != dhbuf.length)
krb5_abortx(context, "asn1 internal error");
@@ -663,27 +632,40 @@ pk_mk_padata(krb5_context context,
struct ContentInfo content_info;
krb5_error_code ret;
const heim_oid *oid;
- PA_PK_AS_REQ req;
size_t size;
krb5_data buf, sd_buf;
int pa_type;
krb5_data_zero(&buf);
krb5_data_zero(&sd_buf);
- memset(&req, 0, sizeof(req));
memset(&content_info, 0, sizeof(content_info));
if (compat == COMPAT_WIN2K) {
AuthPack_Win2k ap;
+ krb5_timestamp sec;
+ int32_t usec;
memset(&ap, 0, sizeof(ap));
- ret = build_auth_pack_win2k(context, nonce, req_body, &ap);
+ /* fill in PKAuthenticator */
+ ret = copy_PrincipalName(req_body->sname, &ap.pkAuthenticator.kdcName);
+ if (ret) {
+ free_AuthPack_Win2k(&ap);
+ krb5_clear_error_string(context);
+ goto out;
+ }
+ ret = copy_Realm(&req_body->realm, &ap.pkAuthenticator.kdcRealm);
if (ret) {
free_AuthPack_Win2k(&ap);
+ krb5_clear_error_string(context);
goto out;
}
+ krb5_us_timeofday(context, &sec, &usec);
+ ap.pkAuthenticator.ctime = sec;
+ ap.pkAuthenticator.cusec = usec;
+ ap.pkAuthenticator.nonce = nonce;
+
ASN1_MALLOC_ENCODE(AuthPack_Win2k, buf.data, buf.length,
&ap, &size, ret);
free_AuthPack_Win2k(&ap);
@@ -695,33 +677,12 @@ pk_mk_padata(krb5_context context,
krb5_abortx(context, "internal ASN1 encoder error");
oid = oid_id_pkcs7_data();
- } else if (compat == COMPAT_19) {
- AuthPack_19 ap;
-
- memset(&ap, 0, sizeof(ap));
-
- ret = build_auth_pack_19(context, nonce, req_body, &ap);
- if (ret) {
- free_AuthPack_19(&ap);
- goto out;
- }
-
- ASN1_MALLOC_ENCODE(AuthPack_19, buf.data, buf.length, &ap, &size, ret);
- free_AuthPack_19(&ap);
- if (ret) {
- krb5_set_error_string(context, "AuthPack_19: %d", ret);
- goto out;
- }
- if (buf.length != size)
- krb5_abortx(context, "internal ASN1 encoder error");
-
- oid = oid_id_pkauthdata();
- } else if (compat == COMPAT_27) {
+ } else if (compat == COMPAT_IETF) {
AuthPack ap;
memset(&ap, 0, sizeof(ap));
- ret = build_auth_pack(context, nonce, ctx->dh, req_body, &ap);
+ ret = build_auth_pack(context, nonce, ctx, ctx->dh, req_body, &ap);
if (ret) {
free_AuthPack(&ap);
goto out;
@@ -755,9 +716,12 @@ pk_mk_padata(krb5_context context,
if (ret)
goto out;
- /* XXX tell the kdc what CAs the client is willing to accept */
- req.trustedCertifiers = NULL;
- req.kdcPkId = NULL;
+ ASN1_MALLOC_ENCODE(ContentInfo, buf.data, buf.length,
+ &content_info, &size, ret);
+ if (ret)
+ goto out;
+ if (buf.length != size)
+ krb5_abortx(context, "Internal ASN1 encoder error");
if (compat == COMPAT_WIN2K) {
PA_PK_AS_REQ_Win2k winreq;
@@ -766,60 +730,29 @@ pk_mk_padata(krb5_context context,
memset(&winreq, 0, sizeof(winreq));
- ASN1_MALLOC_ENCODE(ContentInfo,
- winreq.signed_auth_pack.data,
- winreq.signed_auth_pack.length,
- &content_info,
- &size,
- ret);
- if (ret)
- goto out;
- if (winreq.signed_auth_pack.length != size)
- krb5_abortx(context, "Internal ASN1 encoder error");
+ winreq.signed_auth_pack = buf;
ASN1_MALLOC_ENCODE(PA_PK_AS_REQ_Win2k, buf.data, buf.length,
&winreq, &size, ret);
free_PA_PK_AS_REQ_Win2k(&winreq);
- } else if (compat == COMPAT_19) {
- PA_PK_AS_REQ_19 req_19;
-
- pa_type = KRB5_PADATA_PK_AS_REQ_19;
-
- memset(&req_19, 0, sizeof(req_19));
-
- ret = copy_ContentInfo(&content_info, &req_19.signedAuthPack);
- if (ret) {
- krb5_clear_error_string(context);
- goto out;
- }
- req_19.kdcCert = NULL;
- req_19.trustedCertifiers = NULL;
- req_19.encryptionCert = NULL;
-
- ASN1_MALLOC_ENCODE(PA_PK_AS_REQ_19, buf.data, buf.length,
- &req_19, &size, ret);
-
- free_PA_PK_AS_REQ_19(&req_19);
-
- } else if (compat == COMPAT_27) {
+ } else if (compat == COMPAT_IETF) {
+ PA_PK_AS_REQ req;
pa_type = KRB5_PADATA_PK_AS_REQ;
- ASN1_MALLOC_ENCODE(ContentInfo,
- req.signedAuthPack.data,
- req.signedAuthPack.length,
- &content_info,
- &size,
- ret);
- if (ret)
- goto out;
- if (req.signedAuthPack.length != size)
- krb5_abortx(context, "Internal ASN1 encoder error");
+ memset(&req, 0, sizeof(req));
+ req.signedAuthPack = buf;
+
+ /* XXX tell the kdc what CAs the client is willing to accept */
+ req.trustedCertifiers = NULL;
+ req.kdcPkId = NULL;
ASN1_MALLOC_ENCODE(PA_PK_AS_REQ, buf.data, buf.length,
&req, &size, ret);
+ free_PA_PK_AS_REQ(&req);
+
} else
krb5_abortx(context, "internal pkinit error");
if (ret) {
@@ -832,7 +765,11 @@ pk_mk_padata(krb5_context context,
ret = krb5_padata_add(context, md, pa_type, buf.data, buf.length);
if (ret)
free(buf.data);
- out:
+
+ if (ret == 0 && compat == COMPAT_WIN2K)
+ krb5_padata_add(context, md, KRB5_PADATA_PK_AS_09_BINDING, NULL, 0);
+
+out:
free_ContentInfo(&content_info);
return ret;
@@ -847,11 +784,7 @@ _krb5_pk_mk_padata(krb5_context context,
METHOD_DATA *md)
{
krb5_pk_init_ctx ctx = c;
- krb5_error_code ret;
- size_t size;
- krb5_data buf;
- const char *provisioning_server;
- int win2k_compat;
+ int win2k_compat, type;
win2k_compat = krb5_config_get_bool_default(context, NULL,
FALSE,
@@ -863,45 +796,18 @@ _krb5_pk_mk_padata(krb5_context context,
win2k_compat = 1;
if (win2k_compat) {
- ret = pk_mk_padata(context, COMPAT_WIN2K, ctx, req_body, nonce, md);
- if (ret)
- goto out;
- } else {
-#if 0
- ret = pk_mk_padata(context, COMPAT_19, ctx, req_body, nonce, md);
- if (ret)
- goto out;
-#endif
- ret = pk_mk_padata(context, COMPAT_27, ctx, req_body, nonce, md);
- if (ret)
- goto out;
- }
-
- provisioning_server =
- krb5_config_get_string(context, NULL,
- "realms",
- req_body->realm,
- "packet-cable-provisioning-server",
- NULL);
-
- if (provisioning_server) {
- /* PacketCable requires the PROV-SRV-LOCATION authenticator */
- const PROV_SRV_LOCATION prov_server = rk_UNCONST(provisioning_server);
-
- ASN1_MALLOC_ENCODE(PROV_SRV_LOCATION, buf.data, buf.length,
- &prov_server, &size, ret);
- if (ret)
- goto out;
- if (buf.length != size)
- krb5_abortx(context, "Internal ASN1 encoder error");
+ ctx->require_binding =
+ krb5_config_get_bool_default(context, NULL,
+ FALSE,
+ "realms",
+ req_body->realm,
+ "win2k_pkinit_require_binding",
+ NULL);
+ type = COMPAT_WIN2K;
+ } else
+ type = COMPAT_IETF;
- /* PacketCable uses -1 (application specific) as the auth data type */
- ret = krb5_padata_add(context, md, -1, buf.data, buf.length);
- if (ret)
- free(buf.data);
- }
- out:
- return ret;
+ return pk_mk_padata(context, type, ctx, req_body, nonce, md);
}
static krb5_boolean
@@ -997,7 +903,7 @@ pk_verify_chain_standard(krb5_context context,
int i;
int ret;
- ret = KRB5_KDC_ERROR_CLIENT_NAME_MISMATCH;
+ ret = KRB5_KDC_ERR_CLIENT_NAME_MISMATCH;
for (i = 0; i < sk_X509_num(chain); i++) {
cert = sk_X509_value(chain, i);
if (pk_peer_compare(context, client, cert) == TRUE) {
@@ -1037,7 +943,7 @@ pk_verify_chain_standard(krb5_context context,
ret = 0;
break;
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
- ret = KRB5_KDC_ERROR_CANT_VERIFY_CERTIFICATE;
+ ret = KRB5_KDC_ERR_CANT_VERIFY_CERTIFICATE;
krb5_set_error_string(context, "PKINIT: failed to verify "
"certificate: %s ",
X509_verify_cert_error_string(store_ctx->error));
@@ -1048,7 +954,7 @@ pk_verify_chain_standard(krb5_context context,
case X509_V_ERR_CERT_NOT_YET_VALID:
case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
case X509_V_ERR_CERT_HAS_EXPIRED:
- ret = KRB5_KDC_ERROR_INVALID_CERTIFICATE;
+ ret = KRB5_KDC_ERR_INVALID_CERTIFICATE;
krb5_set_error_string(context, "PKINIT: invalid certificate: %s ",
X509_verify_cert_error_string(store_ctx->error));
break;
@@ -1058,13 +964,13 @@ pk_verify_chain_standard(krb5_context context,
case X509_V_ERR_CERT_CHAIN_TOO_LONG:
case X509_V_ERR_PATH_LENGTH_EXCEEDED:
case X509_V_ERR_INVALID_CA:
- ret = KRB5_KDC_ERROR_INVALID_CERTIFICATE;
+ ret = KRB5_KDC_ERR_INVALID_CERTIFICATE;
krb5_set_error_string(context, "PKINIT: unknown CA or can't "
"verify certificate: %s",
X509_verify_cert_error_string(store_ctx->error));
break;
default:
- ret = KRB5_KDC_ERROR_INVALID_CERTIFICATE; /* XXX */
+ ret = KRB5_KDC_ERR_INVALID_CERTIFICATE; /* XXX */
krb5_set_error_string(context, "PKINIT: failed to verify "
"certificate: %s (%ld) ",
X509_verify_cert_error_string(store_ctx->error),
@@ -1131,7 +1037,7 @@ cert_to_X509(krb5_context context, CertificateSet *set,
krb5_error_code KRB5_LIB_FUNCTION
_krb5_pk_verify_sign(krb5_context context,
- const char *data,
+ const void *data,
size_t length,
struct krb5_pk_identity *id,
heim_oid *contentType,
@@ -1280,41 +1186,41 @@ _krb5_pk_verify_sign(krb5_context context,
}
static krb5_error_code
-get_reply_key_19(krb5_context context,
- const krb5_data *content,
- unsigned nonce,
- krb5_keyblock **key)
+get_reply_key_win(krb5_context context,
+ const krb5_data *content,
+ unsigned nonce,
+ krb5_keyblock **key)
{
- ReplyKeyPack_19 key_pack;
+ ReplyKeyPack_Win2k key_pack;
krb5_error_code ret;
size_t size;
- ret = decode_ReplyKeyPack_19(content->data,
- content->length,
- &key_pack,
- &size);
+ ret = decode_ReplyKeyPack_Win2k(content->data,
+ content->length,
+ &key_pack,
+ &size);
if (ret) {
krb5_set_error_string(context, "PKINIT decoding reply key failed");
- free_ReplyKeyPack_19(&key_pack);
+ free_ReplyKeyPack_Win2k(&key_pack);
return ret;
}
if (key_pack.nonce != nonce) {
krb5_set_error_string(context, "PKINIT enckey nonce is wrong");
- free_ReplyKeyPack_19(&key_pack);
+ free_ReplyKeyPack_Win2k(&key_pack);
return KRB5KRB_AP_ERR_MODIFIED;
}
*key = malloc (sizeof (**key));
if (*key == NULL) {
krb5_set_error_string(context, "PKINIT failed allocating reply key");
- free_ReplyKeyPack_19(&key_pack);
+ free_ReplyKeyPack_Win2k(&key_pack);
krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
}
ret = copy_EncryptionKey(&key_pack.replyKey, *key);
- free_ReplyKeyPack_19(&key_pack);
+ free_ReplyKeyPack_Win2k(&key_pack);
if (ret) {
krb5_set_error_string(context, "PKINIT failed copying reply key");
free(*key);
@@ -1399,6 +1305,7 @@ pk_rd_pa_reply_enckey(krb5_context context,
ContentInfo *rep,
krb5_pk_init_ctx ctx,
krb5_enctype etype,
+ const krb5_krbhst_info *hi,
unsigned nonce,
const krb5_data *req_buffer,
PA_DATA *pa,
@@ -1413,7 +1320,7 @@ pk_rd_pa_reply_enckey(krb5_context context,
int length;
size_t size;
X509 *user_cert;
- char *p;
+ void *p;
krb5_boolean bret;
krb5_data content;
heim_oid contentType = { 0, NULL };
@@ -1481,13 +1388,13 @@ pk_rd_pa_reply_enckey(krb5_context context,
goto out;
- /* verify content type */
- if (type == COMPAT_WIN2K) {
- if (heim_oid_cmp(&ed.encryptedContentInfo.contentType, oid_id_pkcs7_data())) {
- ret = KRB5KRB_AP_ERR_MSG_TYPE;
- goto out;
- }
- } else {
+ /*
+ * Try to verify content type. We can't do this for W2K case
+ * because W2K/W2K3 sends id-pkcs7-data, but Windows Vista sends
+ * id-pkcs7-signedData to all versions, even W2K clients.
+ */
+
+ if (type != COMPAT_WIN2K) {
if (heim_oid_cmp(&ed.encryptedContentInfo.contentType, oid_id_pkcs7_signedData())) {
ret = KRB5KRB_AP_ERR_MSG_TYPE;
goto out;
@@ -1563,7 +1470,7 @@ pk_rd_pa_reply_enckey(krb5_context context,
}
p = ci.content->data;
length = ci.content->length;
- }
+ }
ret = _krb5_pk_verify_sign(context,
p,
@@ -1582,6 +1489,7 @@ pk_rd_pa_reply_enckey(krb5_context context,
goto out;
}
+#if 0
if (type == COMPAT_WIN2K) {
if (heim_oid_cmp(&contentType, oid_id_pkcs7_data()) != 0) {
krb5_set_error_string(context, "PKINIT: reply key, wrong oid");
@@ -1595,13 +1503,15 @@ pk_rd_pa_reply_enckey(krb5_context context,
goto out;
}
}
+#endif
switch(type) {
case COMPAT_WIN2K:
- case COMPAT_19:
- ret = get_reply_key_19(context, &content, nonce, key);
+ ret = get_reply_key(context, &content, req_buffer, key);
+ if (ret != 0 && ctx->require_binding == 0)
+ ret = get_reply_key_win(context, &content, nonce, key);
break;
- case COMPAT_27:
+ case COMPAT_IETF:
ret = get_reply_key(context, &content, req_buffer, key);
break;
}
@@ -1628,6 +1538,7 @@ pk_rd_pa_reply_dh(krb5_context context,
ContentInfo *rep,
krb5_pk_init_ctx ctx,
krb5_enctype etype,
+ const krb5_krbhst_info *hi,
const DHNonce *c_n,
const DHNonce *k_n,
unsigned nonce,
@@ -1674,7 +1585,8 @@ pk_rd_pa_reply_dh(krb5_context context,
goto out;
if (heim_oid_cmp(&contentType, oid_id_pkdhkeydata())) {
- ret = KRB5KRB_AP_ERR_MSG_TYPE; /* XXX */
+ krb5_set_error_string(context, "pkinit - dh reply contains wrong oid");
+ ret = KRB5KRB_AP_ERR_MSG_TYPE;
goto out;
}
@@ -1799,6 +1711,7 @@ krb5_error_code KRB5_LIB_FUNCTION
_krb5_pk_rd_pa_reply(krb5_context context,
void *c,
krb5_enctype etype,
+ const krb5_krbhst_info *hi,
unsigned nonce,
const krb5_data *req_buffer,
PA_DATA *pa,
@@ -1836,8 +1749,10 @@ _krb5_pk_rd_pa_reply(krb5_context context,
free_PA_PK_AS_REP(&rep);
break;
}
- ret = pk_rd_pa_reply_dh(context, &ci, ctx,
- etype, NULL, NULL, nonce, pa, key);
+ ret = pk_rd_pa_reply_dh(context, &ci, ctx, etype, hi,
+ ctx->clientDHNonce,
+ rep.u.dhInfo.serverDHNonce,
+ nonce, pa, key);
free_ContentInfo(&ci);
free_PA_PK_AS_REP(&rep);
@@ -1854,8 +1769,8 @@ _krb5_pk_rd_pa_reply(krb5_context context,
"ContentInfo: %d", ret);
break;
}
- ret = pk_rd_pa_reply_enckey(context, COMPAT_27, &ci, ctx,
- etype, nonce, req_buffer, pa, key);
+ ret = pk_rd_pa_reply_enckey(context, COMPAT_IETF, &ci, ctx,
+ etype, hi, nonce, req_buffer, pa, key);
free_ContentInfo(&ci);
return ret;
default:
@@ -1869,40 +1784,6 @@ _krb5_pk_rd_pa_reply(krb5_context context,
return ret;
}
- /* Check for PK-INIT -19 */
- {
- PA_PK_AS_REP_19 rep19;
-
- memset(&rep19, 0, sizeof(rep19));
-
- ret = decode_PA_PK_AS_REP_19(pa->padata_value.data,
- pa->padata_value.length,
- &rep19,
- &size);
- if (ret == 0) {
- switch(rep19.element) {
- case choice_PA_PK_AS_REP_19_dhSignedData:
- ret = pk_rd_pa_reply_dh(context, &rep19.u.dhSignedData, ctx,
- etype, NULL, NULL,
- nonce, pa, key);
- break;
- case choice_PA_PK_AS_REP_19_encKeyPack:
- ret = pk_rd_pa_reply_enckey(context, COMPAT_19,
- &rep19.u.encKeyPack, ctx,
- etype, nonce, NULL, pa, key);
- break;
- default:
- krb5_set_error_string(context, "PKINIT: -19 reply invalid "
- "content type");
- ret = EINVAL;
- break;
- }
- free_PA_PK_AS_REP_19(&rep19);
- if (ret == 0)
- return 0;
- }
- }
-
/* Check for Windows encoding of the AS-REP pa data */
{
PA_PK_AS_REP_Win2k w2krep;
@@ -1918,6 +1799,8 @@ _krb5_pk_rd_pa_reply(krb5_context context,
"pkinit reply %d", ret);
return ret;
}
+
+ krb5_clear_error_string(context);
switch (w2krep.element) {
case choice_PA_PK_AS_REP_Win2k_encKeyPack:
@@ -1934,7 +1817,7 @@ _krb5_pk_rd_pa_reply(krb5_context context,
return ret;
}
ret = pk_rd_pa_reply_enckey(context, COMPAT_WIN2K, &ci, ctx,
- etype, nonce, NULL, pa, key);
+ etype, hi, nonce, NULL, pa, key);
free_ContentInfo(&ci);
break;
default:
@@ -2546,6 +2429,264 @@ _krb5_pk_load_openssl_id(krb5_context context,
return ret;
}
+static int
+parse_integer(krb5_context context, char **p, const char *file, int lineno,
+ const char *name, heim_integer *integer)
+{
+ int ret;
+ char *p1;
+ p1 = strsep(p, " \t");
+ if (p1 == NULL) {
+ krb5_set_error_string(context, "moduli file %s missing %s on line %d",
+ file, name, lineno);
+ return EINVAL;
+ }
+ ret = der_parse_hex_heim_integer(p1, integer);
+ if (ret) {
+ krb5_set_error_string(context, "moduli file %s failed parsing %s "
+ "on line %d",
+ file, name, lineno);
+ return ret;
+ }
+
+ return 0;
+}
+
+krb5_error_code
+_krb5_parse_moduli_line(krb5_context context,
+ const char *file,
+ int lineno,
+ char *p,
+ struct krb5_dh_moduli **m)
+{
+ struct krb5_dh_moduli *m1;
+ char *p1;
+ int ret;
+
+ *m = NULL;
+
+ m1 = calloc(1, sizeof(*m1));
+ if (m1 == NULL) {
+ krb5_set_error_string(context, "malloc - out of memory");
+ return ENOMEM;
+ }
+
+ while (isspace((unsigned char)*p))
+ p++;
+ if (*p == '#')
+ return 0;
+ ret = EINVAL;
+
+ p1 = strsep(&p, " \t");
+ if (p1 == NULL) {
+ krb5_set_error_string(context, "moduli file %s missing name "
+ "on line %d", file, lineno);
+ goto out;
+ }
+ m1->name = strdup(p1);
+ if (p1 == NULL) {
+ krb5_set_error_string(context, "malloc - out of memeory");
+ ret = ENOMEM;
+ goto out;
+ }
+
+ p1 = strsep(&p, " \t");
+ if (p1 == NULL) {
+ krb5_set_error_string(context, "moduli file %s missing bits on line %d",
+ file, lineno);
+ goto out;
+ }
+
+ m1->bits = atoi(p1);
+ if (m1->bits == 0) {
+ krb5_set_error_string(context, "moduli file %s have un-parsable "
+ "bits on line %d", file, lineno);
+ goto out;
+ }
+
+ ret = parse_integer(context, &p, file, lineno, "p", &m1->p);
+ if (ret)
+ goto out;
+ ret = parse_integer(context, &p, file, lineno, "g", &m1->g);
+ if (ret)
+ goto out;
+ ret = parse_integer(context, &p, file, lineno, "q", &m1->q);
+ if (ret)
+ goto out;
+
+ *m = m1;
+
+ return 0;
+out:
+ free(m1->name);
+ free_heim_integer(&m1->p);
+ free_heim_integer(&m1->g);
+ free_heim_integer(&m1->q);
+ free(m1);
+ return ret;
+}
+
+static void
+_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);
+ free(moduli[i]);
+ }
+ free(moduli);
+}
+
+static const char *default_moduli =
+ /* bits */
+ "RFC2412-MODP-group2 "
+ "1024 "
+ /* p */
+ "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
+ "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
+ "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
+ "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
+ "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
+ "FFFFFFFF" "FFFFFFFF "
+ /* g */
+ "02 "
+ /* q */
+ "7FFFFFFF" "FFFFFFFF" "E487ED51" "10B4611A" "62633145" "C06E0E68"
+ "94812704" "4533E63A" "0105DF53" "1D89CD91" "28A5043C" "C71A026E"
+ "F7CA8CD9" "E69D218D" "98158536" "F92F8A1B" "A7F09AB6" "B6A8E122"
+ "F242DABB" "312F3F63" "7A262174" "D31BF6B5" "85FFAE5B" "7A035BF6"
+ "F71C35FD" "AD44CFD2" "D74F9208" "BE258FF3" "24943328" "F67329C0"
+ "FFFFFFFF" "FFFFFFFF";
+
+
+krb5_error_code
+_krb5_parse_moduli(krb5_context context, const char *file,
+ struct krb5_dh_moduli ***moduli)
+{
+ /* comment bits P G Q */
+ krb5_error_code ret;
+ struct krb5_dh_moduli **m = NULL, **m2;
+ char buf[4096];
+ FILE *f;
+ int lineno = 0, n = 0;
+
+ *moduli = NULL;
+
+ m = calloc(1, sizeof(m[0]) * 2);
+ if (m == NULL) {
+ krb5_set_error_string(context, "malloc: out of memory");
+ return ENOMEM;
+ }
+
+ strlcpy(buf, default_moduli, sizeof(buf));
+ ret = _krb5_parse_moduli_line(context, "builtin", 1, buf, &m[0]);
+ if (ret) {
+ _krb5_free_moduli(m);
+ return ret;
+ }
+ n = 1;
+
+ if (file == NULL) {
+ *moduli = m;
+ return 0;
+ }
+
+ f = fopen(file, "r");
+ if (f == NULL) {
+ *moduli = m;
+ return 0;
+ }
+
+ while(fgets(buf, sizeof(buf), f) != NULL) {
+ struct krb5_dh_moduli *element;
+
+ buf[strcspn(buf, "\n")] = '\0';
+ lineno++;
+
+ m2 = realloc(m, (n + 2) * sizeof(m[0]));
+ if (m2 == NULL) {
+ krb5_set_error_string(context, "malloc: out of memory");
+ _krb5_free_moduli(m);
+ return ENOMEM;
+ }
+ m = m2;
+
+ m[n] = NULL;
+
+ ret = _krb5_parse_moduli_line(context, file, lineno, buf, &element);
+ if (ret) {
+ _krb5_free_moduli(m);
+ return ret;
+ }
+ if (element == NULL)
+ continue;
+
+ m[n] = element;
+ m[n + 1] = NULL;
+ n++;
+ }
+ *moduli = m;
+ return 0;
+}
+
+krb5_error_code
+_krb5_dh_group_ok(krb5_context context, unsigned long bits,
+ heim_integer *p, heim_integer *g, heim_integer *q,
+ struct krb5_dh_moduli **moduli,
+ char **name)
+{
+ int i;
+
+ if (name)
+ *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 &&
+ heim_integer_cmp(&moduli[i]->q, q) == 0)
+ {
+ if (bits && bits > moduli[i]->bits) {
+ krb5_set_error_string(context, "PKINIT: DH group parameter %s "
+ "no accepted, not enough bits generated",
+ moduli[i]->name);
+ return KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED;
+ }
+ if (name)
+ *name = strdup(moduli[i]->name);
+ return 0;
+ }
+ }
+ krb5_set_error_string(context, "PKINIT: DH group parameter no ok");
+ return KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED;
+}
+
+static krb5_error_code
+select_dh_group(krb5_context context, DH *dh, unsigned long bits,
+ struct krb5_dh_moduli **moduli)
+{
+ const struct krb5_dh_moduli *m;
+
+ m = moduli[1]; /* XXX */
+ if (m == NULL)
+ m = moduli[0]; /* XXX */
+
+ dh->p = integer_to_BN(context, "p", &m->p);
+ if (dh->p == NULL)
+ return ENOMEM;
+ dh->g = integer_to_BN(context, "g", &m->g);
+ if (dh->g == NULL)
+ return ENOMEM;
+ dh->q = integer_to_BN(context, "q", &m->q);
+ if (dh->q == NULL)
+ return ENOMEM;
+
+ return 0;
+}
+
+
#endif /* PKINIT */
void KRB5_LIB_FUNCTION
@@ -2554,9 +2695,9 @@ _krb5_get_init_creds_opt_free_pkinit(krb5_get_init_creds_opt *opt)
#ifdef PKINIT
krb5_pk_init_ctx ctx;
- if (opt->private == NULL || opt->private->pk_init_ctx == NULL)
+ if (opt->opt_private == NULL || opt->opt_private->pk_init_ctx == NULL)
return;
- ctx = opt->private->pk_init_ctx;
+ ctx = opt->opt_private->pk_init_ctx;
if (ctx->dh)
DH_free(ctx->dh);
ctx->dh = NULL;
@@ -2572,10 +2713,16 @@ _krb5_get_init_creds_opt_free_pkinit(krb5_get_init_creds_opt *opt)
ENGINE_free(ctx->id->engine);
ctx->id->engine = NULL;
}
+ if (ctx->clientDHNonce) {
+ krb5_free_data(NULL, ctx->clientDHNonce);
+ ctx->clientDHNonce = NULL;
+ }
+ if (ctx->m)
+ _krb5_free_moduli(ctx->m);
free(ctx->id);
ctx->id = NULL;
}
- opt->private->pk_init_ctx = NULL;
+ opt->opt_private->pk_init_ctx = NULL;
#endif
}
@@ -2593,79 +2740,73 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context,
#ifdef PKINIT
krb5_error_code ret;
- if (opt->private == NULL) {
+ if (opt->opt_private == NULL) {
krb5_set_error_string(context, "PKINIT: on non extendable opt");
return EINVAL;
}
- opt->private->pk_init_ctx = malloc(sizeof(*opt->private->pk_init_ctx));
- if (opt->private->pk_init_ctx == NULL) {
+ opt->opt_private->pk_init_ctx =
+ calloc(1, sizeof(*opt->opt_private->pk_init_ctx));
+ if (opt->opt_private->pk_init_ctx == NULL) {
krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
}
- opt->private->pk_init_ctx->dh = NULL;
- opt->private->pk_init_ctx->id = NULL;
+ opt->opt_private->pk_init_ctx->dh = NULL;
+ opt->opt_private->pk_init_ctx->id = NULL;
+ opt->opt_private->pk_init_ctx->clientDHNonce = NULL;
+ opt->opt_private->pk_init_ctx->require_binding = 0;
+
ret = _krb5_pk_load_openssl_id(context,
- &opt->private->pk_init_ctx->id,
+ &opt->opt_private->pk_init_ctx->id,
user_id,
x509_anchors,
prompter,
prompter_data,
password);
if (ret) {
- free(opt->private->pk_init_ctx);
- opt->private->pk_init_ctx = NULL;
+ free(opt->opt_private->pk_init_ctx);
+ opt->opt_private->pk_init_ctx = NULL;
+ return ret;
}
- /* XXX */
- if (ret == 0 && (flags & 1) && !(flags & 2)) {
- DH *dh;
- const char *P =
- "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
- "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
- "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
- "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
- "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
- "FFFFFFFF" "FFFFFFFF";
- const char *G = "2";
- const char *Q =
- "7FFFFFFF" "FFFFFFFF" "E487ED51" "10B4611A" "62633145" "C06E0E68"
- "94812704" "4533E63A" "0105DF53" "1D89CD91" "28A5043C" "C71A026E"
- "F7CA8CD9" "E69D218D" "98158536" "F92F8A1B" "A7F09AB6" "B6A8E122"
- "F242DABB" "312F3F63" "7A262174" "D31BF6B5" "85FFAE5B" "7A035BF6"
- "F71C35FD" "AD44CFD2" "D74F9208" "BE258FF3" "24943328" "F67329C0"
- "FFFFFFFF" "FFFFFFFF";
-
- dh = DH_new();
- if (dh == NULL) {
- krb5_set_error_string(context, "malloc: out of memory");
- _krb5_get_init_creds_opt_free_pkinit(opt);
- return ENOMEM;
- }
- opt->private->pk_init_ctx->dh = dh;
- if (!BN_hex2bn(&dh->p, P)) {
- krb5_set_error_string(context, "malloc: out of memory");
+ if ((flags & 2) == 0) {
+ const char *moduli_file;
+
+ moduli_file = krb5_config_get_string_default(context, NULL,
+ MODULI_FILE,
+ "libdefaults",
+ "moduli",
+ NULL);
+
+ ret = _krb5_parse_moduli(context, moduli_file,
+ &opt->opt_private->pk_init_ctx->m);
+ if (ret) {
_krb5_get_init_creds_opt_free_pkinit(opt);
- return ENOMEM;
+ return ret;
}
- if (!BN_hex2bn(&dh->g, G)) {
+
+ opt->opt_private->pk_init_ctx->dh = DH_new();
+ if (opt->opt_private->pk_init_ctx->dh == NULL) {
krb5_set_error_string(context, "malloc: out of memory");
_krb5_get_init_creds_opt_free_pkinit(opt);
return ENOMEM;
}
- if (!BN_hex2bn(&dh->q, Q)) {
- krb5_set_error_string(context, "malloc: out of memory");
+
+ ret = select_dh_group(context, opt->opt_private->pk_init_ctx->dh, 0,
+ opt->opt_private->pk_init_ctx->m);
+ if (ret) {
_krb5_get_init_creds_opt_free_pkinit(opt);
- return ENOMEM;
+ return ret;
}
- /* XXX generate a new key for each request ? */
- if (DH_generate_key(dh) != 1) {
+
+ if (DH_generate_key(opt->opt_private->pk_init_ctx->dh) != 1) {
krb5_set_error_string(context, "malloc: out of memory");
_krb5_get_init_creds_opt_free_pkinit(opt);
return ENOMEM;
}
}
- return ret;
+
+ return 0;
#else
krb5_set_error_string(context, "no support for PKINIT compiled in");
return EINVAL;
diff --git a/source4/heimdal/lib/krb5/rd_cred.c b/source4/heimdal/lib/krb5/rd_cred.c
index 2571591e9d..ddd5866aeb 100644
--- a/source4/heimdal/lib/krb5/rd_cred.c
+++ b/source4/heimdal/lib/krb5/rd_cred.c
@@ -33,7 +33,7 @@
#include <krb5_locl.h>
-RCSID("$Id: rd_cred.c,v 1.24 2005/07/13 08:22:50 lha Exp $");
+RCSID("$Id: rd_cred.c,v 1.25 2005/09/23 03:37:57 lha Exp $");
static krb5_error_code
compare_addrs(krb5_context context,
@@ -99,24 +99,49 @@ krb5_rd_cred(krb5_context context,
enc_krb_cred_part_data.length = cred.enc_part.cipher.length;
enc_krb_cred_part_data.data = cred.enc_part.cipher.data;
} else {
- if (auth_context->remote_subkey)
+ /* Try both subkey and session key.
+ *
+ * RFC2140 claims we should use the session key, but Heimdal
+ * before 0.8 used the remote subkey if it was send in the
+ * auth_context.
+ */
+
+ if (auth_context->remote_subkey) {
ret = krb5_crypto_init(context, auth_context->remote_subkey,
0, &crypto);
- else
+ if (ret)
+ goto out;
+
+ ret = krb5_decrypt_EncryptedData(context,
+ crypto,
+ KRB5_KU_KRB_CRED,
+ &cred.enc_part,
+ &enc_krb_cred_part_data);
+
+ krb5_crypto_destroy(context, crypto);
+ }
+
+ /*
+ * If there was not subkey, or we failed using subkey,
+ * retry using the session key
+ */
+ if (auth_context->remote_subkey == NULL || ret == KRB5KRB_AP_ERR_BAD_INTEGRITY)
+ {
+
ret = krb5_crypto_init(context, auth_context->keyblock,
0, &crypto);
- /* DK: MIT rsh */
- if (ret)
- goto out;
-
- ret = krb5_decrypt_EncryptedData(context,
- crypto,
- KRB5_KU_KRB_CRED,
- &cred.enc_part,
- &enc_krb_cred_part_data);
-
- krb5_crypto_destroy(context, crypto);
+ if (ret)
+ goto out;
+
+ ret = krb5_decrypt_EncryptedData(context,
+ crypto,
+ KRB5_KU_KRB_CRED,
+ &cred.enc_part,
+ &enc_krb_cred_part_data);
+
+ krb5_crypto_destroy(context, crypto);
+ }
if (ret)
goto out;
}
diff --git a/source4/heimdal/lib/roken/roken-common.h b/source4/heimdal/lib/roken/roken-common.h
index c4ba2edb7c..8368530ff7 100644
--- a/source4/heimdal/lib/roken/roken-common.h
+++ b/source4/heimdal/lib/roken/roken-common.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-/* $Id: roken-common.h,v 1.62 2005/09/01 18:47:35 lha Exp $ */
+/* $Id: roken-common.h,v 1.64 2005/09/28 03:05:58 lha Exp $ */
#ifndef __ROKEN_COMMON_H__
#define __ROKEN_COMMON_H__
@@ -258,8 +258,6 @@
#define __attribute__(x)
#endif
-#define rk_UNCONST(x) ((void *)(unsigned long)(const void *)(x))
-
ROKEN_CPP_START
#ifndef IRIX4 /* fix for compiler bug */
@@ -396,6 +394,8 @@ rk_strpoolprintf(struct rk_strpool *, const char *, ...)
void ROKEN_LIB_FUNCTION
rk_strpoolfree(struct rk_strpool *);
+void ROKEN_LIB_FUNCTION
+rk_dumpdata (const char *, const void *, size_t);
ROKEN_CPP_END
diff --git a/source4/heimdal/lib/roken/roken.h b/source4/heimdal/lib/roken/roken.h
index 04553caf48..853de9b112 100644
--- a/source4/heimdal/lib/roken/roken.h
+++ b/source4/heimdal/lib/roken/roken.h
@@ -32,11 +32,14 @@
* SUCH DAMAGE.
*/
-/* $Id: roken.h.in,v 1.177 2005/08/05 09:06:29 lha Exp $ */
+/* $Id: roken.h.in,v 1.178 2005/09/28 03:04:54 lha Exp $ */
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
#include <string.h>
#include <signal.h>
@@ -138,6 +141,12 @@ typedef int ssize_t;
ROKEN_CPP_START
+#ifdef HAVE_UINTPTR_T
+#define rk_UNCONST(x) ((void *)(uintptr_t)(const void *)(x))
+#else
+#define rk_UNCONST(x) ((void *)(unsigned long)(const void *)(x))
+#endif
+
#if !defined(HAVE_SETSID) && defined(HAVE__SETSID)
#define setsid _setsid
#endif