summaryrefslogtreecommitdiff
path: root/source4/heimdal/lib/krb5
diff options
context:
space:
mode:
Diffstat (limited to 'source4/heimdal/lib/krb5')
-rw-r--r--source4/heimdal/lib/krb5/acache.c9
-rw-r--r--source4/heimdal/lib/krb5/config_file.c8
-rw-r--r--source4/heimdal/lib/krb5/context.c4
-rw-r--r--source4/heimdal/lib/krb5/crypto.c17
-rw-r--r--source4/heimdal/lib/krb5/fcache.c63
-rw-r--r--source4/heimdal/lib/krb5/get_cred.c4
-rw-r--r--source4/heimdal/lib/krb5/init_creds.c7
-rw-r--r--source4/heimdal/lib/krb5/init_creds_pw.c36
-rw-r--r--source4/heimdal/lib/krb5/krb5-private.h34
-rw-r--r--source4/heimdal/lib/krb5/krb5-protos.h189
-rw-r--r--source4/heimdal/lib/krb5/krb5.h9
-rw-r--r--source4/heimdal/lib/krb5/krb5_locl.h14
-rw-r--r--source4/heimdal/lib/krb5/krbhst.c27
-rw-r--r--source4/heimdal/lib/krb5/log.c4
-rwxr-xr-xsource4/heimdal/lib/krb5/mit_glue.c17
-rw-r--r--source4/heimdal/lib/krb5/mk_req_ext.c6
-rw-r--r--source4/heimdal/lib/krb5/pac.c1034
-rwxr-xr-xsource4/heimdal/lib/krb5/pkinit.c220
-rw-r--r--source4/heimdal/lib/krb5/plugin.c10
-rw-r--r--source4/heimdal/lib/krb5/principal.c4
-rw-r--r--source4/heimdal/lib/krb5/rd_req.c43
-rw-r--r--source4/heimdal/lib/krb5/store.c3
-rw-r--r--source4/heimdal/lib/krb5/ticket.c38
-rw-r--r--source4/heimdal/lib/krb5/warn.c8
24 files changed, 1637 insertions, 171 deletions
diff --git a/source4/heimdal/lib/krb5/acache.c b/source4/heimdal/lib/krb5/acache.c
index 004926bc89..d20c24699b 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.16 2006/10/19 11:41:38 lha Exp $");
+RCSID("$Id: acache.c,v 1.17 2007/01/08 15:31:01 lha Exp $");
/* XXX should we fetch these for each open ? */
static HEIMDAL_MUTEX acc_mutex = HEIMDAL_MUTEX_INITIALIZER;
@@ -106,7 +106,12 @@ init_ccapi(krb5_context context)
}
#ifdef HAVE_DLOPEN
- cc_handle = dlopen(lib, 0);
+
+#ifndef RTLD_LAZY
+#define RTLD_LAZY 0
+#endif
+
+ cc_handle = dlopen(lib, RTLD_LAZY);
if (cc_handle == NULL) {
HEIMDAL_MUTEX_unlock(&acc_mutex);
krb5_set_error_string(context, "Failed to load %s", lib);
diff --git a/source4/heimdal/lib/krb5/config_file.c b/source4/heimdal/lib/krb5/config_file.c
index 66051303ed..bbd9cf4c78 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.54 2006/04/02 00:59:19 lha Exp $");
+RCSID("$Id: config_file.c,v 1.55 2006/12/04 23:35:54 lha Exp $");
#ifndef HAVE_NETINFO
@@ -158,8 +158,7 @@ parse_list(struct fileptr *f, unsigned *lineno, krb5_config_binding **parent,
char *p;
++*lineno;
- if (buf[strlen(buf) - 1] == '\n')
- buf[strlen(buf) - 1] = '\0';
+ buf[strcspn(buf, "\r\n")] = '\0';
p = buf;
while(isspace((unsigned char)*p))
++p;
@@ -255,8 +254,7 @@ krb5_config_parse_debug (struct fileptr *f,
char *p;
++*lineno;
- if(buf[strlen(buf) - 1] == '\n')
- buf[strlen(buf) - 1] = '\0';
+ buf[strcspn(buf, "\r\n")] = '\0';
p = buf;
while(isspace((unsigned char)*p))
++p;
diff --git a/source4/heimdal/lib/krb5/context.c b/source4/heimdal/lib/krb5/context.c
index f3b0fad347..d0317da375 100644
--- a/source4/heimdal/lib/krb5/context.c
+++ b/source4/heimdal/lib/krb5/context.c
@@ -34,7 +34,7 @@
#include "krb5_locl.h"
#include <com_err.h>
-RCSID("$Id: context.c,v 1.111 2006/11/08 02:55:46 lha Exp $");
+RCSID("$Id: context.c,v 1.112 2006/11/24 14:24:33 lha Exp $");
#define INIT_FIELD(C, T, E, D, F) \
(C)->E = krb5_config_get_ ## T ## _default ((C), NULL, (D), \
@@ -180,7 +180,7 @@ init_context_from_config_file(krb5_context context)
/* prefer dns_lookup_kdc over srv_lookup. */
INIT_FIELD(context, bool, srv_lookup, TRUE, "srv_lookup");
INIT_FIELD(context, bool, srv_lookup, context->srv_lookup, "dns_lookup_kdc");
- INIT_FIELD(context, int, large_msg_size, 6000, "large_message_size");
+ INIT_FIELD(context, int, large_msg_size, 1400, "large_message_size");
INIT_FIELD(context, bool, dns_canonicalize_hostname, TRUE, "dns_canonicalize_hostname");
context->default_cc_name = NULL;
return 0;
diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c
index 9f6ef6b82b..6d4a81baa8 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.145 2006/10/22 07:32:40 lha Exp $");
+RCSID("$Id: crypto.c,v 1.146 2006/11/17 21:58:47 lha Exp $");
#undef CRYPTO_DEBUG
#ifdef CRYPTO_DEBUG
@@ -1076,6 +1076,21 @@ krb5_enctype_keysize(krb5_context context,
}
krb5_error_code KRB5_LIB_FUNCTION
+krb5_enctype_keybits(krb5_context context,
+ krb5_enctype type,
+ size_t *keybits)
+{
+ struct encryption_type *et = _find_enctype(type);
+ if(et == NULL) {
+ krb5_set_error_string(context, "encryption type %d not supported",
+ type);
+ return KRB5_PROG_ETYPE_NOSUPP;
+ }
+ *keybits = et->keytype->bits;
+ return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
krb5_generate_random_keyblock(krb5_context context,
krb5_enctype type,
krb5_keyblock *key)
diff --git a/source4/heimdal/lib/krb5/fcache.c b/source4/heimdal/lib/krb5/fcache.c
index 79b809d2a2..7441509e38 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.52 2006/04/02 01:04:37 lha Exp $");
+RCSID("$Id: fcache.c,v 1.54 2006/12/15 21:35:52 lha Exp $");
typedef struct krb5_fcache{
char *filename;
@@ -699,6 +699,62 @@ fcc_get_version(krb5_context context,
return FCACHE(id)->version;
}
+struct fcache_iter {
+ int first;
+};
+
+static krb5_error_code
+fcc_get_cache_first(krb5_context context, krb5_cc_cursor *cursor)
+{
+ struct fcache_iter *iter;
+
+ iter = calloc(1, sizeof(*iter));
+ if (iter == NULL) {
+ krb5_set_error_string(context, "malloc - out of memory");
+ return ENOMEM;
+ }
+ iter->first = 1;
+ *cursor = iter;
+ return 0;
+}
+
+static krb5_error_code
+fcc_get_cache_next(krb5_context context, krb5_cc_cursor cursor, krb5_ccache *id)
+{
+ struct fcache_iter *iter = cursor;
+ krb5_error_code ret;
+ const char *fn;
+ char *expandedfn = NULL;
+
+ if (!iter->first) {
+ krb5_clear_error_string(context);
+ return KRB5_CC_END;
+ }
+ iter->first = 0;
+
+ fn = krb5_cc_default_name(context);
+ if (strncasecmp(fn, "FILE:", 5) != 0) {
+ ret = _krb5_expand_default_cc_name(context,
+ KRB5_DEFAULT_CCNAME_FILE,
+ &expandedfn);
+ if (ret)
+ return ret;
+ }
+ ret = krb5_cc_resolve(context, fn, id);
+ if (expandedfn)
+ free(expandedfn);
+
+ return ret;
+}
+
+static krb5_error_code
+fcc_end_cache_get(krb5_context context, krb5_cc_cursor cursor)
+{
+ struct fcache_iter *iter = cursor;
+ free(iter);
+ return 0;
+}
+
const krb5_cc_ops krb5_fcc_ops = {
"FILE",
fcc_get_name,
@@ -715,5 +771,8 @@ const krb5_cc_ops krb5_fcc_ops = {
fcc_end_get,
fcc_remove_cred,
fcc_set_flags,
- fcc_get_version
+ fcc_get_version,
+ fcc_get_cache_first,
+ fcc_get_cache_next,
+ fcc_end_cache_get
};
diff --git a/source4/heimdal/lib/krb5/get_cred.c b/source4/heimdal/lib/krb5/get_cred.c
index b404c30f6e..663b5e7f1b 100644
--- a/source4/heimdal/lib/krb5/get_cred.c
+++ b/source4/heimdal/lib/krb5/get_cred.c
@@ -33,7 +33,7 @@
#include <krb5_locl.h>
-RCSID("$Id: get_cred.c,v 1.112 2006/06/06 21:22:54 lha Exp $");
+RCSID("$Id: get_cred.c,v 1.113 2006/11/21 05:14:01 lha Exp $");
/*
* Take the `body' and encode it into `padata' using the credentials
@@ -458,7 +458,7 @@ get_cred_kdc_usage(krb5_context context,
ret = krb5_create_checksum(context,
crypto,
- KRB5_KU_TGS_IMPERSONATE,
+ KRB5_KU_OTHER_CKSUM,
0,
data.data,
data.length,
diff --git a/source4/heimdal/lib/krb5/init_creds.c b/source4/heimdal/lib/krb5/init_creds.c
index 6dacb316d8..a331524a7e 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.28 2006/09/04 14:28:54 lha Exp $");
+RCSID("$Id: init_creds.c,v 1.30 2006/11/23 16:27:36 lha Exp $");
void KRB5_LIB_FUNCTION
krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt)
@@ -130,9 +130,10 @@ _krb5_get_init_creds_opt_set_krb5_error(krb5_context context,
void KRB5_LIB_FUNCTION
-krb5_get_init_creds_opt_free(krb5_get_init_creds_opt *opt)
+krb5_get_init_creds_opt_free(krb5_context context,
+ krb5_get_init_creds_opt *opt)
{
- if (opt->opt_private == NULL)
+ if (opt == NULL || opt->opt_private == NULL)
return;
if (opt->opt_private->refcount < 1) /* abort ? */
return;
diff --git a/source4/heimdal/lib/krb5/init_creds_pw.c b/source4/heimdal/lib/krb5/init_creds_pw.c
index d43ae0ae6f..f6f6eac7d5 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.101 2006/10/02 12:00:59 lha Exp $");
+RCSID("$Id: init_creds_pw.c,v 1.105 2007/01/09 10:44:59 lha Exp $");
typedef struct krb5_get_init_creds_ctx {
KDCOptions flags;
@@ -656,7 +656,7 @@ free_paid(krb5_context context, struct pa_info_data *ppaid)
{
krb5_free_salt(context, ppaid->salt);
if (ppaid->s2kparams)
- krb5_data_free(ppaid->s2kparams);
+ krb5_free_data(context, ppaid->s2kparams);
}
@@ -729,8 +729,8 @@ pa_etype_info2(krb5_context context,
if (e.val[i].salt == NULL)
krb5_free_salt(context, salt);
if (ret == 0) {
- free_ETYPE_INFO2(&e);
- return paid;
+ free_ETYPE_INFO2(&e);
+ return paid;
}
}
}
@@ -1092,23 +1092,31 @@ process_pa_data_to_md(krb5_context context,
(*out_md)->len = 0;
(*out_md)->val = NULL;
- if (in_md->len != 0) {
- struct pa_info_data paid, *ppaid;
+ /*
+ * Make sure we don't sent both ENC-TS and PK-INIT pa data, no
+ * need to expose our password protecting our PKCS12 key.
+ */
- memset(&paid, 0, sizeof(paid));
+ if (ctx->pk_init_ctx) {
+
+ ret = pa_data_to_md_pkinit(context, a, creds->client, ctx, *out_md);
+ if (ret)
+ return ret;
+ } else if (in_md->len != 0) {
+ struct pa_info_data paid, *ppaid;
+
+ memset(&paid, 0, sizeof(paid));
+
paid.etype = ENCTYPE_NULL;
ppaid = process_pa_info(context, creds->client, a, &paid, in_md);
-
+
pa_data_to_md_ts_enc(context, a, creds->client, ctx, ppaid, *out_md);
if (ppaid)
free_paid(context, ppaid);
}
pa_data_add_pac_request(context, ctx, *out_md);
- ret = pa_data_to_md_pkinit(context, a, creds->client, ctx, *out_md);
- if (ret)
- return ret;
if ((*out_md)->len == 0) {
free(*out_md);
@@ -1503,7 +1511,7 @@ krb5_get_init_creds_password(krb5_context context,
free (q);
if (ret) {
memset (buf, 0, sizeof(buf));
- krb5_get_init_creds_opt_free(options);
+ krb5_get_init_creds_opt_free(context, options);
ret = KRB5_LIBOS_PWDINTR;
krb5_clear_error_string (context);
return ret;
@@ -1515,7 +1523,7 @@ krb5_get_init_creds_password(krb5_context context,
ret = krb5_get_init_creds_opt_set_pa_password(context, options,
password, NULL);
if (ret) {
- krb5_get_init_creds_opt_free(options);
+ krb5_get_init_creds_opt_free(context, options);
memset(buf, 0, sizeof(buf));
return ret;
}
@@ -1523,7 +1531,7 @@ krb5_get_init_creds_password(krb5_context context,
ret = krb5_get_init_creds(context, creds, client, prompter,
data, start_time, in_tkt_service, options);
- krb5_get_init_creds_opt_free(options);
+ krb5_get_init_creds_opt_free(context, options);
memset(buf, 0, sizeof(buf));
return ret;
}
diff --git a/source4/heimdal/lib/krb5/krb5-private.h b/source4/heimdal/lib/krb5/krb5-private.h
index ba2f75ad22..c3e5732753 100644
--- a/source4/heimdal/lib/krb5/krb5-private.h
+++ b/source4/heimdal/lib/krb5/krb5-private.h
@@ -73,15 +73,6 @@ _krb5_extract_ticket (
krb5_decrypt_proc /*decrypt_proc*/,
krb5_const_pointer /*decryptarg*/);
-int
-_krb5_find_type_in_ad (
- krb5_context /*context*/,
- int /*type*/,
- krb5_data */*data*/,
- krb5_boolean */*found*/,
- krb5_keyblock */*sessionkey*/,
- const AuthorizationData */*ad*/);
-
void
_krb5_free_krbhst_info (krb5_krbhst_info */*hi*/);
@@ -299,38 +290,17 @@ _krb5_oid_to_enctype (
const heim_oid */*oid*/,
krb5_enctype */*etype*/);
-void
-_krb5_pac_free (
- krb5_context /*context*/,
- struct krb5_pac */*pac*/);
-
-krb5_error_code
-_krb5_pac_parse (
- krb5_context /*context*/,
- const void */*ptr*/,
- size_t /*len*/,
- struct krb5_pac **/*pac*/);
-
krb5_error_code
_krb5_pac_sign (
krb5_context /*context*/,
struct krb5_pac */*p*/,
time_t /*authtime*/,
krb5_principal /*principal*/,
- krb5_keyblock */*server_key*/,
- krb5_keyblock */*priv_key*/,
+ const krb5_keyblock */*server_key*/,
+ const krb5_keyblock */*priv_key*/,
krb5_data */*data*/);
krb5_error_code
-_krb5_pac_verify (
- krb5_context /*context*/,
- struct krb5_pac */*pac*/,
- time_t /*authtime*/,
- krb5_principal /*principal*/,
- krb5_keyblock */*server*/,
- krb5_keyblock */*privsvr*/);
-
-krb5_error_code
_krb5_parse_moduli (
krb5_context /*context*/,
const char */*file*/,
diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h
index 8b61e8d7d2..9dfe487b0a 100644
--- a/source4/heimdal/lib/krb5/krb5-protos.h
+++ b/source4/heimdal/lib/krb5/krb5-protos.h
@@ -499,10 +499,11 @@ krb5_boolean KRB5_LIB_FUNCTION
krb5_c_is_keyed_cksum (krb5_cksumtype /*ctype*/);
krb5_error_code KRB5_LIB_FUNCTION
-krb5_c_keylength (
+krb5_c_keylengths (
krb5_context /*context*/,
krb5_enctype /*enctype*/,
- size_t */*len*/);
+ size_t */*ilen*/,
+ size_t */*keylen*/);
krb5_error_code KRB5_LIB_FUNCTION
krb5_c_make_checksum (
@@ -1520,6 +1521,12 @@ krb5_enctype_disable (
krb5_enctype /*enctype*/);
krb5_error_code KRB5_LIB_FUNCTION
+krb5_enctype_keybits (
+ krb5_context /*context*/,
+ krb5_enctype /*type*/,
+ size_t */*keybits*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
krb5_enctype_keysize (
krb5_context /*context*/,
krb5_enctype /*type*/,
@@ -2021,7 +2028,9 @@ krb5_get_init_creds_opt_alloc (
krb5_get_init_creds_opt **/*opt*/);
void KRB5_LIB_FUNCTION
-krb5_get_init_creds_opt_free (krb5_get_init_creds_opt */*opt*/);
+krb5_get_init_creds_opt_free (
+ krb5_context /*context*/,
+ krb5_get_init_creds_opt */*opt*/);
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_init_creds_opt_get_error (
@@ -2189,6 +2198,9 @@ krb5_get_server_rcache (
krb5_boolean KRB5_LIB_FUNCTION
krb5_get_use_admin_kdc (krb5_context /*context*/);
+krb5_log_facility * KRB5_LIB_FUNCTION
+krb5_get_warn_dest (krb5_context /*context*/);
+
size_t
krb5_get_wrapped_length (
krb5_context /*context*/,
@@ -2609,12 +2621,172 @@ krb5_net_write_block (
size_t /*len*/,
time_t /*timeout*/);
+krb5_error_code
+krb5_ntlm_alloc (
+ krb5_context /*context*/,
+ krb5_ntlm */*ntlm*/);
+
+krb5_error_code
+krb5_ntlm_free (
+ krb5_context /*context*/,
+ krb5_ntlm /*ntlm*/);
+
+krb5_error_code
+krb5_ntlm_init_get_challange (
+ krb5_context /*context*/,
+ krb5_ntlm /*ntlm*/,
+ krb5_data */*challange*/);
+
+krb5_error_code
+krb5_ntlm_init_get_flags (
+ krb5_context /*context*/,
+ krb5_ntlm /*ntlm*/,
+ uint32_t */*flags*/);
+
+krb5_error_code
+krb5_ntlm_init_get_opaque (
+ krb5_context /*context*/,
+ krb5_ntlm /*ntlm*/,
+ krb5_data */*opaque*/);
+
+krb5_error_code
+krb5_ntlm_init_get_targetinfo (
+ krb5_context /*context*/,
+ krb5_ntlm /*ntlm*/,
+ krb5_data */*data*/);
+
+krb5_error_code
+krb5_ntlm_init_get_targetname (
+ krb5_context /*context*/,
+ krb5_ntlm /*ntlm*/,
+ char **/*name*/);
+
+krb5_error_code
+krb5_ntlm_init_request (
+ krb5_context /*context*/,
+ krb5_ntlm /*ntlm*/,
+ krb5_realm /*realm*/,
+ krb5_ccache /*ccache*/,
+ uint32_t /*flags*/,
+ const char */*hostname*/,
+ const char */*domainname*/);
+
+krb5_error_code
+krb5_ntlm_rep_get_sessionkey (
+ krb5_context /*context*/,
+ krb5_ntlm /*ntlm*/,
+ krb5_data */*data*/);
+
+krb5_boolean
+krb5_ntlm_rep_get_status (
+ krb5_context /*context*/,
+ krb5_ntlm /*ntlm*/);
+
+krb5_error_code
+krb5_ntlm_req_set_flags (
+ krb5_context /*context*/,
+ krb5_ntlm /*ntlm*/,
+ uint32_t /*flags*/);
+
+krb5_error_code
+krb5_ntlm_req_set_lm (
+ krb5_context /*context*/,
+ krb5_ntlm /*ntlm*/,
+ void */*hash*/,
+ size_t /*len*/);
+
+krb5_error_code
+krb5_ntlm_req_set_ntlm (
+ krb5_context /*context*/,
+ krb5_ntlm /*ntlm*/,
+ void */*hash*/,
+ size_t /*len*/);
+
+krb5_error_code
+krb5_ntlm_req_set_opaque (
+ krb5_context /*context*/,
+ krb5_ntlm /*ntlm*/,
+ krb5_data */*opaque*/);
+
+krb5_error_code
+krb5_ntlm_req_set_session (
+ krb5_context /*context*/,
+ krb5_ntlm /*ntlm*/,
+ void */*sessionkey*/,
+ size_t /*length*/);
+
+krb5_error_code
+krb5_ntlm_req_set_targetname (
+ krb5_context /*context*/,
+ krb5_ntlm /*ntlm*/,
+ const char */*targetname*/);
+
+krb5_error_code
+krb5_ntlm_req_set_username (
+ krb5_context /*context*/,
+ krb5_ntlm /*ntlm*/,
+ const char */*username*/);
+
+krb5_error_code
+krb5_ntlm_request (
+ krb5_context /*context*/,
+ krb5_ntlm /*ntlm*/,
+ krb5_realm /*realm*/,
+ krb5_ccache /*ccache*/);
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_openlog (
krb5_context /*context*/,
const char */*program*/,
krb5_log_facility **/*fac*/);
+krb5_error_code
+krb5_pac_add_buffer (
+ krb5_context /*context*/,
+ struct krb5_pac */*p*/,
+ uint32_t /*type*/,
+ const krb5_data */*data*/);
+
+void
+krb5_pac_free (
+ krb5_context /*context*/,
+ struct krb5_pac */*pac*/);
+
+krb5_error_code
+krb5_pac_get_buffer (
+ krb5_context /*context*/,
+ struct krb5_pac */*p*/,
+ uint32_t /*type*/,
+ krb5_data */*data*/);
+
+krb5_error_code
+krb5_pac_get_types (
+ krb5_context /*context*/,
+ struct krb5_pac */*p*/,
+ size_t */*len*/,
+ uint32_t **/*types*/);
+
+krb5_error_code
+krb5_pac_init (
+ krb5_context /*context*/,
+ struct krb5_pac **/*pac*/);
+
+krb5_error_code
+krb5_pac_parse (
+ krb5_context /*context*/,
+ const void */*ptr*/,
+ size_t /*len*/,
+ struct krb5_pac **/*pac*/);
+
+krb5_error_code
+krb5_pac_verify (
+ krb5_context /*context*/,
+ const struct krb5_pac */*pac*/,
+ time_t /*authtime*/,
+ krb5_const_principal /*principal*/,
+ const krb5_keyblock */*server*/,
+ const krb5_keyblock */*privsvr*/);
+
int KRB5_LIB_FUNCTION
krb5_padata_add (
krb5_context /*context*/,
@@ -2904,6 +3076,12 @@ krb5_rd_req_in_set_keytab (
krb5_rd_req_in_ctx /*in*/,
krb5_keytab /*keytab*/);
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_rd_req_in_set_pac_check (
+ krb5_context /*context*/,
+ krb5_rd_req_in_ctx /*in*/,
+ krb5_boolean /*flag*/);
+
void KRB5_LIB_FUNCTION
krb5_rd_req_out_ctx_free (
krb5_context /*context*/,
@@ -3515,6 +3693,11 @@ krb5_ticket_get_client (
const krb5_ticket */*ticket*/,
krb5_principal */*client*/);
+time_t KRB5_LIB_FUNCTION
+krb5_ticket_get_endtime (
+ krb5_context /*context*/,
+ const krb5_ticket */*ticket*/);
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_ticket_get_server (
krb5_context /*context*/,
diff --git a/source4/heimdal/lib/krb5/krb5.h b/source4/heimdal/lib/krb5/krb5.h
index 1b26e8b3e7..55a83fb533 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.255 2006/11/12 08:33:07 lha Exp $ */
+/* $Id: krb5.h,v 1.259 2007/01/03 18:51:52 lha Exp $ */
#ifndef __KRB5_H__
#define __KRB5_H__
@@ -77,8 +77,10 @@ typedef struct krb5_get_creds_opt_data *krb5_get_creds_opt;
struct krb5_digest;
typedef struct krb5_digest *krb5_digest;
+struct krb5_ntlm;
+typedef struct krb5_ntlm *krb5_ntlm;
-struct krb5_pac;
+typedef struct krb5_pac *krb5_pac;
typedef struct krb5_rd_req_in_ctx *krb5_rd_req_in_ctx;
typedef struct krb5_rd_req_out_ctx *krb5_rd_req_out_ctx;
@@ -216,8 +218,6 @@ typedef enum krb5_key_usage {
/* Keyusage for the server referral in a TGS req */
KRB5_KU_SAM_ENC_NONCE_SAD = 27,
/* Encryption of the SAM-NONCE-OR-SAD field */
- KRB5_KU_TGS_IMPERSONATE = -17,
- /* Checksum type used in the impersonate field */
KRB5_KU_DIGEST_ENCRYPT = -18,
/* Encryption key usage used in the digest encryption field */
KRB5_KU_DIGEST_OPAQUE = -19,
@@ -716,6 +716,7 @@ typedef struct krb5_krbhst_data *krb5_krbhst_handle;
#define KRB5_KRBHST_ADMIN 2
#define KRB5_KRBHST_CHANGEPW 3
#define KRB5_KRBHST_KRB524 4
+#define KRB5_KRBHST_KCA 5
typedef struct krb5_krbhst_info {
enum { KRB5_KRBHST_UDP,
diff --git a/source4/heimdal/lib/krb5/krb5_locl.h b/source4/heimdal/lib/krb5/krb5_locl.h
index 3fb5461b3c..35d046c8d9 100644
--- a/source4/heimdal/lib/krb5/krb5_locl.h
+++ b/source4/heimdal/lib/krb5/krb5_locl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2002 Kungliga Tekniska Högskolan
+ * Copyright (c) 1997-2006 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-/* $Id: krb5_locl.h,v 1.93 2006/10/20 18:13:31 lha Exp $ */
+/* $Id: krb5_locl.h,v 1.97 2006/12/15 16:46:51 lha Exp $ */
#ifndef __KRB5_LOCL_H__
#define __KRB5_LOCL_H__
@@ -239,20 +239,20 @@ typedef struct krb5_context_data {
int large_msg_size;
int dns_canonicalize_hostname;
struct send_to_kdc *send_to_kdc;
- void *mem_ctx; /* Some parts of Samba4 need a valid
- memory context (under the event
- context) to use */
} krb5_context_data;
+#define KRB5_DEFAULT_CCNAME_FILE "FILE:/tmp/krb5cc_%{uid}"
+#define KRB5_DEFAULT_CCNAME_API "API:"
+
/*
* Configurable options
*/
#ifndef KRB5_DEFAULT_CCNAME
#ifdef __APPLE__
-#define KRB5_DEFAULT_CCNAME "API:"
+#define KRB5_DEFAULT_CCNAME KRB5_DEFAULT_CCNAME_API
#else
-#define KRB5_DEFAULT_CCNAME "FILE:/tmp/krb5cc_%{uid}"
+#define KRB5_DEFAULT_CCNAME KRB5_DEFAULT_CCNAME_FILE
#endif
#endif
diff --git a/source4/heimdal/lib/krb5/krbhst.c b/source4/heimdal/lib/krb5/krbhst.c
index f395f0d0c3..3e281e5c63 100644
--- a/source4/heimdal/lib/krb5/krbhst.c
+++ b/source4/heimdal/lib/krb5/krbhst.c
@@ -35,7 +35,7 @@
#include <resolve.h>
#include "locate_plugin.h"
-RCSID("$Id: krbhst.c,v 1.58 2006/11/12 20:05:20 lha Exp $");
+RCSID("$Id: krbhst.c,v 1.61 2006/11/30 17:23:08 lha Exp $");
static int
string_to_proto(const char *string)
@@ -493,7 +493,7 @@ add_locate(void *ctx, int type, struct sockaddr *addr)
if (ret != 0)
return 0;
- memset(&hints, 0, sizeof(hints));
+ make_hints(&hints, krbhst_get_default_proto(kd));
ret = getaddrinfo(host, port, &hints, &ai);
if (ret)
return 0;
@@ -521,7 +521,7 @@ plugin_get_hosts(krb5_context context,
struct krb5_krbhst_data *kd,
enum locate_service_type type)
{
- struct krb5_plugin *list, *e;
+ struct krb5_plugin *list = NULL, *e;
krb5_error_code ret;
ret = _krb5_plugin_find(context, PLUGIN_TYPE_DATA, "resolve", &list);
@@ -619,6 +619,13 @@ admin_get_next(krb5_context context,
{
krb5_error_code ret;
+ if ((kd->flags & KD_PLUGIN) == 0) {
+ plugin_get_hosts(context, kd, locate_service_kadmin);
+ kd->flags |= KD_PLUGIN;
+ if(get_next(kd, host))
+ return 0;
+ }
+
if((kd->flags & KD_CONFIG) == 0) {
config_get_hosts(context, kd, "admin_server");
kd->flags |= KD_CONFIG;
@@ -660,6 +667,13 @@ kpasswd_get_next(krb5_context context,
{
krb5_error_code ret;
+ if ((kd->flags & KD_PLUGIN) == 0) {
+ plugin_get_hosts(context, kd, locate_service_kpasswd);
+ kd->flags |= KD_PLUGIN;
+ if(get_next(kd, host))
+ return 0;
+ }
+
if((kd->flags & KD_CONFIG) == 0) {
config_get_hosts(context, kd, "kpasswd_server");
kd->flags |= KD_CONFIG;
@@ -705,6 +719,13 @@ krb524_get_next(krb5_context context,
struct krb5_krbhst_data *kd,
krb5_krbhst_info **host)
{
+ if ((kd->flags & KD_PLUGIN) == 0) {
+ plugin_get_hosts(context, kd, locate_service_krb524);
+ kd->flags |= KD_PLUGIN;
+ if(get_next(kd, host))
+ return 0;
+ }
+
if((kd->flags & KD_CONFIG) == 0) {
config_get_hosts(context, kd, "krb524_server");
if(get_next(kd, host))
diff --git a/source4/heimdal/lib/krb5/log.c b/source4/heimdal/lib/krb5/log.c
index e6fcb6bbb9..9523ca848c 100644
--- a/source4/heimdal/lib/krb5/log.c
+++ b/source4/heimdal/lib/krb5/log.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2002 Kungliga Tekniska Högskolan
+ * Copyright (c) 1997-2006 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -33,7 +33,7 @@
#include "krb5_locl.h"
-RCSID("$Id: log.c,v 1.39 2006/04/24 15:09:27 lha Exp $");
+RCSID("$Id: log.c,v 1.40 2006/11/21 08:08:46 lha Exp $");
struct facility {
int min;
diff --git a/source4/heimdal/lib/krb5/mit_glue.c b/source4/heimdal/lib/krb5/mit_glue.c
index 493c4cd845..c4d3ff5390 100755
--- a/source4/heimdal/lib/krb5/mit_glue.c
+++ b/source4/heimdal/lib/krb5/mit_glue.c
@@ -32,7 +32,7 @@
*/
#include "krb5_locl.h"
-RCSID("$Id: mit_glue.c,v 1.9 2006/11/09 21:24:16 lha Exp $");
+RCSID("$Id: mit_glue.c,v 1.12 2006/11/17 22:17:46 lha Exp $");
/*
* Glue for MIT API
@@ -327,9 +327,16 @@ krb5_c_make_random_key(krb5_context context,
}
krb5_error_code KRB5_LIB_FUNCTION
-krb5_c_keylength(krb5_context context,
- krb5_enctype enctype,
- size_t *len)
+krb5_c_keylengths(krb5_context context,
+ krb5_enctype enctype,
+ size_t *ilen,
+ size_t *keylen)
{
- return krb5_enctype_keysize(context, enctype, len);
+ krb5_error_code ret;
+
+ ret = krb5_enctype_keybits(context, enctype, ilen);
+ if (ret)
+ return ret;
+ *ilen = (*ilen + 7) / 8;
+ return krb5_enctype_keysize(context, enctype, keylen);
}
diff --git a/source4/heimdal/lib/krb5/mk_req_ext.c b/source4/heimdal/lib/krb5/mk_req_ext.c
index 18b0e3552f..8646c4ebea 100644
--- a/source4/heimdal/lib/krb5/mk_req_ext.c
+++ b/source4/heimdal/lib/krb5/mk_req_ext.c
@@ -33,7 +33,7 @@
#include <krb5_locl.h>
-RCSID("$Id: mk_req_ext.c,v 1.32 2006/03/19 20:33:13 lha Exp $");
+RCSID("$Id: mk_req_ext.c,v 1.33 2006/12/27 12:07:22 lha Exp $");
krb5_error_code
_krb5_mk_req_internal(krb5_context context,
@@ -91,7 +91,9 @@ _krb5_mk_req_internal(krb5_context context,
in_data->length,
&c);
} else if(ac->keyblock->keytype == ETYPE_ARCFOUR_HMAC_MD5 ||
- ac->keyblock->keytype == ETYPE_ARCFOUR_HMAC_MD5_56) {
+ ac->keyblock->keytype == ETYPE_ARCFOUR_HMAC_MD5_56 ||
+ ac->keyblock->keytype == ETYPE_DES_CBC_MD4 ||
+ ac->keyblock->keytype == ETYPE_DES_CBC_MD5) {
/* this is to make MS kdc happy */
ret = krb5_create_checksum(context,
NULL,
diff --git a/source4/heimdal/lib/krb5/pac.c b/source4/heimdal/lib/krb5/pac.c
new file mode 100644
index 0000000000..5bc7235459
--- /dev/null
+++ b/source4/heimdal/lib/krb5/pac.c
@@ -0,0 +1,1034 @@
+/*
+ * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "krb5_locl.h"
+
+RCSID("$Id: pac.c,v 1.13 2007/01/09 11:22:56 lha Exp $");
+
+struct PAC_INFO_BUFFER {
+ uint32_t type;
+ uint32_t buffersize;
+ uint32_t offset_hi;
+ uint32_t offset_lo;
+};
+
+struct PACTYPE {
+ uint32_t numbuffers;
+ uint32_t version;
+ struct PAC_INFO_BUFFER buffers[1];
+};
+
+struct krb5_pac {
+ struct PACTYPE *pac;
+ krb5_data data;
+ struct PAC_INFO_BUFFER *server_checksum;
+ struct PAC_INFO_BUFFER *privsvr_checksum;
+ struct PAC_INFO_BUFFER *logon_name;
+};
+
+#define PAC_ALIGNMENT 8
+
+#define PACTYPE_SIZE 8
+#define PAC_INFO_BUFFER_SIZE 16
+
+#define PAC_SERVER_CHECKSUM 6
+#define PAC_PRIVSVR_CHECKSUM 7
+#define PAC_LOGON_NAME 10
+
+#define CHECK(r,f,l) \
+ do { \
+ if (((r) = f ) != 0) { \
+ krb5_clear_error_string(context); \
+ goto l; \
+ } \
+ } while(0)
+
+static const char zeros[PAC_ALIGNMENT] = { 0 };
+
+/*
+ *
+ */
+
+krb5_error_code
+krb5_pac_parse(krb5_context context, const void *ptr, size_t len,
+ struct krb5_pac **pac)
+{
+ krb5_error_code ret;
+ struct krb5_pac *p;
+ krb5_storage *sp = NULL;
+ uint32_t i, tmp, tmp2, header_end;
+
+ p = calloc(1, sizeof(*p));
+ if (p == NULL) {
+ ret = ENOMEM;
+ krb5_set_error_string(context, "out of memory");
+ goto out;
+ }
+
+ sp = krb5_storage_from_readonly_mem(ptr, len);
+ if (sp == NULL) {
+ ret = ENOMEM;
+ krb5_set_error_string(context, "out of memory");
+ goto out;
+ }
+ krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE);
+
+ CHECK(ret, krb5_ret_uint32(sp, &tmp), out);
+ CHECK(ret, krb5_ret_uint32(sp, &tmp2), out);
+ if (tmp < 1) {
+ krb5_set_error_string(context, "PAC have too few buffer");
+ ret = EINVAL; /* Too few buffers */
+ goto out;
+ }
+ if (tmp2 != 0) {
+ krb5_set_error_string(context, "PAC have wrong version");
+ ret = EINVAL; /* Wrong version */
+ goto out;
+ }
+
+ p->pac = calloc(1,
+ sizeof(*p->pac) + (sizeof(p->pac->buffers[0]) * (tmp - 1)));
+ if (p->pac == NULL) {
+ krb5_set_error_string(context, "out of memory");
+ ret = ENOMEM;
+ goto out;
+ }
+
+ p->pac->numbuffers = tmp;
+ p->pac->version = tmp2;
+
+ header_end = PACTYPE_SIZE + (PAC_INFO_BUFFER_SIZE * p->pac->numbuffers);
+ if (header_end > len) {
+ ret = EINVAL;
+ goto out;
+ }
+
+ for (i = 0; i < p->pac->numbuffers; i++) {
+ CHECK(ret, krb5_ret_uint32(sp, &p->pac->buffers[i].type), out);
+ CHECK(ret, krb5_ret_uint32(sp, &p->pac->buffers[i].buffersize), out);
+ CHECK(ret, krb5_ret_uint32(sp, &p->pac->buffers[i].offset_lo), out);
+ CHECK(ret, krb5_ret_uint32(sp, &p->pac->buffers[i].offset_hi), out);
+
+ /* consistency checks */
+ if (p->pac->buffers[i].offset_lo & (PAC_ALIGNMENT - 1)) {
+ krb5_set_error_string(context, "PAC out of allignment");
+ ret = EINVAL;
+ goto out;
+ }
+ if (p->pac->buffers[i].offset_hi) {
+ krb5_set_error_string(context, "PAC high offset set");
+ ret = EINVAL;
+ goto out;
+ }
+ if (p->pac->buffers[i].offset_lo > len) {
+ krb5_set_error_string(context, "PAC offset off end");
+ ret = EINVAL;
+ goto out;
+ }
+ if (p->pac->buffers[i].offset_lo < header_end) {
+ krb5_set_error_string(context, "PAC offset inside header: %d %d",
+ p->pac->buffers[i].offset_lo, header_end);
+ ret = EINVAL;
+ goto out;
+ }
+ if (p->pac->buffers[i].buffersize > len - p->pac->buffers[i].offset_lo){
+ krb5_set_error_string(context, "PAC length off end");
+ ret = EINVAL;
+ goto out;
+ }
+
+ /* let save pointer to data we need later */
+ if (p->pac->buffers[i].type == PAC_SERVER_CHECKSUM) {
+ if (p->server_checksum) {
+ krb5_set_error_string(context, "PAC have two server checksums");
+ ret = EINVAL;
+ goto out;
+ }
+ p->server_checksum = &p->pac->buffers[i];
+ } else if (p->pac->buffers[i].type == PAC_PRIVSVR_CHECKSUM) {
+ if (p->privsvr_checksum) {
+ krb5_set_error_string(context, "PAC have two KDC checksums");
+ ret = EINVAL;
+ goto out;
+ }
+ p->privsvr_checksum = &p->pac->buffers[i];
+ } else if (p->pac->buffers[i].type == PAC_LOGON_NAME) {
+ if (p->logon_name) {
+ krb5_set_error_string(context, "PAC have two logon names");
+ ret = EINVAL;
+ goto out;
+ }
+ p->logon_name = &p->pac->buffers[i];
+ }
+ }
+
+ ret = krb5_data_copy(&p->data, ptr, len);
+ if (ret)
+ goto out;
+
+ krb5_storage_free(sp);
+
+ *pac = p;
+ return 0;
+
+out:
+ if (sp)
+ krb5_storage_free(sp);
+ if (p) {
+ if (p->pac)
+ free(p->pac);
+ free(p);
+ }
+ *pac = NULL;
+
+ return ret;
+}
+
+krb5_error_code
+krb5_pac_init(krb5_context context, struct krb5_pac **pac)
+{
+ krb5_error_code ret;
+ struct krb5_pac *p;
+
+ p = calloc(1, sizeof(*p));
+ if (p == NULL) {
+ krb5_set_error_string(context, "out of memory");
+ return ENOMEM;
+ }
+
+ p->pac = calloc(1, sizeof(*p->pac));
+ if (p->pac == NULL) {
+ free(p);
+ krb5_set_error_string(context, "out of memory");
+ return ENOMEM;
+ }
+
+ ret = krb5_data_alloc(&p->data, PACTYPE_SIZE);
+ if (ret) {
+ free (p->pac);
+ free(p);
+ krb5_set_error_string(context, "out of memory");
+ return ret;
+ }
+
+
+ *pac = p;
+ return 0;
+}
+
+krb5_error_code
+krb5_pac_add_buffer(krb5_context context, struct krb5_pac *p,
+ uint32_t type, const krb5_data *data)
+{
+ krb5_error_code ret;
+ void *ptr;
+ size_t len, offset, header_end;
+ uint32_t i;
+
+ len = p->pac->numbuffers + 1;
+ if (len < p->pac->numbuffers)
+ return EINVAL;
+
+ ptr = realloc(p->pac,
+ sizeof(*p->pac) + (sizeof(p->pac->buffers[0]) * len));
+ if (ptr == NULL) {
+ krb5_set_error_string(context, "out of memory");
+ return ENOMEM;
+ }
+ p->pac = ptr;
+
+ for (i = 0; i < len; i++)
+ p->pac->buffers[i].offset_lo += PAC_INFO_BUFFER_SIZE;
+
+ offset = p->data.length + PAC_INFO_BUFFER_SIZE;
+
+ p->pac->buffers[len - 1].type = type;
+ p->pac->buffers[len - 1].buffersize = data->length;
+ p->pac->buffers[len - 1].offset_lo = offset;
+ p->pac->buffers[len - 1].offset_hi = 0;
+
+ len = p->data.length + data->length + PAC_INFO_BUFFER_SIZE;
+ if (len < p->data.length) {
+ krb5_set_error_string(context, "integer overrun");
+ return EINVAL;
+ }
+
+ /* align to PAC_ALIGNMENT */
+ len = ((len + PAC_ALIGNMENT - 1) / PAC_ALIGNMENT) * PAC_ALIGNMENT;
+
+ ret = krb5_data_realloc(&p->data, len);
+ if (ret) {
+ krb5_set_error_string(context, "out of memory");
+ return ret;
+ }
+
+ /* make place for PAC INFO BUFFER header */
+ header_end = PACTYPE_SIZE + (PAC_INFO_BUFFER_SIZE * p->pac->numbuffers);
+ memmove((unsigned char *)p->data.data + header_end,
+ (unsigned char *)p->data.data + header_end + PAC_INFO_BUFFER_SIZE,
+ PAC_INFO_BUFFER_SIZE);
+
+ /*
+ *
+ */
+
+ memcpy((unsigned char *)p->data.data + offset,
+ data->data, data->length);
+ memset((unsigned char *)p->data.data + offset + data->length,
+ 0, p->data.length - offset - data->length);
+
+ p->pac->numbuffers += 1;
+
+ return 0;
+}
+
+krb5_error_code
+krb5_pac_get_buffer(krb5_context context, struct krb5_pac *p,
+ uint32_t type, krb5_data *data)
+{
+ krb5_error_code ret;
+ uint32_t i;
+
+ /*
+ * Hide the checksums from external consumers
+ */
+
+ if (type == PAC_PRIVSVR_CHECKSUM || type == PAC_SERVER_CHECKSUM) {
+ ret = krb5_data_alloc(data, 16);
+ if (ret) {
+ krb5_set_error_string(context, "out of memory");
+ return ret;
+ }
+ memset(data->data, 0, data->length);
+ return 0;
+ }
+
+ for (i = 0; i < p->pac->numbuffers; i++) {
+ size_t len = p->pac->buffers[i].buffersize;
+ size_t offset = p->pac->buffers[i].offset_lo;
+
+ if (p->pac->buffers[i].type != type)
+ continue;
+
+ ret = krb5_data_copy(data, (unsigned char *)p->data.data + offset, len);
+ if (ret) {
+ krb5_set_error_string(context, "Out of memory");
+ return ret;
+ }
+ return 0;
+ }
+ krb5_set_error_string(context, "No PAC buffer of type %lu was found",
+ (unsigned long)type);
+ return ENOENT;
+}
+
+/*
+ *
+ */
+
+krb5_error_code
+krb5_pac_get_types(krb5_context context,
+ struct krb5_pac *p,
+ size_t *len,
+ uint32_t **types)
+{
+ size_t i;
+
+ *types = calloc(p->pac->numbuffers, sizeof(*types));
+ if (*types == NULL) {
+ *len = 0;
+ krb5_set_error_string(context, "out of memory");
+ return ENOMEM;
+ }
+ for (i = 0; i < p->pac->numbuffers; i++)
+ (*types)[i] = p->pac->buffers[i].type;
+ *len = p->pac->numbuffers;
+
+ return 0;
+}
+
+/*
+ *
+ */
+
+void
+krb5_pac_free(krb5_context context, struct krb5_pac *pac)
+{
+ krb5_data_free(&pac->data);
+ free(pac->pac);
+ free(pac);
+}
+
+/*
+ *
+ */
+
+static krb5_error_code
+verify_checksum(krb5_context context,
+ const struct PAC_INFO_BUFFER *sig,
+ const krb5_data *data,
+ void *ptr, size_t len,
+ const krb5_keyblock *key)
+{
+ krb5_crypto crypto = NULL;
+ krb5_storage *sp = NULL;
+ uint32_t type;
+ krb5_error_code ret;
+ Checksum cksum;
+
+ sp = krb5_storage_from_mem((char *)data->data + sig->offset_lo,
+ sig->buffersize);
+ if (sp == NULL) {
+ krb5_set_error_string(context, "out of memory");
+ return ENOMEM;
+ }
+ krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE);
+
+ CHECK(ret, krb5_ret_uint32(sp, &type), out);
+ cksum.cksumtype = type;
+ cksum.checksum.length =
+ sig->buffersize - krb5_storage_seek(sp, 0, SEEK_CUR);
+ cksum.checksum.data = malloc(cksum.checksum.length);
+ if (cksum.checksum.data == NULL) {
+ krb5_set_error_string(context, "out of memory");
+ ret = ENOMEM;
+ goto out;
+ }
+ ret = krb5_storage_read(sp, cksum.checksum.data, cksum.checksum.length);
+ if (ret != cksum.checksum.length) {
+ krb5_set_error_string(context, "PAC checksum missing checksum");
+ ret = EINVAL;
+ goto out;
+ }
+
+ if (!krb5_checksum_is_keyed(context, cksum.cksumtype)) {
+ krb5_set_error_string (context, "Checksum type %d not keyed",
+ cksum.cksumtype);
+ ret = EINVAL;
+ goto out;
+ }
+
+ ret = krb5_crypto_init(context, key, 0, &crypto);
+ if (ret)
+ goto out;
+
+ ret = krb5_verify_checksum(context, crypto, KRB5_KU_OTHER_CKSUM,
+ ptr, len, &cksum);
+ krb5_crypto_destroy(context, crypto);
+ krb5_storage_free(sp);
+
+ return ret;
+
+out:
+ if (sp)
+ krb5_storage_free(sp);
+ if (crypto)
+ krb5_crypto_destroy(context, crypto);
+ return ret;
+}
+
+static krb5_error_code
+create_checksum(krb5_context context,
+ const krb5_keyblock *key,
+ void *data, size_t datalen,
+ void *sig, size_t siglen)
+{
+ krb5_crypto crypto = NULL;
+ krb5_error_code ret;
+ Checksum cksum;
+
+ ret = krb5_crypto_init(context, key, 0, &crypto);
+ if (ret)
+ return ret;
+
+ ret = krb5_create_checksum(context, crypto, KRB5_KU_OTHER_CKSUM, 0,
+ data, datalen, &cksum);
+ krb5_crypto_destroy(context, crypto);
+ if (ret)
+ return ret;
+
+ if (cksum.checksum.length != siglen) {
+ krb5_set_error_string(context, "pac checksum wrong length");
+ free_Checksum(&cksum);
+ return EINVAL;
+ }
+
+ memcpy(sig, cksum.checksum.data, siglen);
+ free_Checksum(&cksum);
+
+ return 0;
+}
+
+
+/*
+ *
+ */
+
+#define NTTIME_EPOCH 0x019DB1DED53E8000LL
+
+static uint64_t
+unix2nttime(time_t unix_time)
+{
+ long long wt;
+ wt = unix_time * (uint64_t)10000000 + (uint64_t)NTTIME_EPOCH;
+ return wt;
+}
+
+static krb5_error_code
+verify_logonname(krb5_context context,
+ const struct PAC_INFO_BUFFER *logon_name,
+ const krb5_data *data,
+ time_t authtime,
+ krb5_const_principal principal)
+{
+ krb5_error_code ret;
+ krb5_principal p2;
+ uint32_t time1, time2;
+ krb5_storage *sp;
+ uint16_t len;
+ char *s;
+
+ sp = krb5_storage_from_readonly_mem((const char *)data->data + logon_name->offset_lo,
+ logon_name->buffersize);
+ if (sp == NULL) {
+ krb5_set_error_string(context, "Out of memory");
+ return ENOMEM;
+ }
+
+ krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE);
+
+ CHECK(ret, krb5_ret_uint32(sp, &time1), out);
+ CHECK(ret, krb5_ret_uint32(sp, &time2), out);
+
+ {
+ uint64_t t1, t2;
+ t1 = unix2nttime(authtime);
+ t2 = ((uint64_t)time2 << 32) | time1;
+ if (t1 != t2) {
+ krb5_storage_free(sp);
+ krb5_set_error_string(context, "PAC timestamp mismatch");
+ return EINVAL;
+ }
+ }
+ CHECK(ret, krb5_ret_uint16(sp, &len), out);
+ if (len == 0) {
+ krb5_storage_free(sp);
+ krb5_set_error_string(context, "PAC logon name length missing");
+ return EINVAL;
+ }
+
+ s = malloc(len);
+ if (s == NULL) {
+ krb5_storage_free(sp);
+ krb5_set_error_string(context, "Out of memory");
+ return ENOMEM;
+ }
+ ret = krb5_storage_read(sp, s, len);
+ if (ret != len) {
+ krb5_storage_free(sp);
+ krb5_set_error_string(context, "Failed to read pac logon name");
+ return EINVAL;
+ }
+ krb5_storage_free(sp);
+#if 1 /* cheat for now */
+ {
+ size_t i;
+
+ if (len & 1) {
+ krb5_set_error_string(context, "PAC logon name malformed");
+ return EINVAL;
+ }
+
+ for (i = 0; i < len / 2; i++) {
+ if (s[(i * 2) + 1]) {
+ krb5_set_error_string(context, "PAC logon name not ASCII");
+ return EINVAL;
+ }
+ s[i] = s[i * 2];
+ }
+ s[i] = '\0';
+ }
+#else
+ {
+ uint16_t *ucs2;
+ ssize_t ucs2len;
+ size_t u8len;
+
+ ucs2 = malloc(sizeof(ucs2[0]) * len / 2);
+ if (ucs2)
+ abort();
+ ucs2len = wind_ucs2read(s, len / 2, ucs2);
+ free(s);
+ if (len < 0)
+ return -1;
+ ret = wind_ucs2toutf8(ucs2, ucs2len, NULL, &u8len);
+ if (ret < 0)
+ abort();
+ s = malloc(u8len + 1);
+ if (s == NULL)
+ abort();
+ wind_ucs2toutf8(ucs2, ucs2len, s, &u8len);
+ free(ucs2);
+ }
+#endif
+ ret = krb5_parse_name_flags(context, s, KRB5_PRINCIPAL_PARSE_NO_REALM, &p2);
+ free(s);
+ if (ret)
+ return ret;
+
+ if (krb5_principal_compare_any_realm(context, principal, p2) != TRUE) {
+ krb5_set_error_string(context, "PAC logon name mismatch");
+ ret = EINVAL;
+ }
+ krb5_free_principal(context, p2);
+ return ret;
+out:
+ return ret;
+}
+
+/*
+ *
+ */
+
+static krb5_error_code
+build_logon_name(krb5_context context,
+ time_t authtime,
+ krb5_const_principal principal,
+ krb5_data *logon)
+{
+ krb5_error_code ret;
+ krb5_storage *sp;
+ uint64_t t;
+ char *s, *s2;
+ size_t i, len;
+
+ t = unix2nttime(authtime);
+
+ krb5_data_zero(logon);
+
+ sp = krb5_storage_emem();
+ if (sp == NULL) {
+ krb5_set_error_string(context, "out of memory");
+ return ENOMEM;
+ }
+ krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE);
+
+ CHECK(ret, krb5_store_uint32(sp, t & 0xffffffff), out);
+ CHECK(ret, krb5_store_uint32(sp, t >> 32), out);
+
+ ret = krb5_unparse_name_flags(context, principal,
+ KRB5_PRINCIPAL_UNPARSE_NO_REALM, &s);
+ if (ret)
+ goto out;
+
+ len = strlen(s);
+
+ CHECK(ret, krb5_store_uint16(sp, len * 2), out);
+
+#if 1 /* cheat for now */
+ s2 = malloc(len * 2);
+ if (s2 == NULL) {
+ ret = ENOMEM;
+ free(s);
+ goto out;
+ }
+ for (i = 0; i < len; i++) {
+ s2[i * 2] = s[i];
+ s2[i * 2 + 1] = 0;
+ }
+ free(s);
+#else
+ /* write libwind code here */
+#endif
+
+ ret = krb5_storage_write(sp, s2, len * 2);
+ free(s2);
+ if (ret != len * 2) {
+ ret = ENOMEM;
+ goto out;
+ }
+ ret = krb5_storage_to_data(sp, logon);
+ if (ret)
+ goto out;
+ krb5_storage_free(sp);
+
+ return 0;
+out:
+ krb5_storage_free(sp);
+ return ret;
+}
+
+
+/*
+ *
+ */
+
+krb5_error_code
+krb5_pac_verify(krb5_context context,
+ const struct krb5_pac *pac,
+ time_t authtime,
+ krb5_const_principal principal,
+ const krb5_keyblock *server,
+ const krb5_keyblock *privsvr)
+{
+ krb5_error_code ret;
+
+ if (pac->server_checksum == NULL) {
+ krb5_set_error_string(context, "PAC missing server checksum");
+ return EINVAL;
+ }
+ if (pac->privsvr_checksum == NULL) {
+ krb5_set_error_string(context, "PAC missing kdc checksum");
+ return EINVAL;
+ }
+ if (pac->logon_name == NULL) {
+ krb5_set_error_string(context, "PAC missing logon name");
+ return EINVAL;
+ }
+
+ ret = verify_logonname(context,
+ pac->logon_name,
+ &pac->data,
+ authtime,
+ principal);
+ if (ret)
+ return ret;
+
+ /*
+ * in the service case, clean out data option of the privsvr and
+ * server checksum before checking the checksum.
+ */
+ {
+ krb5_data *copy;
+
+ ret = krb5_copy_data(context, &pac->data, &copy);
+ if (ret)
+ return ret;
+
+ if (pac->server_checksum->buffersize < 4)
+ return EINVAL;
+ if (pac->privsvr_checksum->buffersize < 4)
+ return EINVAL;
+
+ memset((char *)copy->data + pac->server_checksum->offset_lo + 4,
+ 0,
+ pac->server_checksum->buffersize - 4);
+
+ memset((char *)copy->data + pac->privsvr_checksum->offset_lo + 4,
+ 0,
+ pac->privsvr_checksum->buffersize - 4);
+
+ ret = verify_checksum(context,
+ pac->server_checksum,
+ &pac->data,
+ copy->data,
+ copy->length,
+ server);
+ krb5_free_data(context, copy);
+ if (ret)
+ return ret;
+ }
+ if (privsvr) {
+ ret = verify_checksum(context,
+ pac->privsvr_checksum,
+ &pac->data,
+ (char *)pac->data.data
+ + pac->server_checksum->offset_lo + 4,
+ pac->server_checksum->buffersize - 4,
+ privsvr);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+/*
+ *
+ */
+
+static krb5_error_code
+fill_zeros(krb5_context context, krb5_storage *sp, size_t len)
+{
+ ssize_t sret;
+ size_t l;
+
+ while (len) {
+ l = len;
+ if (l > sizeof(zeros))
+ l = sizeof(zeros);
+ sret = krb5_storage_write(sp, zeros, l);
+ if (sret <= 0) {
+ krb5_set_error_string(context, "out of memory");
+ return ENOMEM;
+ }
+ len -= sret;
+ }
+ return 0;
+}
+
+static krb5_error_code
+pac_checksum(krb5_context context,
+ const krb5_keyblock *key,
+ uint32_t *cksumtype,
+ size_t *cksumsize)
+{
+ krb5_cksumtype cktype;
+ krb5_error_code ret;
+ krb5_crypto crypto = NULL;
+
+ ret = krb5_crypto_init(context, key, 0, &crypto);
+ if (ret)
+ return ret;
+
+ ret = krb5_crypto_get_checksum_type(context, crypto, &cktype);
+ ret = krb5_crypto_destroy(context, crypto);
+ if (ret)
+ return ret;
+
+ if (krb5_checksum_is_keyed(context, cktype) == FALSE) {
+ krb5_set_error_string(context, "PAC checksum type is not keyed");
+ return EINVAL;
+ }
+
+ ret = krb5_checksumsize(context, cktype, cksumsize);
+ if (ret)
+ return ret;
+
+ *cksumtype = (uint32_t)cktype;
+
+ return 0;
+}
+
+krb5_error_code
+_krb5_pac_sign(krb5_context context,
+ struct krb5_pac *p,
+ time_t authtime,
+ krb5_principal principal,
+ const krb5_keyblock *server_key,
+ const krb5_keyblock *priv_key,
+ krb5_data *data)
+{
+ krb5_error_code ret;
+ krb5_storage *sp = NULL, *spdata = NULL;
+ uint32_t end;
+ size_t server_size, priv_size;
+ uint32_t server_offset = 0, priv_offset = 0;
+ uint32_t server_cksumtype = 0, priv_cksumtype = 0;
+ int i, num = 0;
+ krb5_data logon, d;
+
+ krb5_data_zero(&logon);
+
+ if (p->server_checksum == NULL)
+ num++;
+ if (p->privsvr_checksum == NULL)
+ num++;
+ if (p->logon_name == NULL)
+ num++;
+
+ if (num) {
+ void *ptr;
+
+ ptr = realloc(p->pac, sizeof(*p->pac) + (sizeof(p->pac->buffers[0]) * (p->pac->numbuffers + num - 1)));
+ if (ptr == NULL) {
+ krb5_set_error_string(context, "out of memory");
+ return ENOMEM;
+ }
+ p->pac = ptr;
+
+ if (p->server_checksum == NULL) {
+ p->server_checksum = &p->pac->buffers[p->pac->numbuffers++];
+ memset(p->server_checksum, 0, sizeof(*p->server_checksum));
+ p->server_checksum->type = PAC_SERVER_CHECKSUM;
+ }
+ if (p->privsvr_checksum == NULL) {
+ p->privsvr_checksum = &p->pac->buffers[p->pac->numbuffers++];
+ memset(p->privsvr_checksum, 0, sizeof(*p->privsvr_checksum));
+ p->privsvr_checksum->type = PAC_PRIVSVR_CHECKSUM;
+ }
+ if (p->logon_name == NULL) {
+ p->logon_name = &p->pac->buffers[p->pac->numbuffers++];
+ memset(p->logon_name, 0, sizeof(*p->logon_name));
+ p->logon_name->type = PAC_LOGON_NAME;
+ }
+ }
+
+ /* Calculate LOGON NAME */
+ ret = build_logon_name(context, authtime, principal, &logon);
+ if (ret)
+ goto out;
+
+ /* Set lengths for checksum */
+
+ ret = pac_checksum(context, server_key, &server_cksumtype, &server_size);
+ if (ret)
+ goto out;
+ ret = pac_checksum(context, priv_key, &priv_cksumtype, &priv_size);
+ if (ret)
+ goto out;
+
+ /* Encode PAC */
+ sp = krb5_storage_emem();
+ if (sp == NULL) {
+ krb5_set_error_string(context, "out of memory");
+ return ENOMEM;
+ }
+ krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE);
+
+ spdata = krb5_storage_emem();
+ if (spdata == NULL) {
+ krb5_storage_free(sp);
+ krb5_set_error_string(context, "out of memory");
+ return ENOMEM;
+ }
+ krb5_storage_set_flags(spdata, KRB5_STORAGE_BYTEORDER_LE);
+
+ CHECK(ret, krb5_store_uint32(sp, p->pac->numbuffers), out);
+ CHECK(ret, krb5_store_uint32(sp, p->pac->version), out);
+
+ end = PACTYPE_SIZE + (PAC_INFO_BUFFER_SIZE * p->pac->numbuffers);
+
+ for (i = 0; i < p->pac->numbuffers; i++) {
+ uint32_t len;
+ size_t sret;
+ void *ptr = NULL;
+
+ /* store data */
+
+ if (p->pac->buffers[i].type == PAC_SERVER_CHECKSUM) {
+ len = server_size + 4;
+ server_offset = end + 4;
+ CHECK(ret, krb5_store_uint32(spdata, server_cksumtype), out);
+ CHECK(ret, fill_zeros(context, spdata, server_size), out);
+ } else if (p->pac->buffers[i].type == PAC_PRIVSVR_CHECKSUM) {
+ len = priv_size + 4;
+ priv_offset = end + 4;
+ CHECK(ret, krb5_store_uint32(spdata, priv_cksumtype), out);
+ CHECK(ret, fill_zeros(context, spdata, priv_size), out);
+ } else if (p->pac->buffers[i].type == PAC_LOGON_NAME) {
+ len = krb5_storage_write(spdata, logon.data, logon.length);
+ if (logon.length != len) {
+ ret = EINVAL;
+ goto out;
+ }
+ } else {
+ len = p->pac->buffers[i].buffersize;
+ ptr = (char *)p->data.data + p->pac->buffers[i].offset_lo;
+
+ sret = krb5_storage_write(spdata, ptr, len);
+ if (sret != len) {
+ krb5_set_error_string(context, "out of memory");
+ ret = ENOMEM;
+ goto out;
+ }
+ /* XXX if not aligned, fill_zeros */
+ }
+
+ /* write header */
+ CHECK(ret, krb5_store_uint32(sp, p->pac->buffers[i].type), out);
+ CHECK(ret, krb5_store_uint32(sp, len), out);
+ CHECK(ret, krb5_store_uint32(sp, end), out);
+ CHECK(ret, krb5_store_uint32(sp, 0), out);
+
+ /* advance data endpointer and align */
+ {
+ int32_t e;
+
+ end += len;
+ e = ((end + PAC_ALIGNMENT - 1) / PAC_ALIGNMENT) * PAC_ALIGNMENT;
+ if (end != e) {
+ CHECK(ret, fill_zeros(context, spdata, e - end), out);
+ }
+ end = e;
+ }
+
+ }
+
+ /* assert (server_offset != 0 && priv_offset != 0); */
+
+ /* export PAC */
+ ret = krb5_storage_to_data(spdata, &d);
+ if (ret) {
+ krb5_set_error_string(context, "out of memory");
+ goto out;
+ }
+ ret = krb5_storage_write(sp, d.data, d.length);
+ if (ret != d.length) {
+ krb5_data_free(&d);
+ krb5_set_error_string(context, "out of memory");
+ ret = ENOMEM;
+ goto out;
+ }
+ krb5_data_free(&d);
+
+ ret = krb5_storage_to_data(sp, &d);
+ if (ret) {
+ krb5_set_error_string(context, "out of memory");
+ goto out;
+ }
+
+ /* sign */
+
+ ret = create_checksum(context, server_key,
+ d.data, d.length,
+ (char *)d.data + server_offset, server_size);
+ if (ret) {
+ krb5_data_free(&d);
+ goto out;
+ }
+
+ ret = create_checksum(context, priv_key,
+ (char *)d.data + server_offset, server_size,
+ (char *)d.data + priv_offset, priv_size);
+ if (ret) {
+ krb5_data_free(&d);
+ goto out;
+ }
+
+ /* done */
+ *data = d;
+
+ krb5_data_free(&logon);
+ krb5_storage_free(sp);
+ krb5_storage_free(spdata);
+
+ return 0;
+out:
+ krb5_data_free(&logon);
+ if (sp)
+ krb5_storage_free(sp);
+ if (spdata)
+ krb5_storage_free(spdata);
+ return ret;
+}
diff --git a/source4/heimdal/lib/krb5/pkinit.c b/source4/heimdal/lib/krb5/pkinit.c
index f519b5ad08..4f8ed8fe07 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.110 2006/10/14 09:52:50 lha Exp $");
+RCSID("$Id: pkinit.c,v 1.120 2006/12/08 02:48:09 lha Exp $");
struct krb5_dh_moduli {
char *name;
@@ -81,12 +81,26 @@ struct krb5_pk_init_ctx_data {
DH *dh;
krb5_data *clientDHNonce;
struct krb5_dh_moduli **m;
+ hx509_peer_info peer;
+ int type;
int require_binding;
int require_eku;
int require_krbtgt_otherName;
int require_hostname_match;
};
+static void
+_krb5_pk_copy_error(krb5_context context,
+ hx509_context hx509ctx,
+ int hxret,
+ const char *fmt,
+ ...)
+ __attribute__ ((format (printf, 4, 5)));
+
+/*
+ *
+ */
+
void KRB5_LIB_FUNCTION
_krb5_pk_cert_free(struct krb5_pk_cert *cert)
{
@@ -130,6 +144,7 @@ _krb5_pk_create_sign(krb5_context context,
const heim_oid *eContentType,
krb5_data *eContent,
struct krb5_pk_identity *id,
+ hx509_peer_info peer,
krb5_data *sd_data)
{
hx509_cert cert;
@@ -137,16 +152,22 @@ _krb5_pk_create_sign(krb5_context context,
int ret;
ret = hx509_query_alloc(id->hx509ctx, &q);
- if (ret)
+ if (ret) {
+ _krb5_pk_copy_error(context, id->hx509ctx, ret,
+ "Allocate query to find signing certificate");
return ret;
+ }
hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE);
ret = hx509_certs_find(id->hx509ctx, id->certs, q, &cert);
hx509_query_free(id->hx509ctx, q);
- if (ret)
+ if (ret) {
+ _krb5_pk_copy_error(context, id->hx509ctx, ret,
+ "Find certificate to signed CMS data");
return ret;
+ }
ret = hx509_cms_create_signed_1(id->hx509ctx,
eContentType,
@@ -154,9 +175,12 @@ _krb5_pk_create_sign(krb5_context context,
eContent->length,
NULL,
cert,
+ peer,
NULL,
- NULL,
+ id->certs,
sd_data);
+ if (ret)
+ _krb5_pk_copy_error(context, id->hx509ctx, ret, "create CMS signedData");
hx509_cert_free(cert);
return ret;
@@ -402,6 +426,19 @@ build_auth_pack(krb5_context context,
a->clientPublicValue->subjectPublicKey.data = dhbuf.data;
}
+ {
+ a->supportedCMSTypes = calloc(1, sizeof(*a->supportedCMSTypes));
+ if (a->supportedCMSTypes == NULL)
+ return ENOMEM;
+
+ ret = hx509_crypto_available(ctx->id->hx509ctx, HX509_SELECT_ALL, NULL,
+ &a->supportedCMSTypes->val,
+ &a->supportedCMSTypes->len);
+ if (ret)
+ return ret;
+ }
+
+
return ret;
}
@@ -429,7 +466,6 @@ _krb5_pk_mk_ContentInfo(krb5_context context,
static krb5_error_code
pk_mk_padata(krb5_context context,
- int compat,
krb5_pk_init_ctx ctx,
const KDC_REQ_BODY *req_body,
unsigned nonce,
@@ -446,7 +482,7 @@ pk_mk_padata(krb5_context context,
krb5_data_zero(&sd_buf);
memset(&content_info, 0, sizeof(content_info));
- if (compat == COMPAT_WIN2K) {
+ if (ctx->type == COMPAT_WIN2K) {
AuthPack_Win2k ap;
krb5_timestamp sec;
int32_t usec;
@@ -483,7 +519,7 @@ pk_mk_padata(krb5_context context,
krb5_abortx(context, "internal ASN1 encoder error");
oid = oid_id_pkcs7_data();
- } else if (compat == COMPAT_IETF) {
+ } else if (ctx->type == COMPAT_IETF) {
AuthPack ap;
memset(&ap, 0, sizeof(ap));
@@ -510,7 +546,8 @@ pk_mk_padata(krb5_context context,
ret = _krb5_pk_create_sign(context,
oid,
&buf,
- ctx->id,
+ ctx->id,
+ ctx->peer,
&sd_buf);
krb5_data_free(&buf);
if (ret)
@@ -529,7 +566,7 @@ pk_mk_padata(krb5_context context,
if (buf.length != size)
krb5_abortx(context, "Internal ASN1 encoder error");
- if (compat == COMPAT_WIN2K) {
+ if (ctx->type == COMPAT_WIN2K) {
PA_PK_AS_REQ_Win2k winreq;
pa_type = KRB5_PADATA_PK_AS_REQ_WIN;
@@ -542,7 +579,7 @@ pk_mk_padata(krb5_context context,
&winreq, &size, ret);
free_PA_PK_AS_REQ_Win2k(&winreq);
- } else if (compat == COMPAT_IETF) {
+ } else if (ctx->type == COMPAT_IETF) {
PA_PK_AS_REQ req;
pa_type = KRB5_PADATA_PK_AS_REQ;
@@ -583,7 +620,7 @@ pk_mk_padata(krb5_context context,
if (ret)
free(buf.data);
- if (ret == 0 && compat == COMPAT_WIN2K)
+ if (ret == 0 && ctx->type == COMPAT_WIN2K)
krb5_padata_add(context, md, KRB5_PADATA_PK_AS_09_BINDING, NULL, 0);
out:
@@ -601,13 +638,13 @@ _krb5_pk_mk_padata(krb5_context context,
METHOD_DATA *md)
{
krb5_pk_init_ctx ctx = c;
- int win2k_compat, type;
+ int win2k_compat;
win2k_compat = krb5_config_get_bool_default(context, NULL,
FALSE,
"realms",
req_body->realm,
- "win2k_pkinit",
+ "pkinit_win2k",
NULL);
if (context->pkinit_flags & KRB5_PKINIT_WIN2K)
win2k_compat = 1;
@@ -618,11 +655,11 @@ _krb5_pk_mk_padata(krb5_context context,
FALSE,
"realms",
req_body->realm,
- "win2k_pkinit_require_binding",
+ "pkinit_win2k_require_binding",
NULL);
- type = COMPAT_WIN2K;
+ ctx->type = COMPAT_WIN2K;
} else
- type = COMPAT_IETF;
+ ctx->type = COMPAT_IETF;
ctx->require_eku =
krb5_config_get_bool_default(context, NULL,
@@ -647,7 +684,7 @@ _krb5_pk_mk_padata(krb5_context context,
"pkinit_require_hostname_match",
NULL);
- return pk_mk_padata(context, type, ctx, req_body, nonce, md);
+ return pk_mk_padata(context, ctx, req_body, nonce, md);
}
krb5_error_code KRB5_LIB_FUNCTION
@@ -673,13 +710,8 @@ _krb5_pk_verify_sign(krb5_context context,
content,
&signer_certs);
if (ret) {
- char *s = hx509_get_error_string(id->hx509ctx, ret);
- if (s) {
- krb5_set_error_string(context,
- "CMS verify signed failed with %s", s);
- free(s);
- } else
- krb5_clear_error_string(context);
+ _krb5_pk_copy_error(context, id->hx509ctx, ret,
+ "CMS verify signed failed");
return ret;
}
@@ -692,7 +724,8 @@ _krb5_pk_verify_sign(krb5_context context,
ret = hx509_get_one_cert(id->hx509ctx, signer_certs, &(*signer)->cert);
if (ret) {
- krb5_clear_error_string(context);
+ _krb5_pk_copy_error(context, id->hx509ctx, ret,
+ "Failed to get on of the signer certs");
goto out;
}
@@ -932,8 +965,11 @@ pk_rd_pa_reply_enckey(krb5_context context,
NULL,
&contentType,
&content);
- if (ret)
+ if (ret) {
+ _krb5_pk_copy_error(context, ctx->id->hx509ctx, ret,
+ "Failed to unenvelope CMS data in PK-INIT reply");
return ret;
+ }
p = content.data;
length = content.length;
@@ -1212,8 +1248,13 @@ _krb5_pk_rd_pa_reply(krb5_context context,
size_t size;
/* Check for IETF PK-INIT first */
- if (pa->padata_type == KRB5_PADATA_PK_AS_REP) {
+ if (ctx->type == COMPAT_IETF) {
PA_PK_AS_REP rep;
+
+ if (pa->padata_type != KRB5_PADATA_PK_AS_REP) {
+ krb5_set_error_string(context, "PKINIT: wrong padata recv");
+ return EINVAL;
+ }
memset(&rep, 0, sizeof(rep));
@@ -1269,14 +1310,19 @@ _krb5_pk_rd_pa_reply(krb5_context context,
ret = EINVAL;
break;
}
- if (ret == 0)
- return ret;
- }
- /* Check for Windows encoding of the AS-REP pa data */
- {
+ } else if (ctx->type == COMPAT_WIN2K) {
PA_PK_AS_REP_Win2k w2krep;
+ /* Check for Windows encoding of the AS-REP pa data */
+
+#if 0 /* should this be ? */
+ if (pa->padata_type != KRB5_PADATA_PK_AS_REP) {
+ krb5_set_error_string(context, "PKINIT: wrong padata recv");
+ return EINVAL;
+ }
+#endif
+
memset(&w2krep, 0, sizeof(w2krep));
ret = decode_PA_PK_AS_REP_Win2k(pa->padata_value.data,
@@ -1317,6 +1363,9 @@ _krb5_pk_rd_pa_reply(krb5_context context,
break;
}
+ } else {
+ krb5_set_error_string(context, "PKINIT: unknown reply type");
+ ret = EINVAL;
}
return ret;
@@ -1428,25 +1477,34 @@ _krb5_pk_load_id(krb5_context context,
}
ret = hx509_certs_init(id->hx509ctx, user_id, 0, lock, &id->certs);
- if (ret)
+ if (ret) {
+ _krb5_pk_copy_error(context, id->hx509ctx, ret,
+ "Failed to init cert certs");
goto out;
+ }
ret = hx509_certs_init(id->hx509ctx, anchor_id, 0, NULL, &id->anchors);
- if (ret)
+ if (ret) {
+ _krb5_pk_copy_error(context, id->hx509ctx, ret,
+ "Failed to init anchors");
goto out;
+ }
ret = hx509_certs_init(id->hx509ctx, "MEMORY:pkinit-cert-chain",
0, NULL, &id->certpool);
- if (ret)
+ if (ret) {
+ _krb5_pk_copy_error(context, id->hx509ctx, ret,
+ "Failed to init chain");
goto out;
+ }
while (chain_list && *chain_list) {
ret = hx509_certs_append(id->hx509ctx, id->certpool,
NULL, *chain_list);
if (ret) {
- krb5_set_error_string(context,
- "pkinit failed to load chain %s",
- *chain_list);
+ _krb5_pk_copy_error(context, id->hx509ctx, ret,
+ "Failed to laod chain %s",
+ *chain_list);
goto out;
}
chain_list++;
@@ -1455,7 +1513,8 @@ _krb5_pk_load_id(krb5_context context,
if (revoke_list) {
ret = hx509_revoke_init(id->hx509ctx, &id->revokectx);
if (ret) {
- krb5_set_error_string(context, "revoke failed to init");
+ _krb5_pk_copy_error(context, id->hx509ctx, ret,
+ "Failed init revoke list");
goto out;
}
@@ -1464,9 +1523,8 @@ _krb5_pk_load_id(krb5_context context,
id->revokectx,
*revoke_list);
if (ret) {
- krb5_set_error_string(context,
- "pkinit failed to load revoke %s",
- *revoke_list);
+ _krb5_pk_copy_error(context, id->hx509ctx, ret,
+ "Failed load revoke list");
goto out;
}
revoke_list++;
@@ -1475,8 +1533,11 @@ _krb5_pk_load_id(krb5_context context,
hx509_context_set_missing_revoke(id->hx509ctx, 1);
ret = hx509_verify_init_ctx(id->hx509ctx, &id->verify_ctx);
- if (ret)
+ if (ret) {
+ _krb5_pk_copy_error(context, id->hx509ctx, ret,
+ "Failed init verify context");
goto out;
+ }
hx509_verify_attach_anchors(id->verify_ctx, id->anchors);
hx509_verify_attach_revoke(id->verify_ctx, id->revokectx);
@@ -1504,9 +1565,25 @@ select_dh_group(krb5_context context, DH *dh, unsigned long bits,
{
const struct krb5_dh_moduli *m;
- m = moduli[1]; /* XXX */
- if (m == NULL)
- m = moduli[0]; /* XXX */
+ if (bits == 0) {
+ m = moduli[1]; /* XXX */
+ if (m == NULL)
+ m = moduli[0]; /* XXX */
+ } else {
+ int i;
+ for (i = 0; moduli[i] != NULL; i++) {
+ if (bits < moduli[i]->bits)
+ break;
+ }
+ if (moduli[i] == NULL) {
+ krb5_set_error_string(context,
+ "Did not find a DH group parameter "
+ "matching requirement of %lu bits",
+ bits);
+ return EINVAL;
+ }
+ m = moduli[i];
+ }
dh->p = integer_to_BN(context, "p", &m->p);
if (dh->p == NULL)
@@ -1822,25 +1899,25 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context,
opt->opt_private->pk_init_ctx->require_binding = 0;
opt->opt_private->pk_init_ctx->require_eku = 1;
opt->opt_private->pk_init_ctx->require_krbtgt_otherName = 1;
-
+ opt->opt_private->pk_init_ctx->peer = NULL;
/* XXX implement krb5_appdefault_strings */
if (pool == NULL)
pool = krb5_config_get_strings(context, NULL,
"appdefaults",
- "pkinit-pool",
+ "pkinit_pool",
NULL);
if (pki_revoke == NULL)
pki_revoke = krb5_config_get_strings(context, NULL,
"appdefaults",
- "pkinit-revoke",
+ "pkinit_revoke",
NULL);
if (x509_anchors == NULL) {
krb5_appdefault_string(context, "kinit",
krb5_principal_get_realm(context, principal),
- "pkinit-anchors", NULL, &anchors);
+ "pkinit_anchors", NULL, &anchors);
x509_anchors = anchors;
}
@@ -1861,12 +1938,19 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context,
if ((flags & 2) == 0) {
const char *moduli_file;
+ unsigned long dh_min_bits;
moduli_file = krb5_config_get_string(context, NULL,
"libdefaults",
"moduli",
NULL);
+ dh_min_bits =
+ krb5_config_get_int_default(context, NULL, 0,
+ "libdefaults",
+ "pkinit_dh_min_bits",
+ NULL);
+
ret = _krb5_parse_moduli(context, moduli_file,
&opt->opt_private->pk_init_ctx->m);
if (ret) {
@@ -1881,7 +1965,8 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context,
return ENOMEM;
}
- ret = select_dh_group(context, opt->opt_private->pk_init_ctx->dh, 0,
+ ret = select_dh_group(context, opt->opt_private->pk_init_ctx->dh,
+ dh_min_bits,
opt->opt_private->pk_init_ctx->m);
if (ret) {
_krb5_get_init_creds_opt_free_pkinit(opt);
@@ -1901,3 +1986,36 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context,
return EINVAL;
#endif
}
+
+/*
+ *
+ */
+
+static void
+_krb5_pk_copy_error(krb5_context context,
+ hx509_context hx509ctx,
+ int hxret,
+ const char *fmt,
+ ...)
+{
+ va_list va;
+ char *s, *f;
+
+ va_start(va, fmt);
+ vasprintf(&f, fmt, va);
+ va_end(va);
+ if (f == NULL) {
+ krb5_clear_error_string(context);
+ return;
+ }
+
+ s = hx509_get_error_string(hx509ctx, hxret);
+ if (s == NULL) {
+ krb5_clear_error_string(context);
+ free(f);
+ return;
+ }
+ krb5_set_error_string(context, "%s: %s", f, s);
+ free(s);
+ free(f);
+}
diff --git a/source4/heimdal/lib/krb5/plugin.c b/source4/heimdal/lib/krb5/plugin.c
index 294807faab..ce7171dbf0 100644
--- a/source4/heimdal/lib/krb5/plugin.c
+++ b/source4/heimdal/lib/krb5/plugin.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 Kungliga Tekniska Högskolan
+ * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -32,7 +32,7 @@
*/
#include "krb5_locl.h"
-RCSID("$Id: plugin.c,v 1.2 2006/11/12 21:39:43 lha Exp $");
+RCSID("$Id: plugin.c,v 1.4 2007/01/09 17:46:01 lha Exp $");
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
#endif
@@ -89,7 +89,11 @@ loadlib(krb5_context context,
return ENOMEM;
}
- (*e)->dsohandle = dlopen(lib, 0);
+#ifndef RTLD_LAZY
+#define RTLD_LAZY 0
+#endif
+
+ (*e)->dsohandle = dlopen(lib, RTLD_LAZY);
if ((*e)->dsohandle == NULL) {
free(*e);
krb5_set_error_string(context, "Failed to load %s: %s",
diff --git a/source4/heimdal/lib/krb5/principal.c b/source4/heimdal/lib/krb5/principal.c
index 4d13e7db11..57fcf63dcf 100644
--- a/source4/heimdal/lib/krb5/principal.c
+++ b/source4/heimdal/lib/krb5/principal.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2002 Kungliga Tekniska Högskolan
+ * Copyright (c) 1997-2006 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -41,7 +41,7 @@
#include <fnmatch.h>
#include "resolve.h"
-RCSID("$Id: principal.c,v 1.99 2006/10/18 06:53:22 lha Exp $");
+RCSID("$Id: principal.c,v 1.100 2006/12/17 22:53:39 lha Exp $");
#define princ_num_comp(P) ((P)->name.name_string.len)
#define princ_type(P) ((P)->name.name_type)
diff --git a/source4/heimdal/lib/krb5/rd_req.c b/source4/heimdal/lib/krb5/rd_req.c
index 3352334f65..b7dea2a327 100644
--- a/source4/heimdal/lib/krb5/rd_req.c
+++ b/source4/heimdal/lib/krb5/rd_req.c
@@ -33,7 +33,7 @@
#include <krb5_locl.h>
-RCSID("$Id: rd_req.c,v 1.68 2006/11/07 17:11:31 lha Exp $");
+RCSID("$Id: rd_req.c,v 1.70 2007/01/04 11:27:20 lha Exp $");
static krb5_error_code
decrypt_tkt_enc_part (krb5_context context,
@@ -513,6 +513,7 @@ krb5_verify_ap_req2(krb5_context context,
struct krb5_rd_req_in_ctx {
krb5_keytab keytab;
krb5_keyblock *keyblock;
+ krb5_boolean no_pac_check;
};
struct krb5_rd_req_out_ctx {
@@ -546,6 +547,16 @@ krb5_rd_req_in_set_keytab(krb5_context context,
}
krb5_error_code KRB5_LIB_FUNCTION
+krb5_rd_req_in_set_pac_check(krb5_context context,
+ krb5_rd_req_in_ctx in,
+ krb5_boolean flag)
+{
+ in->no_pac_check = !flag;
+ return 0;
+}
+
+
+krb5_error_code KRB5_LIB_FUNCTION
krb5_rd_req_in_set_keyblock(krb5_context context,
krb5_rd_req_in_ctx in,
krb5_keyblock *keyblock)
@@ -822,6 +833,36 @@ krb5_rd_req_ctx(krb5_context context,
&o->ap_req_options,
&o->ticket);
+ if (ret)
+ goto out;
+
+ /* If there is a PAC, verify its server signature */
+ if (inctx->no_pac_check == FALSE) {
+ krb5_pac pac;
+ krb5_data data;
+
+ ret = krb5_ticket_get_authorization_data_type(context,
+ o->ticket,
+ KRB5_AUTHDATA_WIN2K_PAC,
+ &data);
+ if (ret == 0) {
+ ret = krb5_pac_parse(context, data.data, data.length, &pac);
+ krb5_data_free(&data);
+ if (ret)
+ goto out;
+
+ ret = krb5_pac_verify(context,
+ pac,
+ o->ticket->ticket.authtime,
+ o->ticket->client,
+ o->keyblock,
+ NULL);
+ krb5_pac_free(context, pac);
+ if (ret)
+ goto out;
+ }
+ ret = 0;
+ }
out:
if (ret || outctx == NULL) {
krb5_rd_req_out_ctx_free(context, o);
diff --git a/source4/heimdal/lib/krb5/store.c b/source4/heimdal/lib/krb5/store.c
index e75f28ca5f..5422c540b9 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.59 2006/08/18 08:39:13 lha Exp $");
+RCSID("$Id: store.c,v 1.60 2006/12/17 22:49:37 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)
@@ -577,6 +577,7 @@ krb5_ret_principal(krb5_storage *sp,
p->name.name_string.val = calloc(ncomp, sizeof(*p->name.name_string.val));
if(p->name.name_string.val == NULL && ncomp != 0){
free(p->realm);
+ free(p);
return ENOMEM;
}
for(i = 0; i < ncomp; i++){
diff --git a/source4/heimdal/lib/krb5/ticket.c b/source4/heimdal/lib/krb5/ticket.c
index fdc2a1b3a5..81372c158e 100644
--- a/source4/heimdal/lib/krb5/ticket.c
+++ b/source4/heimdal/lib/krb5/ticket.c
@@ -33,7 +33,7 @@
#include "krb5_locl.h"
-RCSID("$Id: ticket.c,v 1.15 2006/10/14 09:53:19 lha Exp $");
+RCSID("$Id: ticket.c,v 1.18 2006/12/28 20:49:18 lha Exp $");
krb5_error_code KRB5_LIB_FUNCTION
krb5_free_ticket(krb5_context context,
@@ -97,6 +97,13 @@ krb5_ticket_get_server(krb5_context context,
return krb5_copy_principal(context, ticket->server, server);
}
+time_t KRB5_LIB_FUNCTION
+krb5_ticket_get_endtime(krb5_context context,
+ const krb5_ticket *ticket)
+{
+ return ticket->ticket.endtime;
+}
+
static int
find_type_in_ad(krb5_context context,
int type,
@@ -107,10 +114,6 @@ find_type_in_ad(krb5_context context,
const AuthorizationData *ad,
int level)
{
- /* It is not an error if nothing in here, that is reported by *found */
- /* Setting a default error causes found to be set to FALSE, on
- * recursion to an second embedded authz data even if the first
- * element contains the required type */
krb5_error_code ret = 0;
int i;
@@ -148,8 +151,8 @@ find_type_in_ad(krb5_context context,
"IF_RELEVANT with %d", ret);
goto out;
}
- ret = find_type_in_ad(context, type, data, found, 0, sessionkey,
- &child, level + 1);
+ ret = find_type_in_ad(context, type, data, found, FALSE,
+ sessionkey, &child, level + 1);
free_AuthorizationData(&child);
if (ret)
goto out;
@@ -232,19 +235,6 @@ out:
return ret;
}
-int
-_krb5_find_type_in_ad(krb5_context context,
- int type,
- krb5_data *data,
- krb5_boolean *found,
- krb5_keyblock *sessionkey,
- const AuthorizationData *ad)
-{
- krb5_data_zero(data);
- return find_type_in_ad(context, type, data, found, TRUE, sessionkey, ad, 0);
-}
-
-
/*
* Extract the authorization data type of `type' from the
* 'ticket'. Store the field in `data'. This function is to use for
@@ -259,7 +249,9 @@ krb5_ticket_get_authorization_data_type(krb5_context context,
{
AuthorizationData *ad;
krb5_error_code ret;
- krb5_boolean found = 0;
+ krb5_boolean found = FALSE;
+
+ krb5_data_zero(data);
ad = ticket->ticket.authorization_data;
if (ticket->ticket.authorization_data == NULL) {
@@ -267,8 +259,8 @@ krb5_ticket_get_authorization_data_type(krb5_context context,
return ENOENT; /* XXX */
}
- ret = _krb5_find_type_in_ad(context, type, data, &found, &ticket->ticket.key,
- ticket->ticket.authorization_data);
+ ret = find_type_in_ad(context, type, data, &found, TRUE,
+ &ticket->ticket.key, ad, 0);
if (ret)
return ret;
if (!found) {
diff --git a/source4/heimdal/lib/krb5/warn.c b/source4/heimdal/lib/krb5/warn.c
index f9825914ee..4252865301 100644
--- a/source4/heimdal/lib/krb5/warn.c
+++ b/source4/heimdal/lib/krb5/warn.c
@@ -34,7 +34,7 @@
#include "krb5_locl.h"
#include <err.h>
-RCSID("$Id: warn.c,v 1.15 2004/05/25 21:46:26 lha Exp $");
+RCSID("$Id: warn.c,v 1.16 2006/11/21 08:06:40 lha Exp $");
static krb5_error_code _warnerr(krb5_context context, int do_errtext,
krb5_error_code code, int level, const char *fmt, va_list ap)
@@ -203,3 +203,9 @@ krb5_set_warn_dest(krb5_context context, krb5_log_facility *fac)
context->warn_dest = fac;
return 0;
}
+
+krb5_log_facility * KRB5_LIB_FUNCTION
+krb5_get_warn_dest(krb5_context context)
+{
+ return context->warn_dest;
+}