From c33f6b2c370379dfd010600adc59e7439f1318f7 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 24 Apr 2006 09:36:24 +0000 Subject: r15192: Update Samba4 to use current lorikeet-heimdal. Andrew Bartlett (This used to be commit f0e538126c5cb29ca14ad0d8281eaa0a715ed94f) --- source4/heimdal/lib/krb5/acache.c | 64 +- source4/heimdal/lib/krb5/addr_families.c | 3 +- source4/heimdal/lib/krb5/build_auth.c | 11 +- source4/heimdal/lib/krb5/cache.c | 5 +- source4/heimdal/lib/krb5/config_file.c | 4 +- source4/heimdal/lib/krb5/crypto.c | 6 +- source4/heimdal/lib/krb5/data.c | 3 +- source4/heimdal/lib/krb5/fcache.c | 7 +- source4/heimdal/lib/krb5/get_for_creds.c | 7 +- source4/heimdal/lib/krb5/init_creds.c | 4 +- source4/heimdal/lib/krb5/init_creds_pw.c | 29 +- source4/heimdal/lib/krb5/keytab_any.c | 33 +- source4/heimdal/lib/krb5/keytab_file.c | 40 +- source4/heimdal/lib/krb5/keytab_keyfile.c | 3 +- source4/heimdal/lib/krb5/keytab_krb4.c | 13 +- source4/heimdal/lib/krb5/krb5-private.h | 14 +- source4/heimdal/lib/krb5/krb5-protos.h | 2 + source4/heimdal/lib/krb5/krb5_ccapi.h | 21 +- source4/heimdal/lib/krb5/krbhst.c | 7 +- source4/heimdal/lib/krb5/log.c | 8 +- source4/heimdal/lib/krb5/pkinit.c | 1732 ++++++----------------------- source4/heimdal/lib/krb5/principal.c | 22 +- source4/heimdal/lib/krb5/rd_cred.c | 7 +- source4/heimdal/lib/krb5/rd_priv.c | 8 +- source4/heimdal/lib/krb5/rd_req.c | 25 +- source4/heimdal/lib/krb5/replay.c | 10 +- source4/heimdal/lib/krb5/send_to_kdc.c | 5 +- source4/heimdal/lib/krb5/store.c | 23 +- source4/heimdal/lib/krb5/transited.c | 11 +- source4/heimdal/lib/krb5/v4_glue.c | 19 +- 30 files changed, 594 insertions(+), 1552 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/acache.c b/source4/heimdal/lib/krb5/acache.c index 7cf2c65d89..b38104fc2d 100644 --- a/source4/heimdal/lib/krb5/acache.c +++ b/source4/heimdal/lib/krb5/acache.c @@ -37,7 +37,7 @@ #include #endif -RCSID("$Id: acache.c,v 1.14 2005/10/03 08:44:18 lha Exp $"); +RCSID("$Id: acache.c,v 1.15 2006/03/27 04:22:23 lha Exp $"); /* XXX should we fetch these for each open ? */ static HEIMDAL_MUTEX acc_mutex = HEIMDAL_MUTEX_INITIALIZER; @@ -218,7 +218,36 @@ make_cred_from_ccred(krb5_context context, } } - cred->flags.b = int2TicketFlags(incred->ticket_flags); /* XXX */ + cred->flags.i = 0; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_FORWARDABLE) + cred->flags.b.forwardable = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_FORWARDED) + cred->flags.b.forwarded = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_PROXIABLE) + cred->flags.b.proxiable = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_PROXY) + cred->flags.b.proxy = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_MAY_POSTDATE) + cred->flags.b.may_postdate = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_POSTDATED) + cred->flags.b.postdated = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_INVALID) + cred->flags.b.invalid = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_RENEWABLE) + cred->flags.b.renewable = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_INITIAL) + cred->flags.b.initial = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_PRE_AUTH) + cred->flags.b.pre_authent = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_HW_AUTH) + cred->flags.b.hw_authent = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_TRANSIT_POLICY_CHECKED) + cred->flags.b.transited_policy_checked = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_OK_AS_DELEGATE) + cred->flags.b.ok_as_delegate = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_ANONYMOUS) + cred->flags.b.anonymous = 1; + return 0; nomem: @@ -310,7 +339,36 @@ make_ccred_from_cred(krb5_context context, } cred->addresses[i] = NULL; - cred->ticket_flags = TicketFlags2int(incred->flags.b); /* XXX */ + cred->ticket_flags = 0; + if (incred->flags.b.forwardable) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_FORWARDABLE; + if (incred->flags.b.forwarded) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_FORWARDED; + if (incred->flags.b.proxiable) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_PROXIABLE; + if (incred->flags.b.proxy) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_PROXY; + if (incred->flags.b.may_postdate) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_MAY_POSTDATE; + if (incred->flags.b.postdated) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_POSTDATED; + if (incred->flags.b.invalid) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_INVALID; + if (incred->flags.b.renewable) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_RENEWABLE; + if (incred->flags.b.initial) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_INITIAL; + if (incred->flags.b.pre_authent) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_PRE_AUTH; + if (incred->flags.b.hw_authent) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_HW_AUTH; + if (incred->flags.b.transited_policy_checked) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_TRANSIT_POLICY_CHECKED; + if (incred->flags.b.ok_as_delegate) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_OK_AS_DELEGATE; + if (incred->flags.b.anonymous) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_ANONYMOUS; + return 0; fail: diff --git a/source4/heimdal/lib/krb5/addr_families.c b/source4/heimdal/lib/krb5/addr_families.c index cf460ba725..ebdbcfed46 100644 --- a/source4/heimdal/lib/krb5/addr_families.c +++ b/source4/heimdal/lib/krb5/addr_families.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: addr_families.c,v 1.50 2006/03/17 22:12:13 lha Exp $"); +RCSID("$Id: addr_families.c,v 1.51 2006/04/02 02:17:31 lha Exp $"); struct addr_operations { int af; @@ -1136,6 +1136,7 @@ krb5_make_addrport (krb5_context context, if (ret) { krb5_set_error_string(context, "malloc: out of memory"); free (*res); + *res = NULL; return ret; } p = (*res)->address.data; diff --git a/source4/heimdal/lib/krb5/build_auth.c b/source4/heimdal/lib/krb5/build_auth.c index 1c38721b02..9eff09bb0a 100644 --- a/source4/heimdal/lib/krb5/build_auth.c +++ b/source4/heimdal/lib/krb5/build_auth.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: build_auth.c,v 1.42 2005/01/05 02:34:53 lukeh Exp $"); +RCSID("$Id: build_auth.c,v 1.43 2006/04/10 08:53:21 lha Exp $"); static krb5_error_code make_etypelist(krb5_context context, @@ -116,13 +116,12 @@ krb5_build_authenticator (krb5_context context, krb5_error_code ret; krb5_crypto crypto; - auth = malloc(sizeof(*auth)); + auth = calloc(1, sizeof(*auth)); if (auth == NULL) { krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } - memset (auth, 0, sizeof(*auth)); auth->authenticator_vno = 5; copy_Realm(&cred->client->realm, &auth->crealm); copy_PrincipalName(&cred->client->name, &auth->cname); @@ -161,10 +160,8 @@ krb5_build_authenticator (krb5_context context, /* XXX - Copy more to auth_context? */ - if (auth_context) { - auth_context->authenticator->ctime = auth->ctime; - auth_context->authenticator->cusec = auth->cusec; - } + auth_context->authenticator->ctime = auth->ctime; + auth_context->authenticator->cusec = auth->cusec; ASN1_MALLOC_ENCODE(Authenticator, buf, buf_size, auth, &len, ret); if (ret) diff --git a/source4/heimdal/lib/krb5/cache.c b/source4/heimdal/lib/krb5/cache.c index efb2ad1374..b21d42d653 100644 --- a/source4/heimdal/lib/krb5/cache.c +++ b/source4/heimdal/lib/krb5/cache.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: cache.c,v 1.77 2005/12/13 15:42:36 lha Exp $"); +RCSID("$Id: cache.c,v 1.79 2006/04/02 00:54:48 lha Exp $"); /* * Add a new ccache type with operations `ops', overwriting any @@ -316,7 +316,7 @@ _krb5_expand_default_cc_name(krb5_context context, const char *str, char **res) } if (append == NULL) { free(*res); - res = NULL; + *res = NULL; krb5_set_error_string(context, "malloc - out of memory"); return ENOMEM; } @@ -324,6 +324,7 @@ _krb5_expand_default_cc_name(krb5_context context, const char *str, char **res) tlen = strlen(append); tmp = realloc(*res, len + tlen + 1); if (tmp == NULL) { + free(append); free(*res); *res = NULL; krb5_set_error_string(context, "malloc - out of memory"); diff --git a/source4/heimdal/lib/krb5/config_file.c b/source4/heimdal/lib/krb5/config_file.c index 86e286c638..66051303ed 100644 --- a/source4/heimdal/lib/krb5/config_file.c +++ b/source4/heimdal/lib/krb5/config_file.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: config_file.c,v 1.53 2005/06/16 20:22:53 lha Exp $"); +RCSID("$Id: config_file.c,v 1.54 2006/04/02 00:59:19 lha Exp $"); #ifndef HAVE_NETINFO @@ -574,7 +574,7 @@ krb5_config_vget_strings(krb5_context context, } if(nstr){ char **tmp = realloc(strings, (nstr + 1) * sizeof(*strings)); - if(strings == NULL) + if(tmp == NULL) goto cleanup; strings = tmp; strings[nstr] = NULL; diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c index 039484c650..3a90995283 100644 --- a/source4/heimdal/lib/krb5/crypto.c +++ b/source4/heimdal/lib/krb5/crypto.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: crypto.c,v 1.133 2006/03/07 19:34:55 lha Exp $"); +RCSID("$Id: crypto.c,v 1.134 2006/04/10 08:58:53 lha Exp $"); #undef CRYPTO_DEBUG #ifdef CRYPTO_DEBUG @@ -4096,7 +4096,7 @@ krb5_string_to_key_derived(krb5_context context, struct encryption_type *et = _find_enctype(etype); krb5_error_code ret; struct key_data kd; - size_t keylen = et->keytype->bits / 8; + size_t keylen; u_char *tmp; if(et == NULL) { @@ -4104,6 +4104,8 @@ krb5_string_to_key_derived(krb5_context context, etype); return KRB5_PROG_ETYPE_NOSUPP; } + keylen = et->keytype->bits / 8; + ALLOC(kd.key, 1); if(kd.key == NULL) { krb5_set_error_string (context, "malloc: out of memory"); diff --git a/source4/heimdal/lib/krb5/data.c b/source4/heimdal/lib/krb5/data.c index 9cf1410e70..3192c4c64f 100644 --- a/source4/heimdal/lib/krb5/data.c +++ b/source4/heimdal/lib/krb5/data.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: data.c,v 1.19 2004/05/25 21:22:23 lha Exp $"); +RCSID("$Id: data.c,v 1.20 2006/04/02 01:06:07 lha Exp $"); void KRB5_LIB_FUNCTION krb5_data_zero(krb5_data *p) @@ -114,6 +114,7 @@ krb5_copy_data(krb5_context context, if(ret) { krb5_clear_error_string (context); free(*outdata); + *outdata = NULL; } return ret; } diff --git a/source4/heimdal/lib/krb5/fcache.c b/source4/heimdal/lib/krb5/fcache.c index f8ebe837b7..79b809d2a2 100644 --- a/source4/heimdal/lib/krb5/fcache.c +++ b/source4/heimdal/lib/krb5/fcache.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: fcache.c,v 1.51 2005/08/12 13:31:19 lha Exp $"); +RCSID("$Id: fcache.c,v 1.52 2006/04/02 01:04:37 lha Exp $"); typedef struct krb5_fcache{ char *filename; @@ -269,10 +269,11 @@ fcc_gen_new(krb5_context context, krb5_ccache *id) } fd = mkstemp(file); if(fd < 0) { + int ret = errno; + krb5_set_error_string(context, "mkstemp %s", file); free(f); free(file); - krb5_set_error_string(context, "mkstemp %s", file); - return errno; + return ret; } close(fd); f->filename = file; diff --git a/source4/heimdal/lib/krb5/get_for_creds.c b/source4/heimdal/lib/krb5/get_for_creds.c index dafe668b5d..661d05663b 100644 --- a/source4/heimdal/lib/krb5/get_for_creds.c +++ b/source4/heimdal/lib/krb5/get_for_creds.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: get_for_creds.c,v 1.48 2006/03/07 19:38:09 lha Exp $"); +RCSID("$Id: get_for_creds.c,v 1.49 2006/04/10 09:28:15 lha Exp $"); static krb5_error_code add_addrs(krb5_context context, @@ -180,10 +180,7 @@ krb5_get_forwarded_creds (krb5_context context, addrs.len = 0; addrs.val = NULL; - if (in_creds->client && in_creds->client->realm) - realm = in_creds->client->realm; - else - realm = in_creds->server->realm; + realm = in_creds->client->realm; krb5_appdefault_boolean(context, NULL, realm, "no-addresses-ever", TRUE, &noaddr_ever); diff --git a/source4/heimdal/lib/krb5/init_creds.c b/source4/heimdal/lib/krb5/init_creds.c index 316c2f02eb..88de280a00 100644 --- a/source4/heimdal/lib/krb5/init_creds.c +++ b/source4/heimdal/lib/krb5/init_creds.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: init_creds.c,v 1.22 2006/02/03 11:42:31 lha Exp $"); +RCSID("$Id: init_creds.c,v 1.23 2006/04/02 01:08:30 lha Exp $"); void KRB5_LIB_FUNCTION krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt) @@ -75,7 +75,7 @@ _krb5_get_init_creds_opt_copy(krb5_context context, krb5_get_init_creds_opt *opt; *out = NULL; - opt = malloc(sizeof(*opt)); + opt = calloc(1, sizeof(*opt)); if (opt == NULL) { krb5_set_error_string(context, "out of memory"); return ENOMEM; diff --git a/source4/heimdal/lib/krb5/init_creds_pw.c b/source4/heimdal/lib/krb5/init_creds_pw.c index 3c694624bf..489a88a31b 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.90 2005/10/12 12:45:11 lha Exp $"); +RCSID("$Id: init_creds_pw.c,v 1.92 2006/04/02 01:20:15 lha Exp $"); typedef struct krb5_get_init_creds_ctx { krb5_kdc_flags flags; @@ -79,8 +79,10 @@ default_s2k_func(krb5_context context, krb5_enctype type, return ENOMEM; ret = krb5_string_to_key_data_salt_opaque(context, type, password, salt, opaque, *key); - if (ret) + if (ret) { free(*key); + *key = NULL; + } return ret; } @@ -545,23 +547,14 @@ init_creds_init_as_req (krb5_context context, krb5_set_error_string(context, "malloc: out of memory"); goto fail; } - if (creds->client) { - ret = _krb5_principal2principalname (a->req_body.cname, creds->client); - if (ret) - goto fail; - ret = copy_Realm(&creds->client->realm, &a->req_body.realm); - if (ret) - goto fail; - } else { - krb5_realm realm; - a->req_body.cname = NULL; - ret = krb5_get_default_realm(context, &realm); - if (ret) - goto fail; - ret = copy_Realm(&realm, &a->req_body.realm); - free(realm); - } + ret = _krb5_principal2principalname (a->req_body.cname, creds->client); + if (ret) + goto fail; + ret = copy_Realm(&creds->client->realm, &a->req_body.realm); + if (ret) + goto fail; + ret = _krb5_principal2principalname (a->req_body.sname, creds->server); if (ret) goto fail; diff --git a/source4/heimdal/lib/krb5/keytab_any.c b/source4/heimdal/lib/krb5/keytab_any.c index 667788c69d..d5130aaad8 100644 --- a/source4/heimdal/lib/krb5/keytab_any.c +++ b/source4/heimdal/lib/krb5/keytab_any.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab_any.c,v 1.7 2002/10/21 13:36:59 joda Exp $"); +RCSID("$Id: keytab_any.c,v 1.8 2006/04/10 09:20:13 lha Exp $"); struct any_data { krb5_keytab kt; @@ -162,23 +162,22 @@ any_next_entry (krb5_context context, ret = krb5_kt_next_entry(context, ed->a->kt, entry, &ed->cursor); if (ret == 0) return 0; - else if (ret == KRB5_KT_END) { - ret2 = krb5_kt_end_seq_get (context, ed->a->kt, &ed->cursor); - if (ret2) - return ret2; - while ((ed->a = ed->a->next) != NULL) { - ret2 = krb5_kt_start_seq_get(context, ed->a->kt, &ed->cursor); - if (ret2 == 0) - break; - } - if (ed->a == NULL) { - krb5_clear_error_string (context); - return KRB5_KT_END; - } - } else + else if (ret != KRB5_KT_END) return ret; - } while (ret == KRB5_KT_END); - return ret; + + ret2 = krb5_kt_end_seq_get (context, ed->a->kt, &ed->cursor); + if (ret2) + return ret2; + while ((ed->a = ed->a->next) != NULL) { + ret2 = krb5_kt_start_seq_get(context, ed->a->kt, &ed->cursor); + if (ret2 == 0) + break; + } + if (ed->a == NULL) { + krb5_clear_error_string (context); + return KRB5_KT_END; + } + } while (1); } static krb5_error_code diff --git a/source4/heimdal/lib/krb5/keytab_file.c b/source4/heimdal/lib/krb5/keytab_file.c index 6ff2680ed1..f9a76e634a 100644 --- a/source4/heimdal/lib/krb5/keytab_file.c +++ b/source4/heimdal/lib/krb5/keytab_file.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab_file.c,v 1.20 2005/07/13 06:08:07 lha Exp $"); +RCSID("$Id: keytab_file.c,v 1.22 2006/04/07 21:57:31 lha Exp $"); #define KRB5_KT_VNO_1 1 #define KRB5_KT_VNO_2 2 @@ -164,7 +164,7 @@ krb5_kt_ret_principal(krb5_context context, int i; int ret; krb5_principal p; - int16_t tmp; + int16_t len; ALLOC(p, 1); if(p == NULL) { @@ -172,25 +172,34 @@ krb5_kt_ret_principal(krb5_context context, return ENOMEM; } - ret = krb5_ret_int16(sp, &tmp); - if(ret) - return ret; + ret = krb5_ret_int16(sp, &len); + if(ret) { + krb5_set_error_string(context, + "Failed decoding length of keytab principal"); + goto out; + } if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS)) - tmp--; - p->name.name_string.len = tmp; + len--; + if (len < 0) { + krb5_set_error_string(context, + "Keytab principal contains invalid length"); + ret = KRB5_KT_END; + goto out; + } ret = krb5_kt_ret_string(context, sp, &p->realm); if(ret) - return ret; - p->name.name_string.val = calloc(p->name.name_string.len, - sizeof(*p->name.name_string.val)); + goto out; + p->name.name_string.val = calloc(len, sizeof(*p->name.name_string.val)); if(p->name.name_string.val == NULL) { krb5_set_error_string (context, "malloc: out of memory"); - return ENOMEM; + ret = ENOMEM; + goto out; } + p->name.name_string.len = len; for(i = 0; i < p->name.name_string.len; i++){ ret = krb5_kt_ret_string(context, sp, p->name.name_string.val + i); if(ret) - return ret; + goto out; } if (krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) p->name.name_type = KRB5_NT_UNKNOWN; @@ -199,10 +208,13 @@ krb5_kt_ret_principal(krb5_context context, ret = krb5_ret_int32(sp, &tmp32); p->name.name_type = tmp32; if (ret) - return ret; + goto out; } *princ = p; return 0; +out: + krb5_free_principal(context, p); + return ret; } static krb5_error_code @@ -423,7 +435,7 @@ loop: } } if(start) *start = pos; - if(end) *end = *start + 4 + len; + if(end) *end = pos + 4 + len; out: krb5_storage_seek(cursor->sp, pos + 4 + len, SEEK_SET); return ret; diff --git a/source4/heimdal/lib/krb5/keytab_keyfile.c b/source4/heimdal/lib/krb5/keytab_keyfile.c index 5c94291e72..32fb48a8a2 100644 --- a/source4/heimdal/lib/krb5/keytab_keyfile.c +++ b/source4/heimdal/lib/krb5/keytab_keyfile.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab_keyfile.c,v 1.17 2005/09/30 11:20:53 lha Exp $"); +RCSID("$Id: keytab_keyfile.c,v 1.18 2006/04/02 01:24:52 lha Exp $"); /* afs keyfile operations --------------------------------------- */ @@ -94,6 +94,7 @@ get_cell_and_realm (krb5_context context, f = fopen (AFS_SERVERMAGICKRBCONF, "r"); if (f != NULL) { if (fgets (buf, sizeof(buf), f) == NULL) { + free (d->cell); fclose (f); krb5_set_error_string (context, "no realm in %s", AFS_SERVERMAGICKRBCONF); diff --git a/source4/heimdal/lib/krb5/keytab_krb4.c b/source4/heimdal/lib/krb5/keytab_krb4.c index 1a83faca57..19e7f106bf 100644 --- a/source4/heimdal/lib/krb5/keytab_krb4.c +++ b/source4/heimdal/lib/krb5/keytab_krb4.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab_krb4.c,v 1.13 2005/05/19 04:13:18 lha Exp $"); +RCSID("$Id: keytab_krb4.c,v 1.15 2006/04/10 17:10:53 lha Exp $"); struct krb4_kt_data { char *filename; @@ -139,6 +139,11 @@ krb4_kt_start_seq_get_int (krb5_context context, return ret; } c->sp = krb5_storage_from_fd(c->fd); + if(c->sp == NULL) { + close(c->fd); + free(ed); + return ENOMEM; + } krb5_storage_set_eof_code(c->sp, KRB5_KT_END); return 0; } @@ -302,11 +307,11 @@ krb4_kt_add_entry (krb5_context context, } } sp = krb5_storage_from_fd(fd); - krb5_storage_set_eof_code(sp, KRB5_KT_END); if(sp == NULL) { close(fd); return ENOMEM; } + krb5_storage_set_eof_code(sp, KRB5_KT_END); ret = krb4_store_keytab_entry(context, entry, sp); krb5_storage_free(sp); if(close (fd) < 0) @@ -316,8 +321,8 @@ krb4_kt_add_entry (krb5_context context, static krb5_error_code krb4_kt_remove_entry(krb5_context context, - krb5_keytab id, - krb5_keytab_entry *entry) + krb5_keytab id, + krb5_keytab_entry *entry) { struct krb4_kt_data *d = id->data; krb5_error_code ret; diff --git a/source4/heimdal/lib/krb5/krb5-private.h b/source4/heimdal/lib/krb5/krb5-private.h index 8d9b3c62ac..00126d60ed 100644 --- a/source4/heimdal/lib/krb5/krb5-private.h +++ b/source4/heimdal/lib/krb5/krb5-private.h @@ -302,19 +302,13 @@ void KRB5_LIB_FUNCTION _krb5_pk_cert_free (struct krb5_pk_cert */*cert*/); krb5_error_code KRB5_LIB_FUNCTION -_krb5_pk_create_sign ( - krb5_context /*context*/, - const heim_oid */*eContentType*/, - krb5_data */*eContent*/, - struct krb5_pk_identity */*id*/, - krb5_data */*sd_data*/); - -krb5_error_code KRB5_LIB_FUNCTION -_krb5_pk_load_openssl_id ( +_krb5_pk_load_id ( krb5_context /*context*/, struct krb5_pk_identity **/*ret_id*/, const char */*user_id*/, - const char */*x509_anchors*/, + const char */*anchor_id*/, + char * const */*chain*/, + char * const */*revoke*/, krb5_prompter_fct /*prompter*/, void */*prompter_data*/, char */*password*/); diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h index d7e74621ef..56f43f6c3d 100644 --- a/source4/heimdal/lib/krb5/krb5-protos.h +++ b/source4/heimdal/lib/krb5/krb5-protos.h @@ -1874,6 +1874,8 @@ krb5_get_init_creds_opt_set_pkinit ( krb5_principal /*principal*/, const char */*user_id*/, const char */*x509_anchors*/, + char * const * /*chain*/, + char * const * /*revoke*/, int /*flags*/, krb5_prompter_fct /*prompter*/, void */*prompter_data*/, diff --git a/source4/heimdal/lib/krb5/krb5_ccapi.h b/source4/heimdal/lib/krb5/krb5_ccapi.h index 00c30d7791..29b2ddbecc 100644 --- a/source4/heimdal/lib/krb5/krb5_ccapi.h +++ b/source4/heimdal/lib/krb5/krb5_ccapi.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5_ccapi.h,v 1.1 2004/09/11 04:00:42 lha Exp $ */ +/* $Id: krb5_ccapi.h,v 1.2 2006/03/27 04:21:06 lha Exp $ */ #ifndef KRB5_CCAPI_H #define KRB5_CCAPI_H 1 @@ -43,7 +43,8 @@ enum { }; enum { - ccapi_version_3 = 3 + ccapi_version_3 = 3, + ccapi_version_4 = 4 }; enum { @@ -108,7 +109,21 @@ struct cc_credentials_v5_t { cc_time_t endtime; cc_time_t renew_till; cc_uint32 is_skey; - cc_uint32 ticket_flags; /* XXX ticket flags undefined */ + cc_uint32 ticket_flags; +#define KRB5_CCAPI_TKT_FLG_FORWARDABLE 0x40000000 +#define KRB5_CCAPI_TKT_FLG_FORWARDED 0x20000000 +#define KRB5_CCAPI_TKT_FLG_PROXIABLE 0x10000000 +#define KRB5_CCAPI_TKT_FLG_PROXY 0x08000000 +#define KRB5_CCAPI_TKT_FLG_MAY_POSTDATE 0x04000000 +#define KRB5_CCAPI_TKT_FLG_POSTDATED 0x02000000 +#define KRB5_CCAPI_TKT_FLG_INVALID 0x01000000 +#define KRB5_CCAPI_TKT_FLG_RENEWABLE 0x00800000 +#define KRB5_CCAPI_TKT_FLG_INITIAL 0x00400000 +#define KRB5_CCAPI_TKT_FLG_PRE_AUTH 0x00200000 +#define KRB5_CCAPI_TKT_FLG_HW_AUTH 0x00100000 +#define KRB5_CCAPI_TKT_FLG_TRANSIT_POLICY_CHECKED 0x00080000 +#define KRB5_CCAPI_TKT_FLG_OK_AS_DELEGATE 0x00040000 +#define KRB5_CCAPI_TKT_FLG_ANONYMOUS 0x00020000 cc_data **addresses; cc_data ticket; cc_data second_ticket; diff --git a/source4/heimdal/lib/krb5/krbhst.c b/source4/heimdal/lib/krb5/krbhst.c index ef9f5dbd60..221bd706f4 100644 --- a/source4/heimdal/lib/krb5/krbhst.c +++ b/source4/heimdal/lib/krb5/krbhst.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include -RCSID("$Id: krbhst.c,v 1.53 2005/10/08 15:40:50 lha Exp $"); +RCSID("$Id: krbhst.c,v 1.55 2006/04/02 10:32:20 lha Exp $"); static int string_to_proto(const char *string) @@ -241,8 +241,9 @@ _krb5_krbhost_info_move(krb5_context context, krb5_krbhst_info *from, krb5_krbhst_info **to) { + size_t hostnamelen = strlen(from->hostname); /* trailing NUL is included in structure */ - *to = calloc(1, sizeof(**to) + strlen(from->hostname)); + *to = calloc(1, sizeof(**to) + hostnamelen); if(*to == NULL) { krb5_set_error_string(context, "malloc - out of memory"); return ENOMEM; @@ -254,7 +255,7 @@ _krb5_krbhost_info_move(krb5_context context, (*to)->ai = from->ai; from->ai = NULL; (*to)->next = NULL; - strcpy((*to)->hostname, from->hostname); + memcpy((*to)->hostname, from->hostname, hostnamelen + 1); return 0; } diff --git a/source4/heimdal/lib/krb5/log.c b/source4/heimdal/lib/krb5/log.c index 4f6381c858..7e478bf1e0 100644 --- a/source4/heimdal/lib/krb5/log.c +++ b/source4/heimdal/lib/krb5/log.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: log.c,v 1.36 2005/06/17 04:25:05 lha Exp $"); +RCSID("$Id: log.c,v 1.38 2006/04/10 09:41:26 lha Exp $"); struct facility { int min; @@ -284,7 +284,7 @@ krb5_addlog_dest(krb5_context context, krb5_log_facility *f, const char *orig) ret = open_file(context, f, min, max, NULL, NULL, stderr, 1); }else if(strcmp(p, "CONSOLE") == 0){ ret = open_file(context, f, min, max, "/dev/console", "w", NULL, 0); - }else if(strncmp(p, "FILE:", 4) == 0 && (p[4] == ':' || p[4] == '=')){ + }else if(strncmp(p, "FILE", 4) == 0 && (p[4] == ':' || p[4] == '=')){ char *fn; FILE *file = NULL; int keep_open = 0; @@ -300,6 +300,7 @@ krb5_addlog_dest(krb5_context context, krb5_log_facility *f, const char *orig) ret = errno; krb5_set_error_string (context, "open(%s): %s", fn, strerror(ret)); + free(fn); return ret; } file = fdopen(i, "a"); @@ -308,12 +309,13 @@ krb5_addlog_dest(krb5_context context, krb5_log_facility *f, const char *orig) close(i); krb5_set_error_string (context, "fdopen(%s): %s", fn, strerror(ret)); + free(fn); return ret; } keep_open = 1; } ret = open_file(context, f, min, max, fn, "a", file, keep_open); - }else if(strncmp(p, "DEVICE=", 6) == 0){ + }else if(strncmp(p, "DEVICE", 6) == 0 && (p[6] == ':' || p[6] == '=')){ ret = open_file(context, f, min, max, strdup(p + 7), "w", NULL, 0); }else if(strncmp(p, "SYSLOG", 6) == 0 && (p[6] == '\0' || p[6] == ':')){ char severity[128] = ""; diff --git a/source4/heimdal/lib/krb5/pkinit.c b/source4/heimdal/lib/krb5/pkinit.c index 1247bb22ca..fa4fb4699e 100755 --- a/source4/heimdal/lib/krb5/pkinit.c +++ b/source4/heimdal/lib/krb5/pkinit.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 - 2005 Kungliga Tekniska Högskolan + * Copyright (c) 2003 - 2006 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: pkinit.c,v 1.77 2006/02/14 10:08:29 lha Exp $"); +RCSID("$Id: pkinit.c,v 1.88 2006/04/23 21:30:17 lha Exp $"); struct krb5_dh_moduli { char *name; @@ -45,71 +45,35 @@ struct krb5_dh_moduli { #ifdef PKINIT -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_DIRENT_H -#include -#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#include -#include "heim_asn1.h" -#include "rfc2459_asn1.h" -#include "cms_asn1.h" -#include "pkinit_asn1.h" +#include enum { COMPAT_WIN2K = 1, COMPAT_IETF = 2 }; -#define OPENSSL_ASN1_MALLOC_ENCODE(T, B, BL, S, R) \ -{ \ - unsigned char *p; \ - (BL) = i2d_##T((S), NULL); \ - if ((BL) <= 0) { \ - (R) = EINVAL; \ - } else { \ - (B) = malloc((BL)); \ - if ((B) == NULL) { \ - (R) = ENOMEM; \ - } else { \ - p = (B); \ - (R) = 0; \ - (BL) = i2d_##T((S), &p); \ - if ((BL) <= 0) { \ - free((B)); \ - (R) = ASN1_OVERRUN; \ - } \ - } \ - } \ -} - -/* ENGING_load_private_key requires a UI_METHOD and data - * if to be usable from PAM - */ - -struct krb5_ui_data { - krb5_context context; - krb5_prompter_fct prompter; - void * prompter_data; -}; - struct krb5_pk_identity { - EVP_PKEY *private_key; - STACK_OF(X509) *cert; - STACK_OF(X509) *trusted_certs; - STACK_OF(X509_CRL) *crls; - ENGINE *engine; + hx509_context hx509ctx; + hx509_verify_ctx verify_ctx; + hx509_certs certs; + hx509_certs anchors; + hx509_certs certpool; + hx509_revoke_ctx revoke; }; struct krb5_pk_cert { - X509 *cert; + hx509_cert cert; }; struct krb5_pk_init_ctx_data { @@ -118,13 +82,16 @@ struct krb5_pk_init_ctx_data { krb5_data *clientDHNonce; struct krb5_dh_moduli **m; int require_binding; + int require_eku; + int require_krbtgt_otherName; }; void KRB5_LIB_FUNCTION _krb5_pk_cert_free(struct krb5_pk_cert *cert) { - if (cert->cert) - X509_free(cert->cert); + if (cert->cert) { + hx509_cert_free(cert->cert); + } free(cert); } @@ -138,7 +105,7 @@ BN_to_integer(krb5_context context, BIGNUM *bn, heim_integer *integer) return ENOMEM; } BN_bn2bin(bn, integer->data); - integer->negative = bn->neg; + integer->negative = BN_is_negative(bn); return 0; } @@ -152,315 +119,44 @@ integer_to_BN(krb5_context context, const char *field, const heim_integer *f) krb5_set_error_string(context, "PKINIT: parsing BN failed %s", field); return NULL; } - bn->neg = f->negative; + BN_set_negative(bn, 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 - */ - -static int -krb5_ui_method_read_string(UI *ui, UI_STRING *uis) -{ - char *buffer; - size_t length; - krb5_error_code ret; - krb5_prompt prompt; - krb5_data password_data; - struct krb5_ui_data *ui_data; - - ui_data = (struct krb5_ui_data *)UI_get_app_data(ui); - - switch (UI_get_string_type(uis)) { - case UIT_INFO: - case UIT_ERROR: - /* looks like the RedHat pam_prompter might handle - * INFO and ERROR, Will see what happens */ - case UIT_VERIFY: - case UIT_PROMPT: - length = UI_get_result_maxsize(uis); - buffer = malloc(length); - if (buffer == NULL) { - krb5_set_error_string(ui_data->context, "malloc: out of memory"); - return 0; - } - password_data.data = buffer; - password_data.length = length; - - prompt.prompt = UI_get0_output_string(uis); - prompt.hidden = !(UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO); - prompt.reply = &password_data; - prompt.type = KRB5_PROMPT_TYPE_PASSWORD; - - ret = (*ui_data->prompter)(ui_data->context, - ui_data->prompter_data, - NULL, NULL, 1, &prompt); - if (ret == 0) { - buffer[length - 1] = '\0'; - UI_set_result(ui, uis, password_data.data); - - /* - * RedHat pam_krb5 pam_prompter does a strdup but others - * may copy into buffer. XXX should we just leak the - * memory instead ? - */ - - if (buffer != password_data.data) - free(password_data.data); - memset (buffer, 0, length); - free(buffer); - return 1; - } - memset (buffer, 0, length); - free(buffer); - break; - case UIT_NONE: - case UIT_BOOLEAN: - /* XXX for now do not handle */ - break; - - } - return 0; -} - static krb5_error_code -set_digest_alg(DigestAlgorithmIdentifier *id, - const heim_oid *oid, - void *param, size_t length) -{ - krb5_error_code ret; - if (param) { - id->parameters = malloc(sizeof(*id->parameters)); - if (id->parameters == NULL) - return ENOMEM; - id->parameters->data = malloc(length); - if (id->parameters->data == NULL) { - free(id->parameters); - id->parameters = NULL; - return ENOMEM; - } - memcpy(id->parameters->data, param, length); - id->parameters->length = length; - } else - id->parameters = NULL; - ret = copy_oid(oid, &id->algorithm); - if (ret) { - if (id->parameters) { - free(id->parameters->data); - free(id->parameters); - id->parameters = NULL; - } - return ret; - } - return 0; -} - -krb5_error_code KRB5_LIB_FUNCTION _krb5_pk_create_sign(krb5_context context, const heim_oid *eContentType, krb5_data *eContent, struct krb5_pk_identity *id, krb5_data *sd_data) { - SignerInfo *signer_info; - X509 *user_cert; - heim_integer *serial; - krb5_error_code ret; - krb5_data buf; - SignedData sd; - EVP_MD_CTX md; - int i; - unsigned len; - size_t size; - - X509_NAME *issuer_name; - - memset(&sd, 0, sizeof(sd)); - - if (id == NULL) - return HEIM_PKINIT_NO_CERTIFICATE; - if (id->cert == NULL) - return HEIM_PKINIT_NO_CERTIFICATE; - if (id->private_key == NULL) - return HEIM_PKINIT_NO_PRIVATE_KEY; - - if (sk_X509_num(id->cert) == 0) - return HEIM_PKINIT_NO_CERTIFICATE; - - sd.version = 3; - - sd.digestAlgorithms.len = 0; - sd.digestAlgorithms.val = NULL; - copy_oid(eContentType, &sd.encapContentInfo.eContentType); - ALLOC(sd.encapContentInfo.eContent, 1); - if (sd.encapContentInfo.eContent == NULL) { - krb5_clear_error_string(context); - ret = ENOMEM; - goto out; - } - - ret = krb5_data_copy(&buf, eContent->data, eContent->length); - if (ret) { - krb5_clear_error_string(context); - ret = ENOMEM; - goto out; - } - - sd.encapContentInfo.eContent->data = buf.data; - sd.encapContentInfo.eContent->length = buf.length; - - ALLOC_SEQ(&sd.signerInfos, 1); - if (sd.signerInfos.val == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); - ret = ENOMEM; - goto out; - } - - signer_info = &sd.signerInfos.val[0]; - - user_cert = sk_X509_value(id->cert, 0); - if (user_cert == NULL) { - krb5_set_error_string(context, "pkinit: no user certificate"); - ret = HEIM_PKINIT_NO_CERTIFICATE; - goto out; - } - - signer_info->version = 1; - - issuer_name = X509_get_issuer_name(user_cert); - - OPENSSL_ASN1_MALLOC_ENCODE(X509_NAME, - buf.data, - buf.length, - issuer_name, - ret); - if (ret) { - krb5_set_error_string(context, "pkinit: failed encoding name"); - goto out; - } - ret = decode_Name(buf.data, buf.length, - &signer_info->sid.u.issuerAndSerialNumber.issuer, - NULL); - free(buf.data); - if (ret) { - krb5_set_error_string(context, "pkinit: failed to parse Name"); - goto out; - } - signer_info->sid.element = choice_CMSIdentifier_issuerAndSerialNumber; - - serial = &signer_info->sid.u.issuerAndSerialNumber.serialNumber; - { - ASN1_INTEGER *isn = X509_get_serialNumber(user_cert); - BIGNUM *bn = ASN1_INTEGER_to_BN(isn, NULL); - if (bn == NULL) { - ret = ENOMEM; - krb5_set_error_string(context, "pkinit: failed allocating " - "serial number"); - goto out; - } - ret = BN_to_integer(context, bn, serial); - BN_free(bn); - if (ret) { - krb5_set_error_string(context, "pkinit: failed encoding " - "serial number"); - goto out; - } - } - - ret = set_digest_alg(&signer_info->digestAlgorithm, - oid_id_secsig_sha_1(), "\x05\x00", 2); - if (ret) { - krb5_set_error_string(context, "malloc: out of memory"); - goto out; - } - - signer_info->signedAttrs = NULL; - signer_info->unsignedAttrs = NULL; - - copy_oid(oid_id_pkcs1_rsaEncryption(), - &signer_info->signatureAlgorithm.algorithm); - signer_info->signatureAlgorithm.parameters = NULL; - - buf.data = malloc(EVP_PKEY_size(id->private_key)); - if (buf.data == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); - ret = ENOMEM; - goto out; - } - - EVP_SignInit(&md, EVP_sha1()); - EVP_SignUpdate(&md, - sd.encapContentInfo.eContent->data, - sd.encapContentInfo.eContent->length); - ret = EVP_SignFinal(&md, buf.data, &len, id->private_key); - if (ret != 1) { - free(buf.data); - krb5_set_error_string(context, "PKINIT: failed to sign with " - "private key: %s", - ERR_error_string(ERR_get_error(), NULL)); - ret = EINVAL; - goto out; - } - - signer_info->signature.data = buf.data; - signer_info->signature.length = len; - - ALLOC_SEQ(&sd.digestAlgorithms, 1); - if (sd.digestAlgorithms.val == NULL) { - krb5_clear_error_string(context); - ret = ENOMEM; - goto out; - } - - ret = set_digest_alg(&sd.digestAlgorithms.val[0], - oid_id_secsig_sha_1(), "\x05\x00", 2); - if (ret) { - krb5_set_error_string(context, "malloc: out of memory"); - goto out; - } + hx509_cert cert; + hx509_query *q; + int ret; - ALLOC(sd.certificates, 1); - if (sd.certificates == NULL) { - krb5_clear_error_string(context); - ret = ENOMEM; - goto out; - } + ret = hx509_query_alloc(id->hx509ctx, &q); + if (ret) + return ret; - i = sk_X509_num(id->cert); - sd.certificates->val = malloc(sizeof(sd.certificates->val[0]) * i); - if (sd.certificates->val == NULL) { - krb5_clear_error_string(context); - ret = ENOMEM; - goto out; - } - sd.certificates->len = i; - - for (i = 0; i < sk_X509_num(id->cert); i++) { - OPENSSL_ASN1_MALLOC_ENCODE(X509, - sd.certificates->val[i].data, - sd.certificates->val[i].length, - sk_X509_value(id->cert, i), - ret); - if (ret) { - krb5_clear_error_string(context); - goto out; - } - } + hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); + hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE); - ASN1_MALLOC_ENCODE(SignedData, sd_data->data, sd_data->length, - &sd, &size, ret); - if (ret) { - krb5_set_error_string(context, "SignedData failed %d", ret); - goto out; - } - if (sd_data->length != size) - krb5_abortx(context, "internal ASN1 encoder error"); + ret = hx509_certs_find(id->hx509ctx, id->certs, q, &cert); + hx509_query_free(id->hx509ctx, q); + if (ret) + return ret; - out: - free_SignedData(&sd); + ret = hx509_cms_create_signed_1(id->hx509ctx, + eContentType, + eContent->data, + eContent->length, + NULL, + cert, + NULL, + NULL, + sd_data); + hx509_cert_free(cert); return ret; } @@ -813,230 +509,23 @@ _krb5_pk_mk_padata(krb5_context context, } else type = COMPAT_IETF; - return pk_mk_padata(context, type, ctx, req_body, nonce, md); -} + ctx->require_eku = + krb5_config_get_bool_default(context, NULL, + TRUE, + "realms", + req_body->realm, + "pkinit_require_eku", + NULL); + ctx->require_krbtgt_otherName = + krb5_config_get_bool_default(context, NULL, + TRUE, + "realms", + req_body->realm, + "pkinit_require_krbtgt_otherName", + NULL); -static krb5_boolean -pk_peer_compare(krb5_context context, - const SignerIdentifier *peer1, - X509 *peer2) -{ - switch (peer1->element) { - case choice_CMSIdentifier_issuerAndSerialNumber: { - ASN1_INTEGER *i; - const heim_integer *serial; - X509_NAME *name; - unsigned char *p; - size_t len; - - i = X509_get_serialNumber(peer2); - serial = &peer1->u.issuerAndSerialNumber.serialNumber; - - if (i->length != serial->length || - memcmp(i->data, serial->data, i->length) != 0) - return FALSE; - - p = peer1->u.issuerAndSerialNumber.issuer._save.data; - len = peer1->u.issuerAndSerialNumber.issuer._save.length; - name = d2i_X509_NAME(NULL, &p, len); - if (name == NULL) - return FALSE; - - if (X509_NAME_cmp(name, X509_get_issuer_name(peer2)) != 0) { - X509_NAME_free(name); - return FALSE; - } - X509_NAME_free(name); - break; - } - case choice_CMSIdentifier_subjectKeyIdentifier: - return FALSE; - default: - return FALSE; - } - return TRUE; -} - -static krb5_error_code -pk_decrypt_key(krb5_context context, - heim_octet_string *encrypted_key, - EVP_PKEY *priv_key, - krb5_keyblock *key) -{ - int ret; - unsigned char *buf; - buf = malloc(EVP_PKEY_size(priv_key)); - if (buf == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); - return ENOMEM; - } - ret = EVP_PKEY_decrypt(buf, - encrypted_key->data, - encrypted_key->length, - priv_key); - if (ret <= 0) { - free(buf); - krb5_set_error_string(context, "Can't decrypt key: %s", - ERR_error_string(ERR_get_error(), NULL)); - return ENOMEM; - } - - key->keytype = 0; - key->keyvalue.length = ret; - key->keyvalue.data = malloc(ret); - if (key->keyvalue.data == NULL) { - free(buf); - krb5_set_error_string(context, "malloc: out of memory"); - return ENOMEM; - } - memcpy(key->keyvalue.data, buf, ret); - free(buf); - return 0; -} - - -static krb5_error_code -pk_verify_chain_standard(krb5_context context, - struct krb5_pk_identity *id, - const SignerIdentifier *client, - STACK_OF(X509) *chain, - X509 **client_cert) -{ - X509_STORE *cert_store = NULL; - X509_STORE_CTX *store_ctx = NULL; - X509 *cert = NULL; - int i; - int ret; - - 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) { - ret = 0; - break; - } - } - if (ret) { - krb5_set_error_string(context, "PKINIT: verify chain failed " - "to find client in chain"); - return ret; - } - - cert_store = X509_STORE_new(); - if (cert_store == NULL) { - ret = ENOMEM; - krb5_set_error_string(context, "PKINIT: can't create X509 store: %s", - ERR_error_string(ERR_get_error(), NULL)); - } - - store_ctx = X509_STORE_CTX_new(); - if (store_ctx == NULL) { - ret = ENOMEM; - krb5_set_error_string(context, - "PKINIT: can't create X509 store ctx: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto end; - } - - X509_STORE_CTX_init(store_ctx, cert_store, cert, chain); - X509_STORE_CTX_trusted_stack(store_ctx, id->trusted_certs); - X509_verify_cert(store_ctx); - /* the last checked certificate is in store_ctx->current_cert */ - krb5_clear_error_string(context); - switch(store_ctx->error) { - case X509_V_OK: - ret = 0; - break; - case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: - 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)); - break; - case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: - case X509_V_ERR_CERT_SIGNATURE_FAILURE: - case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: - 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_ERR_INVALID_CERTIFICATE; - krb5_set_error_string(context, "PKINIT: invalid certificate: %s ", - X509_verify_cert_error_string(store_ctx->error)); - break; - case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: - case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: - case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: - case X509_V_ERR_CERT_CHAIN_TOO_LONG: - case X509_V_ERR_PATH_LENGTH_EXCEEDED: - case X509_V_ERR_INVALID_CA: - 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_ERR_INVALID_CERTIFICATE; /* XXX */ - krb5_set_error_string(context, "PKINIT: failed to verify " - "certificate: %s (%ld) ", - X509_verify_cert_error_string(store_ctx->error), - (long)store_ctx->error); - break; - } - if (ret) - goto end; - - /* - * Since X509_verify_cert() doesn't do CRL checking at all, we have to - * perform own verification against CRLs - */ - /* - * XXX add crl checking - */ - - if (client_cert && cert) - *client_cert = X509_dup(cert); - - end: - if (cert_store) - X509_STORE_free(cert_store); - if (store_ctx) - X509_STORE_CTX_free(store_ctx); - return ret; -} - -static int -cert_to_X509(krb5_context context, CertificateSet *set, - STACK_OF(X509_CRL) **certs) -{ - krb5_error_code ret; - int i; - - *certs = sk_X509_new_null(); - - if (set == NULL) - return 0; - - ret = 0; - for (i = 0; i < set->len; i++) { - unsigned char *p; - X509 *cert; - - p = set->val[i].data; - cert = d2i_X509(NULL, &p, set->val[i].length); - if (cert == NULL) { - ret = ASN1_BAD_FORMAT; - break; - } - sk_X509_insert(*certs, cert, i); - } - if (ret) { - krb5_set_error_string(context, - "PKINIT: Failed to decode certificate chain"); - sk_X509_free(*certs); - *certs = NULL; - } - return ret; + return pk_mk_padata(context, type, ctx, req_body, nonce, md); } krb5_error_code KRB5_LIB_FUNCTION @@ -1048,144 +537,67 @@ _krb5_pk_verify_sign(krb5_context context, krb5_data *content, struct krb5_pk_cert **signer) { - STACK_OF(X509) *certificates; - SignerInfo *signer_info; - const EVP_MD *evp_type; - EVP_PKEY *public_key; - krb5_error_code ret; - EVP_MD_CTX md; - X509 *cert = NULL; - SignedData sd; - size_t size; - - *signer = NULL; - krb5_data_zero(content); - contentType->length = 0; - contentType->components = NULL; - - memset(&sd, 0, sizeof(sd)); - - ret = decode_SignedData(data, length, &sd, &size); - if (ret) { - krb5_set_error_string(context, - "PKINIT: decoding failed SignedData: %d", - ret); - goto out; - } - - if (sd.encapContentInfo.eContent == NULL) { - krb5_set_error_string(context, - "PKINIT: signature missing encapContent"); - ret = KRB5KRB_AP_ERR_MSG_TYPE; - goto out; - } - - /* XXX Check CMS version */ - - if (sd.signerInfos.len < 1) { - krb5_set_error_string(context, - "PKINIT: signature information missing from " - "pkinit response"); - ret = KRB5_KDC_ERR_INVALID_SIG; - goto out; - } - - signer_info = &sd.signerInfos.val[0]; - - { - CertificateSet set; - set.val = sd.certificates->val; - set.len = sd.certificates->len; + hx509_certs signer_certs; + int ret; - ret = cert_to_X509(context, &set, &certificates); - } - if (ret) { - krb5_set_error_string(context, - "PKINIT: failed to decode Certificates"); - goto out; - } + *signer = NULL; - ret = pk_verify_chain_standard(context, id, - &signer_info->sid, - certificates, - &cert); - sk_X509_free(certificates); + ret = hx509_cms_verify_signed(id->hx509ctx, + id->verify_ctx, + data, + length, + id->certpool, + contentType, + content, + &signer_certs); if (ret) - goto out; - - if (signer_info->signature.length == 0) { - free_SignedData(&sd); - X509_free(cert); - krb5_set_error_string(context, "PKINIT: signature missing from" - "pkinit response"); - return KRB5_KDC_ERR_INVALID_SIG; - } - - public_key = X509_get_pubkey(cert); - - /* verify signature */ - if (heim_oid_cmp(&signer_info->digestAlgorithm.algorithm, - oid_id_pkcs1_sha1WithRSAEncryption()) == 0) - evp_type = EVP_sha1(); - else if (heim_oid_cmp(&signer_info->digestAlgorithm.algorithm, - oid_id_pkcs1_md5WithRSAEncryption()) == 0) - evp_type = EVP_md5(); - else if (heim_oid_cmp(&signer_info->digestAlgorithm.algorithm, - oid_id_secsig_sha_1()) == 0) - evp_type = EVP_sha1(); - else { - X509_free(cert); - krb5_set_error_string(context, "PKINIT: The requested digest " - "algorithm is not supported"); - ret = KRB5_KDC_ERR_INVALID_SIG; - goto out; - } - - EVP_VerifyInit(&md, evp_type); - EVP_VerifyUpdate(&md, - sd.encapContentInfo.eContent->data, - sd.encapContentInfo.eContent->length); - ret = EVP_VerifyFinal(&md, - signer_info->signature.data, - signer_info->signature.length, - public_key); - if (ret != 1) { - X509_free(cert); - krb5_set_error_string(context, "PKINIT: signature didn't verify: %s", - ERR_error_string(ERR_get_error(), NULL)); - ret = KRB5_KDC_ERR_INVALID_SIG; - goto out; - } - - ret = copy_oid(&sd.encapContentInfo.eContentType, contentType); - if (ret) { - krb5_clear_error_string(context); - goto out; - } + return ret; - content->data = malloc(sd.encapContentInfo.eContent->length); - if (content->data == NULL) { + *signer = calloc(1, sizeof(**signer)); + if (*signer == NULL) { krb5_clear_error_string(context); ret = ENOMEM; goto out; } - content->length = sd.encapContentInfo.eContent->length; - memcpy(content->data,sd.encapContentInfo.eContent->data,content->length); + + /* XXX */ + { + hx509_cursor cursor; - *signer = malloc(sizeof(**signer)); - if (*signer == NULL) { - krb5_clear_error_string(context); - ret = ENOMEM; - goto out; + ret = hx509_certs_start_seq(id->hx509ctx, + signer_certs, + &cursor); + if (ret) { + krb5_clear_error_string(context); + goto out; + } + ret = hx509_certs_next_cert(id->hx509ctx, + signer_certs, + cursor, + &(*signer)->cert); + if (ret) { + krb5_clear_error_string(context); + goto out; + } + ret = hx509_certs_end_seq(id->hx509ctx, + signer_certs, + cursor); + if (ret) { + krb5_clear_error_string(context); + goto out; + } } - (*signer)->cert = cert; - out: - free_SignedData(&sd); +out: + hx509_certs_free(&signer_certs); if (ret) { - free_oid(contentType); - krb5_data_free(content); + if (*signer) { + hx509_cert_free((*signer)->cert); + free(*signer); + *signer = NULL; + } } + return ret; } @@ -1297,10 +709,60 @@ get_reply_key(krb5_context context, static krb5_error_code -pk_verify_host(krb5_context context, struct krb5_pk_cert *host) +pk_verify_host(krb5_context context, + struct krb5_pk_init_ctx_data *ctx, + struct krb5_pk_cert *host) { - /* XXX */ - return 0; + krb5_error_code ret = 0; + + if (ctx->require_eku) { + ret = hx509_cert_check_eku(ctx->id->hx509ctx, host->cert, + oid_id_pkkdcekuoid(), 0); + if (ret) { + krb5_clear_error_string(context); + return ret; + } + } + if (ctx->require_krbtgt_otherName) { + hx509_octet_string_list list; + krb5_error_code ret; + int i; + + ret = hx509_cert_find_subjectAltName_otherName(host->cert, + oid_id_pkinit_san(), + &list); + if (ret) { + krb5_clear_error_string(context); + return ret; + } + + for (i = 0; i < list.len; i++) { + KRB5PrincipalName r; + ret = decode_KRB5PrincipalName(list.val[i].data, + list.val[i].length, + &r, + NULL); + if (ret) { + krb5_clear_error_string(context); + break; + } + +#if 0 + if (r.principalName.name.len != 2) { + krb5_clear_error_string(context); + ret = EINVAL; + } +#endif + /* XXX verify realm */ + + free_KRB5PrincipalName(&r); + if (ret) + break; + } + hx509_free_octet_string_list(&list); + } + + return ret; } static krb5_error_code @@ -1316,33 +778,12 @@ pk_rd_pa_reply_enckey(krb5_context context, krb5_keyblock **key) { krb5_error_code ret; - EnvelopedData ed; - krb5_keyblock tmp_key; - krb5_crypto crypto; - krb5_data plain; - KeyTransRecipientInfo *ri; - int length; + struct krb5_pk_cert *host = NULL; size_t size; - X509 *user_cert; + int length; void *p; - krb5_boolean bret; krb5_data content; heim_oid contentType = { 0, NULL }; - struct krb5_pk_cert *host = NULL; - heim_octet_string encryptedContent; - heim_octet_string *any; - krb5_data ivec; - krb5_data params; - - - memset(&tmp_key, 0, sizeof(tmp_key)); - memset(&ed, 0, sizeof(ed)); - krb5_data_zero(&plain); - krb5_data_zero(&content); - krb5_data_zero(&encryptedContent); - krb5_data_zero(&ivec); - - user_cert = sk_X509_value(ctx->id->cert, 0); if (heim_oid_cmp(oid_id_pkcs7_envelopedData(), &rep->contentType)) { krb5_set_error_string(context, "PKINIT: Invalid content type"); @@ -1354,106 +795,17 @@ pk_rd_pa_reply_enckey(krb5_context context, return EINVAL; } - ret = decode_EnvelopedData(rep->content->data, + ret = hx509_cms_unenvelope(ctx->id->hx509ctx, + ctx->id->certs, + rep->content->data, rep->content->length, - &ed, - &size); - if (ret) { - free_EnvelopedData(&ed); - return ret; - } - - if (ed.recipientInfos.len != 1) { - free_EnvelopedData(&ed); - krb5_set_error_string(context, "pkinit: Number of recipient infos " - "not one (%d)", - ed.recipientInfos.len); - return EINVAL; /* XXX */ - } - - ri = &ed.recipientInfos.val[0]; - - /* XXX make SignerIdentifier and RecipientIdentifier the same */ - bret = pk_peer_compare(context, (SignerIdentifier *)&ri->rid, user_cert); - if (bret == FALSE) { - ret = KRB5KRB_AP_ERR_BADMATCH; /* XXX */ - goto out; - } - - if (heim_oid_cmp(oid_id_pkcs1_rsaEncryption(), - &ri->keyEncryptionAlgorithm.algorithm)) { - krb5_set_error_string(context, "PKINIT: invalid content type"); - return EINVAL; - } - - ret = pk_decrypt_key(context, &ri->encryptedKey, - ctx->id->private_key, &tmp_key); - if (ret) - goto out; - - - /* - * 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; - } - } - - if (ed.encryptedContentInfo.encryptedContent == NULL) { - krb5_set_error_string(context, "PKINIT: OPTIONAL encryptedContent " - "field not filled in in KDC reply"); - ret = KRB5_BADMSGTYPE; - goto out; - } - - any = ed.encryptedContentInfo.encryptedContent; - ret = der_get_octet_string(any->data, any->length, - &encryptedContent, NULL); - if (ret) { - krb5_set_error_string(context, - "PKINIT: encryptedContent content invalid"); - goto out; - } - - if (ed.encryptedContentInfo.contentEncryptionAlgorithm.parameters == NULL){ - krb5_set_error_string(context, - "PKINIT: encryptedContent parameter missing"); - ret = KRB5_BADMSGTYPE; - goto out; - } - - params.data = ed.encryptedContentInfo.contentEncryptionAlgorithm.parameters->data; - params.length = ed.encryptedContentInfo.contentEncryptionAlgorithm.parameters->length; - - ret = _krb5_oid_to_enctype(context, - &ed.encryptedContentInfo.contentEncryptionAlgorithm.algorithm, - &tmp_key.keytype); - if (ret) - goto out; - - ret = krb5_crypto_init(context, &tmp_key, 0, &crypto); - if (ret) - goto out; - - ret = krb5_crypto_get_params(context, crypto, ¶ms, &ivec); + &contentType, + &content); if (ret) - goto out; - - ret = krb5_decrypt_ivec(context, crypto, - 0, - encryptedContent.data, - encryptedContent.length, - &plain, - ivec.data); + return ret; - p = plain.data; - length = plain.length; + p = content.data; + length = content.length; /* win2k uses ContentInfo */ if (type == COMPAT_WIN2K) { @@ -1472,6 +824,13 @@ pk_rd_pa_reply_enckey(krb5_context context, krb5_set_error_string(context, "PKINIT: Invalid content type"); goto out; } + if (ci.content == NULL) { + ret = EINVAL; /* XXX */ + krb5_set_error_string(context, "PKINIT: Invalid content type"); + goto out; + } + krb5_data_free(&content); + content = *ci.content; p = ci.content->data; length = ci.content->length; } @@ -1487,7 +846,7 @@ pk_rd_pa_reply_enckey(krb5_context context, goto out; /* make sure that it is the kdc's certificate */ - ret = pk_verify_host(context, host); + ret = pk_verify_host(context, ctx, host); if (ret) { krb5_set_error_string(context, "PKINIT: failed verify host: %d", ret); goto out; @@ -1528,11 +887,7 @@ pk_rd_pa_reply_enckey(krb5_context context, if (host) _krb5_pk_cert_free(host); free_oid(&contentType); - free_octet_string(&encryptedContent); krb5_data_free(&content); - krb5_free_keyblock_contents(context, &tmp_key); - krb5_data_free(&plain); - krb5_data_free(&ivec); return ret; } @@ -1550,7 +905,6 @@ pk_rd_pa_reply_dh(krb5_context context, krb5_keyblock **key) { unsigned char *p, *dh_gen_key = NULL; - ASN1_INTEGER *dh_pub_key = NULL; struct krb5_pk_cert *host = NULL; BIGNUM *kdc_dh_pubkey = NULL; KDCDHKeyInfo kdc_dh_info; @@ -1584,7 +938,7 @@ pk_rd_pa_reply_dh(krb5_context context, goto out; /* make sure that it is the kdc's certificate */ - ret = pk_verify_host(context, host); + ret = pk_verify_host(context, ctx, host); if (ret) goto out; @@ -1623,7 +977,7 @@ pk_rd_pa_reply_dh(krb5_context context, } } else { if (k_n) { - krb5_set_error_string(context, "pkinit; got server nonce " + krb5_set_error_string(context, "pkinit: got server nonce " "without key expiration"); ret = KRB5KRB_ERR_GENERIC; goto out; @@ -1634,22 +988,24 @@ pk_rd_pa_reply_dh(krb5_context context, p = kdc_dh_info.subjectPublicKey.data; size = (kdc_dh_info.subjectPublicKey.length + 7) / 8; - dh_pub_key = d2i_ASN1_INTEGER(NULL, &p, size); - if (dh_pub_key == NULL) { - krb5_set_error_string(context, - "PKINIT: Can't parse KDC's DH public key"); - ret = KRB5KRB_ERR_GENERIC; - goto out; - } - kdc_dh_pubkey = ASN1_INTEGER_to_BN(dh_pub_key, NULL); - if (kdc_dh_pubkey == NULL) { - krb5_set_error_string(context, - "PKINIT: Can't convert KDC's DH public key"); - ret = KRB5KRB_ERR_GENERIC; - goto out; - } + { + DHPublicKey k; + ret = decode_DHPublicKey(p, size, &k, NULL); + if (ret) { + krb5_set_error_string(context, "pkinit: can't decode " + "without key expiration"); + goto out; + } + kdc_dh_pubkey = integer_to_BN(context, "DHPublicKey", &k); + free_DHPublicKey(&k); + if (kdc_dh_pubkey == NULL) { + ret = KRB5KRB_ERR_GENERIC; + goto out; + } + } + dh_gen_keylen = DH_size(ctx->dh); size = BN_num_bytes(ctx->dh->p); if (size < dh_gen_keylen) @@ -1667,8 +1023,7 @@ pk_rd_pa_reply_dh(krb5_context context, kdc_dh_pubkey, ctx->dh); if (dh_gen_keylen == -1) { krb5_set_error_string(context, - "PKINIT: Can't compute Diffie-Hellman key (%s)", - ERR_error_string(ERR_get_error(), NULL)); + "PKINIT: Can't compute Diffie-Hellman key"); ret = KRB5KRB_ERR_GENERIC; goto out; } @@ -1700,8 +1055,6 @@ pk_rd_pa_reply_dh(krb5_context context, memset(dh_gen_key, 0, DH_size(ctx->dh)); free(dh_gen_key); } - if (dh_pub_key) - ASN1_INTEGER_free(dh_pub_key); if (host) _krb5_pk_cert_free(host); if (content.data) @@ -1726,7 +1079,7 @@ _krb5_pk_rd_pa_reply(krb5_context context, ContentInfo ci; size_t size; - /* Check for PK-INIT -27 */ + /* Check for IETF PK-INIT first */ if (pa->padata_type == KRB5_PADATA_PK_AS_REP) { PA_PK_AS_REP rep; @@ -1747,7 +1100,7 @@ _krb5_pk_rd_pa_reply(krb5_context context, &size); if (ret) { krb5_set_error_string(context, - "PKINIT: -25 decoding failed DH " + "PKINIT: decoding failed DH " "ContentInfo: %d", ret); free_PA_PK_AS_REP(&rep); @@ -1821,7 +1174,7 @@ _krb5_pk_rd_pa_reply(krb5_context context, return ret; } ret = pk_rd_pa_reply_enckey(context, COMPAT_WIN2K, &ci, ctx, - etype, hi, nonce, NULL, pa, key); + etype, hi, nonce, req_buffer, pa, key); free_ContentInfo(&ci); break; default: @@ -1837,598 +1190,158 @@ _krb5_pk_rd_pa_reply(krb5_context context, return ret; } -static int -ssl_pass_cb(char *buf, int size, int rwflag, void *u) +struct prompter { + krb5_context context; + krb5_prompter_fct prompter; + void *prompter_data; +}; + +static int +hx_pass_prompter(void *data, const hx509_prompt *prompter) { krb5_error_code ret; krb5_prompt prompt; krb5_data password_data; - krb5_prompter_fct prompter = u; + struct prompter *p = data; - password_data.data = buf; - password_data.length = size; + password_data.data = prompter->reply->data; + password_data.length = prompter->reply->length; prompt.prompt = "Enter your private key passphrase: "; prompt.hidden = 1; prompt.reply = &password_data; - prompt.type = KRB5_PROMPT_TYPE_PASSWORD; + if (prompter->hidden) + prompt.type = KRB5_PROMPT_TYPE_PASSWORD; + else + prompt.type = KRB5_PROMPT_TYPE_PREAUTH; /* XXX */ - ret = (*prompter)(NULL, NULL, NULL, NULL, 1, &prompt); + ret = (*p->prompter)(p->context, p->prompter_data, NULL, NULL, 1, &prompt); if (ret) { - memset (buf, 0, size); + memset (prompter->reply->data, 0, prompter->reply->length); return 0; } - return strlen(buf); -} - -static krb5_error_code -load_openssl_cert(krb5_context context, - const char *file, - STACK_OF(X509) **c) -{ - STACK_OF(X509) *certificate; - krb5_error_code ret; - FILE *f; - - f = fopen(file, "r"); - if (f == NULL) { - ret = errno; - krb5_set_error_string(context, "PKINIT: open failed %s: %s", - file, strerror(ret)); - return ret; - } - - certificate = sk_X509_new_null(); - while (1) { - /* see http://www.openssl.org/docs/crypto/pem.html section BUGS */ - X509 *cert; - cert = PEM_read_X509(f, NULL, NULL, NULL); - if (cert == NULL) { - if (ERR_GET_REASON(ERR_peek_error()) == PEM_R_NO_START_LINE) { - /* End of file reached. no error */ - ERR_clear_error(); - break; - } - krb5_set_error_string(context, "PKINIT: Can't read certificate"); - fclose(f); - return HEIM_PKINIT_CERTIFICATE_INVALID; - } - sk_X509_insert(certificate, cert, sk_X509_num(certificate)); - } - fclose(f); - if (sk_X509_num(certificate) == 0) { - krb5_set_error_string(context, "PKINIT: No certificate found"); - return HEIM_PKINIT_NO_CERTIFICATE; - } - *c = certificate; - return 0; -} - -static krb5_error_code -load_openssl_file(krb5_context context, - char *password, - krb5_prompter_fct prompter, - void *prompter_data, - const char *user_id, - struct krb5_pk_identity *id) -{ - krb5_error_code ret; - STACK_OF(X509) *certificate = NULL; - char *cert_file = NULL, *key_file; - EVP_PKEY *private_key = NULL; - FILE *f; - - cert_file = strdup(user_id); - if (cert_file == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); - return ENOMEM; - } - key_file = strchr(cert_file, ','); - if (key_file == NULL) { - krb5_set_error_string(context, "PKINIT: key file missing"); - ret = HEIM_PKINIT_NO_PRIVATE_KEY; - goto out; - } - *key_file++ = '\0'; - - ret = load_openssl_cert(context, cert_file, &certificate); - if (ret) - goto out; - - /* load private key */ - f = fopen(key_file, "r"); - if (f == NULL) { - ret = errno; - krb5_set_error_string(context, "PKINIT: open %s: %s", - key_file, strerror(ret)); - goto out; - } - if (password == NULL || password[0] == '\0') { - if (prompter == NULL) - prompter = krb5_prompter_posix; - private_key = PEM_read_PrivateKey(f, NULL, ssl_pass_cb, prompter); - } else - private_key = PEM_read_PrivateKey(f, NULL, NULL, password); - fclose(f); - if (private_key == NULL) { - krb5_set_error_string(context, "PKINIT: Can't read private key"); - ret = HEIM_PKINIT_PRIVATE_KEY_INVALID; - goto out; - } - ret = X509_check_private_key(sk_X509_value(certificate, 0), private_key); - if (ret != 1) { - ret = HEIM_PKINIT_PRIVATE_KEY_INVALID; - krb5_set_error_string(context, - "PKINIT: The private key doesn't match " - "the public key certificate"); - goto out; - } - - id->private_key = private_key; - id->cert = certificate; - - return 0; - out: - if (cert_file) - free(cert_file); - if (certificate) - sk_X509_pop_free(certificate, X509_free); - if (private_key) - EVP_PKEY_free(private_key); - - return ret; -} - -static int -add_pair(krb5_context context, char *str, char ***cmds, int *num) -{ - char **c; - char *p; - int i; - - p = strchr(str, ':'); - if (p) { - *p = '\0'; - p++; - } - - /* filter out dup keys */ - for (i = 0; i < *num; i++) - if (strcmp((*cmds)[i * 2], str) == 0) - return 0; - - c = realloc(*cmds, sizeof(*c) * ((*num + 1) * 2)); - if (c == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); - return ENOMEM; - } - - c[(*num * 2)] = str; - c[(*num * 2) + 1] = p; - *num += 1; - *cmds = c; - return 0; -} - -static krb5_error_code -eval_pairs(krb5_context context, ENGINE *e, const char *name, - const char *type, char **cmds, int num) -{ - int i; - - for (i = 0; i < num; i++) { - char *a1 = cmds[i * 2], *a2 = cmds[(i * 2) + 1]; - if(!ENGINE_ctrl_cmd_string(e, a1, a2, 0)) { - krb5_set_error_string(context, - "PKINIT: Failed %scommand (%s - %s:%s): %s", - type, name, a1, a2 ? a2 : "(NULL)", - ERR_error_string(ERR_get_error(), NULL)); - return HEIM_PKINIT_NO_PRIVATE_KEY; - } - } - return 0; -} - -struct engine_context { - char **pre_cmds; - char **post_cmds; - int num_pre; - int num_post; - char *engine_name; - char *cert_file; - char *key_id; -}; - -static krb5_error_code -parse_openssl_engine_conf(krb5_context context, - struct engine_context *ctx, - char *line) -{ - krb5_error_code ret; - char *last, *p, *q; - - for (p = strtok_r(line, ",", &last); - p != NULL; - p = strtok_r(NULL, ",", &last)) { - - q = strchr(p, '='); - if (q == NULL) { - krb5_set_error_string(context, - "PKINIT: openssl engine configuration " - "key %s missing = and thus value", p); - return HEIM_PKINIT_NO_PRIVATE_KEY; - } - *q = '\0'; - q++; - if (strcasecmp("PRE", p) == 0) { - ret = add_pair(context, q, &ctx->pre_cmds, &ctx->num_pre); - if (ret) - return ret; - } else if (strcasecmp("POST", p) == 0) { - ret = add_pair(context, q, &ctx->post_cmds, &ctx->num_post); - if (ret) - return ret; - } else if (strcasecmp("KEY", p) == 0) { - ctx->key_id = q; - } else if (strcasecmp("CERT", p) == 0) { - ctx->cert_file = q; - } else if (strcasecmp("ENGINE", p) == 0) { - ctx->engine_name = q; - } else { - krb5_set_error_string(context, - "PKINIT: openssl engine configuration " - "key %s is unknown", p); - return HEIM_PKINIT_NO_PRIVATE_KEY; - } - } - return 0; -} - - -static krb5_error_code -load_openssl_engine(krb5_context context, - char *password, - krb5_prompter_fct prompter, - void *prompter_data, - const char *string, - struct krb5_pk_identity *id) -{ - struct engine_context ctx; - krb5_error_code ret; - const char *f; - char *file_conf = NULL, *user_conf = NULL; - ENGINE *e = NULL; - - memset(&ctx, 0, sizeof(ctx)); - - ENGINE_load_builtin_engines(); - - user_conf = strdup(string); - if (user_conf == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); - return ENOMEM; - } - - ret = parse_openssl_engine_conf(context, &ctx, user_conf); - if (ret) - goto out; - - f = krb5_config_get_string_default(context, NULL, NULL, - "libdefaults", - "pkinit-openssl-engine", - NULL); - if (f) { - file_conf = strdup(f); - if (file_conf) { - ret = parse_openssl_engine_conf(context, &ctx, file_conf); - if (ret) - goto out; - } - } - - if (ctx.cert_file == NULL) { - krb5_set_error_string(context, - "PKINIT: openssl engine missing certificate"); - ret = HEIM_PKINIT_NO_CERTIFICATE; - goto out; - } - if (ctx.key_id == NULL) { - krb5_set_error_string(context, - "PKINIT: openssl engine missing key id"); - ret = HEIM_PKINIT_NO_PRIVATE_KEY; - goto out; - } - if (ctx.engine_name == NULL) { - krb5_set_error_string(context, - "PKINIT: openssl engine missing engine name"); - ret = HEIM_PKINIT_NO_PRIVATE_KEY; - goto out; - } - - e = ENGINE_by_id(ctx.engine_name); - if (e == NULL) { - krb5_set_error_string(context, - "PKINIT: failed getting openssl engine %s: %s", - ctx.engine_name, - ERR_error_string(ERR_get_error(), NULL)); - ret = HEIM_PKINIT_NO_PRIVATE_KEY; - goto out; - } - - ret = eval_pairs(context, e, ctx.engine_name, "pre", - ctx.pre_cmds, ctx.num_pre); - if (ret) - goto out; - - if(!ENGINE_init(e)) { - ret = HEIM_PKINIT_NO_PRIVATE_KEY; - krb5_set_error_string(context, - "PKINIT: openssl engine init %s failed: %s", - ctx.engine_name, - ERR_error_string(ERR_get_error(), NULL)); - ENGINE_free(e); - goto out; - } - - ret = eval_pairs(context, e, ctx.engine_name, "post", - ctx.post_cmds, ctx.num_post); - if (ret) - goto out; - - /* - * If the engine supports a LOAD_CERT_CTRL function, lets try - * it. OpenSC support this function. Eventially this should be - * a ENGINE_load_cert function if it failes, treat it like a - * non fatal error. - */ - { - struct { - const char * cert_id; - X509 * cert; - } parms; - - parms.cert_id = ctx.cert_file; - parms.cert = NULL; - ENGINE_ctrl_cmd(e, "LOAD_CERT_CTRL", 0, &parms, NULL, 1); - if (parms.cert) { - id->cert = sk_X509_new_null(); - sk_X509_insert(id->cert, parms.cert, 0); - } - } - - if (id->cert == NULL) { - ret = load_openssl_cert(context, ctx.cert_file, &id->cert); - if (ret) - goto out; - } - - { - UI_METHOD * krb5_ui_method = NULL; - struct krb5_ui_data ui_data; - - krb5_ui_method = UI_create_method("Krb5 ui method"); - if (krb5_ui_method == NULL) { - krb5_set_error_string(context, - "PKINIT: failed to setup prompter " - "function: %s", - ERR_error_string(ERR_get_error(), NULL)); - ret = HEIM_PKINIT_NO_PRIVATE_KEY; - goto out; - } - UI_method_set_reader(krb5_ui_method, krb5_ui_method_read_string); - - ui_data.context = context; - ui_data.prompter = prompter; - if (prompter == NULL) - ui_data.prompter = krb5_prompter_posix; - ui_data.prompter_data = prompter_data; - - id->private_key = ENGINE_load_private_key(e, - ctx.key_id, - krb5_ui_method, - (void*) &ui_data); - UI_destroy_method(krb5_ui_method); - } - - if (id->private_key == NULL) { - krb5_set_error_string(context, - "PKINIT: failed to load private key: %s", - ERR_error_string(ERR_get_error(), NULL)); - ret = HEIM_PKINIT_NO_PRIVATE_KEY; - goto out; - } - - ret = X509_check_private_key(sk_X509_value(id->cert, 0), id->private_key); - if (ret != 1) { - ret = HEIM_PKINIT_PRIVATE_KEY_INVALID; - krb5_set_error_string(context, - "PKINIT: The private key doesn't match " - "the public key certificate"); - goto out; - } - - if (user_conf) - free(user_conf); - if (file_conf) - free(file_conf); - - id->engine = e; - - return 0; - - out: - if (user_conf) - free(user_conf); - if (file_conf) - free(file_conf); - if (e) { - ENGINE_finish(e); /* make sure all shared libs are unloaded */ - ENGINE_free(e); - } - - return ret; + return strlen(prompter->reply->data); } krb5_error_code KRB5_LIB_FUNCTION -_krb5_pk_load_openssl_id(krb5_context context, - struct krb5_pk_identity **ret_id, - const char *user_id, - const char *x509_anchors, - krb5_prompter_fct prompter, - void *prompter_data, - char *password) +_krb5_pk_load_id(krb5_context context, + struct krb5_pk_identity **ret_id, + const char *user_id, + const char *anchor_id, + char * const *chain, + char * const *revoke, + krb5_prompter_fct prompter, + void *prompter_data, + char *password) { - STACK_OF(X509) *trusted_certs = NULL; struct krb5_pk_identity *id = NULL; - krb5_error_code ret; - struct dirent *file; - char *dirname = NULL; - DIR *dir; - FILE *f; - krb5_error_code (*load_pair)(krb5_context, - char *, - krb5_prompter_fct, - void *, - const char *, - struct krb5_pk_identity *) = NULL; - + hx509_lock lock = NULL; + struct prompter p; + int ret; *ret_id = NULL; - if (x509_anchors == NULL) { - krb5_set_error_string(context, "PKINIT: No root ca directory given"); + if (anchor_id == NULL) { + krb5_set_error_string(context, "PKINIT: No anchor given"); return HEIM_PKINIT_NO_VALID_CA; } if (user_id == NULL) { krb5_set_error_string(context, - "PKINIT: No user X509 source given given"); + "PKINIT: No user certificate given"); return HEIM_PKINIT_NO_PRIVATE_KEY; } - /* - * - */ - - if (strncasecmp(user_id, "FILE:", 5) == 0) { - load_pair = load_openssl_file; - user_id += 5; - } else if (strncasecmp(user_id, "ENGINE:", 7) == 0) { - load_pair = load_openssl_engine; - user_id += 7; - } else { - krb5_set_error_string(context, "PKINIT: user identity not FILE"); - return HEIM_PKINIT_NO_CERTIFICATE; - } - if (strncasecmp(x509_anchors, "OPENSSL-ANCHOR-DIR:", 19) != 0) { - krb5_set_error_string(context, "PKINIT: anchor OPENSSL-ANCHOR-DIR"); - return HEIM_PKINIT_NO_VALID_CA; - } - x509_anchors += 19; + /* load cert */ - id = malloc(sizeof(*id)); + id = calloc(1, sizeof(*id)); if (id == NULL) { krb5_set_error_string(context, "malloc: out of memory"); ret = ENOMEM; goto out; } - memset(id, 0, sizeof(*id)); - OpenSSL_add_all_algorithms(); - ERR_load_crypto_strings(); - - - ret = (*load_pair)(context, password, prompter, prompter_data, user_id, id); + ret = hx509_context_init(&id->hx509ctx); if (ret) goto out; - /* load anchors */ + ret = hx509_lock_init(id->hx509ctx, &lock); + if (password) + hx509_lock_add_password(lock, password); - dirname = strdup(x509_anchors); - if (dirname == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); - ret = ENOMEM; - goto out; - } + if (prompter) { + p.context = context; + p.prompter = prompter; + p.prompter_data = prompter_data; - { - size_t len; - len = strlen(dirname); - if (dirname[len - 1] == '/') - dirname[len - 1] = '\0'; + ret = hx509_lock_set_prompter(lock, hx_pass_prompter, &p); + if (ret) + goto out; } - /* read ca certificates */ - dir = opendir(dirname); - if (dir == NULL) { - ret = errno; - krb5_set_error_string(context, "PKINIT: open directory %s: %s", - dirname, strerror(ret)); + ret = hx509_certs_init(id->hx509ctx, user_id, 0, NULL, &id->certs); + if (ret) goto out; - } - trusted_certs = sk_X509_new_null(); - while ((file = readdir(dir)) != NULL) { - X509 *cert; - char *filename; + ret = hx509_certs_init(id->hx509ctx, anchor_id, 0, NULL, &id->anchors); + if (ret) + goto out; - /* - * Assume the certificate filenames constist of hashed subject - * name followed by suffix ".0" - */ + ret = hx509_certs_init(id->hx509ctx, "MEMORY:pkinit-cert-chain", + 0, NULL, &id->certpool); + if (ret) + goto out; - if (strlen(file->d_name) == 10 && strcmp(&file->d_name[8],".0") == 0) { - asprintf(&filename, "%s/%s", dirname, file->d_name); - if (filename == NULL) { - ret = ENOMEM; - krb5_set_error_string(context, "malloc: out or memory"); - goto out; - } - f = fopen(filename, "r"); - if (f == NULL) { - ret = errno; - krb5_set_error_string(context, "PKINIT: open %s: %s", - filename, strerror(ret)); - free(filename); - closedir(dir); - goto out; - } - cert = PEM_read_X509(f, NULL, NULL, NULL); - fclose(f); - if (cert != NULL) { - /* order of the certs is not important */ - sk_X509_push(trusted_certs, cert); - } - free(filename); + while (chain && *chain) { + ret = hx509_certs_append(id->hx509ctx, id->certpool, NULL, *chain); + if (ret) { + krb5_set_error_string(context, + "pkinit failed to load chain %s", + *chain); + goto out; } + chain++; } - closedir(dir); - if (sk_X509_num(trusted_certs) == 0) { - krb5_set_error_string(context, - "PKINIT: No CA certificate(s) found in %s", - dirname); - ret = HEIM_PKINIT_NO_VALID_CA; - goto out; - } + if (revoke) { + ret = hx509_revoke_init(id->hx509ctx, &id->revoke); + if (ret) { + krb5_set_error_string(context, "revoke failed to init"); + goto out; + } - id->trusted_certs = trusted_certs; + while (*revoke) { + ret = hx509_revoke_add_crl(id->hx509ctx, id->revoke, *revoke); + if (ret) { + krb5_set_error_string(context, + "pkinit failed to load revoke %s", + *revoke); + goto out; + } + revoke++; + } + } else + hx509_context_set_missing_revoke(id->hx509ctx, 1); - *ret_id = id; + ret = hx509_verify_init_ctx(id->hx509ctx, &id->verify_ctx); + if (ret) + goto out; - return 0; + hx509_verify_attach_anchors(id->verify_ctx, id->anchors); + hx509_verify_attach_revoke(id->verify_ctx, id->revoke); - out: - if (dirname) - free(dirname); - if (trusted_certs) - sk_X509_pop_free(trusted_certs, X509_free); - if (id) { - if (id->cert) - sk_X509_pop_free(id->cert, X509_free); - if (id->private_key) - EVP_PKEY_free(id->private_key); +out: + if (ret) { + hx509_verify_destroy_ctx(id->verify_ctx); + hx509_certs_free(&id->certs); + hx509_certs_free(&id->anchors); + hx509_certs_free(&id->certpool); + hx509_revoke_free(&id->revoke); + hx509_context_free(&id->hx509ctx); free(id); - } + } else + *ret_id = id; + + hx509_lock_free(lock); return ret; } @@ -2704,17 +1617,12 @@ _krb5_get_init_creds_opt_free_pkinit(krb5_get_init_creds_opt *opt) DH_free(ctx->dh); ctx->dh = NULL; if (ctx->id) { - if (ctx->id->cert) - sk_X509_pop_free(ctx->id->cert, X509_free); - if (ctx->id->trusted_certs) - sk_X509_pop_free(ctx->id->trusted_certs, X509_free); - if (ctx->id->private_key) - EVP_PKEY_free(ctx->id->private_key); - if (ctx->id->engine) { - ENGINE_finish(ctx->id->engine); /* unload shared libs etc */ - ENGINE_free(ctx->id->engine); - ctx->id->engine = NULL; - } + hx509_verify_destroy_ctx(ctx->id->verify_ctx); + hx509_certs_free(&ctx->id->certs); + hx509_certs_free(&ctx->id->anchors); + hx509_certs_free(&ctx->id->certpool); + hx509_context_free(&ctx->id->hx509ctx); + if (ctx->clientDHNonce) { krb5_free_data(NULL, ctx->clientDHNonce); ctx->clientDHNonce = NULL; @@ -2734,6 +1642,8 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context, krb5_principal principal, const char *user_id, const char *x509_anchors, + char * const * chain, + char * const * revoke, int flags, krb5_prompter_fct prompter, void *prompter_data, @@ -2757,14 +1667,18 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context, 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->opt_private->pk_init_ctx->id, - user_id, - x509_anchors, - prompter, - prompter_data, - password); + opt->opt_private->pk_init_ctx->require_eku = 1; + opt->opt_private->pk_init_ctx->require_krbtgt_otherName = 1; + + ret = _krb5_pk_load_id(context, + &opt->opt_private->pk_init_ctx->id, + user_id, + x509_anchors, + chain, + revoke, + prompter, + prompter_data, + password); if (ret) { free(opt->opt_private->pk_init_ctx); opt->opt_private->pk_init_ctx = NULL; diff --git a/source4/heimdal/lib/krb5/principal.c b/source4/heimdal/lib/krb5/principal.c index 6cc49945cc..34086b1fbe 100644 --- a/source4/heimdal/lib/krb5/principal.c +++ b/source4/heimdal/lib/krb5/principal.c @@ -41,7 +41,7 @@ #include #include "resolve.h" -RCSID("$Id: principal.c,v 1.92 2005/12/11 17:48:13 lha Exp $"); +RCSID("$Id: principal.c,v 1.94 2006/04/10 10:10:01 lha Exp $"); #define princ_num_comp(P) ((P)->name.name_string.len) #define princ_type(P) ((P)->name.name_type) @@ -105,7 +105,7 @@ parse_name(krb5_context context, { krb5_error_code ret; heim_general_string *comp; - heim_general_string realm; + heim_general_string realm = NULL; int ncomp; const char *p; @@ -246,6 +246,7 @@ exit: free(comp[--n]); } free(comp); + free(realm); free(s); return ret; } @@ -825,16 +826,21 @@ krb5_425_conv_principal_ext2(krb5_context context, struct dns_reply *r; r = dns_lookup(instance, "aaaa"); - if (r && r->head && r->head->type == T_AAAA) { - inst = strdup(r->head->domain); + if (r) { + if (r->head && r->head->type == T_AAAA) { + inst = strdup(r->head->domain); + dns_free_data(r); + passed = TRUE; + } dns_free_data(r); - passed = TRUE; } else { r = dns_lookup(instance, "a"); - if(r && r->head && r->head->type == T_A) { - inst = strdup(r->head->domain); + if (r) { + if(r->head && r->head->type == T_A) { + inst = strdup(r->head->domain); + passed = TRUE; + } dns_free_data(r); - passed = TRUE; } } #else diff --git a/source4/heimdal/lib/krb5/rd_cred.c b/source4/heimdal/lib/krb5/rd_cred.c index d62adadf26..520b3a1418 100644 --- a/source4/heimdal/lib/krb5/rd_cred.c +++ b/source4/heimdal/lib/krb5/rd_cred.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: rd_cred.c,v 1.26 2005/11/02 08:36:42 lha Exp $"); +RCSID("$Id: rd_cred.c,v 1.28 2006/04/02 02:27:33 lha Exp $"); static krb5_error_code compare_addrs(krb5_context context, @@ -257,8 +257,10 @@ krb5_rd_cred(krb5_context context, ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length, &cred.tickets.val[i], &len, ret); - if (ret) + if (ret) { + free(creds); goto out; + } if(creds->ticket.length != len) krb5_abortx(context, "internal error in ASN.1 encoder"); copy_EncryptionKey (&kci->key, &creds->session); @@ -302,6 +304,7 @@ krb5_rd_cred(krb5_context context, for(i = 0; (*ret_creds)[i]; i++) krb5_free_creds(context, (*ret_creds)[i]); free(*ret_creds); + *ret_creds = NULL; } return ret; } diff --git a/source4/heimdal/lib/krb5/rd_priv.c b/source4/heimdal/lib/krb5/rd_priv.c index bf82ad556e..c52ac175fd 100644 --- a/source4/heimdal/lib/krb5/rd_priv.c +++ b/source4/heimdal/lib/krb5/rd_priv.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: rd_priv.c,v 1.32 2006/03/18 22:15:57 lha Exp $"); +RCSID("$Id: rd_priv.c,v 1.33 2006/04/12 16:18:10 lha Exp $"); krb5_error_code KRB5_LIB_FUNCTION krb5_rd_priv(krb5_context context, @@ -50,8 +50,8 @@ krb5_rd_priv(krb5_context context, krb5_keyblock *key; krb5_crypto crypto; - if (outdata) - krb5_data_zero(outdata); + if (outbuf) + krb5_data_zero(outbuf); if ((auth_context->flags & (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE)) && @@ -161,7 +161,7 @@ krb5_rd_priv(krb5_context context, (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE))) { /* if these fields are not present in the priv-part, silently return zero */ - krb5_data_zero(outdata); + memset(outdata, 0, sizeof(*outdata)); if(part.timestamp) outdata->timestamp = *part.timestamp; if(part.usec) diff --git a/source4/heimdal/lib/krb5/rd_req.c b/source4/heimdal/lib/krb5/rd_req.c index 313c14f6e6..0d4635b964 100644 --- a/source4/heimdal/lib/krb5/rd_req.c +++ b/source4/heimdal/lib/krb5/rd_req.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: rd_req.c,v 1.61 2005/11/29 18:22:51 lha Exp $"); +RCSID("$Id: rd_req.c,v 1.63 2006/04/10 10:14:44 lha Exp $"); static krb5_error_code decrypt_tkt_enc_part (krb5_context context, @@ -279,8 +279,10 @@ krb5_verify_authenticator_checksum(krb5_context context, &authenticator); if(ret) return ret; - if(authenticator->cksum == NULL) + if(authenticator->cksum == NULL) { + krb5_free_authenticator(context, &authenticator); return -17; + } ret = krb5_auth_con_getkey(context, ac, &key); if(ret) { krb5_free_authenticator(context, &authenticator); @@ -340,6 +342,9 @@ krb5_verify_ap_req2(krb5_context context, krb5_error_code ret; EtypeList etypes; + if (ticket) + *ticket = NULL; + if (auth_context && *auth_context) { ac = *auth_context; } else { @@ -348,13 +353,12 @@ krb5_verify_ap_req2(krb5_context context, return ret; } - t = malloc(sizeof(*t)); + t = calloc(1, sizeof(*t)); if (t == NULL) { ret = ENOMEM; krb5_clear_error_string (context); goto out; } - memset(t, 0, sizeof(*t)); if (ap_req->ap_options.use_session_key && ac->keyblock){ ret = krb5_decrypt_ticket(context, &ap_req->ticket, @@ -372,14 +376,17 @@ krb5_verify_ap_req2(krb5_context context, if(ret) goto out; - _krb5_principalname2krb5_principal(&t->server, ap_req->ticket.sname, - ap_req->ticket.realm); - _krb5_principalname2krb5_principal(&t->client, t->ticket.cname, - t->ticket.crealm); + ret = _krb5_principalname2krb5_principal(&t->server, ap_req->ticket.sname, + ap_req->ticket.realm); + if (ret) goto out; + ret = _krb5_principalname2krb5_principal(&t->client, t->ticket.cname, + t->ticket.crealm); + if (ret) goto out; /* save key */ - krb5_copy_keyblock(context, &t->ticket.key, &ac->keyblock); + ret = krb5_copy_keyblock(context, &t->ticket.key, &ac->keyblock); + if (ret) goto out; ret = decrypt_authenticator (context, &t->ticket.key, diff --git a/source4/heimdal/lib/krb5/replay.c b/source4/heimdal/lib/krb5/replay.c index ec99f86c7c..b89f150159 100644 --- a/source4/heimdal/lib/krb5/replay.c +++ b/source4/heimdal/lib/krb5/replay.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include -RCSID("$Id: replay.c,v 1.10 2004/05/25 21:41:15 lha Exp $"); +RCSID("$Id: replay.c,v 1.12 2006/04/10 17:13:49 lha Exp $"); struct krb5_rcache_data { char *name; @@ -58,6 +58,7 @@ krb5_rc_resolve_type(krb5_context context, krb5_rcache *id, const char *type) { + *id = NULL; if(strcmp(type, "FILE")) { krb5_set_error_string (context, "replay cache type %s not supported", type); @@ -77,6 +78,9 @@ krb5_rc_resolve_full(krb5_context context, const char *string_name) { krb5_error_code ret; + + *id = NULL; + if(strncmp(string_name, "FILE:", 5)) { krb5_set_error_string (context, "replay cache type %s not supported", string_name); @@ -86,6 +90,10 @@ krb5_rc_resolve_full(krb5_context context, if(ret) return ret; ret = krb5_rc_resolve(context, *id, string_name + 5); + if (ret) { + krb5_rc_close(context, *id); + *id = NULL; + } return ret; } diff --git a/source4/heimdal/lib/krb5/send_to_kdc.c b/source4/heimdal/lib/krb5/send_to_kdc.c index d3d21aea3f..0bcafa70a1 100644 --- a/source4/heimdal/lib/krb5/send_to_kdc.c +++ b/source4/heimdal/lib/krb5/send_to_kdc.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: send_to_kdc.c,v 1.57 2006/03/07 19:39:59 lha Exp $"); +RCSID("$Id: send_to_kdc.c,v 1.58 2006/04/02 02:32:03 lha Exp $"); struct send_and_recv { krb5_send_and_recv_func_t func; @@ -231,6 +231,7 @@ send_and_recv_http(int fd, s[rep->length] = 0; p = strstr(s, "\r\n\r\n"); if(p == NULL) { + krb5_data_zero(rep); free(s); return -1; } @@ -238,12 +239,14 @@ send_and_recv_http(int fd, rep->data = s; rep->length -= p - s; if(rep->length < 4) { /* remove length */ + krb5_data_zero(rep); free(s); return -1; } rep->length -= 4; _krb5_get_int(p, &rep_len, 4); if (rep_len != rep->length) { + krb5_data_zero(rep); free(s); return -1; } diff --git a/source4/heimdal/lib/krb5/store.c b/source4/heimdal/lib/krb5/store.c index 42667765fb..4a567bb379 100644 --- a/source4/heimdal/lib/krb5/store.c +++ b/source4/heimdal/lib/krb5/store.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include "store-int.h" -RCSID("$Id: store.c,v 1.50 2005/06/17 04:36:33 lha Exp $"); +RCSID("$Id: store.c,v 1.51 2006/04/07 22:23:20 lha Exp $"); #define BYTEORDER_IS(SP, V) (((SP)->flags & KRB5_STORAGE_BYTEORDER_MASK) == (V)) #define BYTEORDER_IS_LE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_LE) @@ -420,7 +420,7 @@ krb5_ret_principal(krb5_storage *sp, if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) type = KRB5_NT_UNKNOWN; - else if((ret = krb5_ret_int32(sp, &type))){ + else if((ret = krb5_ret_int32(sp, &type))){ free(p); return ret; } @@ -430,18 +430,31 @@ krb5_ret_principal(krb5_storage *sp, } if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS)) ncomp--; + if (ncomp < 0) { + free(p); + return EINVAL; + } p->name.name_type = type; p->name.name_string.len = ncomp; ret = krb5_ret_string(sp, &p->realm); - if(ret) return ret; + if(ret) { + free(p); + return ret; + } p->name.name_string.val = calloc(ncomp, sizeof(*p->name.name_string.val)); - if(p->name.name_string.val == NULL){ + if(p->name.name_string.val == NULL && ncomp != 0){ free(p->realm); return ENOMEM; } for(i = 0; i < ncomp; i++){ ret = krb5_ret_string(sp, &p->name.name_string.val[i]); - if(ret) return ret; /* XXX */ + if(ret) { + while (i >= 0) + free(p->name.name_string.val[i--]); + free(p->realm); + free(p); + return ret; + } } *princ = p; return 0; diff --git a/source4/heimdal/lib/krb5/transited.c b/source4/heimdal/lib/krb5/transited.c index 9e24db0da0..7f18b30c88 100644 --- a/source4/heimdal/lib/krb5/transited.c +++ b/source4/heimdal/lib/krb5/transited.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: transited.c,v 1.16 2005/06/17 04:53:35 lha Exp $"); +RCSID("$Id: transited.c,v 1.18 2006/04/10 10:26:35 lha Exp $"); /* this is an attempt at one of the most horrible `compression' schemes that has ever been invented; it's so amazingly brain-dead @@ -100,8 +100,10 @@ make_path(krb5_context context, struct tr_realm *r, p = from + strlen(from); while(1){ while(p >= from && *p != '/') p--; - if(p == from) + if(p == from) { + r->next = path; /* XXX */ return KRB5KDC_ERR_POLICY; + } if(strncmp(to, from, p - from) == 0) break; tmp = calloc(1, sizeof(*tmp)); @@ -166,10 +168,13 @@ expand_realms(krb5_context context, for(r = realms; r; r = r->next){ if(r->trailing_dot){ char *tmp; - size_t len = strlen(r->realm) + strlen(prev_realm) + 1; + size_t len; if(prev_realm == NULL) prev_realm = client_realm; + + len = strlen(r->realm) + strlen(prev_realm) + 1; + tmp = realloc(r->realm, len); if(tmp == NULL){ free_realms(realms); diff --git a/source4/heimdal/lib/krb5/v4_glue.c b/source4/heimdal/lib/krb5/v4_glue.c index c66b06c09f..dd294c8943 100644 --- a/source4/heimdal/lib/krb5/v4_glue.c +++ b/source4/heimdal/lib/krb5/v4_glue.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: v4_glue.c,v 1.2 2005/04/24 13:44:02 lha Exp $"); +RCSID("$Id: v4_glue.c,v 1.3 2006/04/02 01:39:54 lha Exp $"); #include "krb5-v4compat.h" @@ -155,19 +155,20 @@ write_v4_cc(krb5_context context, const char *tkfile, fd = open(path, O_WRONLY|O_CREAT, 0600); if (fd < 0) { - free(path); + ret = errno; krb5_set_error_string(context, "krb5_krb_tf_setup: error opening file %s", path); - return errno; + free(path); + return ret; } if (fstat(fd, &sb) != 0 || !S_ISREG(sb.st_mode)) { - free(path); - close(fd); krb5_set_error_string(context, "krb5_krb_tf_setup: tktfile %s is not a file", path); + free(path); + close(fd); return KRB5_FCC_PERM; } @@ -178,11 +179,11 @@ write_v4_cc(krb5_context context, const char *tkfile, break; } if (i == KRB5_TF_LCK_RETRY_COUNT) { - free(path); - close(fd); krb5_set_error_string(context, "krb5_krb_tf_setup: failed to lock %s", path); + free(path); + close(fd); return KRB5_FCC_PERM; } @@ -190,11 +191,11 @@ write_v4_cc(krb5_context context, const char *tkfile, ret = ftruncate(fd, 0); if (ret < 0) { flock(fd, LOCK_UN); - free(path); - close(fd); krb5_set_error_string(context, "krb5_krb_tf_setup: failed to truncate %s", path); + free(path); + close(fd); return KRB5_FCC_PERM; } } -- cgit