summaryrefslogtreecommitdiff
path: root/source4/heimdal/lib/krb5
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2007-01-10 01:57:32 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 14:37:20 -0500
commitf7242f643763ccb6e10801af4ce53d0873e2d3e1 (patch)
treecd06665f49d12795e23699e6666d85da1f64d7bd /source4/heimdal/lib/krb5
parent08976cb3d2adfe5ea90ed53e6aa6fa8161649f7a (diff)
downloadsamba-f7242f643763ccb6e10801af4ce53d0873e2d3e1.tar.gz
samba-f7242f643763ccb6e10801af4ce53d0873e2d3e1.tar.bz2
samba-f7242f643763ccb6e10801af4ce53d0873e2d3e1.zip
r20640: Commit part 2/2
Update Heimdal to match current lorikeet-heimdal. This includes integrated PAC hooks, so Samba doesn't have to handle this any more. This also brings in the PKINIT code, hence so many new files. Andrew Bartlett (This used to be commit 351f7040f7bb73b9a60b22b564686f7c2f98a729)
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;
+}