summaryrefslogtreecommitdiff
path: root/source4/heimdal/lib/krb5
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2009-06-08 19:06:16 +1000
committerAndrew Bartlett <abartlet@samba.org>2009-06-12 07:45:48 +1000
commit9b261c008a395a323e0516f4cd3f3134aa050577 (patch)
tree91cf543ba7ccd560313bea52fa8678f0456e8485 /source4/heimdal/lib/krb5
parent5cef57ff7d899773a084d23838b7f18a83f6e79d (diff)
downloadsamba-9b261c008a395a323e0516f4cd3f3134aa050577.tar.gz
samba-9b261c008a395a323e0516f4cd3f3134aa050577.tar.bz2
samba-9b261c008a395a323e0516f4cd3f3134aa050577.zip
s4:heimdal: import lorikeet-heimdal-200906080040 (commit 904d0124b46eed7a8ad6e5b73e892ff34b6865ba)
Also including the supporting changes required to pass make test A number of heimdal functions and constants have changed since we last imported a tree (for the better, but inconvenient for us). Andrew Bartlett
Diffstat (limited to 'source4/heimdal/lib/krb5')
-rw-r--r--source4/heimdal/lib/krb5/acache.c25
-rw-r--r--source4/heimdal/lib/krb5/add_et_list.c2
-rw-r--r--source4/heimdal/lib/krb5/addr_families.c12
-rw-r--r--source4/heimdal/lib/krb5/appdefault.c2
-rw-r--r--source4/heimdal/lib/krb5/asn1_glue.c18
-rw-r--r--source4/heimdal/lib/krb5/auth_context.c2
-rw-r--r--source4/heimdal/lib/krb5/build_ap_req.c2
-rw-r--r--source4/heimdal/lib/krb5/build_auth.c4
-rw-r--r--source4/heimdal/lib/krb5/cache.c328
-rw-r--r--source4/heimdal/lib/krb5/changepw.c28
-rw-r--r--source4/heimdal/lib/krb5/codec.c39
-rw-r--r--source4/heimdal/lib/krb5/config_file.c53
-rw-r--r--source4/heimdal/lib/krb5/config_file_netinfo.c180
-rw-r--r--source4/heimdal/lib/krb5/constants.c9
-rw-r--r--source4/heimdal/lib/krb5/context.c135
-rw-r--r--source4/heimdal/lib/krb5/convert_creds.c6
-rw-r--r--source4/heimdal/lib/krb5/copy_host_realm.c2
-rw-r--r--source4/heimdal/lib/krb5/crc.c2
-rw-r--r--source4/heimdal/lib/krb5/creds.c21
-rw-r--r--source4/heimdal/lib/krb5/crypto.c492
-rw-r--r--source4/heimdal/lib/krb5/data.c21
-rw-r--r--source4/heimdal/lib/krb5/eai_to_heim_errno.c2
-rw-r--r--source4/heimdal/lib/krb5/error_string.c84
-rw-r--r--source4/heimdal/lib/krb5/expand_hostname.c37
-rw-r--r--source4/heimdal/lib/krb5/fcache.c52
-rw-r--r--source4/heimdal/lib/krb5/free.c2
-rw-r--r--source4/heimdal/lib/krb5/free_host_realm.c11
-rw-r--r--source4/heimdal/lib/krb5/generate_seq_number.c2
-rw-r--r--source4/heimdal/lib/krb5/generate_subkey.c2
-rw-r--r--source4/heimdal/lib/krb5/get_addrs.c11
-rw-r--r--source4/heimdal/lib/krb5/get_cred.c25
-rw-r--r--source4/heimdal/lib/krb5/get_default_principal.c2
-rw-r--r--source4/heimdal/lib/krb5/get_default_realm.c2
-rw-r--r--source4/heimdal/lib/krb5/get_for_creds.c2
-rw-r--r--source4/heimdal/lib/krb5/get_host_realm.c16
-rw-r--r--source4/heimdal/lib/krb5/get_in_tkt.c539
-rw-r--r--source4/heimdal/lib/krb5/get_in_tkt_with_keytab.c99
-rw-r--r--source4/heimdal/lib/krb5/get_port.c2
-rw-r--r--source4/heimdal/lib/krb5/heim_err.et2
-rw-r--r--source4/heimdal/lib/krb5/heim_threads.h175
-rw-r--r--source4/heimdal/lib/krb5/init_creds.c166
-rw-r--r--source4/heimdal/lib/krb5/init_creds_pw.c1184
-rw-r--r--source4/heimdal/lib/krb5/kcm.c121
-rw-r--r--source4/heimdal/lib/krb5/keyblock.c79
-rw-r--r--source4/heimdal/lib/krb5/keytab.c439
-rw-r--r--source4/heimdal/lib/krb5/keytab_any.c3
-rw-r--r--source4/heimdal/lib/krb5/keytab_file.c40
-rw-r--r--source4/heimdal/lib/krb5/keytab_keyfile.c5
-rw-r--r--source4/heimdal/lib/krb5/keytab_memory.c3
-rw-r--r--source4/heimdal/lib/krb5/krb5.h75
-rw-r--r--source4/heimdal/lib/krb5/krb5_ccapi.h11
-rw-r--r--source4/heimdal/lib/krb5/krb5_err.et8
-rw-r--r--source4/heimdal/lib/krb5/krb5_locl.h9
-rw-r--r--source4/heimdal/lib/krb5/krbhst.c22
-rw-r--r--source4/heimdal/lib/krb5/locate_plugin.h4
-rw-r--r--source4/heimdal/lib/krb5/log.c2
-rw-r--r--source4/heimdal/lib/krb5/mcache.c2
-rw-r--r--source4/heimdal/lib/krb5/misc.c2
-rw-r--r--source4/heimdal/lib/krb5/mit_glue.c20
-rw-r--r--source4/heimdal/lib/krb5/mk_error.c2
-rw-r--r--source4/heimdal/lib/krb5/mk_priv.c3
-rw-r--r--source4/heimdal/lib/krb5/mk_rep.c2
-rw-r--r--source4/heimdal/lib/krb5/mk_req.c2
-rw-r--r--source4/heimdal/lib/krb5/mk_req_ext.c2
-rw-r--r--source4/heimdal/lib/krb5/n-fold.c20
-rw-r--r--source4/heimdal/lib/krb5/pac.c3
-rw-r--r--source4/heimdal/lib/krb5/padata.c2
-rw-r--r--source4/heimdal/lib/krb5/pkinit.c814
-rw-r--r--source4/heimdal/lib/krb5/plugin.c44
-rw-r--r--source4/heimdal/lib/krb5/principal.c123
-rw-r--r--source4/heimdal/lib/krb5/prog_setup.c2
-rw-r--r--source4/heimdal/lib/krb5/prompter_posix.c2
-rw-r--r--source4/heimdal/lib/krb5/rd_cred.c17
-rw-r--r--source4/heimdal/lib/krb5/rd_error.c2
-rw-r--r--source4/heimdal/lib/krb5/rd_priv.c2
-rw-r--r--source4/heimdal/lib/krb5/rd_rep.c13
-rw-r--r--source4/heimdal/lib/krb5/rd_req.c301
-rw-r--r--source4/heimdal/lib/krb5/replay.c2
-rw-r--r--source4/heimdal/lib/krb5/send_to_kdc.c6
-rw-r--r--source4/heimdal/lib/krb5/set_default_realm.c2
-rw-r--r--source4/heimdal/lib/krb5/store-int.h1
-rw-r--r--source4/heimdal/lib/krb5/store.c281
-rw-r--r--source4/heimdal/lib/krb5/store_emem.c48
-rw-r--r--source4/heimdal/lib/krb5/store_fd.c24
-rw-r--r--source4/heimdal/lib/krb5/store_mem.c61
-rw-r--r--source4/heimdal/lib/krb5/ticket.c484
-rw-r--r--source4/heimdal/lib/krb5/time.c2
-rw-r--r--source4/heimdal/lib/krb5/transited.c2
-rw-r--r--source4/heimdal/lib/krb5/v4_glue.c7
-rw-r--r--source4/heimdal/lib/krb5/version.c2
-rw-r--r--source4/heimdal/lib/krb5/warn.c137
91 files changed, 4331 insertions, 2729 deletions
diff --git a/source4/heimdal/lib/krb5/acache.c b/source4/heimdal/lib/krb5/acache.c
index bd0a9846e4..0ecda99348 100644
--- a/source4/heimdal/lib/krb5/acache.c
+++ b/source4/heimdal/lib/krb5/acache.c
@@ -37,12 +37,8 @@
#include <dlfcn.h>
#endif
-RCSID("$Id$");
-
-/* XXX should we fetch these for each open ? */
static HEIMDAL_MUTEX acc_mutex = HEIMDAL_MUTEX_INITIALIZER;
static cc_initialize_func init_func;
-
#ifdef HAVE_DLOPEN
static void *cc_handle;
#endif
@@ -135,7 +131,7 @@ init_ccapi(krb5_context context)
#else
HEIMDAL_MUTEX_unlock(&acc_mutex);
krb5_set_error_message(context, KRB5_CC_NOSUPP,
- N_("no support for shared object", "file, error"));
+ N_("no support for shared object", ""));
return KRB5_CC_NOSUPP;
#endif
}
@@ -342,6 +338,7 @@ make_ccred_from_cred(krb5_context context,
addr->length = incred->addresses.val[i].address.length;
addr->data = malloc(addr->length);
if (addr->data == NULL) {
+ free(addr);
ret = ENOMEM;
goto fail;
}
@@ -490,16 +487,23 @@ acc_resolve(krb5_context context, krb5_ccache *id, const char *res)
error = (*a->context->func->open_ccache)(a->context, res, &a->ccache);
if (error == ccNoError) {
+ cc_time_t offset;
error = get_cc_name(a);
if (error != ccNoError) {
acc_close(context, *id);
*id = NULL;
return translate_cc_error(context, error);
}
+
+ error = (*a->ccache->func->get_kdc_time_offset)(a->ccache,
+ cc_credentials_v5,
+ &offset);
+ if (error == 0)
+ context->kdc_sec_offset = offset;
+
} else if (error == ccErrCCacheNotFound) {
a->ccache = NULL;
a->cache_name = NULL;
- error = 0;
} else {
*id = NULL;
return translate_cc_error(context, error);
@@ -572,6 +576,11 @@ acc_initialize(krb5_context context,
name);
}
+ if (error == 0 && context->kdc_sec_offset)
+ error = (*a->ccache->func->set_kdc_time_offset)(a->ccache,
+ cc_credentials_v5,
+ context->kdc_sec_offset);
+
return translate_cc_error(context, error);
}
@@ -946,8 +955,10 @@ acc_move(krb5_context context, krb5_ccache from, krb5_ccache to)
return translate_cc_error(context, error);
}
-
error = (*ato->ccache->func->move)(afrom->ccache, ato->ccache);
+
+ acc_destroy(context, from);
+
return translate_cc_error(context, error);
}
diff --git a/source4/heimdal/lib/krb5/add_et_list.c b/source4/heimdal/lib/krb5/add_et_list.c
index f08c0fe718..ccffd93b2c 100644
--- a/source4/heimdal/lib/krb5/add_et_list.c
+++ b/source4/heimdal/lib/krb5/add_et_list.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
/**
* Add a specified list of error messages to the et list in context.
* Call func (probably a comerr-generated function) with a pointer to
diff --git a/source4/heimdal/lib/krb5/addr_families.c b/source4/heimdal/lib/krb5/addr_families.c
index 9e2fb3d63a..f88fb2276a 100644
--- a/source4/heimdal/lib/krb5/addr_families.c
+++ b/source4/heimdal/lib/krb5/addr_families.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
struct addr_operations {
int af;
krb5_address_type atype;
@@ -678,6 +676,9 @@ addrport_print_addr (const krb5_address *addr, char *str, size_t len)
krb5_storage *sp;
sp = krb5_storage_from_data((krb5_data*)rk_UNCONST(&addr->address));
+ if (sp == NULL)
+ return ENOMEM;
+
/* for totally obscure reasons, these are not in network byteorder */
krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_LE);
@@ -1142,10 +1143,12 @@ krb5_parse_address(krb5_context context,
for (a = ai, i = 0; a != NULL; a = a->ai_next) {
if (krb5_sockaddr2address (context, ai->ai_addr, &addresses->val[i]))
continue;
- if(krb5_address_search(context, &addresses->val[i], addresses))
+ if(krb5_address_search(context, &addresses->val[i], addresses)) {
+ krb5_free_address(context, &addresses->val[i]);
continue;
- addresses->len = i;
+ }
i++;
+ addresses->len = i;
}
freeaddrinfo (ai);
return 0;
@@ -1454,7 +1457,6 @@ krb5_make_addrport (krb5_context context,
*p++ = (2 >> 24) & 0xFF;
memcpy (p, &port, 2);
- p += 2;
return 0;
}
diff --git a/source4/heimdal/lib/krb5/appdefault.c b/source4/heimdal/lib/krb5/appdefault.c
index d49fc4997a..383e82dad4 100644
--- a/source4/heimdal/lib/krb5/appdefault.c
+++ b/source4/heimdal/lib/krb5/appdefault.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
void KRB5_LIB_FUNCTION
krb5_appdefault_boolean(krb5_context context, const char *appname,
krb5_const_realm realm, const char *option,
diff --git a/source4/heimdal/lib/krb5/asn1_glue.c b/source4/heimdal/lib/krb5/asn1_glue.c
index cb86c324fb..59c0fbd64b 100644
--- a/source4/heimdal/lib/krb5/asn1_glue.c
+++ b/source4/heimdal/lib/krb5/asn1_glue.c
@@ -37,8 +37,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
krb5_error_code KRB5_LIB_FUNCTION
_krb5_principal2principalname (PrincipalName *p,
const krb5_principal from)
@@ -52,13 +50,23 @@ _krb5_principalname2krb5_principal (krb5_context context,
const PrincipalName from,
const Realm realm)
{
- krb5_principal p = malloc(sizeof(*p));
+ krb5_error_code ret;
+ krb5_principal p;
+
+ p = malloc(sizeof(*p));
if (p == NULL)
return ENOMEM;
- copy_PrincipalName(&from, &p->name);
+ ret = copy_PrincipalName(&from, &p->name);
+ if (ret) {
+ free(p);
+ return ret;
+ }
p->realm = strdup(realm);
- if (p->realm == NULL)
+ if (p->realm == NULL) {
+ free_PrincipalName(&p->name);
+ free(p);
return ENOMEM;
+ }
*principal = p;
return 0;
}
diff --git a/source4/heimdal/lib/krb5/auth_context.c b/source4/heimdal/lib/krb5/auth_context.c
index 66eccbbc07..bfc183d168 100644
--- a/source4/heimdal/lib/krb5/auth_context.c
+++ b/source4/heimdal/lib/krb5/auth_context.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_init(krb5_context context,
krb5_auth_context *auth_context)
diff --git a/source4/heimdal/lib/krb5/build_ap_req.c b/source4/heimdal/lib/krb5/build_ap_req.c
index 92c03cb782..1550239faf 100644
--- a/source4/heimdal/lib/krb5/build_ap_req.c
+++ b/source4/heimdal/lib/krb5/build_ap_req.c
@@ -33,8 +33,6 @@
#include <krb5_locl.h>
-RCSID("$Id$");
-
krb5_error_code KRB5_LIB_FUNCTION
krb5_build_ap_req (krb5_context context,
krb5_enctype enctype,
diff --git a/source4/heimdal/lib/krb5/build_auth.c b/source4/heimdal/lib/krb5/build_auth.c
index bbf4f274af..bf77fd4e77 100644
--- a/source4/heimdal/lib/krb5/build_auth.c
+++ b/source4/heimdal/lib/krb5/build_auth.c
@@ -33,8 +33,6 @@
#include <krb5_locl.h>
-RCSID("$Id$");
-
static krb5_error_code
make_etypelist(krb5_context context,
krb5_authdata **auth_data)
@@ -81,12 +79,14 @@ make_etypelist(krb5_context context,
ALLOC(*auth_data, 1);
if (*auth_data == NULL) {
+ free(buf);
krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
return ENOMEM;
}
ALLOC_SEQ(*auth_data, 1);
if ((*auth_data)->val == NULL) {
+ free(*auth_data);
free(buf);
krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
return ENOMEM;
diff --git a/source4/heimdal/lib/krb5/cache.c b/source4/heimdal/lib/krb5/cache.c
index 80b755cd27..12097470d5 100644
--- a/source4/heimdal/lib/krb5/cache.c
+++ b/source4/heimdal/lib/krb5/cache.c
@@ -33,7 +33,70 @@
#include "krb5_locl.h"
-RCSID("$Id$");
+/**
+ * @page krb5_ccache_intro The credential cache functions
+ * @section section_krb5_ccache Kerberos credential caches
+ *
+ * krb5_ccache structure holds a Kerberos credential cache.
+ *
+ * Heimdal support the follow types of credential caches:
+ *
+ * - SCC
+ * Store the credential in a database
+ * - FILE
+ * Store the credential in memory
+ * - MEMORY
+ * Store the credential in memory
+ * - API
+ * A credential cache server based solution for Mac OS X
+ * - KCM
+ * A credential cache server based solution for all platforms
+ *
+ * @subsection Example
+ *
+ * This is a minimalistic version of klist:
+@code
+#include <krb5.h>
+
+int
+main (int argc, char **argv)
+{
+ krb5_context context;
+ krb5_cc_cursor cursor;
+ krb5_error_code ret;
+ krb5_ccache id;
+ krb5_creds creds;
+
+ if (krb5_init_context (&context) != 0)
+ errx(1, "krb5_context");
+
+ ret = krb5_cc_default (context, &id);
+ if (ret)
+ krb5_err(context, 1, ret, "krb5_cc_default");
+
+ ret = krb5_cc_start_seq_get(context, id, &cursor);
+ if (ret)
+ krb5_err(context, 1, ret, "krb5_cc_start_seq_get");
+
+ while((ret = krb5_cc_next_cred(context, id, &cursor, &creds)) == 0){
+ char *principal;
+
+ krb5_unparse_name_short(context, creds.server, &principal);
+ printf("principal: %s\\n", principal);
+ free(principal);
+ krb5_free_cred_contents (context, &creds);
+ }
+ ret = krb5_cc_end_seq_get(context, id, &cursor);
+ if (ret)
+ krb5_err(context, 1, ret, "krb5_cc_end_seq_get");
+
+ krb5_cc_close(context, id);
+
+ krb5_free_context(context);
+ return 0;
+}
+* @endcode
+*/
/**
* Add a new ccache type with operations `ops', overwriting any
@@ -176,23 +239,6 @@ krb5_cc_resolve(krb5_context context,
}
/**
- * Generate a new ccache of type `ops' in `id'.
- *
- * @return Return an error code or 0, see krb5_get_error_message().
- *
- * @ingroup krb5_ccache
- */
-
-
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_cc_gen_new(krb5_context context,
- const krb5_cc_ops *ops,
- krb5_ccache *id)
-{
- return krb5_cc_new_unique(context, ops->prefix, NULL, id);
-}
-
-/**
* Generates a new unique ccache of `type` in `id'. If `type' is NULL,
* the library chooses the default credential cache type. The supplied
* `hint' (that can be NULL) is a string that the credential cache
@@ -221,7 +267,12 @@ krb5_cc_new_unique(krb5_context context, const char *type,
ret = _krb5_cc_allocate(context, ops, id);
if (ret)
return ret;
- return (*id)->ops->gen_new(context, id);
+ ret = (*id)->ops->gen_new(context, id);
+ if (ret) {
+ free(*id);
+ *id = NULL;
+ }
+ return ret;
}
/**
@@ -676,7 +727,7 @@ krb5_cc_get_principal(krb5_context context,
/**
* Start iterating over `id', `cursor' is initialized to the
- * beginning.
+ * beginning. Caller must free the cursor with krb5_cc_end_seq_get().
*
* @return Return an error code or 0, see krb5_get_error_message().
*
@@ -712,32 +763,6 @@ krb5_cc_next_cred (krb5_context context,
}
/**
- * Like krb5_cc_next_cred, but allow for selective retrieval
- *
- * @ingroup krb5_ccache
- */
-
-
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_cc_next_cred_match(krb5_context context,
- const krb5_ccache id,
- krb5_cc_cursor * cursor,
- krb5_creds * creds,
- krb5_flags whichfields,
- const krb5_creds * mcreds)
-{
- krb5_error_code ret;
- while (1) {
- ret = krb5_cc_next_cred(context, id, cursor, creds);
- if (ret)
- return ret;
- if (mcreds == NULL || krb5_compare_creds(context, whichfields, mcreds, creds))
- return 0;
- krb5_free_cred_contents(context, creds);
- }
-}
-
-/**
* Destroy the cursor `cursor'.
*
* @ingroup krb5_ccache
@@ -806,25 +831,37 @@ krb5_cc_get_flags(krb5_context context,
}
/**
- * Copy the contents of `from' to `to'.
+ * Copy the contents of `from' to `to' if the given match function
+ * return true.
+ *
+ * @param context A Kerberos 5 context.
+ * @param from the cache to copy data from.
+ * @param to the cache to copy data to.
+ * @param match a match function that should return TRUE if cred argument should be copied, if NULL, all credentials are copied.
+ * @param matchctx context passed to match function.
+ * @param matched set to true if there was a credential that matched, may be NULL.
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
*
* @ingroup krb5_ccache
*/
-
krb5_error_code KRB5_LIB_FUNCTION
-krb5_cc_copy_cache_match(krb5_context context,
- const krb5_ccache from,
- krb5_ccache to,
- krb5_flags whichfields,
- const krb5_creds * mcreds,
- unsigned int *matched)
+krb5_cc_copy_match_f(krb5_context context,
+ const krb5_ccache from,
+ krb5_ccache to,
+ krb5_boolean (*match)(krb5_context, void *, const krb5_creds *),
+ void *matchctx,
+ unsigned int *matched)
{
krb5_error_code ret;
krb5_cc_cursor cursor;
krb5_creds cred;
krb5_principal princ;
+ if (matched)
+ *matched = 0;
+
ret = krb5_cc_get_principal(context, from, &princ);
if (ret)
return ret;
@@ -838,24 +875,26 @@ krb5_cc_copy_cache_match(krb5_context context,
krb5_free_principal(context, princ);
return ret;
}
- if (matched)
- *matched = 0;
- while (ret == 0 &&
- krb5_cc_next_cred_match(context, from, &cursor, &cred,
- whichfields, mcreds) == 0) {
- if (matched)
- (*matched)++;
- ret = krb5_cc_store_cred(context, to, &cred);
- krb5_free_cred_contents(context, &cred);
+
+ while ((ret = krb5_cc_next_cred(context, from, &cursor, &cred)) == 0) {
+ if (match == NULL || (*match)(context, matchctx, &cred) == 0) {
+ if (matched)
+ (*matched)++;
+ ret = krb5_cc_store_cred(context, to, &cred);
+ if (ret)
+ break;
+ }
+ krb5_free_cred_contents(context, &cred);
}
krb5_cc_end_seq_get(context, from, &cursor);
krb5_free_principal(context, princ);
+ if (ret == KRB5_CC_END)
+ ret = 0;
return ret;
}
-
/**
- * Just like krb5_cc_copy_cache_match, but copy everything.
+ * Just like krb5_cc_copy_match_f(), but copy everything.
*
* @ingroup @krb5_ccache
*/
@@ -865,21 +904,7 @@ krb5_cc_copy_cache(krb5_context context,
const krb5_ccache from,
krb5_ccache to)
{
- return krb5_cc_copy_cache_match(context, from, to, 0, NULL, NULL);
-}
-
-/**
- * MIT compat glue
- *
- * @ingroup krb5_ccache
- */
-
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_cc_copy_creds(krb5_context context,
- const krb5_ccache from,
- krb5_ccache to)
-{
- return krb5_cc_copy_cache(context, from, to);
+ return krb5_cc_copy_match_f(context, from, to, NULL, NULL, NULL);
}
/**
@@ -1057,10 +1082,14 @@ krb5_cc_cache_end_seq_get (krb5_context context,
}
/**
- * Search for a matching credential cache of type `type' that have the
+ * Search for a matching credential cache that have the
* `principal' as the default principal. On success, `id' needs to be
* freed with krb5_cc_close() or krb5_cc_destroy().
*
+ * @param context A Kerberos 5 context
+ * @param client The principal to search for
+ * @param id the returned credential cache
+ *
* @return On failure, error code is returned and `id' is set to NULL.
*
* @ingroup krb5_ccache
@@ -1082,7 +1111,7 @@ krb5_cc_cache_match (krb5_context context,
if (ret)
return ret;
- while ((ret = krb5_cccol_cursor_next (context, cursor, &cache)) == 0) {
+ while (krb5_cccol_cursor_next (context, cursor, &cache) == 0 && cache != NULL) {
krb5_principal principal;
ret = krb5_cc_get_principal(context, cache, &principal);
@@ -1107,7 +1136,7 @@ krb5_cc_cache_match (krb5_context context,
krb5_unparse_name(context, client, &str);
krb5_set_error_message(context, KRB5_CC_NOTFOUND,
- N_("Principal %s not found in a "
+ N_("Principal %s not found in any "
"credential cache", ""),
str ? str : "<out of memory>");
if (str)
@@ -1178,7 +1207,7 @@ build_conf_principals(krb5_context context, krb5_ccache id,
}
ret = krb5_make_principal(context, &cred->server,
- krb5_principal_get_realm(context, client),
+ KRB5_REALM_NAME,
KRB5_CONF_NAME, name, pname, NULL);
free(pname);
if (ret) {
@@ -1224,7 +1253,7 @@ krb5_is_config_principal(krb5_context context,
* @param principal configuration for a specific principal, if
* NULL, global for the whole cache.
* @param name name under which the configuraion is stored.
- * @param data data to store
+ * @param data data to store, if NULL, configure is removed.
*
* @ingroup krb5_ccache
*/
@@ -1246,15 +1275,17 @@ krb5_cc_set_config(krb5_context context, krb5_ccache id,
if (ret && ret != KRB5_CC_NOTFOUND)
goto out;
- /* not that anyone care when this expire */
- cred.times.authtime = time(NULL);
- cred.times.endtime = cred.times.authtime + 3600 * 24 * 30;
-
- ret = krb5_data_copy(&cred.ticket, data->data, data->length);
- if (ret)
- goto out;
-
- ret = krb5_cc_store_cred(context, id, &cred);
+ if (data) {
+ /* not that anyone care when this expire */
+ cred.times.authtime = time(NULL);
+ cred.times.endtime = cred.times.authtime + 3600 * 24 * 30;
+
+ ret = krb5_data_copy(&cred.ticket, data->data, data->length);
+ if (ret)
+ goto out;
+
+ ret = krb5_cc_store_cred(context, id, &cred);
+ }
out:
krb5_free_cred_contents (context, &cred);
@@ -1345,6 +1376,8 @@ krb5_cccol_cursor_new(krb5_context context, krb5_cccol_cursor *cursor)
* @param cache the returned cursor, pointer is set to NULL on failure
* and a cache on success. The returned cache needs to be freed
* with krb5_cc_close() or destroyed with krb5_cc_destroy().
+ * MIT Kerberos behavies slightly diffrent and sets cache to NULL
+ * when all caches are iterated over and return 0.
*
* @return Return 0 or and error, KRB5_CC_END is returned at the end
* of iteration. See krb5_get_error_message().
@@ -1446,7 +1479,7 @@ krb5_cc_last_change_time(krb5_context context,
* and mtime is 0, there was no credentials in the caches.
*
* @param context A Kerberos 5 context
- * @param id The credential cache to probe
+ * @param type The credential cache to probe, if NULL, all type are traversed.
* @param mtime the last modification time, set to 0 on error.
* @return Return 0 or and error. See krb5_get_error_message().
@@ -1470,7 +1503,7 @@ krb5_cccol_last_change_time(krb5_context context,
if (ret)
return ret;
- while ((ret = krb5_cccol_cursor_next (context, cursor, &id)) == 0) {
+ while (krb5_cccol_cursor_next(context, cursor, &id) == 0 && id != NULL) {
if (type && strcmp(krb5_cc_get_type(context, id), type) != 0)
continue;
@@ -1487,3 +1520,106 @@ krb5_cccol_last_change_time(krb5_context context,
return 0;
}
+/**
+ * Return a friendly name on credential cache. Free the result with krb5_xfree().
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_ccache
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_get_friendly_name(krb5_context context,
+ krb5_ccache id,
+ char **name)
+{
+ krb5_error_code ret;
+ krb5_data data;
+
+ ret = krb5_cc_get_config(context, id, NULL, "FriendlyName", &data);
+ if (ret) {
+ krb5_principal principal;
+ ret = krb5_cc_get_principal(context, id, &principal);
+ if (ret)
+ return ret;
+ ret = krb5_unparse_name(context, principal, name);
+ krb5_free_principal(context, principal);
+ } else {
+ ret = asprintf(name, "%.*s", (int)data.length, (char *)data.data);
+ krb5_data_free(&data);
+ if (ret <= 0) {
+ ret = ENOMEM;
+ krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
+ } else
+ ret = 0;
+ }
+
+ return ret;
+}
+
+/**
+ * Set the friendly name on credential cache.
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_ccache
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_set_friendly_name(krb5_context context,
+ krb5_ccache id,
+ const char *name)
+{
+ krb5_data data;
+
+ data.data = rk_UNCONST(name);
+ data.length = strlen(name);
+
+ return krb5_cc_set_config(context, id, NULL, "FriendlyName", &data);
+}
+
+/**
+ * Get the lifetime of the initial ticket in the cache
+ *
+ * Get the lifetime of the initial ticket in the cache, if the initial
+ * ticket was not found, the error code KRB5_CC_END is returned.
+ *
+ * @param context A Kerberos 5 context.
+ * @param id a credential cache
+ * @param t the relative lifetime of the initial ticket
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_ccache
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_get_lifetime(krb5_context context, krb5_ccache id, time_t *t)
+{
+ krb5_cc_cursor cursor;
+ krb5_error_code ret;
+ krb5_creds cred;
+ time_t now;
+
+ *t = 0;
+ now = time(NULL);
+
+ ret = krb5_cc_start_seq_get(context, id, &cursor);
+ if (ret)
+ return ret;
+
+ while ((ret = krb5_cc_next_cred(context, id, &cursor, &cred)) == 0) {
+ if (cred.flags.b.initial) {
+ if (now < cred.times.endtime)
+ *t = cred.times.endtime - now;
+ krb5_free_cred_contents(context, &cred);
+ goto out;
+ }
+ krb5_free_cred_contents(context, &cred);
+ }
+
+ out:
+ krb5_cc_end_seq_get(context, id, &cursor);
+
+ return ret;
+}
diff --git a/source4/heimdal/lib/krb5/changepw.c b/source4/heimdal/lib/krb5/changepw.c
index 91ed9c5ba0..207b86b488 100644
--- a/source4/heimdal/lib/krb5/changepw.c
+++ b/source4/heimdal/lib/krb5/changepw.c
@@ -31,9 +31,9 @@
* SUCH DAMAGE.
*/
-#include <krb5_locl.h>
+#define KRB5_DEPRECATED
-RCSID("$Id$");
+#include <krb5_locl.h>
#undef __attribute__
#define __attribute__(X)
@@ -82,7 +82,6 @@ chgpw_send_request (krb5_context context,
krb5_data passwd_data;
size_t len;
u_char header[6];
- u_char *p;
struct iovec iov[3];
struct msghdr msghdr;
@@ -118,13 +117,12 @@ chgpw_send_request (krb5_context context,
goto out2;
len = 6 + ap_req_data.length + krb_priv_data.length;
- p = header;
- *p++ = (len >> 8) & 0xFF;
- *p++ = (len >> 0) & 0xFF;
- *p++ = 0;
- *p++ = 1;
- *p++ = (ap_req_data.length >> 8) & 0xFF;
- *p++ = (ap_req_data.length >> 0) & 0xFF;
+ header[0] = (len >> 8) & 0xFF;
+ header[1] = (len >> 0) & 0xFF;
+ header[2] = 0;
+ header[3] = 1;
+ header[4] = (ap_req_data.length >> 8) & 0xFF;
+ header[5] = (ap_req_data.length >> 0) & 0xFF;
memset(&msghdr, 0, sizeof(msghdr));
msghdr.msg_name = NULL;
@@ -231,7 +229,7 @@ setpw_send_request (krb5_context context,
*p++ = 0xff;
*p++ = 0x80;
*p++ = (ap_req_data.length >> 8) & 0xFF;
- *p++ = (ap_req_data.length >> 0) & 0xFF;
+ *p = (ap_req_data.length >> 0) & 0xFF;
memset(&msghdr, 0, sizeof(msghdr));
msghdr.msg_name = NULL;
@@ -693,7 +691,7 @@ krb5_change_password (krb5_context context,
int *result_code,
krb5_data *result_code_string,
krb5_data *result_string)
- __attribute__((deprecated))
+ KRB5_DEPRECATED
{
struct kpwd_proc *p = find_chpw_proto("change password");
@@ -711,7 +709,7 @@ krb5_change_password (krb5_context context,
#endif /* HEIMDAL_SMALLER */
/**
- * Change passwrod using creds.
+ * Change password using creds.
*
* @param context a Keberos context
* @param creds The initial kadmin/passwd for the principal or an admin principal
@@ -767,8 +765,6 @@ krb5_set_password(krb5_context context,
return ret;
}
-#ifndef HEIMDAL_SMALLER
-
/*
*
*/
@@ -834,8 +830,6 @@ krb5_set_password_using_ccache(krb5_context context,
return ret;
}
-#endif /* !HEIMDAL_SMALLER */
-
/*
*
*/
diff --git a/source4/heimdal/lib/krb5/codec.c b/source4/heimdal/lib/krb5/codec.c
index bd0dcc5371..ebda3e51f7 100644
--- a/source4/heimdal/lib/krb5/codec.c
+++ b/source4/heimdal/lib/krb5/codec.c
@@ -31,12 +31,9 @@
* SUCH DAMAGE.
*/
-#include "krb5_locl.h"
-
-#undef __attribute__
-#define __attribute__(x)
+#define KRB5_DEPRECATED
-RCSID("$Id$");
+#include "krb5_locl.h"
#ifndef HEIMDAL_SMALLER
@@ -46,7 +43,7 @@ krb5_decode_EncTicketPart (krb5_context context,
size_t length,
EncTicketPart *t,
size_t *len)
- __attribute__((deprecated))
+ KRB5_DEPRECATED
{
return decode_EncTicketPart(data, length, t, len);
}
@@ -57,7 +54,7 @@ krb5_encode_EncTicketPart (krb5_context context,
size_t length,
EncTicketPart *t,
size_t *len)
- __attribute__((deprecated))
+ KRB5_DEPRECATED
{
return encode_EncTicketPart(data, length, t, len);
}
@@ -68,7 +65,7 @@ krb5_decode_EncASRepPart (krb5_context context,
size_t length,
EncASRepPart *t,
size_t *len)
- __attribute__((deprecated))
+ KRB5_DEPRECATED
{
return decode_EncASRepPart(data, length, t, len);
}
@@ -79,7 +76,7 @@ krb5_encode_EncASRepPart (krb5_context context,
size_t length,
EncASRepPart *t,
size_t *len)
- __attribute__((deprecated))
+ KRB5_DEPRECATED
{
return encode_EncASRepPart(data, length, t, len);
}
@@ -90,7 +87,7 @@ krb5_decode_EncTGSRepPart (krb5_context context,
size_t length,
EncTGSRepPart *t,
size_t *len)
- __attribute__((deprecated))
+ KRB5_DEPRECATED
{
return decode_EncTGSRepPart(data, length, t, len);
}
@@ -101,7 +98,7 @@ krb5_encode_EncTGSRepPart (krb5_context context,
size_t length,
EncTGSRepPart *t,
size_t *len)
- __attribute__((deprecated))
+ KRB5_DEPRECATED
{
return encode_EncTGSRepPart(data, length, t, len);
}
@@ -112,7 +109,7 @@ krb5_decode_EncAPRepPart (krb5_context context,
size_t length,
EncAPRepPart *t,
size_t *len)
- __attribute__((deprecated))
+ KRB5_DEPRECATED
{
return decode_EncAPRepPart(data, length, t, len);
}
@@ -123,7 +120,7 @@ krb5_encode_EncAPRepPart (krb5_context context,
size_t length,
EncAPRepPart *t,
size_t *len)
- __attribute__((deprecated))
+ KRB5_DEPRECATED
{
return encode_EncAPRepPart(data, length, t, len);
}
@@ -134,7 +131,7 @@ krb5_decode_Authenticator (krb5_context context,
size_t length,
Authenticator *t,
size_t *len)
- __attribute__((deprecated))
+ KRB5_DEPRECATED
{
return decode_Authenticator(data, length, t, len);
}
@@ -145,7 +142,7 @@ krb5_encode_Authenticator (krb5_context context,
size_t length,
Authenticator *t,
size_t *len)
- __attribute__((deprecated))
+ KRB5_DEPRECATED
{
return encode_Authenticator(data, length, t, len);
}
@@ -156,7 +153,7 @@ krb5_decode_EncKrbCredPart (krb5_context context,
size_t length,
EncKrbCredPart *t,
size_t *len)
- __attribute__((deprecated))
+ KRB5_DEPRECATED
{
return decode_EncKrbCredPart(data, length, t, len);
}
@@ -167,7 +164,7 @@ krb5_encode_EncKrbCredPart (krb5_context context,
size_t length,
EncKrbCredPart *t,
size_t *len)
- __attribute__((deprecated))
+ KRB5_DEPRECATED
{
return encode_EncKrbCredPart (data, length, t, len);
}
@@ -178,7 +175,7 @@ krb5_decode_ETYPE_INFO (krb5_context context,
size_t length,
ETYPE_INFO *t,
size_t *len)
- __attribute__((deprecated))
+ KRB5_DEPRECATED
{
return decode_ETYPE_INFO(data, length, t, len);
}
@@ -189,7 +186,7 @@ krb5_encode_ETYPE_INFO (krb5_context context,
size_t length,
ETYPE_INFO *t,
size_t *len)
- __attribute__((deprecated))
+ KRB5_DEPRECATED
{
return encode_ETYPE_INFO (data, length, t, len);
}
@@ -200,7 +197,7 @@ krb5_decode_ETYPE_INFO2 (krb5_context context,
size_t length,
ETYPE_INFO2 *t,
size_t *len)
- __attribute__((deprecated))
+ KRB5_DEPRECATED
{
return decode_ETYPE_INFO2(data, length, t, len);
}
@@ -211,7 +208,7 @@ krb5_encode_ETYPE_INFO2 (krb5_context context,
size_t length,
ETYPE_INFO2 *t,
size_t *len)
- __attribute__((deprecated))
+ KRB5_DEPRECATED
{
return encode_ETYPE_INFO2 (data, length, t, len);
}
diff --git a/source4/heimdal/lib/krb5/config_file.c b/source4/heimdal/lib/krb5/config_file.c
index 75c48a001b..ee226c78a2 100644
--- a/source4/heimdal/lib/krb5/config_file.c
+++ b/source4/heimdal/lib/krb5/config_file.c
@@ -32,9 +32,6 @@
*/
#include "krb5_locl.h"
-RCSID("$Id$");
-
-#ifndef HAVE_NETINFO
/* Gaah! I want a portable funopen */
struct fileptr {
@@ -302,21 +299,65 @@ krb5_config_parse_string_multi(krb5_context context,
return 0;
}
+/**
+ * Parse a configuration file and add the result into res. This
+ * interface can be used to parse several configuration files into one
+ * resulting krb5_config_section by calling it repeatably.
+ *
+ * @param context a Kerberos 5 context.
+ * @param fname a file name to a Kerberos configuration file
+ * @param res the returned result, must be free with krb5_free_config_files().
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_support
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_config_parse_file_multi (krb5_context context,
const char *fname,
krb5_config_section **res)
{
const char *str;
+ char *newfname = NULL;
unsigned lineno = 0;
krb5_error_code ret;
struct fileptr f;
+
+ /**
+ * If the fname starts with "~/" parse configuration file in the
+ * current users home directory. The behavior can be disabled and
+ * enabled by calling krb5_set_home_dir_access().
+ */
+ if (_krb5_homedir_access(context) && fname[0] == '~' && fname[1] == '/') {
+ const char *home = NULL;
+
+ if(!issuid())
+ home = getenv("HOME");
+
+ if (home == NULL) {
+ struct passwd *pw = getpwuid(getuid());
+ if(pw != NULL)
+ home = pw->pw_dir;
+ }
+ if (home) {
+ asprintf(&newfname, "%s%s", home, &fname[1]);
+ if (newfname == NULL) {
+ krb5_set_error_message(context, ENOMEM,
+ N_("malloc: out of memory", ""));
+ return ENOMEM;
+ }
+ fname = newfname;
+ }
+ }
+
f.f = fopen(fname, "r");
f.s = NULL;
if(f.f == NULL) {
ret = errno;
krb5_set_error_message (context, ret, "open %s: %s",
fname, strerror(ret));
+ if (newfname)
+ free(newfname);
return ret;
}
@@ -324,8 +365,12 @@ krb5_config_parse_file_multi (krb5_context context,
fclose(f.f);
if (ret) {
krb5_set_error_message (context, ret, "%s:%u: %s", fname, lineno, str);
+ if (newfname)
+ free(newfname);
return ret;
}
+ if (newfname)
+ free(newfname);
return 0;
}
@@ -338,8 +383,6 @@ krb5_config_parse_file (krb5_context context,
return krb5_config_parse_file_multi(context, fname, res);
}
-#endif /* !HAVE_NETINFO */
-
static void
free_binding (krb5_context context, krb5_config_binding *b)
{
diff --git a/source4/heimdal/lib/krb5/config_file_netinfo.c b/source4/heimdal/lib/krb5/config_file_netinfo.c
deleted file mode 100644
index e6993bbb4a..0000000000
--- a/source4/heimdal/lib/krb5/config_file_netinfo.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright (c) 1997 - 2001 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$");
-
-/*
- * Netinfo implementation from Luke Howard <lukeh@xedoc.com.au>
- */
-
-#ifdef HAVE_NETINFO
-#include <netinfo/ni.h>
-static ni_status
-ni_proplist2binding(ni_proplist *pl, krb5_config_section **ret)
-{
- int i, j;
- krb5_config_section **next = NULL;
-
- for (i = 0; i < pl->ni_proplist_len; i++) {
- if (!strcmp(pl->nipl_val[i].nip_name, "name"))
- continue;
-
- for (j = 0; j < pl->nipl_val[i].nip_val.ni_namelist_len; j++) {
- krb5_config_binding *b;
-
- b = malloc(sizeof(*b));
- if (b == NULL)
- return NI_FAILED;
-
- b->next = NULL;
- b->type = krb5_config_string;
- b->name = ni_name_dup(pl->nipl_val[i].nip_name);
- b->u.string = ni_name_dup(pl->nipl_val[i].nip_val.ninl_val[j]);
-
- if (next == NULL) {
- *ret = b;
- } else {
- *next = b;
- }
- next = &b->next;
- }
- }
- return NI_OK;
-}
-
-static ni_status
-ni_idlist2binding(void *ni, ni_idlist *idlist, krb5_config_section **ret)
-{
- int i;
- ni_status nis;
- krb5_config_section **next;
-
- for (i = 0; i < idlist->ni_idlist_len; i++) {
- ni_proplist pl;
- ni_id nid;
- ni_idlist children;
- krb5_config_binding *b;
- ni_index index;
-
- nid.nii_instance = 0;
- nid.nii_object = idlist->ni_idlist_val[i];
-
- nis = ni_read(ni, &nid, &pl);
-
- if (nis != NI_OK) {
- return nis;
- }
- index = ni_proplist_match(pl, "name", NULL);
- b = malloc(sizeof(*b));
- if (b == NULL) return NI_FAILED;
-
- if (i == 0) {
- *ret = b;
- } else {
- *next = b;
- }
-
- b->type = krb5_config_list;
- b->name = ni_name_dup(pl.nipl_val[index].nip_val.ninl_val[0]);
- b->next = NULL;
- b->u.list = NULL;
-
- /* get the child directories */
- nis = ni_children(ni, &nid, &children);
- if (nis == NI_OK) {
- nis = ni_idlist2binding(ni, &children, &b->u.list);
- if (nis != NI_OK) {
- return nis;
- }
- }
-
- nis = ni_proplist2binding(&pl, b->u.list == NULL ? &b->u.list : &b->u.list->next);
- ni_proplist_free(&pl);
- if (nis != NI_OK) {
- return nis;
- }
- next = &b->next;
- }
- ni_idlist_free(idlist);
- return NI_OK;
-}
-
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_config_parse_file (krb5_context context,
- const char *fname,
- krb5_config_section **res)
-{
- void *ni = NULL, *lastni = NULL;
- int i;
- ni_status nis;
- ni_id nid;
- ni_idlist children;
-
- krb5_config_section *s;
- int ret;
-
- s = NULL;
-
- for (i = 0; i < 256; i++) {
- if (i == 0) {
- nis = ni_open(NULL, ".", &ni);
- } else {
- if (lastni != NULL) ni_free(lastni);
- lastni = ni;
- nis = ni_open(lastni, "..", &ni);
- }
- if (nis != NI_OK)
- break;
- nis = ni_pathsearch(ni, &nid, "/locations/kerberos");
- if (nis == NI_OK) {
- nis = ni_children(ni, &nid, &children);
- if (nis != NI_OK)
- break;
- nis = ni_idlist2binding(ni, &children, &s);
- break;
- }
- }
-
- if (ni != NULL) ni_free(ni);
- if (ni != lastni && lastni != NULL) ni_free(lastni);
-
- ret = (nis == NI_OK) ? 0 : -1;
- if (ret == 0) {
- *res = s;
- } else {
- *res = NULL;
- }
- return ret;
-}
-#endif /* HAVE_NETINFO */
diff --git a/source4/heimdal/lib/krb5/constants.c b/source4/heimdal/lib/krb5/constants.c
index b41fb3f663..a3b3d09f41 100644
--- a/source4/heimdal/lib/krb5/constants.c
+++ b/source4/heimdal/lib/krb5/constants.c
@@ -33,11 +33,16 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
KRB5_LIB_VARIABLE const char *krb5_config_file =
#ifdef __APPLE__
+"~/Library/Preferences/edu.mit.Kerberos:"
"/Library/Preferences/edu.mit.Kerberos:"
#endif
SYSCONFDIR "/krb5.conf:/etc/krb5.conf";
KRB5_LIB_VARIABLE const char *krb5_defkeyname = KEYTAB_DEFAULT;
+
+KRB5_LIB_VARIABLE const char *krb5_cc_type_api = "API";
+KRB5_LIB_VARIABLE const char *krb5_cc_type_file = "FILE";
+KRB5_LIB_VARIABLE const char *krb5_cc_type_memory = "MEMORY";
+KRB5_LIB_VARIABLE const char *krb5_cc_type_kcm = "KCM";
+KRB5_LIB_VARIABLE const char *krb5_cc_type_scc = "SCC";
diff --git a/source4/heimdal/lib/krb5/context.c b/source4/heimdal/lib/krb5/context.c
index 127dfa117d..fe94135030 100644
--- a/source4/heimdal/lib/krb5/context.c
+++ b/source4/heimdal/lib/krb5/context.c
@@ -34,8 +34,6 @@
#include "krb5_locl.h"
#include <com_err.h>
-RCSID("$Id$");
-
#define INIT_FIELD(C, T, E, D, F) \
(C)->E = krb5_config_get_ ## T ## _default ((C), NULL, (D), \
"libdefaults", F, NULL)
@@ -243,9 +241,7 @@ cc_ops_register(krb5_context context)
krb5_cc_register(context, &krb5_acc_ops, TRUE);
krb5_cc_register(context, &krb5_fcc_ops, TRUE);
krb5_cc_register(context, &krb5_mcc_ops, TRUE);
-#ifdef HAVE_SQLITE
krb5_cc_register(context, &krb5_scc_ops, TRUE);
-#endif
#ifdef HAVE_KCM
krb5_cc_register(context, &krb5_kcm_ops, TRUE);
#endif
@@ -310,6 +306,8 @@ krb5_init_context(krb5_context *context)
}
HEIMDAL_MUTEX_init(p->mutex);
+ p->flags |= KRB5_CTX_F_HOMEDIR_ACCESS;
+
ret = krb5_get_default_config_files(&files);
if(ret)
goto out;
@@ -336,7 +334,7 @@ out:
* Make a copy for the Kerberos 5 context, allocated krb5_contex shoud
* be freed with krb5_free_context().
*
- * @param in the Kerberos context to copy
+ * @param context the Kerberos context to copy
* @param out the copy of the Kerberos, set to NULL error.
*
* @return Returns 0 to indicate success. Otherwise an kerberos et
@@ -453,10 +451,10 @@ krb5_free_context(krb5_context context)
krb5_set_extra_addresses(context, NULL);
krb5_set_ignore_addresses(context, NULL);
krb5_set_send_to_kdc_func(context, NULL, NULL);
- if (context->mutex != NULL) {
- HEIMDAL_MUTEX_destroy(context->mutex);
- free(context->mutex);
- }
+
+ HEIMDAL_MUTEX_destroy(context->mutex);
+ free(context->mutex);
+
memset(context, 0, sizeof(*context));
free(context);
}
@@ -552,7 +550,7 @@ krb5_prepend_config_files(const char *filelist, char **pq, char ***ret_pp)
krb5_free_config_files(pp);
return ENOMEM;
}
- l = strsep_copy(&p, ":", fn, l + 1);
+ (void)strsep_copy(&p, ":", fn, l + 1);
ret = add_file(&pp, &len, fn);
if (ret) {
krb5_free_config_files(pp);
@@ -641,7 +639,8 @@ krb5_get_default_config_files(char ***pfilenames)
/**
* Free a list of configuration files.
*
- * @param filenames list to be freed.
+ * @param filenames list, terminated with a NULL pointer, to be
+ * freed. NULL is an valid argument.
*
* @return Returns 0 to indicate success. Otherwise an kerberos et
* error code is returned, see krb5_get_error_message().
@@ -653,7 +652,7 @@ void KRB5_LIB_FUNCTION
krb5_free_config_files(char **filenames)
{
char **p;
- for(p = filenames; *p != NULL; p++)
+ for(p = filenames; p && *p != NULL; p++)
free(*p);
free(filenames);
}
@@ -1226,3 +1225,115 @@ krb5_set_max_time_skew (krb5_context context, time_t t)
{
context->max_skew = t;
}
+
+/**
+ * Init encryption types in len, val with etypes.
+ *
+ * @param context Kerberos 5 context.
+ * @param len output length of val.
+ * @param val output array of enctypes.
+ * @param etypes etypes to set val and len to, if NULL, use default enctypes.
+
+ * @return Returns 0 to indicate success. Otherwise an kerberos et
+ * error code is returned, see krb5_get_error_message().
+ *
+ * @ingroup krb5
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_init_etype (krb5_context context,
+ unsigned *len,
+ krb5_enctype **val,
+ const krb5_enctype *etypes)
+{
+ unsigned int i;
+ krb5_error_code ret;
+ krb5_enctype *tmp = NULL;
+
+ ret = 0;
+ if (etypes == NULL) {
+ ret = krb5_get_default_in_tkt_etypes(context, &tmp);
+ if (ret)
+ return ret;
+ etypes = tmp;
+ }
+
+ for (i = 0; etypes[i]; ++i)
+ ;
+ *len = i;
+ *val = malloc(i * sizeof(**val));
+ if (i != 0 && *val == NULL) {
+ ret = ENOMEM;
+ krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
+ goto cleanup;
+ }
+ memmove (*val,
+ etypes,
+ i * sizeof(*tmp));
+cleanup:
+ if (tmp != NULL)
+ free (tmp);
+ return ret;
+}
+
+/*
+ * Allow homedir accces
+ */
+
+static HEIMDAL_MUTEX homedir_mutex = HEIMDAL_MUTEX_INITIALIZER;
+static krb5_boolean allow_homedir = TRUE;
+
+krb5_boolean
+_krb5_homedir_access(krb5_context context)
+{
+ krb5_boolean allow;
+
+ /* is never allowed for root */
+ if (geteuid() == 0)
+ return FALSE;
+
+ if (context && (context->flags & KRB5_CTX_F_HOMEDIR_ACCESS) == 0)
+ return FALSE;
+
+ HEIMDAL_MUTEX_lock(&homedir_mutex);
+ allow = allow_homedir;
+ HEIMDAL_MUTEX_unlock(&homedir_mutex);
+ return allow;
+}
+
+/**
+ * Enable and disable home directory access on either the global state
+ * or the krb5_context state. By calling krb5_set_home_dir_access()
+ * with context set to NULL, the global state is configured otherwise
+ * the state for the krb5_context is modified.
+ *
+ * For home directory access to be allowed, both the global state and
+ * the krb5_context state have to be allowed.
+ *
+ * Administrator (root user), never uses the home directory.
+ *
+ * @param context a Kerberos 5 context or NULL
+ * @param allow allow if TRUE home directory
+ * @return the old value
+ *
+ */
+
+krb5_boolean
+krb5_set_home_dir_access(krb5_context context, krb5_boolean allow)
+{
+ krb5_boolean old;
+ if (context) {
+ old = (context->flags & KRB5_CTX_F_HOMEDIR_ACCESS) ? TRUE : FALSE;
+ if (allow)
+ context->flags |= KRB5_CTX_F_HOMEDIR_ACCESS;
+ else
+ context->flags &= ~KRB5_CTX_F_HOMEDIR_ACCESS;
+ } else {
+ HEIMDAL_MUTEX_lock(&homedir_mutex);
+ old = allow_homedir;
+ allow_homedir = allow;
+ HEIMDAL_MUTEX_unlock(&homedir_mutex);
+ }
+
+ return old;
+}
diff --git a/source4/heimdal/lib/krb5/convert_creds.c b/source4/heimdal/lib/krb5/convert_creds.c
index fc81d96bec..35454bf983 100644
--- a/source4/heimdal/lib/krb5/convert_creds.c
+++ b/source4/heimdal/lib/krb5/convert_creds.c
@@ -32,10 +32,10 @@
*/
#include "krb5_locl.h"
-RCSID("$Id$");
-
#include "krb5-v4compat.h"
+#ifndef HEIMDAL_SMALLER
+
static krb5_error_code
check_ticket_flags(TicketFlags f)
{
@@ -204,3 +204,5 @@ krb524_convert_creds_kdc_ccache(krb5_context context,
krb5_free_creds (context, v5_creds);
return ret;
}
+
+#endif
diff --git a/source4/heimdal/lib/krb5/copy_host_realm.c b/source4/heimdal/lib/krb5/copy_host_realm.c
index 37e27110b6..7f19ddd3de 100644
--- a/source4/heimdal/lib/krb5/copy_host_realm.c
+++ b/source4/heimdal/lib/krb5/copy_host_realm.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
/**
* Copy the list of realms from `from' to `to'.
*
diff --git a/source4/heimdal/lib/krb5/crc.c b/source4/heimdal/lib/krb5/crc.c
index a900cabbba..eab946541d 100644
--- a/source4/heimdal/lib/krb5/crc.c
+++ b/source4/heimdal/lib/krb5/crc.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
static u_long table[256];
#define CRC_GEN 0xEDB88320L
diff --git a/source4/heimdal/lib/krb5/creds.c b/source4/heimdal/lib/krb5/creds.c
index 087a4850eb..26c0dfbecb 100644
--- a/source4/heimdal/lib/krb5/creds.c
+++ b/source4/heimdal/lib/krb5/creds.c
@@ -33,23 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
-#undef __attribute__
-#define __attribute__(X)
-
-#ifndef HEIMDAL_SMALLER
-
-/* keep this for compatibility with older code */
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_free_creds_contents (krb5_context context, krb5_creds *c)
- __attribute__((deprecated))
-{
- return krb5_free_cred_contents (context, c);
-}
-
-#endif /* HEIMDAL_SMALLER */
-
/**
* Free content of krb5_creds.
*
@@ -235,9 +218,7 @@ krb5_compare_creds(krb5_context context, krb5_flags whichfields,
}
if (match && (whichfields & KRB5_TC_MATCH_KEYTYPE))
- match = krb5_enctypes_compatible_keys(context,
- mcreds->session.keytype,
- creds->session.keytype);
+ match = mcreds->session.keytype == creds->session.keytype;
if (match && (whichfields & KRB5_TC_MATCH_FLAGS_EXACT))
match = mcreds->flags.i == creds->flags.i;
diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c
index bc6512cf1a..9fd2117345 100644
--- a/source4/heimdal/lib/krb5/crypto.c
+++ b/source4/heimdal/lib/krb5/crypto.c
@@ -31,13 +31,11 @@
* SUCH DAMAGE.
*/
+#define KRB5_DEPRECATED
+
#include "krb5_locl.h"
-RCSID("$Id$");
#include <pkinit_asn1.h>
-#undef __attribute__
-#define __attribute__(X)
-
#define WEAK_ENCTYPES 1
#ifndef HEIMDAL_SMALLER
@@ -164,6 +162,9 @@ static krb5_error_code hmac(krb5_context context,
static void free_key_data(krb5_context,
struct key_data *,
struct encryption_type *);
+static void free_key_schedule(krb5_context,
+ struct key_data *,
+ struct encryption_type *);
static krb5_error_code usage2arcfour (krb5_context, unsigned *);
static void xor (DES_cblock *, const unsigned char *);
@@ -1158,7 +1159,16 @@ _key_schedule(krb5_context context,
{
krb5_error_code ret;
struct encryption_type *et = _find_enctype(key->key->keytype);
- struct key_type *kt = et->keytype;
+ struct key_type *kt;
+
+ if (et == NULL) {
+ krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
+ N_("encryption type %d not supported", ""),
+ key->key->keytype);
+ return KRB5_PROG_ETYPE_NOSUPP;
+ }
+
+ kt = et->keytype;
if(kt->schedule == NULL)
return 0;
@@ -1841,14 +1851,25 @@ verify_checksum(krb5_context context,
return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */
}
keyed_checksum = (ct->flags & F_KEYED) != 0;
- if(keyed_checksum && crypto == NULL) {
- krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
- N_("Checksum type %s is keyed but no "
- "crypto context (key) was passed in", ""),
- ct->name);
- return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
- }
if(keyed_checksum) {
+ struct checksum_type *kct;
+ if (crypto == NULL) {
+ krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
+ N_("Checksum type %s is keyed but no "
+ "crypto context (key) was passed in", ""),
+ ct->name);
+ return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
+ }
+ kct = crypto->et->keyed_checksum;
+ if (kct != NULL && kct->type != ct->type) {
+ krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
+ N_("Checksum type %s is keyed, but "
+ "the key type %s passed didnt have that checksum "
+ "type as the keyed type", ""),
+ ct->name, crypto->et->name);
+ return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
+ }
+
ret = get_checksum_key(context, crypto, usage, ct, &dkey);
if (ret)
return ret;
@@ -2348,10 +2369,11 @@ AES_PRF(krb5_context context,
{
const EVP_CIPHER *c = (*crypto->et->keytype->evp)();
EVP_CIPHER_CTX ctx;
- /* XXX blksz 1 for cts, so we can't use that */
+
EVP_CIPHER_CTX_init(&ctx); /* ivec all zero */
EVP_CipherInit_ex(&ctx, c, NULL, derived->keyvalue.data, NULL, 1);
- EVP_Cipher(&ctx, out->data, result.checksum.data, 16);
+ EVP_Cipher(&ctx, out->data, result.checksum.data,
+ crypto->et->blocksize);
EVP_CIPHER_CTX_cleanup(&ctx);
}
@@ -2737,17 +2759,6 @@ krb5_cksumtype_valid(krb5_context context,
}
-/* if two enctypes have compatible keys */
-krb5_boolean KRB5_LIB_FUNCTION
-krb5_enctypes_compatible_keys(krb5_context context,
- krb5_enctype etype1,
- krb5_enctype etype2)
-{
- struct encryption_type *e1 = _find_enctype(etype1);
- struct encryption_type *e2 = _find_enctype(etype2);
- return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype;
-}
-
static krb5_boolean
derived_crypto(krb5_context context,
krb5_crypto crypto)
@@ -3147,10 +3158,10 @@ find_iv(krb5_crypto_iov *data, int num_data, int type)
* Kerberos encrypted data look like this:
*
* 1. KRB5_CRYPTO_TYPE_HEADER
- * 2. array KRB5_CRYPTO_TYPE_DATA and KRB5_CRYPTO_TYPE_SIGN_ONLY in
- * any order, however the receiver have to aware of the
- * order. KRB5_CRYPTO_TYPE_SIGN_ONLY is commonly used headers and
- * trailers.
+ * 2. array [1,...] KRB5_CRYPTO_TYPE_DATA and array [0,...]
+ * KRB5_CRYPTO_TYPE_SIGN_ONLY in any order, however the receiver
+ * have to aware of the order. KRB5_CRYPTO_TYPE_SIGN_ONLY is
+ * commonly used headers and trailers.
* 3. KRB5_CRYPTO_TYPE_PADDING, at least on padsize long if padsize > 1
* 4. KRB5_CRYPTO_TYPE_TRAILER
*/
@@ -3160,17 +3171,23 @@ krb5_encrypt_iov_ivec(krb5_context context,
krb5_crypto crypto,
unsigned usage,
krb5_crypto_iov *data,
- size_t num_data,
+ int num_data,
void *ivec)
{
size_t headersz, trailersz, len;
- size_t i, sz, block_sz, pad_sz;
+ int i;
+ size_t sz, block_sz, pad_sz;
Checksum cksum;
unsigned char *p, *q;
krb5_error_code ret;
struct key_data *dkey;
const struct encryption_type *et = crypto->et;
- krb5_crypto_iov *tiv, *piv, *hiv;
+ krb5_crypto_iov *tiv, *piv, *hiv, *div;
+
+ if (num_data < 0) {
+ krb5_clear_error_message(context);
+ return KRB5_CRYPTO_INTERNAL;
+ }
if(!derived_crypto(context, crypto)) {
krb5_clear_error_message(context);
@@ -3180,18 +3197,16 @@ krb5_encrypt_iov_ivec(krb5_context context,
headersz = et->confoundersize;
trailersz = CHECKSUMSIZE(et->keyed_checksum);
- for (len = 0, i = 0; i < num_data; i++) {
- if (data[i].flags != KRB5_CRYPTO_TYPE_HEADER &&
- data[i].flags == KRB5_CRYPTO_TYPE_DATA) {
- len += data[i].data.length;
- }
- }
+ div = find_iv(data, num_data, KRB5_CRYPTO_TYPE_DATA);
+ if (div == NULL)
+ return KRB5_CRYPTO_INTERNAL;
+
+ len = div->data.length;
sz = headersz + len;
block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
pad_sz = block_sz - sz;
- trailersz += pad_sz;
/* header */
@@ -3278,13 +3293,9 @@ krb5_encrypt_iov_ivec(krb5_context context,
/* XXX replace with EVP_Cipher */
- len = hiv->data.length;
- for (i = 0; i < num_data; i++) {
- if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
- data[i].flags != KRB5_CRYPTO_TYPE_PADDING)
- continue;
- len += data[i].data.length;
- }
+ len = hiv->data.length + div->data.length;
+ if (piv)
+ len += piv->data.length;
p = q = malloc(len);
if(p == NULL)
@@ -3292,13 +3303,9 @@ krb5_encrypt_iov_ivec(krb5_context context,
memcpy(q, hiv->data.data, hiv->data.length);
q += hiv->data.length;
- for (i = 0; i < num_data; i++) {
- if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
- data[i].flags != KRB5_CRYPTO_TYPE_PADDING)
- continue;
- memcpy(q, data[i].data.data, data[i].data.length);
- q += data[i].data.length;
- }
+ memcpy(q, div->data.data, div->data.length);
+ q += div->data.length;
+ memset(q, 0, pad_sz);
ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
if(ret) {
@@ -3319,16 +3326,15 @@ krb5_encrypt_iov_ivec(krb5_context context,
/* now copy data back to buffers */
q = p;
+
memcpy(hiv->data.data, q, hiv->data.length);
q += hiv->data.length;
- for (i = 0; i < num_data; i++) {
- if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
- data[i].flags != KRB5_CRYPTO_TYPE_PADDING)
- continue;
- memcpy(data[i].data.data, q, data[i].data.length);
- q += data[i].data.length;
- }
+ memcpy(div->data.data, q, div->data.length);
+ q += div->data.length;
+
+ if (piv)
+ memcpy(piv->data.data, q, pad_sz);
free(p);
return ret;
@@ -3348,7 +3354,7 @@ krb5_encrypt_iov_ivec(krb5_context context,
* @ingroup krb5_crypto
*
* 1. KRB5_CRYPTO_TYPE_HEADER
- * 2. array KRB5_CRYPTO_TYPE_DATA and KRB5_CRYPTO_TYPE_SIGN_ONLY in
+ * 2. one KRB5_CRYPTO_TYPE_DATA and array [0,...] of KRB5_CRYPTO_TYPE_SIGN_ONLY in
* any order, however the receiver have to aware of the
* order. KRB5_CRYPTO_TYPE_SIGN_ONLY is commonly used unencrypoted
* protocol headers and trailers. The output data will be of same
@@ -3360,17 +3366,23 @@ krb5_decrypt_iov_ivec(krb5_context context,
krb5_crypto crypto,
unsigned usage,
krb5_crypto_iov *data,
- size_t num_data,
+ unsigned int num_data,
void *ivec)
{
+ unsigned int i;
size_t headersz, trailersz, len;
- size_t i, sz, block_sz, pad_sz;
+ size_t sz, block_sz, pad_sz;
Checksum cksum;
unsigned char *p, *q;
krb5_error_code ret;
struct key_data *dkey;
struct encryption_type *et = crypto->et;
- krb5_crypto_iov *tiv, *hiv;
+ krb5_crypto_iov *tiv, *hiv, *div;
+
+ if (num_data < 0) {
+ krb5_clear_error_message(context);
+ return KRB5_CRYPTO_INTERNAL;
+ }
if(!derived_crypto(context, crypto)) {
krb5_clear_error_message(context);
@@ -3380,9 +3392,13 @@ krb5_decrypt_iov_ivec(krb5_context context,
headersz = et->confoundersize;
trailersz = CHECKSUMSIZE(et->keyed_checksum);
- for (len = 0, i = 0; i < num_data; i++)
- if (data[i].flags == KRB5_CRYPTO_TYPE_DATA)
+ for (len = 0, i = 0; i < num_data; i++) {
+ if (data[i].flags == KRB5_CRYPTO_TYPE_DATA) {
+ if (len != 0)
+ return KRB5_CRYPTO_INTERNAL;
len += data[i].data.length;
+ }
+ }
sz = headersz + len;
block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
@@ -3404,7 +3420,9 @@ krb5_decrypt_iov_ivec(krb5_context context,
return KRB5_BAD_MSIZE;
tiv->data.length = trailersz;
- /* body */
+ div = find_iv(data, num_data, KRB5_CRYPTO_TYPE_DATA);
+ if (div == NULL)
+ return KRB5_CRYPTO_INTERNAL;
/* XXX replace with EVP_Cipher */
@@ -3421,12 +3439,7 @@ krb5_decrypt_iov_ivec(krb5_context context,
memcpy(q, hiv->data.data, hiv->data.length);
q += hiv->data.length;
- for (i = 0; i < num_data; i++) {
- if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
- continue;
- memcpy(q, data[i].data.data, data[i].data.length);
- q += data[i].data.length;
- }
+ memcpy(q, div->data.data, div->data.length);
ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
if(ret) {
@@ -3445,24 +3458,12 @@ krb5_decrypt_iov_ivec(krb5_context context,
return ret;
}
- /* XXX now copy data back to buffers */
- q = p;
- memcpy(hiv->data.data, q, hiv->data.length);
- q += hiv->data.length;
- len -= hiv->data.length;
-
- for (i = 0; i < num_data; i++) {
- if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
- continue;
- if (len < data[i].data.length)
- data[i].data.length = len;
- memcpy(data[i].data.data, q, data[i].data.length);
- q += data[i].data.length;
- len -= data[i].data.length;
- }
+ /* copy data back to buffers */
+ memcpy(hiv->data.data, p, hiv->data.length);
+ memcpy(div->data.data, p + hiv->data.length, len - hiv->data.length);
free(p);
- if (len)
- krb5_abortx(context, "data still in the buffer");
+
+ /* check signature */
len = hiv->data.length;
for (i = 0; i < num_data; i++) {
@@ -3506,7 +3507,7 @@ krb5_decrypt_iov_ivec(krb5_context context,
* @param usage Key usage for this buffer
* @param data array of buffers to process
* @param num_data length of array
- * @param result output data
+ * @param type output data
*
* @return Return an error code or 0.
* @ingroup krb5_crypto
@@ -3517,16 +3518,21 @@ krb5_create_checksum_iov(krb5_context context,
krb5_crypto crypto,
unsigned usage,
krb5_crypto_iov *data,
- size_t num_data,
+ unsigned int num_data,
krb5_cksumtype *type)
{
Checksum cksum;
krb5_crypto_iov *civ;
krb5_error_code ret;
- unsigned int i;
+ int i;
size_t len;
char *p, *q;
+ if (num_data < 0) {
+ krb5_clear_error_message(context);
+ return KRB5_CRYPTO_INTERNAL;
+ }
+
if(!derived_crypto(context, crypto)) {
krb5_clear_error_message(context);
return KRB5_CRYPTO_INTERNAL;
@@ -3765,18 +3771,6 @@ krb5_generate_random_block(void *buf, size_t len)
krb5_abortx(NULL, "Failed to generate random block");
}
-static void
-DES3_postproc(krb5_context context,
- unsigned char *k, size_t len, struct key_data *key)
-{
- DES3_random_to_key(context, key->key, k, len);
-
- if (key->schedule) {
- krb5_free_data(context, key->schedule);
- key->schedule = NULL;
- }
-}
-
static krb5_error_code
derive_key(krb5_context context,
struct encryption_type *et,
@@ -3784,7 +3778,7 @@ derive_key(krb5_context context,
const void *constant,
size_t len)
{
- unsigned char *k;
+ unsigned char *k = NULL;
unsigned int nblocks = 0, i;
krb5_error_code ret = 0;
struct key_type *kt = et->keytype;
@@ -3796,15 +3790,16 @@ derive_key(krb5_context context,
nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8);
k = malloc(nblocks * et->blocksize);
if(k == NULL) {
- krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
- return ENOMEM;
+ ret = ENOMEM;
+ krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
+ goto out;
}
ret = _krb5_n_fold(constant, len, k, et->blocksize);
if (ret) {
- free(k);
krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
- return ret;
+ goto out;
}
+
for(i = 0; i < nblocks; i++) {
if(i > 0)
memcpy(k + i * et->blocksize,
@@ -3819,30 +3814,31 @@ derive_key(krb5_context context,
size_t res_len = (kt->bits + 7) / 8;
if(len != 0 && c == NULL) {
- krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
- return ENOMEM;
+ ret = ENOMEM;
+ krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
+ goto out;
}
memcpy(c, constant, len);
(*et->encrypt)(context, key, c, len, 1, 0, NULL);
k = malloc(res_len);
if(res_len != 0 && k == NULL) {
free(c);
- krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
- return ENOMEM;
+ ret = ENOMEM;
+ krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
+ goto out;
}
ret = _krb5_n_fold(c, len, k, res_len);
+ free(c);
if (ret) {
- free(k);
krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
- return ret;
+ goto out;
}
- free(c);
}
/* XXX keytype dependent post-processing */
switch(kt->type) {
case KEYTYPE_DES3:
- DES3_postproc(context, k, nblocks * et->blocksize, key);
+ DES3_random_to_key(context, key->key, k, nblocks * et->blocksize);
break;
case KEYTYPE_AES128:
case KEYTYPE_AES256:
@@ -3855,12 +3851,15 @@ derive_key(krb5_context context,
kt->type);
break;
}
+ out:
if (key->schedule) {
- krb5_free_data(context, key->schedule);
+ free_key_schedule(context, key, et);
key->schedule = NULL;
}
- memset(k, 0, nblocks * et->blocksize);
- free(k);
+ if (k) {
+ memset(k, 0, nblocks * et->blocksize);
+ free(k);
+ }
return ret;
}
@@ -3983,15 +3982,24 @@ krb5_crypto_init(krb5_context context,
}
static void
+free_key_schedule(krb5_context context,
+ struct key_data *key,
+ struct encryption_type *et)
+{
+ if (et->keytype->cleanup)
+ (*et->keytype->cleanup)(context, key);
+ memset(key->schedule->data, 0, key->schedule->length);
+ krb5_free_data(context, key->schedule);
+}
+
+static void
free_key_data(krb5_context context, struct key_data *key,
struct encryption_type *et)
{
krb5_free_keyblock(context, key->key);
if(key->schedule) {
- if (et->keytype->cleanup)
- (*et->keytype->cleanup)(context, key);
- memset(key->schedule->data, 0, key->schedule->length);
- krb5_free_data(context, key->schedule);
+ free_key_schedule(context, key, et);
+ key->schedule = NULL;
}
}
@@ -4154,7 +4162,7 @@ krb5_string_to_key_derived(krb5_context context,
return ret;
}
kd.schedule = NULL;
- DES3_postproc (context, tmp, keylen, &kd); /* XXX */
+ DES3_random_to_key(context, kd.key, tmp, keylen);
memset(tmp, 0, keylen);
free(tmp);
ret = derive_key(context,
@@ -4263,6 +4271,23 @@ krb5_crypto_overhead (krb5_context context, krb5_crypto crypto)
return crypto_overhead (context, crypto);
}
+/**
+ * Converts the random bytestring to a protocol key according to
+ * Kerberos crypto frame work. It may be assumed that all the bits of
+ * the input string are equally random, even though the entropy
+ * present in the random source may be limited.
+ *
+ * @param context Kerberos 5 context
+ * @param type the enctype resulting key will be of
+ * @param data input random data to convert to a key
+ * @param data size of input random data, at least krb5_enctype_keysize() long
+ * @param data key, output key, free with krb5_free_keyblock_contents()
+ *
+ * @return Return an error code or 0.
+ *
+ * @ingroup krb5_crypto
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_random_to_key(krb5_context context,
krb5_enctype type,
@@ -4312,7 +4337,7 @@ _krb5_pk_octetstring2key(krb5_context context,
size_t keylen, offset;
void *keydata;
unsigned char counter;
- unsigned char shaoutput[20];
+ unsigned char shaoutput[SHA_DIGEST_LENGTH];
if(et == NULL) {
krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
@@ -4463,9 +4488,9 @@ _krb5_pk_kdf(krb5_context context,
size_t keylen, offset;
uint32_t counter;
unsigned char *keydata;
- unsigned char shaoutput[20];
+ unsigned char shaoutput[SHA_DIGEST_LENGTH];
- if (der_heim_oid_cmp(oid_id_pkinit_kdf_ah_sha1(), &ai->algorithm) != 0) {
+ if (der_heim_oid_cmp(&asn1_oid_id_pkinit_kdf_ah_sha1, &ai->algorithm) != 0) {
krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
N_("KDF not supported", ""));
return KRB5_PROG_ETYPE_NOSUPP;
@@ -4572,118 +4597,131 @@ krb5_crypto_prf(krb5_context context,
return (*et->prf)(context, crypto, input, output);
}
-#ifndef HEIMDAL_SMALLER
+static krb5_error_code
+krb5_crypto_prfplus(krb5_context context,
+ const krb5_crypto crypto,
+ const krb5_data *input,
+ size_t length,
+ krb5_data *output)
+{
+ krb5_error_code ret;
+ krb5_data input2;
+ unsigned char i = 1;
+ unsigned char *p;
-static struct key_type *keytypes[] = {
- &keytype_null,
- &keytype_des,
- &keytype_des3_derived,
-#ifdef DES3_OLD_ENCTYPE
- &keytype_des3,
-#endif
- &keytype_aes128,
- &keytype_aes256,
- &keytype_arcfour
-};
+ krb5_data_zero(&input2);
+ krb5_data_zero(output);
-static int num_keytypes = sizeof(keytypes) / sizeof(keytypes[0]);
+ krb5_clear_error_message(context);
+ ret = krb5_data_alloc(output, length);
+ if (ret) goto out;
+ ret = krb5_data_alloc(&input2, input->length + 1);
+ if (ret) goto out;
-static struct key_type *
-_find_keytype(krb5_keytype type)
-{
- int i;
- for(i = 0; i < num_keytypes; i++)
- if(keytypes[i]->type == type)
- return keytypes[i];
- return NULL;
-}
+ krb5_clear_error_message(context);
-/*
- * First take the configured list of etypes for `keytype' if available,
- * else, do `krb5_keytype_to_enctypes'.
- */
+ memcpy(((unsigned char *)input2.data) + 1, input->data, input->length);
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_keytype_to_enctypes_default (krb5_context context,
- krb5_keytype keytype,
- unsigned *len,
- krb5_enctype **val)
- __attribute__((deprecated))
-{
- unsigned int i, n;
- krb5_enctype *ret;
+ p = output->data;
- if (keytype != KEYTYPE_DES || context->etypes_des == NULL)
- return krb5_keytype_to_enctypes (context, keytype, len, val);
+ while (length) {
+ krb5_data block;
- for (n = 0; context->etypes_des[n]; ++n)
- ;
- ret = malloc (n * sizeof(*ret));
- if (ret == NULL && n != 0) {
- krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
- return ENOMEM;
- }
- for (i = 0; i < n; ++i)
- ret[i] = context->etypes_des[i];
- *len = n;
- *val = ret;
- return 0;
-}
+ ((unsigned char *)input2.data)[0] = i++;
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_keytype_to_string(krb5_context context,
- krb5_keytype keytype,
- char **string)
- __attribute__((deprecated))
-{
- struct key_type *kt = _find_keytype(keytype);
- if(kt == NULL) {
- krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
- "key type %d not supported", keytype);
- return KRB5_PROG_KEYTYPE_NOSUPP;
- }
- *string = strdup(kt->name);
- if(*string == NULL) {
- krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
- return ENOMEM;
+ ret = krb5_crypto_prf(context, crypto, &input2, &block);
+ if (ret)
+ goto out;
+
+ if (block.length < length) {
+ memcpy(p, block.data, block.length);
+ length -= block.length;
+ } else {
+ memcpy(p, block.data, length);
+ length = 0;
+ }
+ p += block.length;
+ krb5_data_free(&block);
}
+
+ out:
+ krb5_data_free(&input2);
+ if (ret)
+ krb5_data_free(output);
return 0;
}
+/**
+ * The FX-CF2 key derivation function, used in FAST and preauth framework.
+ *
+ * @param context Kerberos 5 context
+ * @param crypto1 first key to combine
+ * @param crypto2 second key to combine
+ * @param pepper1 factor to combine with first key to garante uniqueness
+ * @param pepper1 factor to combine with second key to garante uniqueness
+ * @param enctype the encryption type of the resulting key
+ * @param res allocated key, free with krb5_free_keyblock_contents()
+ *
+ * @return Return an error code or 0.
+ *
+ * @ingroup krb5_crypto
+ */
krb5_error_code KRB5_LIB_FUNCTION
-krb5_string_to_keytype(krb5_context context,
- const char *string,
- krb5_keytype *keytype)
- __attribute__((deprecated))
+krb5_crypto_fx_cf2(krb5_context context,
+ const krb5_crypto crypto1,
+ const krb5_crypto crypto2,
+ krb5_data *pepper1,
+ krb5_data *pepper2,
+ krb5_enctype enctype,
+ krb5_keyblock *res)
{
- char *end;
- int i;
+ krb5_error_code ret;
+ krb5_data os1, os2;
+ size_t i, keysize;
- for(i = 0; i < num_keytypes; i++)
- if(strcasecmp(keytypes[i]->name, string) == 0){
- *keytype = keytypes[i]->type;
- return 0;
- }
+ memset(res, 0, sizeof(*res));
- /* check if the enctype is a number */
- *keytype = strtol(string, &end, 0);
- if(*end == '\0' && *keytype != 0) {
- if (krb5_enctype_valid(context, *keytype) == 0)
- return 0;
+ ret = krb5_enctype_keysize(context, enctype, &keysize);
+ if (ret)
+ return ret;
+
+ ret = krb5_data_alloc(&res->keyvalue, keysize);
+ if (ret)
+ goto out;
+ ret = krb5_crypto_prfplus(context, crypto1, pepper1, keysize, &os1);
+ if (ret)
+ goto out;
+ ret = krb5_crypto_prfplus(context, crypto2, pepper2, keysize, &os2);
+ if (ret)
+ goto out;
+
+ res->keytype = enctype;
+ {
+ unsigned char *p1 = os1.data, *p2 = os2.data, *p3 = res->keyvalue.data;
+ for (i = 0; i < keysize; i++)
+ p3[i] = p1[i] ^ p2[i];
}
+ out:
+ if (ret)
+ krb5_data_free(&res->keyvalue);
+ krb5_data_free(&os1);
+ krb5_data_free(&os2);
- krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
- "key type %s not supported", string);
- return KRB5_PROG_KEYTYPE_NOSUPP;
+ return ret;
}
+
+
+#ifndef HEIMDAL_SMALLER
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_keytype_to_enctypes (krb5_context context,
krb5_keytype keytype,
unsigned *len,
krb5_enctype **val)
+ KRB5_DEPRECATED
{
int i;
unsigned n = 0;
@@ -4691,18 +4729,26 @@ krb5_keytype_to_enctypes (krb5_context context,
for (i = num_etypes - 1; i >= 0; --i) {
if (etypes[i]->keytype->type == keytype
- && !(etypes[i]->flags & F_PSEUDO))
+ && !(etypes[i]->flags & F_PSEUDO)
+ && krb5_enctype_valid(context, etypes[i]->type) == 0)
++n;
}
+ if (n == 0) {
+ krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
+ "Keytype have no mapping");
+ return KRB5_PROG_KEYTYPE_NOSUPP;
+ }
+
ret = malloc(n * sizeof(*ret));
if (ret == NULL && n != 0) {
- krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
+ krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
return ENOMEM;
}
n = 0;
for (i = num_etypes - 1; i >= 0; --i) {
if (etypes[i]->keytype->type == keytype
- && !(etypes[i]->flags & F_PSEUDO))
+ && !(etypes[i]->flags & F_PSEUDO)
+ && krb5_enctype_valid(context, etypes[i]->type) == 0)
ret[n++] = etypes[i]->type;
}
*len = n;
@@ -4710,4 +4756,16 @@ krb5_keytype_to_enctypes (krb5_context context,
return 0;
}
+/* if two enctypes have compatible keys */
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_enctypes_compatible_keys(krb5_context context,
+ krb5_enctype etype1,
+ krb5_enctype etype2)
+ KRB5_DEPRECATED
+{
+ struct encryption_type *e1 = _find_enctype(etype1);
+ struct encryption_type *e2 = _find_enctype(etype2);
+ return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype;
+}
+
#endif /* HEIMDAL_SMALLER */
diff --git a/source4/heimdal/lib/krb5/data.c b/source4/heimdal/lib/krb5/data.c
index d6099c3c6c..993d6058bf 100644
--- a/source4/heimdal/lib/krb5/data.c
+++ b/source4/heimdal/lib/krb5/data.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
/**
* Reset the (potentially uninitalized) krb5_data structure.
*
@@ -52,7 +50,9 @@ krb5_data_zero(krb5_data *p)
/**
* Free the content of krb5_data structure, its ok to free a zeroed
- * structure. When done, the structure will be zeroed.
+ * structure (with memset() or krb5_data_zero()). When done, the
+ * structure will be zeroed. The same function is called
+ * krb5_free_data_contents() in MIT Kerberos.
*
* @param p krb5_data to free.
*
@@ -68,21 +68,6 @@ krb5_data_free(krb5_data *p)
}
/**
- * Same as krb5_data_free().
- *
- * @param context Kerberos 5 context.
- * @param data krb5_data to free.
- *
- * @ingroup krb5
- */
-
-void KRB5_LIB_FUNCTION
-krb5_free_data_contents(krb5_context context, krb5_data *data)
-{
- krb5_data_free(data);
-}
-
-/**
* Free krb5_data (and its content).
*
* @param context Kerberos 5 context.
diff --git a/source4/heimdal/lib/krb5/eai_to_heim_errno.c b/source4/heimdal/lib/krb5/eai_to_heim_errno.c
index 594f998e26..499150f469 100644
--- a/source4/heimdal/lib/krb5/eai_to_heim_errno.c
+++ b/source4/heimdal/lib/krb5/eai_to_heim_errno.c
@@ -33,8 +33,6 @@
#include <krb5_locl.h>
-RCSID("$Id$");
-
/**
* Convert the getaddrinfo() error code to a Kerberos et error code.
*
diff --git a/source4/heimdal/lib/krb5/error_string.c b/source4/heimdal/lib/krb5/error_string.c
index 6374fa17ae..829c080a55 100644
--- a/source4/heimdal/lib/krb5/error_string.c
+++ b/source4/heimdal/lib/krb5/error_string.c
@@ -33,10 +33,8 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
#undef __attribute__
-#define __attribute__(X)
+#define __attribute__(x)
/**
* Clears the error message from the Kerberos 5 context.
@@ -172,6 +170,9 @@ krb5_get_error_message(krb5_context context, krb5_error_code code)
}
HEIMDAL_MUTEX_unlock(context->mutex);
+ if (code == 0)
+ return strdup("Success");
+
cstr = krb5_get_err_text(context, code);
if (cstr)
return strdup(cstr);
@@ -198,80 +199,3 @@ krb5_free_error_message(krb5_context context, const char *msg)
{
free(rk_UNCONST(msg));
}
-
-#ifndef HEIMDAL_SMALLER
-
-/**
- * Free the error message returned by krb5_get_error_string(),
- * deprecated, use krb5_free_error_message().
- *
- * @param context Kerberos context
- * @param msg error message to free
- *
- * @ingroup krb5_deprecated
- */
-
-void KRB5_LIB_FUNCTION
-krb5_free_error_string(krb5_context context, char *str)
- __attribute__((deprecated))
-{
- krb5_free_error_message(context, str);
-}
-
-/**
- * Set the error message returned by krb5_get_error_string(),
- * deprecated, use krb5_set_error_message().
- *
- * @param context Kerberos context
- * @param msg error message to free
- *
- * @ingroup krb5_deprecated
- */
-
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_set_error_string(krb5_context context, const char *fmt, ...)
- __attribute__((format (printf, 2, 3))) __attribute__((deprecated))
-{
- va_list ap;
-
- va_start(ap, fmt);
- krb5_vset_error_message (context, 0, fmt, ap);
- va_end(ap);
- return 0;
-}
-
-/**
- * Set the error message returned by krb5_get_error_string(),
- * deprecated, use krb5_set_error_message().
- *
- * @param context Kerberos context
- * @param msg error message to free
- *
- * @ingroup krb5_deprecated
- */
-
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_vset_error_string(krb5_context context, const char *fmt, va_list args)
- __attribute__ ((format (printf, 2, 0))) __attribute__((deprecated))
-{
- krb5_vset_error_message(context, 0, fmt, args);
- return 0;
-}
-
-/**
- * Clar the error message returned by krb5_get_error_string(),
- * deprecated, use krb5_clear_error_message().
- *
- * @param context Kerberos context
- *
- * @ingroup krb5_deprecated
- */
-
-void KRB5_LIB_FUNCTION
-krb5_clear_error_string(krb5_context context)
- __attribute__((deprecated))
-{
- krb5_clear_error_message(context);
-}
-
-#endif /* !HEIMDAL_SMALLER */
diff --git a/source4/heimdal/lib/krb5/expand_hostname.c b/source4/heimdal/lib/krb5/expand_hostname.c
index a712d9c83a..67988d0d7b 100644
--- a/source4/heimdal/lib/krb5/expand_hostname.c
+++ b/source4/heimdal/lib/krb5/expand_hostname.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
static krb5_error_code
copy_hostname(krb5_context context,
const char *orig_hostname,
@@ -50,9 +48,19 @@ copy_hostname(krb5_context context,
return 0;
}
-/*
- * Try to make `orig_hostname' into a more canonical one in the newly
- * allocated space returned in `new_hostname'.
+/**
+ * krb5_expand_hostname() tries to make orig_hostname into a more
+ * canonical one in the newly allocated space returned in
+ * new_hostname.
+
+ * @param context a Keberos context
+ * @param orig_hostname hostname to canonicalise.
+ * @param new_hostname output hostname, caller must free hostname with
+ * krb5_xfree().
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_support
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -114,9 +122,22 @@ vanilla_hostname (krb5_context context,
return 0;
}
-/*
- * expand `hostname' to a name we believe to be a hostname in newly
- * allocated space in `host' and return realms in `realms'.
+/**
+ * krb5_expand_hostname_realms() expands orig_hostname to a name we
+ * believe to be a hostname in newly allocated space in new_hostname
+ * and return the realms new_hostname is believed to belong to in
+ * realms.
+ *
+ * @param context a Keberos context
+ * @param orig_hostname hostname to canonicalise.
+ * @param new_hostname output hostname, caller must free hostname with
+ * krb5_xfree().
+ * @param realms output possible realms, is an array that is terminated
+ * with NULL. Caller must free with krb5_free_host_realm().
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_support
*/
krb5_error_code KRB5_LIB_FUNCTION
diff --git a/source4/heimdal/lib/krb5/fcache.c b/source4/heimdal/lib/krb5/fcache.c
index b745c67e11..f8e74f1ddc 100644
--- a/source4/heimdal/lib/krb5/fcache.c
+++ b/source4/heimdal/lib/krb5/fcache.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
typedef struct krb5_fcache{
char *filename;
int version;
@@ -233,8 +231,8 @@ scrub_file (int fd)
* hardlink)
*/
-static krb5_error_code
-erase_file(krb5_context context, const char *filename)
+krb5_error_code
+_krb5_erase_file(krb5_context context, const char *filename)
{
int fd;
struct stat sb1, sb2;
@@ -453,7 +451,7 @@ static krb5_error_code
fcc_destroy(krb5_context context,
krb5_ccache id)
{
- erase_file(context, FILENAME(id));
+ _krb5_erase_file(context, FILENAME(id));
return 0;
}
@@ -740,8 +738,10 @@ fcc_remove_cred(krb5_context context,
{
krb5_error_code ret;
krb5_ccache copy, newfile;
+ char *newname;
+ int fd;
- ret = krb5_cc_gen_new(context, &krb5_mcc_ops, &copy);
+ ret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &copy);
if (ret)
return ret;
@@ -757,8 +757,24 @@ fcc_remove_cred(krb5_context context,
return ret;
}
- ret = krb5_cc_gen_new(context, &krb5_fcc_ops, &newfile);
+ asprintf(&newname, "FILE:%s.XXXXXX", FILENAME(id));
+ if (newname == NULL) {
+ krb5_cc_destroy(context, copy);
+ return ret;
+ }
+
+ fd = mkstemp(&newname[5]);
+ if (fd < 0) {
+ ret = errno;
+ krb5_cc_destroy(context, copy);
+ return ret;
+ }
+ close(fd);
+
+ ret = krb5_cc_resolve(context, newname, &newfile);
if (ret) {
+ unlink(&newname[5]);
+ free(newname);
krb5_cc_destroy(context, copy);
return ret;
}
@@ -766,11 +782,18 @@ fcc_remove_cred(krb5_context context,
ret = krb5_cc_copy_cache(context, copy, newfile);
krb5_cc_destroy(context, copy);
if (ret) {
+ free(newname);
krb5_cc_destroy(context, newfile);
return ret;
}
- return krb5_cc_move(context, newfile, id);
+ ret = rename(&newname[5], FILENAME(id));
+ if (ret)
+ ret = errno;
+ free(newname);
+ krb5_cc_close(context, newfile);
+
+ return ret;
}
static krb5_error_code
@@ -822,12 +845,13 @@ fcc_get_cache_next(krb5_context context, krb5_cc_cursor cursor, krb5_ccache *id)
iter->first = 0;
fn = krb5_cc_default_name(context);
- if (strncasecmp(fn, "FILE:", 5) != 0) {
+ if (fn == NULL || strncasecmp(fn, "FILE:", 5) != 0) {
ret = _krb5_expand_default_cc_name(context,
KRB5_DEFAULT_CCNAME_FILE,
&expandedfn);
if (ret)
return ret;
+ fn = expandedfn;
}
ret = krb5_cc_resolve(context, fn, id);
if (expandedfn)
@@ -900,10 +924,10 @@ fcc_move(krb5_context context, krb5_ccache from, krb5_ccache to)
fcc_unlock(context, fd1);
close(fd1);
- erase_file(context, FILENAME(from));
+ _krb5_erase_file(context, FILENAME(from));
if (ret) {
- erase_file(context, FILENAME(to));
+ _krb5_erase_file(context, FILENAME(to));
return ret;
}
}
@@ -913,10 +937,14 @@ fcc_move(krb5_context context, krb5_ccache from, krb5_ccache to)
krb5_storage *sp;
int fd;
ret = init_fcc (context, to, &sp, &fd);
- krb5_storage_free(sp);
+ if (sp)
+ krb5_storage_free(sp);
fcc_unlock(context, fd);
close(fd);
}
+
+ fcc_destroy(context, from);
+
return ret;
}
diff --git a/source4/heimdal/lib/krb5/free.c b/source4/heimdal/lib/krb5/free.c
index da1eb1de1c..7f4374374b 100644
--- a/source4/heimdal/lib/krb5/free.c
+++ b/source4/heimdal/lib/krb5/free.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
krb5_error_code KRB5_LIB_FUNCTION
krb5_free_kdc_rep(krb5_context context, krb5_kdc_rep *rep)
{
diff --git a/source4/heimdal/lib/krb5/free_host_realm.c b/source4/heimdal/lib/krb5/free_host_realm.c
index 581b61a15b..f6e9f6e247 100644
--- a/source4/heimdal/lib/krb5/free_host_realm.c
+++ b/source4/heimdal/lib/krb5/free_host_realm.c
@@ -33,10 +33,15 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
-/*
+/**
* Free all memory allocated by `realmlist'
+ *
+ * @param context A Kerberos 5 context.
+ * @param realmlist realmlist to free, NULL is ok
+ *
+ * @return a Kerberos error code, always 0.
+ *
+ * @ingroup krb5_support
*/
krb5_error_code KRB5_LIB_FUNCTION
diff --git a/source4/heimdal/lib/krb5/generate_seq_number.c b/source4/heimdal/lib/krb5/generate_seq_number.c
index 99745b8305..2764f1a914 100644
--- a/source4/heimdal/lib/krb5/generate_seq_number.c
+++ b/source4/heimdal/lib/krb5/generate_seq_number.c
@@ -33,8 +33,6 @@
#include <krb5_locl.h>
-RCSID("$Id$");
-
krb5_error_code KRB5_LIB_FUNCTION
krb5_generate_seq_number(krb5_context context,
const krb5_keyblock *key,
diff --git a/source4/heimdal/lib/krb5/generate_subkey.c b/source4/heimdal/lib/krb5/generate_subkey.c
index 4ab4b9bf6c..efb6cce288 100644
--- a/source4/heimdal/lib/krb5/generate_subkey.c
+++ b/source4/heimdal/lib/krb5/generate_subkey.c
@@ -33,8 +33,6 @@
#include <krb5_locl.h>
-RCSID("$Id$");
-
krb5_error_code KRB5_LIB_FUNCTION
krb5_generate_subkey(krb5_context context,
const krb5_keyblock *key,
diff --git a/source4/heimdal/lib/krb5/get_addrs.c b/source4/heimdal/lib/krb5/get_addrs.c
index ce16785319..8f366fa148 100644
--- a/source4/heimdal/lib/krb5/get_addrs.c
+++ b/source4/heimdal/lib/krb5/get_addrs.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id: get_addrs.c 23815 2008-09-13 09:21:03Z lha $");
-
#ifdef __osf__
/* hate */
struct rtentry;
@@ -43,9 +41,7 @@ struct mbuf;
#ifdef HAVE_NET_IF_H
#include <net/if.h>
#endif
-#ifdef HAVE_IFADDR_H
#include <ifaddrs.h>
-#endif
static krb5_error_code
gethostname_fallback (krb5_context context, krb5_addresses *res)
@@ -106,8 +102,6 @@ find_all_addresses (krb5_context context, krb5_addresses *res, int flags)
unsigned int num, idx;
krb5_addresses ignore_addresses;
- res->val = NULL;
-
if (getifaddrs(&ifa0) == -1) {
ret = errno;
krb5_set_error_message(context, ret, "getifaddrs: %s", strerror(ret));
@@ -232,13 +226,14 @@ get_addrs_int (krb5_context context, krb5_addresses *res, int flags)
{
krb5_error_code ret = -1;
+ res->len = 0;
+ res->val = NULL;
+
if (flags & SCAN_INTERFACES) {
ret = find_all_addresses (context, res, flags);
if(ret || res->len == 0)
ret = gethostname_fallback (context, res);
} else {
- res->len = 0;
- res->val = NULL;
ret = 0;
}
diff --git a/source4/heimdal/lib/krb5/get_cred.c b/source4/heimdal/lib/krb5/get_cred.c
index 97e0022ee1..e609bcadcc 100644
--- a/source4/heimdal/lib/krb5/get_cred.c
+++ b/source4/heimdal/lib/krb5/get_cred.c
@@ -33,8 +33,6 @@
#include <krb5_locl.h>
-RCSID("$Id$");
-
/*
* Take the `body' and encode it into `padata' using the credentials
* in `creds'.
@@ -375,17 +373,18 @@ decrypt_tkt_with_subkey (krb5_context context,
if (ret)
return ret;
- ret = krb5_decode_EncASRepPart(context,
- data.data,
+ ret = decode_EncASRepPart(data.data,
+ data.length,
+ &dec_rep->enc_part,
+ &size);
+ if (ret)
+ ret = decode_EncTGSRepPart(data.data,
data.length,
&dec_rep->enc_part,
&size);
if (ret)
- ret = krb5_decode_EncTGSRepPart(context,
- data.data,
- data.length,
- &dec_rep->enc_part,
- &size);
+ krb5_set_error_message(context, ret,
+ N_("Failed to decode encpart in ticket", ""));
krb5_data_free (&data);
return ret;
}
@@ -477,7 +476,7 @@ get_cred_kdc(krb5_context context,
if (len != size)
krb5_abortx(context, "internal asn1 error");
- ret = krb5_padata_add(context, &padata, KRB5_PADATA_S4U2SELF, buf, len);
+ ret = krb5_padata_add(context, &padata, KRB5_PADATA_FOR_USER, buf, len);
if (ret)
goto out;
}
@@ -561,7 +560,7 @@ get_cred_kdc(krb5_context context,
} else if(krb5_rd_error(context, &resp, &error) == 0) {
ret = krb5_error_from_rd_error(context, &error, in_creds);
krb5_free_error_contents(context, &error);
- } else if(resp.data && ((char*)resp.data)[0] == 4) {
+ } else if(resp.length > 0 && ((char*)resp.data)[0] == 4) {
ret = KRB5KRB_AP_ERR_V4_REPLY;
krb5_clear_error_message(context);
} else {
@@ -1217,6 +1216,10 @@ krb5_get_creds_opt_free(krb5_context context, krb5_get_creds_opt opt)
{
if (opt->self)
krb5_free_principal(context, opt->self);
+ if (opt->ticket) {
+ free_Ticket(opt->ticket);
+ free(opt->ticket);
+ }
memset(opt, 0, sizeof(*opt));
free(opt);
}
diff --git a/source4/heimdal/lib/krb5/get_default_principal.c b/source4/heimdal/lib/krb5/get_default_principal.c
index c804ab9e56..82d0642934 100644
--- a/source4/heimdal/lib/krb5/get_default_principal.c
+++ b/source4/heimdal/lib/krb5/get_default_principal.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
/*
* Try to find out what's a reasonable default principal.
*/
diff --git a/source4/heimdal/lib/krb5/get_default_realm.c b/source4/heimdal/lib/krb5/get_default_realm.c
index a2518bbab7..f09df264c1 100644
--- a/source4/heimdal/lib/krb5/get_default_realm.c
+++ b/source4/heimdal/lib/krb5/get_default_realm.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
/*
* Return a NULL-terminated list of default realms in `realms'.
* Free this memory with krb5_free_host_realm.
diff --git a/source4/heimdal/lib/krb5/get_for_creds.c b/source4/heimdal/lib/krb5/get_for_creds.c
index a7072a0136..19e48173df 100644
--- a/source4/heimdal/lib/krb5/get_for_creds.c
+++ b/source4/heimdal/lib/krb5/get_for_creds.c
@@ -33,8 +33,6 @@
#include <krb5_locl.h>
-RCSID("$Id$");
-
static krb5_error_code
add_addrs(krb5_context context,
krb5_addresses *addr,
diff --git a/source4/heimdal/lib/krb5/get_host_realm.c b/source4/heimdal/lib/krb5/get_host_realm.c
index 2ea075f6c5..7d7fef6e1c 100644
--- a/source4/heimdal/lib/krb5/get_host_realm.c
+++ b/source4/heimdal/lib/krb5/get_host_realm.c
@@ -34,8 +34,6 @@
#include "krb5_locl.h"
#include <resolve.h>
-RCSID("$Id$");
-
/* To automagically find the correct realm of a host (without
* [domain_realm] in krb5.conf) add a text record for your domain with
* the name of your realm, like this:
@@ -51,14 +49,14 @@ RCSID("$Id$");
*/
static int
-copy_txt_to_realms (struct resource_record *head,
+copy_txt_to_realms (struct rk_resource_record *head,
krb5_realm **realms)
{
- struct resource_record *rr;
+ struct rk_resource_record *rr;
unsigned int n, i;
for(n = 0, rr = head; rr; rr = rr->next)
- if (rr->type == T_TXT)
+ if (rr->type == rk_ns_t_txt)
++n;
if (n == 0)
@@ -72,7 +70,7 @@ copy_txt_to_realms (struct resource_record *head,
(*realms)[i] = NULL;
for (i = 0, rr = head; rr; rr = rr->next) {
- if (rr->type == T_TXT) {
+ if (rr->type == rk_ns_t_txt) {
char *tmp;
tmp = strdup(rr->u.txt);
@@ -96,7 +94,7 @@ dns_find_realm(krb5_context context,
{
static const char *default_labels[] = { "_kerberos", NULL };
char dom[MAXHOSTNAMELEN];
- struct dns_reply *r;
+ struct rk_dns_reply *r;
const char **labels;
char **config_labels;
int i, ret;
@@ -116,10 +114,10 @@ dns_find_realm(krb5_context context,
krb5_config_free_strings(config_labels);
return -1;
}
- r = dns_lookup(dom, "TXT");
+ r = rk_dns_lookup(dom, "TXT");
if(r != NULL) {
ret = copy_txt_to_realms (r->head, realms);
- dns_free_data(r);
+ rk_dns_free_data(r);
if(ret == 0) {
if (config_labels)
krb5_config_free_strings(config_labels);
diff --git a/source4/heimdal/lib/krb5/get_in_tkt.c b/source4/heimdal/lib/krb5/get_in_tkt.c
index cc49e16030..84b1ffb71f 100644
--- a/source4/heimdal/lib/krb5/get_in_tkt.c
+++ b/source4/heimdal/lib/krb5/get_in_tkt.c
@@ -31,529 +31,11 @@
* SUCH DAMAGE.
*/
-#include "krb5_locl.h"
-
-RCSID("$Id$");
-
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_init_etype (krb5_context context,
- unsigned *len,
- krb5_enctype **val,
- const krb5_enctype *etypes)
-{
- unsigned int i;
- krb5_error_code ret;
- krb5_enctype *tmp = NULL;
-
- ret = 0;
- if (etypes == NULL) {
- ret = krb5_get_default_in_tkt_etypes(context,
- &tmp);
- if (ret)
- return ret;
- etypes = tmp;
- }
-
- for (i = 0; etypes[i]; ++i)
- ;
- *len = i;
- *val = malloc(i * sizeof(**val));
- if (i != 0 && *val == NULL) {
- ret = ENOMEM;
- krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
- goto cleanup;
- }
- memmove (*val,
- etypes,
- i * sizeof(*tmp));
-cleanup:
- if (tmp != NULL)
- free (tmp);
- return ret;
-}
-
-static krb5_error_code
-check_server_referral(krb5_context context,
- krb5_kdc_rep *rep,
- unsigned flags,
- krb5_const_principal requested,
- krb5_const_principal returned,
- const krb5_keyblock const * key)
-{
- krb5_error_code ret;
- PA_ServerReferralData ref;
- krb5_crypto session;
- EncryptedData ed;
- size_t len;
- krb5_data data;
- PA_DATA *pa;
- int i = 0, cmp;
-
- if (rep->kdc_rep.padata == NULL)
- goto noreferral;
-
- pa = krb5_find_padata(rep->kdc_rep.padata->val,
- rep->kdc_rep.padata->len,
- KRB5_PADATA_SERVER_REFERRAL, &i);
- if (pa == NULL)
- goto noreferral;
-
- memset(&ed, 0, sizeof(ed));
- memset(&ref, 0, sizeof(ref));
-
- ret = decode_EncryptedData(pa->padata_value.data,
- pa->padata_value.length,
- &ed, &len);
- if (ret)
- return ret;
- if (len != pa->padata_value.length) {
- free_EncryptedData(&ed);
- krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
- N_("Referral EncryptedData wrong for realm %s",
- "realm"), requested->realm);
- return KRB5KRB_AP_ERR_MODIFIED;
- }
-
- ret = krb5_crypto_init(context, key, 0, &session);
- if (ret) {
- free_EncryptedData(&ed);
- return ret;
- }
-
- ret = krb5_decrypt_EncryptedData(context, session,
- KRB5_KU_PA_SERVER_REFERRAL,
- &ed, &data);
- free_EncryptedData(&ed);
- krb5_crypto_destroy(context, session);
- if (ret)
- return ret;
-
- ret = decode_PA_ServerReferralData(data.data, data.length, &ref, &len);
- if (ret) {
- krb5_data_free(&data);
- return ret;
- }
- krb5_data_free(&data);
-
- if (strcmp(requested->realm, returned->realm) != 0) {
- free_PA_ServerReferralData(&ref);
- krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
- N_("server ref realm mismatch, "
- "requested realm %s got back %s", ""),
- requested->realm, returned->realm);
- return KRB5KRB_AP_ERR_MODIFIED;
- }
-
- if (returned->name.name_string.len == 2 &&
- strcmp(returned->name.name_string.val[0], KRB5_TGS_NAME) == 0)
- {
- const char *realm = returned->name.name_string.val[1];
-
- if (ref.referred_realm == NULL
- || strcmp(*ref.referred_realm, realm) != 0)
- {
- free_PA_ServerReferralData(&ref);
- krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
- N_("tgt returned with wrong ref", ""));
- return KRB5KRB_AP_ERR_MODIFIED;
- }
- } else if (krb5_principal_compare(context, returned, requested) == 0) {
- free_PA_ServerReferralData(&ref);
- krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
- N_("req princ no same as returned", ""));
- return KRB5KRB_AP_ERR_MODIFIED;
- }
-
- if (ref.requested_principal_name) {
- cmp = _krb5_principal_compare_PrincipalName(context,
- requested,
- ref.requested_principal_name);
- if (!cmp) {
- free_PA_ServerReferralData(&ref);
- krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
- N_("referred principal not same "
- "as requested", ""));
- return KRB5KRB_AP_ERR_MODIFIED;
- }
- } else if (flags & EXTRACT_TICKET_AS_REQ) {
- free_PA_ServerReferralData(&ref);
- krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
- N_("Requested principal missing on AS-REQ", ""));
- return KRB5KRB_AP_ERR_MODIFIED;
- }
-
- free_PA_ServerReferralData(&ref);
-
- return ret;
-noreferral:
- if (krb5_principal_compare(context, requested, returned) == FALSE) {
- krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
- N_("Not same server principal returned "
- "as requested", ""));
- return KRB5KRB_AP_ERR_MODIFIED;
- }
- return 0;
-}
-
-
-/*
- * Verify referral data
- */
-
-
-static krb5_error_code
-check_client_referral(krb5_context context,
- krb5_kdc_rep *rep,
- krb5_const_principal requested,
- krb5_const_principal mapped,
- krb5_keyblock const * key)
-{
- krb5_error_code ret;
- PA_ClientCanonicalized canon;
- krb5_crypto crypto;
- krb5_data data;
- PA_DATA *pa;
- size_t len;
- int i = 0;
-
- if (rep->kdc_rep.padata == NULL)
- goto noreferral;
-
- pa = krb5_find_padata(rep->kdc_rep.padata->val,
- rep->kdc_rep.padata->len,
- KRB5_PADATA_CLIENT_CANONICALIZED, &i);
- if (pa == NULL)
- goto noreferral;
-
- ret = decode_PA_ClientCanonicalized(pa->padata_value.data,
- pa->padata_value.length,
- &canon, &len);
- if (ret) {
- krb5_set_error_message(context, ret,
- N_("Failed to decode ClientCanonicalized "
- "from realm %s", ""), requested->realm);
- return ret;
- }
-
- ASN1_MALLOC_ENCODE(PA_ClientCanonicalizedNames, data.data, data.length,
- &canon.names, &len, ret);
- if (ret) {
- free_PA_ClientCanonicalized(&canon);
- return ret;
- }
- if (data.length != len)
- krb5_abortx(context, "internal asn.1 error");
-
- ret = krb5_crypto_init(context, key, 0, &crypto);
- if (ret) {
- free(data.data);
- free_PA_ClientCanonicalized(&canon);
- return ret;
- }
-
- ret = krb5_verify_checksum(context, crypto, KRB5_KU_CANONICALIZED_NAMES,
- data.data, data.length,
- &canon.canon_checksum);
- krb5_crypto_destroy(context, crypto);
- free(data.data);
- if (ret) {
- krb5_set_error_message(context, ret,
- N_("Failed to verify client canonicalized "
- "data from realm %s", ""),
- requested->realm);
- free_PA_ClientCanonicalized(&canon);
- return ret;
- }
-
- if (!_krb5_principal_compare_PrincipalName(context,
- requested,
- &canon.names.requested_name))
- {
- free_PA_ClientCanonicalized(&canon);
- krb5_set_error_message(context, KRB5_PRINC_NOMATCH,
- N_("Requested name doesn't match"
- " in client referral", ""));
- return KRB5_PRINC_NOMATCH;
- }
- if (!_krb5_principal_compare_PrincipalName(context,
- mapped,
- &canon.names.mapped_name))
- {
- free_PA_ClientCanonicalized(&canon);
- krb5_set_error_message(context, KRB5_PRINC_NOMATCH,
- N_("Mapped name doesn't match"
- " in client referral", ""));
- return KRB5_PRINC_NOMATCH;
- }
-
- return 0;
-
-noreferral:
- if (krb5_principal_compare(context, requested, mapped) == FALSE) {
- krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
- N_("Not same client principal returned "
- "as requested", ""));
- return KRB5KRB_AP_ERR_MODIFIED;
- }
- return 0;
-}
-
-
+#define KRB5_DEPRECATED
-static krb5_error_code
-decrypt_tkt (krb5_context context,
- krb5_keyblock *key,
- krb5_key_usage usage,
- krb5_const_pointer decrypt_arg,
- krb5_kdc_rep *dec_rep)
-{
- krb5_error_code ret;
- krb5_data data;
- size_t size;
- krb5_crypto crypto;
-
- ret = krb5_crypto_init(context, key, 0, &crypto);
- if (ret)
- return ret;
-
- ret = krb5_decrypt_EncryptedData (context,
- crypto,
- usage,
- &dec_rep->kdc_rep.enc_part,
- &data);
- krb5_crypto_destroy(context, crypto);
-
- if (ret)
- return ret;
-
- ret = krb5_decode_EncASRepPart(context,
- data.data,
- data.length,
- &dec_rep->enc_part,
- &size);
- if (ret)
- ret = krb5_decode_EncTGSRepPart(context,
- data.data,
- data.length,
- &dec_rep->enc_part,
- &size);
- krb5_data_free (&data);
- if (ret)
- return ret;
- return 0;
-}
-
-int
-_krb5_extract_ticket(krb5_context context,
- krb5_kdc_rep *rep,
- krb5_creds *creds,
- krb5_keyblock *key,
- krb5_const_pointer keyseed,
- krb5_key_usage key_usage,
- krb5_addresses *addrs,
- unsigned nonce,
- unsigned flags,
- krb5_decrypt_proc decrypt_proc,
- krb5_const_pointer decryptarg)
-{
- krb5_error_code ret;
- krb5_principal tmp_principal;
- size_t len;
- time_t tmp_time;
- krb5_timestamp sec_now;
-
- /* decrypt */
-
- if (decrypt_proc == NULL)
- decrypt_proc = decrypt_tkt;
-
- ret = (*decrypt_proc)(context, key, key_usage, decryptarg, rep);
- if (ret)
- goto out;
-
- /* save session key */
-
- creds->session.keyvalue.length = 0;
- creds->session.keyvalue.data = NULL;
- creds->session.keytype = rep->enc_part.key.keytype;
- ret = krb5_data_copy (&creds->session.keyvalue,
- rep->enc_part.key.keyvalue.data,
- rep->enc_part.key.keyvalue.length);
- if (ret) {
- krb5_clear_error_message(context);
- goto out;
- }
-
- /*
- * HACK:
- * this is really a ugly hack, to support using the Netbios Domain Name
- * as realm against windows KDC's, they always return the full realm
- * based on the DNS Name.
- */
- flags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH;
- flags |= EXTRACT_TICKET_ALLOW_CNAME_MISMATCH;
-
- /* compare client and save */
- ret = _krb5_principalname2krb5_principal (context,
- &tmp_principal,
- rep->kdc_rep.cname,
- rep->kdc_rep.crealm);
- if (ret)
- goto out;
-
- /* check client referral and save principal */
- /* anonymous here ? */
- if((flags & EXTRACT_TICKET_ALLOW_CNAME_MISMATCH) == 0) {
- ret = check_client_referral(context, rep,
- creds->client,
- tmp_principal,
- &creds->session);
- if (ret) {
- krb5_free_principal (context, tmp_principal);
- goto out;
- }
- }
- krb5_free_principal (context, creds->client);
- creds->client = tmp_principal;
-
- /* check server referral and save principal */
- ret = _krb5_principalname2krb5_principal (context,
- &tmp_principal,
- rep->kdc_rep.ticket.sname,
- rep->kdc_rep.ticket.realm);
- if (ret)
- goto out;
- if((flags & EXTRACT_TICKET_ALLOW_SERVER_MISMATCH) == 0){
- ret = check_server_referral(context,
- rep,
- flags,
- creds->server,
- tmp_principal,
- &creds->session);
- if (ret) {
- krb5_free_principal (context, tmp_principal);
- goto out;
- }
- }
- krb5_free_principal(context, creds->server);
- creds->server = tmp_principal;
-
- /* verify names */
- if(flags & EXTRACT_TICKET_MATCH_REALM){
- const char *srealm = krb5_principal_get_realm(context, creds->server);
- const char *crealm = krb5_principal_get_realm(context, creds->client);
-
- if (strcmp(rep->enc_part.srealm, srealm) != 0 ||
- strcmp(rep->enc_part.srealm, crealm) != 0)
- {
- ret = KRB5KRB_AP_ERR_MODIFIED;
- krb5_clear_error_message(context);
- goto out;
- }
- }
-
- /* compare nonces */
-
- if (nonce != rep->enc_part.nonce) {
- ret = KRB5KRB_AP_ERR_MODIFIED;
- krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
- goto out;
- }
-
- /* set kdc-offset */
-
- krb5_timeofday (context, &sec_now);
- if (rep->enc_part.flags.initial
- && context->kdc_sec_offset == 0
- && krb5_config_get_bool (context, NULL,
- "libdefaults",
- "kdc_timesync",
- NULL)) {
- context->kdc_sec_offset = rep->enc_part.authtime - sec_now;
- krb5_timeofday (context, &sec_now);
- }
-
- /* check all times */
-
- if (rep->enc_part.starttime) {
- tmp_time = *rep->enc_part.starttime;
- } else
- tmp_time = rep->enc_part.authtime;
-
- if (creds->times.starttime == 0
- && abs(tmp_time - sec_now) > context->max_skew) {
- ret = KRB5KRB_AP_ERR_SKEW;
- krb5_set_error_message (context, ret,
- N_("time skew (%d) larger than max (%d)", ""),
- abs(tmp_time - sec_now),
- (int)context->max_skew);
- goto out;
- }
-
- if (creds->times.starttime != 0
- && tmp_time != creds->times.starttime) {
- krb5_clear_error_message (context);
- ret = KRB5KRB_AP_ERR_MODIFIED;
- goto out;
- }
-
- creds->times.starttime = tmp_time;
-
- if (rep->enc_part.renew_till) {
- tmp_time = *rep->enc_part.renew_till;
- } else
- tmp_time = 0;
-
- if (creds->times.renew_till != 0
- && tmp_time > creds->times.renew_till) {
- krb5_clear_error_message (context);
- ret = KRB5KRB_AP_ERR_MODIFIED;
- goto out;
- }
-
- creds->times.renew_till = tmp_time;
-
- creds->times.authtime = rep->enc_part.authtime;
-
- if (creds->times.endtime != 0
- && rep->enc_part.endtime > creds->times.endtime) {
- krb5_clear_error_message (context);
- ret = KRB5KRB_AP_ERR_MODIFIED;
- goto out;
- }
-
- creds->times.endtime = rep->enc_part.endtime;
-
- if(rep->enc_part.caddr)
- krb5_copy_addresses (context, rep->enc_part.caddr, &creds->addresses);
- else if(addrs)
- krb5_copy_addresses (context, addrs, &creds->addresses);
- else {
- creds->addresses.len = 0;
- creds->addresses.val = NULL;
- }
- creds->flags.b = rep->enc_part.flags;
-
- creds->authdata.len = 0;
- creds->authdata.val = NULL;
-
- /* extract ticket */
- ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length,
- &rep->kdc_rep.ticket, &len, ret);
- if(ret)
- goto out;
- if (creds->ticket.length != len)
- krb5_abortx(context, "internal error in ASN.1 encoder");
- creds->second_ticket.length = 0;
- creds->second_ticket.data = NULL;
-
-
-out:
- memset (rep->enc_part.key.keyvalue.data, 0,
- rep->enc_part.key.keyvalue.length);
- return ret;
-}
+#include "krb5_locl.h"
+#ifndef HEIMDAL_SMALLER
static krb5_error_code
make_pa_enc_timestamp(krb5_context context, PA_DATA *pa,
@@ -626,6 +108,8 @@ add_padata(krb5_context context,
if(salt == NULL) {
/* default to standard salt */
ret = krb5_get_pw_salt (context, client, &salt2);
+ if (ret)
+ return ret;
salt = &salt2;
}
if (!enctypes) {
@@ -861,11 +345,10 @@ set_ptypes(krb5_context context,
*preauth = &preauth2;
ALLOC_SEQ(*preauth, 1);
(*preauth)->val[0].type = KRB5_PADATA_ENC_TIMESTAMP;
- krb5_decode_ETYPE_INFO(context,
- md.val[i].padata_value.data,
- md.val[i].padata_value.length,
- &(*preauth)->val[0].info,
- NULL);
+ decode_ETYPE_INFO(md.val[i].padata_value.data,
+ md.val[i].padata_value.length,
+ &(*preauth)->val[0].info,
+ NULL);
break;
default:
break;
@@ -891,6 +374,7 @@ krb5_get_in_cred(krb5_context context,
krb5_const_pointer decryptarg,
krb5_creds *creds,
krb5_kdc_rep *ret_as_reply)
+ KRB5_DEPRECATED
{
krb5_error_code ret;
AS_REQ a;
@@ -1055,6 +539,7 @@ krb5_get_in_tkt(krb5_context context,
krb5_creds *creds,
krb5_ccache ccache,
krb5_kdc_rep *ret_as_reply)
+ KRB5_DEPRECATED
{
krb5_error_code ret;
@@ -1076,3 +561,5 @@ krb5_get_in_tkt(krb5_context context,
ret = krb5_cc_store_cred (context, ccache, creds);
return ret;
}
+
+#endif /* HEIMDAL_SMALLER */
diff --git a/source4/heimdal/lib/krb5/get_in_tkt_with_keytab.c b/source4/heimdal/lib/krb5/get_in_tkt_with_keytab.c
deleted file mode 100644
index 0dedbefd2c..0000000000
--- a/source4/heimdal/lib/krb5/get_in_tkt_with_keytab.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 1997 - 2001 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$");
-
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_keytab_key_proc (krb5_context context,
- krb5_enctype enctype,
- krb5_salt salt,
- krb5_const_pointer keyseed,
- krb5_keyblock **key)
-{
- krb5_keytab_key_proc_args *args = rk_UNCONST(keyseed);
- krb5_keytab keytab = args->keytab;
- krb5_principal principal = args->principal;
- krb5_error_code ret;
- krb5_keytab real_keytab;
- krb5_keytab_entry entry;
-
- if(keytab == NULL)
- krb5_kt_default(context, &real_keytab);
- else
- real_keytab = keytab;
-
- ret = krb5_kt_get_entry (context, real_keytab, principal,
- 0, enctype, &entry);
-
- if (keytab == NULL)
- krb5_kt_close (context, real_keytab);
-
- if (ret)
- return ret;
-
- ret = krb5_copy_keyblock (context, &entry.keyblock, key);
- krb5_kt_free_entry(context, &entry);
- return ret;
-}
-
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_get_in_tkt_with_keytab (krb5_context context,
- krb5_flags options,
- krb5_addresses *addrs,
- const krb5_enctype *etypes,
- const krb5_preauthtype *pre_auth_types,
- krb5_keytab keytab,
- krb5_ccache ccache,
- krb5_creds *creds,
- krb5_kdc_rep *ret_as_reply)
-{
- krb5_keytab_key_proc_args a;
-
- a.principal = creds->client;
- a.keytab = keytab;
-
- return krb5_get_in_tkt (context,
- options,
- addrs,
- etypes,
- pre_auth_types,
- krb5_keytab_key_proc,
- &a,
- NULL,
- NULL,
- creds,
- ccache,
- ret_as_reply);
-}
diff --git a/source4/heimdal/lib/krb5/get_port.c b/source4/heimdal/lib/krb5/get_port.c
index c9869eb450..5d0361b816 100644
--- a/source4/heimdal/lib/krb5/get_port.c
+++ b/source4/heimdal/lib/krb5/get_port.c
@@ -33,8 +33,6 @@
#include <krb5_locl.h>
-RCSID("$Id$");
-
int KRB5_LIB_FUNCTION
krb5_getportbyname (krb5_context context,
const char *service,
diff --git a/source4/heimdal/lib/krb5/heim_err.et b/source4/heimdal/lib/krb5/heim_err.et
index 547a14e04c..2e8a0d18d8 100644
--- a/source4/heimdal/lib/krb5/heim_err.et
+++ b/source4/heimdal/lib/krb5/heim_err.et
@@ -17,6 +17,8 @@ error_code OPNOTSUPP, "Operation not supported"
error_code EOF, "End of file"
error_code BAD_MKEY, "Failed to get the master key"
error_code SERVICE_NOMATCH, "Unacceptable service used"
+error_code NOT_SEEKABLE, "File descriptor not seekable"
+error_code TOO_BIG, "Offset too large"
index 64
prefix HEIM_PKINIT
diff --git a/source4/heimdal/lib/krb5/heim_threads.h b/source4/heimdal/lib/krb5/heim_threads.h
deleted file mode 100644
index c4f841fb61..0000000000
--- a/source4/heimdal/lib/krb5/heim_threads.h
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright (c) 2003 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.
- */
-
-/* $Id$ */
-
-/*
- * Provide wrapper macros for thread synchronization primitives so we
- * can use native thread functions for those operating system that
- * supports it.
- *
- * This is so libkrb5.so (or more importantly, libgssapi.so) can have
- * thread support while the program that that dlopen(3)s the library
- * don't need to be linked to libpthread.
- */
-
-#ifndef HEIM_THREADS_H
-#define HEIM_THREADS_H 1
-
-/* assume headers already included */
-
-#if defined(__NetBSD__) && __NetBSD_Version__ >= 106120000 && __NetBSD_Version__< 299001200 && defined(ENABLE_PTHREAD_SUPPORT)
-
-/*
- * NetBSD have a thread lib that we can use that part of libc that
- * works regardless if application are linked to pthreads or not.
- * NetBSD newer then 2.99.11 just use pthread.h, and the same thing
- * will happen.
- */
-#include <threadlib.h>
-
-#define HEIMDAL_MUTEX mutex_t
-#define HEIMDAL_MUTEX_INITIALIZER MUTEX_INITIALIZER
-#define HEIMDAL_MUTEX_init(m) mutex_init(m, NULL)
-#define HEIMDAL_MUTEX_lock(m) mutex_lock(m)
-#define HEIMDAL_MUTEX_unlock(m) mutex_unlock(m)
-#define HEIMDAL_MUTEX_destroy(m) mutex_destroy(m)
-
-#define HEIMDAL_RWLOCK rwlock_t
-#define HEIMDAL_RWLOCK_INITIALIZER RWLOCK_INITIALIZER
-#define HEIMDAL_RWLOCK_init(l) rwlock_init(l, NULL)
-#define HEIMDAL_RWLOCK_rdlock(l) rwlock_rdlock(l)
-#define HEIMDAL_RWLOCK_wrlock(l) rwlock_wrlock(l)
-#define HEIMDAL_RWLOCK_tryrdlock(l) rwlock_tryrdlock(l)
-#define HEIMDAL_RWLOCK_trywrlock(l) rwlock_trywrlock(l)
-#define HEIMDAL_RWLOCK_unlock(l) rwlock_unlock(l)
-#define HEIMDAL_RWLOCK_destroy(l) rwlock_destroy(l)
-
-#define HEIMDAL_thread_key thread_key_t
-#define HEIMDAL_key_create(k,d,r) do { r = thr_keycreate(k,d); } while(0)
-#define HEIMDAL_setspecific(k,s,r) do { r = thr_setspecific(k,s); } while(0)
-#define HEIMDAL_getspecific(k) thr_getspecific(k)
-#define HEIMDAL_key_delete(k) thr_keydelete(k)
-
-#elif defined(ENABLE_PTHREAD_SUPPORT) && (!defined(__NetBSD__) || __NetBSD_Version__ >= 299001200)
-
-#include <pthread.h>
-
-#define HEIMDAL_MUTEX pthread_mutex_t
-#define HEIMDAL_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
-#define HEIMDAL_MUTEX_init(m) pthread_mutex_init(m, NULL)
-#define HEIMDAL_MUTEX_lock(m) pthread_mutex_lock(m)
-#define HEIMDAL_MUTEX_unlock(m) pthread_mutex_unlock(m)
-#define HEIMDAL_MUTEX_destroy(m) pthread_mutex_destroy(m)
-
-#define HEIMDAL_RWLOCK rwlock_t
-#define HEIMDAL_RWLOCK_INITIALIZER RWLOCK_INITIALIZER
-#define HEIMDAL_RWLOCK_init(l) pthread_rwlock_init(l, NULL)
-#define HEIMDAL_RWLOCK_rdlock(l) pthread_rwlock_rdlock(l)
-#define HEIMDAL_RWLOCK_wrlock(l) pthread_rwlock_wrlock(l)
-#define HEIMDAL_RWLOCK_tryrdlock(l) pthread_rwlock_tryrdlock(l)
-#define HEIMDAL_RWLOCK_trywrlock(l) pthread_rwlock_trywrlock(l)
-#define HEIMDAL_RWLOCK_unlock(l) pthread_rwlock_unlock(l)
-#define HEIMDAL_RWLOCK_destroy(l) pthread_rwlock_destroy(l)
-
-#define HEIMDAL_thread_key pthread_key_t
-#define HEIMDAL_key_create(k,d,r) do { r = pthread_key_create(k,d); } while(0)
-#define HEIMDAL_setspecific(k,s,r) do { r = pthread_setspecific(k,s); } while(0)
-#define HEIMDAL_getspecific(k) pthread_getspecific(k)
-#define HEIMDAL_key_delete(k) pthread_key_delete(k)
-
-#elif defined(HEIMDAL_DEBUG_THREADS)
-
-/* no threads support, just do consistency checks */
-#include <stdlib.h>
-
-#define HEIMDAL_MUTEX int
-#define HEIMDAL_MUTEX_INITIALIZER 0
-#define HEIMDAL_MUTEX_init(m) do { (*(m)) = 0; } while(0)
-#define HEIMDAL_MUTEX_lock(m) do { if ((*(m))++ != 0) abort(); } while(0)
-#define HEIMDAL_MUTEX_unlock(m) do { if ((*(m))-- != 1) abort(); } while(0)
-#define HEIMDAL_MUTEX_destroy(m) do {if ((*(m)) != 0) abort(); } while(0)
-
-#define HEIMDAL_RWLOCK rwlock_t int
-#define HEIMDAL_RWLOCK_INITIALIZER 0
-#define HEIMDAL_RWLOCK_init(l) do { } while(0)
-#define HEIMDAL_RWLOCK_rdlock(l) do { } while(0)
-#define HEIMDAL_RWLOCK_wrlock(l) do { } while(0)
-#define HEIMDAL_RWLOCK_tryrdlock(l) do { } while(0)
-#define HEIMDAL_RWLOCK_trywrlock(l) do { } while(0)
-#define HEIMDAL_RWLOCK_unlock(l) do { } while(0)
-#define HEIMDAL_RWLOCK_destroy(l) do { } while(0)
-
-#define HEIMDAL_internal_thread_key 1
-
-#else /* no thread support, no debug case */
-
-#define HEIMDAL_MUTEX int
-#define HEIMDAL_MUTEX_INITIALIZER 0
-#define HEIMDAL_MUTEX_init(m) do { (void)(m); } while(0)
-#define HEIMDAL_MUTEX_lock(m) do { (void)(m); } while(0)
-#define HEIMDAL_MUTEX_unlock(m) do { (void)(m); } while(0)
-#define HEIMDAL_MUTEX_destroy(m) do { (void)(m); } while(0)
-
-#define HEIMDAL_RWLOCK rwlock_t int
-#define HEIMDAL_RWLOCK_INITIALIZER 0
-#define HEIMDAL_RWLOCK_init(l) do { } while(0)
-#define HEIMDAL_RWLOCK_rdlock(l) do { } while(0)
-#define HEIMDAL_RWLOCK_wrlock(l) do { } while(0)
-#define HEIMDAL_RWLOCK_tryrdlock(l) do { } while(0)
-#define HEIMDAL_RWLOCK_trywrlock(l) do { } while(0)
-#define HEIMDAL_RWLOCK_unlock(l) do { } while(0)
-#define HEIMDAL_RWLOCK_destroy(l) do { } while(0)
-
-#define HEIMDAL_internal_thread_key 1
-
-#endif /* no thread support */
-
-#ifdef HEIMDAL_internal_thread_key
-
-typedef struct heim_thread_key {
- void *value;
- void (*destructor)(void *);
-} heim_thread_key;
-
-#define HEIMDAL_thread_key heim_thread_key
-#define HEIMDAL_key_create(k,d,r) \
- do { (k)->value = NULL; (k)->destructor = (d); r = 0; } while(0)
-#define HEIMDAL_setspecific(k,s,r) do { (k).value = s ; r = 0; } while(0)
-#define HEIMDAL_getspecific(k) ((k).value)
-#define HEIMDAL_key_delete(k) do { (*(k).destructor)((k).value); } while(0)
-
-#undef HEIMDAL_internal_thread_key
-#endif /* HEIMDAL_internal_thread_key */
-
-#endif /* HEIM_THREADS_H */
diff --git a/source4/heimdal/lib/krb5/init_creds.c b/source4/heimdal/lib/krb5/init_creds.c
index 89ea3004ed..b1bd94d3b9 100644
--- a/source4/heimdal/lib/krb5/init_creds.c
+++ b/source4/heimdal/lib/krb5/init_creds.c
@@ -36,14 +36,19 @@
#undef __attribute__
#define __attribute__(x)
-RCSID("$Id$");
+/**
+ * @page krb5_init_creds_intro The initial credential handing functions
+ * @section section_krb5_init_creds Initial credential
+ *
+ * Functions to get initial credentials: @ref krb5_credential .
+ */
-void KRB5_LIB_FUNCTION
-krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt)
- __attribute__((deprecated))
-{
- memset (opt, 0, sizeof(*opt));
-}
+/**
+ * Allocate a new krb5_get_init_creds_opt structure, free with
+ * krb5_get_init_creds_opt_free().
+ *
+ * @ingroup krb5_credential
+ */
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_init_creds_opt_alloc(krb5_context context,
@@ -71,67 +76,11 @@ krb5_get_init_creds_opt_alloc(krb5_context context,
return 0;
}
-krb5_error_code
-_krb5_get_init_creds_opt_copy(krb5_context context,
- const krb5_get_init_creds_opt *in,
- krb5_get_init_creds_opt **out)
-{
- krb5_get_init_creds_opt *opt;
-
- *out = NULL;
- opt = calloc(1, sizeof(*opt));
- if (opt == NULL) {
- krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
- return ENOMEM;
- }
- if (in)
- *opt = *in;
- if(opt->opt_private == NULL) {
- opt->opt_private = calloc(1, sizeof(*opt->opt_private));
- if (opt->opt_private == NULL) {
- krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
- free(opt);
- return ENOMEM;
- }
- opt->opt_private->refcount = 1;
- } else
- opt->opt_private->refcount++;
- *out = opt;
- return 0;
-}
-
-void KRB5_LIB_FUNCTION
-_krb5_get_init_creds_opt_free_krb5_error(krb5_get_init_creds_opt *opt)
-{
- if (opt->opt_private == NULL || opt->opt_private->error == NULL)
- return;
- free_KRB_ERROR(opt->opt_private->error);
- free(opt->opt_private->error);
- opt->opt_private->error = NULL;
-}
-
-void KRB5_LIB_FUNCTION
-_krb5_get_init_creds_opt_set_krb5_error(krb5_context context,
- krb5_get_init_creds_opt *opt,
- const KRB_ERROR *error)
-{
- krb5_error_code ret;
-
- if (opt->opt_private == NULL)
- return;
-
- _krb5_get_init_creds_opt_free_krb5_error(opt);
-
- opt->opt_private->error = malloc(sizeof(*opt->opt_private->error));
- if (opt->opt_private->error == NULL)
- return;
- ret = copy_KRB_ERROR(error, opt->opt_private->error);
- if (ret) {
- free(opt->opt_private->error);
- opt->opt_private->error = NULL;
- }
-}
-
+/**
+ * Free krb5_get_init_creds_opt structure.
+ *
+ * @ingroup krb5_credential
+ */
void KRB5_LIB_FUNCTION
krb5_get_init_creds_opt_free(krb5_context context,
@@ -142,7 +91,6 @@ krb5_get_init_creds_opt_free(krb5_context context,
if (opt->opt_private->refcount < 1) /* abort ? */
return;
if (--opt->opt_private->refcount == 0) {
- _krb5_get_init_creds_opt_free_krb5_error(opt);
_krb5_get_init_creds_opt_free_pkinit(opt);
free(opt->opt_private);
}
@@ -369,35 +317,6 @@ krb5_get_init_creds_opt_set_pac_request(krb5_context context,
}
krb5_error_code KRB5_LIB_FUNCTION
-krb5_get_init_creds_opt_get_error(krb5_context context,
- krb5_get_init_creds_opt *opt,
- KRB_ERROR **error)
-{
- krb5_error_code ret;
-
- *error = NULL;
-
- ret = require_ext_opt(context, opt, "init_creds_opt_get_error");
- if (ret)
- return ret;
-
- if (opt->opt_private->error == NULL)
- return 0;
-
- *error = malloc(sizeof(**error));
- if (*error == NULL) {
- krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
- return ENOMEM;
- }
-
- ret = copy_KRB_ERROR(opt->opt_private->error, *error);
- if (ret)
- krb5_clear_error_message(context);
-
- return 0;
-}
-
-krb5_error_code KRB5_LIB_FUNCTION
krb5_get_init_creds_opt_set_addressless(krb5_context context,
krb5_get_init_creds_opt *opt,
krb5_boolean addressless)
@@ -445,3 +364,54 @@ krb5_get_init_creds_opt_set_win2k(krb5_context context,
return 0;
}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_init_creds_opt_set_process_last_req(krb5_context context,
+ krb5_get_init_creds_opt *opt,
+ krb5_gic_process_last_req func,
+ void *ctx)
+{
+ krb5_error_code ret;
+ ret = require_ext_opt(context, opt, "init_creds_opt_set_win2k");
+ if (ret)
+ return ret;
+
+ opt->opt_private->lr.func = func;
+ opt->opt_private->lr.ctx = ctx;
+
+ return 0;
+}
+
+
+#ifndef HEIMDAL_SMALLER
+
+void KRB5_LIB_FUNCTION
+krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt)
+ KRB5_DEPRECATED
+{
+ memset (opt, 0, sizeof(*opt));
+}
+
+/**
+ * Deprecated: use the new krb5_init_creds_init() and
+ * krb5_init_creds_get_error().
+ *
+ * @ingroup krb5_deprecated
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_init_creds_opt_get_error(krb5_context context,
+ krb5_get_init_creds_opt *opt,
+ KRB_ERROR **error)
+ KRB5_DEPRECATED
+{
+ *error = calloc(1, sizeof(**error));
+ if (*error == NULL) {
+ krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
+ return ENOMEM;
+ }
+
+ return 0;
+}
+
+#endif /* HEIMDAL_SMALLER */
diff --git a/source4/heimdal/lib/krb5/init_creds_pw.c b/source4/heimdal/lib/krb5/init_creds_pw.c
index 0b75522e9d..0435ab5d3b 100644
--- a/source4/heimdal/lib/krb5/init_creds_pw.c
+++ b/source4/heimdal/lib/krb5/init_creds_pw.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997 - 2007 Kungliga Tekniska Högskolan
+ * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -33,15 +33,13 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
typedef struct krb5_get_init_creds_ctx {
KDCOptions flags;
krb5_creds cred;
krb5_addresses *addrs;
krb5_enctype *etypes;
krb5_preauthtype *pre_auth_types;
- const char *in_tkt_service;
+ char *in_tkt_service;
unsigned nonce;
unsigned pk_nonce;
@@ -49,13 +47,26 @@ typedef struct krb5_get_init_creds_ctx {
AS_REQ as_req;
int pa_counter;
- const char *password;
- krb5_s2k_proc key_proc;
+ /* password and keytab_data is freed on completion */
+ char *password;
+ krb5_keytab_key_proc_args *keytab_data;
+
+ krb5_pointer *keyseed;
+ krb5_s2k_proc keyproc;
krb5_get_init_creds_tristate req_pac;
krb5_pk_init_ctx pk_init_ctx;
int ic_flags;
+
+ METHOD_DATA md;
+ KRB_ERROR error;
+ AS_REP as_rep;
+ EncKDCRepPart enc_part;
+
+ krb5_prompter_fct prompter;
+ void *prompter_data;
+
} krb5_get_init_creds_ctx;
static krb5_error_code
@@ -74,7 +85,7 @@ default_s2k_func(krb5_context context, krb5_enctype type,
opaque = *s2kparms;
else
krb5_data_zero(&opaque);
-
+
*key = malloc(sizeof(**key));
if (*key == NULL)
return ENOMEM;
@@ -88,14 +99,24 @@ default_s2k_func(krb5_context context, krb5_enctype type,
}
static void
-free_init_creds_ctx(krb5_context context, krb5_get_init_creds_ctx *ctx)
+free_init_creds_ctx(krb5_context context, krb5_init_creds_context ctx)
{
if (ctx->etypes)
free(ctx->etypes);
if (ctx->pre_auth_types)
free (ctx->pre_auth_types);
+ if (ctx->in_tkt_service)
+ free(ctx->in_tkt_service);
+ if (ctx->keytab_data)
+ free(ctx->keytab_data);
+ krb5_data_free(&ctx->req_buffer);
+ krb5_free_cred_contents(context, &ctx->cred);
+ free_METHOD_DATA(&ctx->md);
+ free_AS_REP(&ctx->as_rep);
+ free_EncKDCRepPart(&ctx->enc_part);
+ free_KRB_ERROR(&ctx->error);
free_AS_REQ(&ctx->as_req);
- memset(&ctx->as_req, 0, sizeof(ctx->as_req));
+ memset(ctx, 0, sizeof(*ctx));
}
static int
@@ -127,11 +148,9 @@ init_cred (krb5_context context,
krb5_creds *cred,
krb5_principal client,
krb5_deltat start_time,
- const char *in_tkt_service,
krb5_get_init_creds_opt *options)
{
krb5_error_code ret;
- krb5_const_realm client_realm;
int tmp;
krb5_timestamp now;
@@ -148,8 +167,6 @@ init_cred (krb5_context context,
goto out;
}
- client_realm = krb5_principal_get_realm (context, cred->client);
-
if (start_time)
cred->times.starttime = now + start_time;
@@ -164,18 +181,6 @@ init_cred (krb5_context context,
cred->times.renew_till = now + options->renew_life;
}
- if (in_tkt_service) {
- ret = krb5_parse_name (context, in_tkt_service, &cred->server);
- if (ret)
- goto out;
- krb5_principal_set_realm (context, cred->server, client_realm);
- } else {
- ret = krb5_make_principal(context, &cred->server,
- client_realm, KRB5_TGS_NAME, client_realm,
- NULL);
- if (ret)
- goto out;
- }
return 0;
out:
@@ -195,28 +200,71 @@ report_expiration (krb5_context context,
time_t now)
{
char *p;
-
+
asprintf (&p, "%s%s", str, ctime(&now));
(*prompter) (context, data, NULL, p, 0, NULL);
free (p);
}
/*
- * Parse the last_req data and show it to the user if it's interesting
+ * Check the context, and in the case there is a expiration warning,
+ * use the prompter to print the warning.
+ *
+ * @param context A Kerberos 5 context.
+ * @param options An GIC options structure
+ * @param ctx The krb5_init_creds_context check for expiration.
*/
-static void
-print_expire (krb5_context context,
- krb5_const_realm realm,
- krb5_kdc_rep *rep,
- krb5_prompter_fct prompter,
- krb5_data *data)
+static krb5_error_code
+process_last_request(krb5_context context,
+ krb5_get_init_creds_opt *options,
+ krb5_init_creds_context ctx)
{
- int i;
- LastReq *lr = &rep->enc_part.last_req;
+ krb5_const_realm realm;
+ LastReq *lr;
+ krb5_boolean reported = FALSE;
krb5_timestamp sec;
time_t t;
- krb5_boolean reported = FALSE;
+ size_t i;
+
+ /*
+ * First check if there is a API consumer.
+ */
+
+ realm = krb5_principal_get_realm (context, ctx->cred.client);
+ lr = &ctx->enc_part.last_req;
+
+ if (options && options->opt_private && options->opt_private->lr.func) {
+ krb5_last_req_entry **lre;
+
+ lre = calloc(lr->len + 1, sizeof(**lre));
+ if (lre == NULL) {
+ krb5_set_error_message(context, ENOMEM,
+ N_("malloc: out of memory", ""));
+ return ENOMEM;
+ }
+ for (i = 0; i < lr->len; i++) {
+ lre[i] = calloc(1, sizeof(*lre[i]));
+ if (lre[i] == NULL)
+ break;
+ lre[i]->lr_type = lr->val[i].lr_type;
+ lre[i]->value = lr->val[i].lr_value;
+ }
+
+ (*options->opt_private->lr.func)(context, lre,
+ options->opt_private->lr.ctx);
+
+ for (i = 0; i < lr->len; i++)
+ free(lre[i]);
+ free(lre);
+ }
+
+ /*
+ * Now check if we should prompt the user
+ */
+
+ if (ctx->prompter == NULL)
+ return 0;
krb5_timeofday (context, &sec);
@@ -229,13 +277,15 @@ print_expire (krb5_context context,
if (lr->val[i].lr_value <= t) {
switch (abs(lr->val[i].lr_type)) {
case LR_PW_EXPTIME :
- report_expiration(context, prompter, data,
+ report_expiration(context, ctx->prompter,
+ ctx->prompter_data,
"Your password will expire at ",
lr->val[i].lr_value);
reported = TRUE;
break;
case LR_ACCT_EXPTIME :
- report_expiration(context, prompter, data,
+ report_expiration(context, ctx->prompter,
+ ctx->prompter_data,
"Your account will expire at ",
lr->val[i].lr_value);
reported = TRUE;
@@ -245,12 +295,14 @@ print_expire (krb5_context context,
}
if (!reported
- && rep->enc_part.key_expiration
- && *rep->enc_part.key_expiration <= t) {
- report_expiration(context, prompter, data,
+ && ctx->enc_part.key_expiration
+ && *ctx->enc_part.key_expiration <= t) {
+ report_expiration(context, ctx->prompter,
+ ctx->prompter_data,
"Your password/account will expire at ",
- *rep->enc_part.key_expiration);
+ *ctx->enc_part.key_expiration);
}
+ return 0;
}
static krb5_addresses no_addrs = { 0, NULL };
@@ -259,11 +311,10 @@ static krb5_error_code
get_init_creds_common(krb5_context context,
krb5_principal client,
krb5_deltat start_time,
- const char *in_tkt_service,
krb5_get_init_creds_opt *options,
- krb5_get_init_creds_ctx *ctx)
+ krb5_init_creds_context ctx)
{
- krb5_get_init_creds_opt default_opt;
+ krb5_get_init_creds_opt *default_opt = NULL;
krb5_error_code ret;
krb5_enctype *etypes;
krb5_preauthtype *pre_auth_types;
@@ -271,37 +322,51 @@ get_init_creds_common(krb5_context context,
memset(ctx, 0, sizeof(*ctx));
if (options == NULL) {
- krb5_get_init_creds_opt_init (&default_opt);
- options = &default_opt;
- } else {
- _krb5_get_init_creds_opt_free_krb5_error(options);
+ const char *realm = krb5_principal_get_realm(context, client);
+
+ krb5_get_init_creds_opt_alloc (context, &default_opt);
+ options = default_opt;
+ krb5_get_init_creds_opt_set_default_flags(context, NULL, realm, options);
}
if (options->opt_private) {
- ctx->password = options->opt_private->password;
- ctx->key_proc = options->opt_private->key_proc;
+ if (options->opt_private->password) {
+ ret = krb5_init_creds_set_password(context, ctx,
+ options->opt_private->password);
+ if (ret)
+ goto out;
+ }
+
+ ctx->keyproc = options->opt_private->key_proc;
ctx->req_pac = options->opt_private->req_pac;
ctx->pk_init_ctx = options->opt_private->pk_init_ctx;
ctx->ic_flags = options->opt_private->flags;
} else
ctx->req_pac = KRB5_INIT_CREDS_TRISTATE_UNSET;
- if (ctx->key_proc == NULL)
- ctx->key_proc = default_s2k_func;
+ if (ctx->keyproc == NULL)
+ ctx->keyproc = default_s2k_func;
- if (ctx->ic_flags & KRB5_INIT_CREDS_CANONICALIZE)
+ /* Enterprise name implicitly turns on canonicalize */
+ if ((ctx->ic_flags & KRB5_INIT_CREDS_CANONICALIZE) ||
+ krb5_principal_get_type(context, client) == KRB5_NT_ENTERPRISE_PRINCIPAL)
ctx->flags.canonicalize = 1;
ctx->pre_auth_types = NULL;
ctx->addrs = NULL;
ctx->etypes = NULL;
ctx->pre_auth_types = NULL;
- ctx->in_tkt_service = in_tkt_service;
- ret = init_cred (context, &ctx->cred, client, start_time,
- in_tkt_service, options);
- if (ret)
+ ret = init_cred(context, &ctx->cred, client, start_time, options);
+ if (ret) {
+ if (default_opt)
+ krb5_get_init_creds_opt_free(context, default_opt);
return ret;
+ }
+
+ ret = krb5_init_creds_set_service(context, ctx, NULL);
+ if (ret)
+ goto out;
if (options->flags & KRB5_GET_INIT_CREDS_OPT_FORWARDABLE)
ctx->flags.forwardable = options->forwardable;
@@ -336,8 +401,9 @@ get_init_creds_common(krb5_context context,
etypes = malloc((options->etype_list_length + 1)
* sizeof(krb5_enctype));
if (etypes == NULL) {
- krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
- return ENOMEM;
+ ret = ENOMEM;
+ krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
+ goto out;
}
memcpy (etypes, options->etype_list,
options->etype_list_length * sizeof(krb5_enctype));
@@ -348,19 +414,24 @@ get_init_creds_common(krb5_context context,
pre_auth_types = malloc((options->preauth_list_length + 1)
* sizeof(krb5_preauthtype));
if (pre_auth_types == NULL) {
- krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
- return ENOMEM;
+ ret = ENOMEM;
+ krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
+ goto out;
}
memcpy (pre_auth_types, options->preauth_list,
options->preauth_list_length * sizeof(krb5_preauthtype));
pre_auth_types[options->preauth_list_length] = KRB5_PADATA_NONE;
ctx->pre_auth_types = pre_auth_types;
}
- if (options->flags & KRB5_GET_INIT_CREDS_OPT_SALT)
- ; /* XXX */
if (options->flags & KRB5_GET_INIT_CREDS_OPT_ANONYMOUS)
ctx->flags.request_anonymous = options->anonymous;
+ if (default_opt)
+ krb5_get_init_creds_opt_free(context, default_opt);
return 0;
+ out:
+ if (default_opt)
+ krb5_get_init_creds_opt_free(context, default_opt);
+ return ret;
}
static krb5_error_code
@@ -382,18 +453,20 @@ change_password (krb5_context context,
krb5_data result_code_string;
krb5_data result_string;
char *p;
- krb5_get_init_creds_opt options;
+ krb5_get_init_creds_opt *options;
memset (&cpw_cred, 0, sizeof(cpw_cred));
- krb5_get_init_creds_opt_init (&options);
- krb5_get_init_creds_opt_set_tkt_life (&options, 60);
- krb5_get_init_creds_opt_set_forwardable (&options, FALSE);
- krb5_get_init_creds_opt_set_proxiable (&options, FALSE);
+ ret = krb5_get_init_creds_opt_alloc(context, &options);
+ if (ret)
+ return ret;
+ krb5_get_init_creds_opt_set_tkt_life (options, 60);
+ krb5_get_init_creds_opt_set_forwardable (options, FALSE);
+ krb5_get_init_creds_opt_set_proxiable (options, FALSE);
if (old_options && old_options->flags & KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST)
- krb5_get_init_creds_opt_set_preauth_list (&options,
+ krb5_get_init_creds_opt_set_preauth_list (options,
old_options->preauth_list,
- old_options->preauth_list_length);
+ old_options->preauth_list_length);
krb5_data_zero (&result_code_string);
krb5_data_zero (&result_string);
@@ -406,7 +479,8 @@ change_password (krb5_context context,
data,
0,
"kadmin/changepw",
- &options);
+ options);
+ krb5_get_init_creds_opt_free(context, options);
if (ret)
goto out;
@@ -455,7 +529,9 @@ change_password (krb5_context context,
(int)result_string.length,
result_string.length > 0 ? (char*)result_string.data : "");
- ret = (*prompter) (context, data, NULL, p, 0, NULL);
+ /* return the result */
+ (*prompter) (context, data, NULL, p, 0, NULL);
+
free (p);
if (result_code == 0) {
strlcpy (newpw, buf1, newpw_sz);
@@ -475,6 +551,7 @@ out:
return ret;
}
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_keyblock_key_proc (krb5_context context,
krb5_keytype type,
@@ -485,68 +562,17 @@ krb5_keyblock_key_proc (krb5_context context,
return krb5_copy_keyblock (context, keyseed, key);
}
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_get_init_creds_keytab(krb5_context context,
- krb5_creds *creds,
- krb5_principal client,
- krb5_keytab keytab,
- krb5_deltat start_time,
- const char *in_tkt_service,
- krb5_get_init_creds_opt *options)
-{
- krb5_get_init_creds_ctx ctx;
- krb5_error_code ret;
- krb5_keytab_key_proc_args *a;
-
- ret = get_init_creds_common(context, client, start_time,
- in_tkt_service, options, &ctx);
- if (ret)
- goto out;
-
- a = malloc (sizeof(*a));
- if (a == NULL) {
- ret = ENOMEM;
- krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
- goto out;
- }
- a->principal = ctx.cred.client;
- a->keytab = keytab;
-
- ret = krb5_get_in_cred (context,
- KDCOptions2int(ctx.flags),
- ctx.addrs,
- ctx.etypes,
- ctx.pre_auth_types,
- NULL,
- krb5_keytab_key_proc,
- a,
- NULL,
- NULL,
- &ctx.cred,
- NULL);
- free (a);
-
- if (ret == 0 && creds)
- *creds = ctx.cred;
- else
- krb5_free_cred_contents (context, &ctx.cred);
-
- out:
- free_init_creds_ctx(context, &ctx);
- return ret;
-}
-
/*
*
*/
static krb5_error_code
-init_creds_init_as_req (krb5_context context,
- KDCOptions opts,
- const krb5_creds *creds,
- const krb5_addresses *addrs,
- const krb5_enctype *etypes,
- AS_REQ *a)
+init_as_req (krb5_context context,
+ KDCOptions opts,
+ const krb5_creds *creds,
+ const krb5_addresses *addrs,
+ const krb5_enctype *etypes,
+ AS_REQ *a)
{
krb5_error_code ret;
@@ -906,7 +932,7 @@ make_pa_enc_timestamp(krb5_context context, METHOD_DATA *md,
krb5_crypto_destroy(context, crypto);
if (ret)
return ret;
-
+
ASN1_MALLOC_ENCODE(EncryptedData, buf, buf_size, &encdata, &len, ret);
free_EncryptedData(&encdata);
if (ret)
@@ -924,7 +950,7 @@ static krb5_error_code
add_enc_ts_padata(krb5_context context,
METHOD_DATA *md,
krb5_principal client,
- krb5_s2k_proc key_proc,
+ krb5_s2k_proc keyproc,
krb5_const_pointer keyseed,
krb5_enctype *enctypes,
unsigned netypes,
@@ -939,6 +965,8 @@ add_enc_ts_padata(krb5_context context,
if(salt == NULL) {
/* default to standard salt */
ret = krb5_get_pw_salt (context, client, &salt2);
+ if (ret)
+ return ret;
salt = &salt2;
}
if (!enctypes) {
@@ -951,8 +979,8 @@ add_enc_ts_padata(krb5_context context,
for (i = 0; i < netypes; ++i) {
krb5_keyblock *key;
- ret = (*key_proc)(context, enctypes[i], keyseed,
- *salt, s2kparams, &key);
+ ret = (*keyproc)(context, enctypes[i], keyseed,
+ *salt, s2kparams, &key);
if (ret)
continue;
ret = make_pa_enc_timestamp (context, md, enctypes[i], key);
@@ -973,28 +1001,28 @@ pa_data_to_md_ts_enc(krb5_context context,
struct pa_info_data *ppaid,
METHOD_DATA *md)
{
- if (ctx->key_proc == NULL || ctx->password == NULL)
+ if (ctx->keyproc == NULL || ctx->keyseed == NULL)
return 0;
if (ppaid) {
add_enc_ts_padata(context, md, client,
- ctx->key_proc, ctx->password,
+ ctx->keyproc, ctx->keyseed,
&ppaid->etype, 1,
&ppaid->salt, ppaid->s2kparams);
} else {
krb5_salt salt;
-
+
/* make a v5 salted pa-data */
add_enc_ts_padata(context, md, client,
- ctx->key_proc, ctx->password,
+ ctx->keyproc, ctx->keyseed,
a->req_body.etype.val, a->req_body.etype.len,
NULL, NULL);
-
+
/* make a v4 salted pa-data */
salt.salttype = KRB5_PW_SALT;
krb5_data_zero(&salt.saltvalue);
add_enc_ts_padata(context, md, client,
- ctx->key_proc, ctx->password,
+ ctx->keyproc, ctx->keyseed,
a->req_body.etype.val, a->req_body.etype.len,
&salt, NULL);
}
@@ -1012,7 +1040,7 @@ pa_data_to_key_plain(krb5_context context,
{
krb5_error_code ret;
- ret = (*ctx->key_proc)(context, etype, ctx->password,
+ ret = (*ctx->keyproc)(context, etype, ctx->keyseed,
salt, s2kparams, key);
return ret;
}
@@ -1058,7 +1086,7 @@ pa_data_add_pac_request(krb5_context context,
break;
case KRB5_INIT_CREDS_TRISTATE_FALSE:
req.include_pac = 0;
- }
+ }
ASN1_MALLOC_ENCODE(PA_PAC_REQUEST, buf, length,
&req, &len, ret);
@@ -1111,12 +1139,12 @@ process_pa_data_to_md(krb5_context context,
} 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);
@@ -1137,7 +1165,7 @@ process_pa_data_to_key(krb5_context context,
krb5_get_init_creds_ctx *ctx,
krb5_creds *creds,
AS_REQ *a,
- krb5_kdc_rep *rep,
+ AS_REP *rep,
const krb5_krbhst_info *hi,
krb5_keyblock **key)
{
@@ -1148,12 +1176,12 @@ process_pa_data_to_key(krb5_context context,
memset(&paid, 0, sizeof(paid));
- etype = rep->kdc_rep.enc_part.etype;
+ etype = rep->enc_part.etype;
- if (rep->kdc_rep.padata) {
+ if (rep->padata) {
paid.etype = etype;
ppaid = process_pa_info(context, creds->client, a, &paid,
- rep->kdc_rep.padata);
+ rep->padata);
}
if (ppaid == NULL) {
ret = krb5_get_pw_salt (context, creds->client, &paid.salt);
@@ -1164,16 +1192,16 @@ process_pa_data_to_key(krb5_context context,
}
pa = NULL;
- if (rep->kdc_rep.padata) {
+ if (rep->padata) {
int idx = 0;
- pa = krb5_find_padata(rep->kdc_rep.padata->val,
- rep->kdc_rep.padata->len,
+ pa = krb5_find_padata(rep->padata->val,
+ rep->padata->len,
KRB5_PADATA_PK_AS_REP,
&idx);
if (pa == NULL) {
idx = 0;
- pa = krb5_find_padata(rep->kdc_rep.padata->val,
- rep->kdc_rep.padata->len,
+ pa = krb5_find_padata(rep->padata->val,
+ rep->padata->len,
KRB5_PADATA_PK_AS_REP_19,
&idx);
}
@@ -1193,7 +1221,7 @@ process_pa_data_to_key(krb5_context context,
ret = EINVAL;
krb5_set_error_message(context, ret, N_("no support for PKINIT compiled in", ""));
#endif
- } else if (ctx->password)
+ } else if (ctx->keyseed)
ret = pa_data_to_key_plain(context, creds->client, ctx,
paid.salt, paid.s2kparams, etype, key);
else {
@@ -1205,109 +1233,340 @@ process_pa_data_to_key(krb5_context context,
return ret;
}
-static krb5_error_code
-init_cred_loop(krb5_context context,
- krb5_get_init_creds_opt *init_cred_opts,
- const krb5_prompter_fct prompter,
- void *prompter_data,
- krb5_get_init_creds_ctx *ctx,
- krb5_creds *creds,
- krb5_kdc_rep *ret_as_reply)
+/**
+ * Start a new context to get a new initial credential.
+ *
+ * @param context A Kerberos 5 context.
+ * @param client The Kerberos principal to get the credential for, if
+ * NULL is given, the default principal is used as determined by
+ * krb5_get_default_principal().
+ * @param prompter
+ * @param prompter_data
+ * @param start_time the time the ticket should start to be valid or 0 for now.
+ * @param options a options structure, can be NULL for default options.
+ * @param rctx A new allocated free with krb5_init_creds_free().
+ *
+ * @return 0 for success or an Kerberos 5 error code, see krb5_get_error_message().
+ *
+ * @ingroup krb5_credential
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_init_creds_init(krb5_context context,
+ krb5_principal client,
+ krb5_prompter_fct prompter,
+ void *prompter_data,
+ krb5_deltat start_time,
+ krb5_get_init_creds_opt *options,
+ krb5_init_creds_context *rctx)
{
+ krb5_init_creds_context ctx;
krb5_error_code ret;
- krb5_kdc_rep rep;
- METHOD_DATA md;
- krb5_data resp;
- size_t len;
- size_t size;
- krb5_krbhst_info *hi = NULL;
- krb5_sendto_ctx stctx = NULL;
-
- memset(&md, 0, sizeof(md));
- memset(&rep, 0, sizeof(rep));
+ *rctx = NULL;
- _krb5_get_init_creds_opt_free_krb5_error(init_cred_opts);
-
- if (ret_as_reply)
- memset(ret_as_reply, 0, sizeof(*ret_as_reply));
+ ctx = calloc(1, sizeof(*ctx));
+ if (ctx == NULL) {
+ krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
+ return ENOMEM;
+ }
- ret = init_creds_init_as_req(context, ctx->flags, creds,
- ctx->addrs, ctx->etypes, &ctx->as_req);
- if (ret)
+ ret = get_init_creds_common(context, client, start_time, options, ctx);
+ if (ret) {
+ free(ctx);
return ret;
-
- ret = krb5_sendto_ctx_alloc(context, &stctx);
- if (ret)
- goto out;
- krb5_sendto_ctx_set_func(stctx, _krb5_kdc_retry, NULL);
+ }
/* Set a new nonce. */
krb5_generate_random_block (&ctx->nonce, sizeof(ctx->nonce));
- ctx->nonce &= 0xffffffff;
+ ctx->nonce &= 0x7fffffff;
/* XXX these just needs to be the same when using Windows PK-INIT */
ctx->pk_nonce = ctx->nonce;
- /*
- * Increase counter when we want other pre-auth types then
- * KRB5_PA_ENC_TIMESTAMP.
- */
-#define MAX_PA_COUNTER 3
+ ctx->prompter = prompter;
+ ctx->prompter_data = prompter_data;
- ctx->pa_counter = 0;
- while (ctx->pa_counter < MAX_PA_COUNTER) {
+ *rctx = ctx;
- ctx->pa_counter++;
+ return ret;
+}
- if (ctx->as_req.padata) {
- free_METHOD_DATA(ctx->as_req.padata);
- free(ctx->as_req.padata);
- ctx->as_req.padata = NULL;
- }
+/**
+ * Sets the service that the is requested. This call is only neede for
+ * special initial tickets, by default the a krbtgt is fetched in the default realm.
+ *
+ * @param context a Kerberos 5 context.
+ * @param ctx a krb5_init_creds_context context.
+ * @param service the service given as a string, for example
+ * "kadmind/admin". If NULL, the default krbtgt in the clients
+ * realm is set.
+ *
+ * @return 0 for success, or an Kerberos 5 error code, see krb5_get_error_message().
+ * @ingroup krb5_credential
+ */
- /* Set a new nonce. */
- ctx->as_req.req_body.nonce = ctx->nonce;
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_init_creds_set_service(krb5_context context,
+ krb5_init_creds_context ctx,
+ const char *service)
+{
+ krb5_const_realm client_realm;
+ krb5_principal principal;
+ krb5_error_code ret;
+
+ client_realm = krb5_principal_get_realm (context, ctx->cred.client);
- /* fill_in_md_data */
- ret = process_pa_data_to_md(context, creds, &ctx->as_req, ctx,
- &md, &ctx->as_req.padata,
- prompter, prompter_data);
+ if (service) {
+ ret = krb5_parse_name (context, service, &principal);
if (ret)
- goto out;
+ return ret;
+ krb5_principal_set_realm (context, principal, client_realm);
+ } else {
+ ret = krb5_make_principal(context, &principal,
+ client_realm, KRB5_TGS_NAME, client_realm,
+ NULL);
+ if (ret)
+ return ret;
+ }
+ krb5_free_principal(context, ctx->cred.server);
+ ctx->cred.server = principal;
- krb5_data_free(&ctx->req_buffer);
+ return 0;
+}
- ASN1_MALLOC_ENCODE(AS_REQ,
- ctx->req_buffer.data, ctx->req_buffer.length,
- &ctx->as_req, &len, ret);
- if (ret)
- goto out;
- if(len != ctx->req_buffer.length)
- krb5_abortx(context, "internal error in ASN.1 encoder");
+/**
+ * Sets the password that will use for the request.
+ *
+ * @param context a Kerberos 5 context.
+ * @param ctx ctx krb5_init_creds_context context.
+ * @param password the password to use.
+ *
+ * @return 0 for success, or an Kerberos 5 error code, see krb5_get_error_message().
+ * @ingroup krb5_credential
+ */
- ret = krb5_sendto_context (context, stctx, &ctx->req_buffer,
- creds->client->realm, &resp);
- if (ret)
- goto out;
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_init_creds_set_password(krb5_context context,
+ krb5_init_creds_context ctx,
+ const char *password)
+{
+ if (ctx->password)
+ memset(ctx->password, 0, strlen(ctx->password));
+ if (password) {
+ ctx->password = strdup(password);
+ if (ctx->password == NULL) {
+ krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
+ return ENOMEM;
+ }
+ ctx->keyseed = (void *) ctx->password;
+ } else {
+ ctx->keyseed = NULL;
+ ctx->password = NULL;
+ }
+
+ return 0;
+}
+
+static krb5_error_code
+keytab_key_proc(krb5_context context, krb5_enctype enctype,
+ krb5_const_pointer keyseed,
+ krb5_salt salt, krb5_data *s2kparms,
+ krb5_keyblock **key)
+{
+ krb5_keytab_key_proc_args *args = rk_UNCONST(keyseed);
+ krb5_keytab keytab = args->keytab;
+ krb5_principal principal = args->principal;
+ krb5_error_code ret;
+ krb5_keytab real_keytab;
+ krb5_keytab_entry entry;
+
+ if(keytab == NULL)
+ krb5_kt_default(context, &real_keytab);
+ else
+ real_keytab = keytab;
+
+ ret = krb5_kt_get_entry (context, real_keytab, principal,
+ 0, enctype, &entry);
+
+ if (keytab == NULL)
+ krb5_kt_close (context, real_keytab);
+
+ if (ret)
+ return ret;
+
+ ret = krb5_copy_keyblock (context, &entry.keyblock, key);
+ krb5_kt_free_entry(context, &entry);
+ return ret;
+}
+
+
+/**
+ * Set the keytab to use for authentication.
+ *
+ * @param context a Kerberos 5 context.
+ * @param ctx ctx krb5_init_creds_context context.
+ * @param keytab the keytab to read the key from.
+ *
+ * @return 0 for success, or an Kerberos 5 error code, see krb5_get_error_message().
+ * @ingroup krb5_credential
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_init_creds_set_keytab(krb5_context context,
+ krb5_init_creds_context ctx,
+ krb5_keytab keytab)
+{
+ krb5_keytab_key_proc_args *a;
+
+ a = malloc(sizeof(*a));
+ if (a == NULL) {
+ krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
+ return ENOMEM;
+ }
+
+ a->principal = ctx->cred.client;
+ a->keytab = keytab;
+
+ ctx->keytab_data = a;
+ ctx->keyseed = (void *)a;
+ ctx->keyproc = keytab_key_proc;
+
+ return 0;
+}
+
+static krb5_error_code
+keyblock_key_proc(krb5_context context, krb5_enctype enctype,
+ krb5_const_pointer keyseed,
+ krb5_salt salt, krb5_data *s2kparms,
+ krb5_keyblock **key)
+{
+ return krb5_copy_keyblock (context, keyseed, key);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_init_creds_set_keyblock(krb5_context context,
+ krb5_init_creds_context ctx,
+ krb5_keyblock *keyblock)
+{
+ ctx->keyseed = (void *)keyblock;
+ ctx->keyproc = keyblock_key_proc;
+
+ return 0;
+}
+
+/**
+ * The core loop if krb5_get_init_creds() function family. Create the
+ * packets and have the caller send them off to the KDC.
+ *
+ * If the caller want all work been done for them, use
+ * krb5_init_creds_get() instead.
+ *
+ * @param context a Kerberos 5 context.
+ * @param ctx ctx krb5_init_creds_context context.
+ * @param in input data from KDC, first round it should be reset by krb5_data_zer().
+ * @param out reply to KDC.
+ * @param hostinfo KDC address info, first round it can be NULL.
+ * @param flags status of the round, if 1 is set, continue one more round.
+ *
+ * @return 0 for success, or an Kerberos 5 error code, see
+ * krb5_get_error_message().
+ *
+ * @ingroup krb5_credential
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_init_creds_step(krb5_context context,
+ krb5_init_creds_context ctx,
+ krb5_data *in,
+ krb5_data *out,
+ krb5_krbhst_info *hostinfo,
+ unsigned int *flags)
+{
+ krb5_error_code ret;
+ size_t len;
+ size_t size;
- memset (&rep, 0, sizeof(rep));
- ret = decode_AS_REP(resp.data, resp.length, &rep.kdc_rep, &size);
+ krb5_data_zero(out);
+
+ if (ctx->as_req.req_body.cname == NULL) {
+ ret = init_as_req(context, ctx->flags, &ctx->cred,
+ ctx->addrs, ctx->etypes, &ctx->as_req);
+ if (ret) {
+ free_init_creds_ctx(context, ctx);
+ return ret;
+ }
+ }
+
+#define MAX_PA_COUNTER 10
+ if (ctx->pa_counter > MAX_PA_COUNTER) {
+ krb5_set_error_message(context, KRB5_GET_IN_TKT_LOOP,
+ N_("Looping %d times while getting "
+ "initial credentials", ""),
+ ctx->pa_counter);
+ return KRB5_GET_IN_TKT_LOOP;
+ }
+ ctx->pa_counter++;
+
+ /* Lets process the input packet */
+ if (in && in->length) {
+ krb5_kdc_rep rep;
+
+ memset(&rep, 0, sizeof(rep));
+
+ ret = decode_AS_REP(in->data, in->length, &rep.kdc_rep, &size);
if (ret == 0) {
- krb5_data_free(&resp);
- krb5_clear_error_message(context);
- break;
+ krb5_keyblock *key = NULL;
+ unsigned eflags = EXTRACT_TICKET_AS_REQ;
+
+ if (ctx->flags.canonicalize) {
+ eflags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH;
+ eflags |= EXTRACT_TICKET_MATCH_REALM;
+ }
+ if (ctx->ic_flags & KRB5_INIT_CREDS_NO_C_CANON_CHECK)
+ eflags |= EXTRACT_TICKET_ALLOW_CNAME_MISMATCH;
+
+ ret = process_pa_data_to_key(context, ctx, &ctx->cred,
+ &ctx->as_req, &rep.kdc_rep, hostinfo, &key);
+ if (ret) {
+ free_AS_REP(&rep.kdc_rep);
+ goto out;
+ }
+
+ ret = _krb5_extract_ticket(context,
+ &rep,
+ &ctx->cred,
+ key,
+ NULL,
+ KRB5_KU_AS_REP_ENC_PART,
+ NULL,
+ ctx->nonce,
+ eflags,
+ NULL,
+ NULL);
+ krb5_free_keyblock(context, key);
+
+ *flags = 0;
+
+ if (ret == 0)
+ ret = copy_EncKDCRepPart(&rep.enc_part, &ctx->enc_part);
+
+ free_AS_REP(&rep.kdc_rep);
+ free_EncASRepPart(&rep.enc_part);
+
+ return ret;
+
} else {
/* let's try to parse it as a KRB-ERROR */
- KRB_ERROR error;
- ret = krb5_rd_error(context, &resp, &error);
- if(ret && resp.data && ((char*)resp.data)[0] == 4)
+ free_KRB_ERROR(&ctx->error);
+
+ ret = krb5_rd_error(context, in, &ctx->error);
+ if(ret && in->length && ((char*)in->data)[0] == 4)
ret = KRB5KRB_AP_ERR_V4_REPLY;
- krb5_data_free(&resp);
if (ret)
goto out;
- ret = krb5_error_from_rd_error(context, &error, creds);
+ ret = krb5_error_from_rd_error(context, &ctx->error, &ctx->cred);
/*
* If no preauth was set and KDC requires it, give it one
@@ -1315,169 +1574,198 @@ init_cred_loop(krb5_context context,
*/
if (ret == KRB5KDC_ERR_PREAUTH_REQUIRED) {
- free_METHOD_DATA(&md);
- memset(&md, 0, sizeof(md));
- if (error.e_data) {
- ret = decode_METHOD_DATA(error.e_data->data,
- error.e_data->length,
- &md,
+ free_METHOD_DATA(&ctx->md);
+ memset(&ctx->md, 0, sizeof(ctx->md));
+
+ if (ctx->error.e_data) {
+ ret = decode_METHOD_DATA(ctx->error.e_data->data,
+ ctx->error.e_data->length,
+ &ctx->md,
NULL);
if (ret)
krb5_set_error_message(context, ret,
- N_("failed to decode METHOD DATA", ""));
+ N_("Failed to decode METHOD-DATA", ""));
} else {
- /* XXX guess what the server want here add add md */
+ krb5_set_error_message(context, ret,
+ N_("Preauth required but no preauth "
+ "options send by KDC", ""));
}
- krb5_free_error_contents(context, &error);
- if (ret)
+ } else if (ret == KRB5KRB_AP_ERR_SKEW && context->kdc_sec_offset == 0) {
+ /*
+ * Try adapt to timeskrew when we are using pre-auth, and
+ * if there was a time skew, try again.
+ */
+ krb5_set_real_time(context, ctx->error.stime, -1);
+ if (context->kdc_sec_offset)
+ ret = 0;
+ } else if (ret == KRB5_KDC_ERR_WRONG_REALM && ctx->flags.canonicalize) {
+ /* client referal to a new realm */
+ if (ctx->error.crealm) {
+ krb5_set_error_message(context, ret,
+ N_("Got a client referral, not but no realm", ""));
goto out;
- } else {
- _krb5_get_init_creds_opt_set_krb5_error(context,
- init_cred_opts,
- &error);
- if (ret_as_reply)
- rep.error = error;
- else
- krb5_free_error_contents(context, &error);
- goto out;
+ }
+ ret = krb5_principal_set_realm(context,
+ ctx->cred.client,
+ *ctx->error.crealm);
}
+ if (ret)
+ goto out;
}
}
- {
- krb5_keyblock *key = NULL;
- unsigned flags = EXTRACT_TICKET_AS_REQ;
+ if (ctx->as_req.padata) {
+ free_METHOD_DATA(ctx->as_req.padata);
+ free(ctx->as_req.padata);
+ ctx->as_req.padata = NULL;
+ }
- if (ctx->flags.request_anonymous)
- flags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH;
- if (ctx->flags.canonicalize) {
- flags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH;
- flags |= EXTRACT_TICKET_MATCH_REALM;
- }
- if (ctx->ic_flags & KRB5_INIT_CREDS_NO_C_CANON_CHECK)
- flags |= EXTRACT_TICKET_ALLOW_CNAME_MISMATCH;
+ /* Set a new nonce. */
+ ctx->as_req.req_body.nonce = ctx->nonce;
+
+ /* fill_in_md_data */
+ ret = process_pa_data_to_md(context, &ctx->cred, &ctx->as_req, ctx,
+ &ctx->md, &ctx->as_req.padata,
+ ctx->prompter, ctx->prompter_data);
+ if (ret)
+ goto out;
- ret = process_pa_data_to_key(context, ctx, creds,
- &ctx->as_req, &rep, hi, &key);
- if (ret)
- goto out;
-
- ret = _krb5_extract_ticket(context,
- &rep,
- creds,
- key,
- NULL,
- KRB5_KU_AS_REP_ENC_PART,
- NULL,
- ctx->nonce,
- flags,
- NULL,
- NULL);
- krb5_free_keyblock(context, key);
- }
-out:
- if (stctx)
- krb5_sendto_ctx_free(context, stctx);
krb5_data_free(&ctx->req_buffer);
- free_METHOD_DATA(&md);
- memset(&md, 0, sizeof(md));
- if (ret == 0 && ret_as_reply)
- *ret_as_reply = rep;
- else
- krb5_free_kdc_rep (context, &rep);
+ ASN1_MALLOC_ENCODE(AS_REQ,
+ ctx->req_buffer.data, ctx->req_buffer.length,
+ &ctx->as_req, &len, ret);
+ if (ret)
+ goto out;
+ if(len != ctx->req_buffer.length)
+ krb5_abortx(context, "internal error in ASN.1 encoder");
+
+ out->data = ctx->req_buffer.data;
+ out->length = ctx->req_buffer.length;
+
+ *flags = 1;
+
+ return 0;
+ out:
return ret;
}
+/**
+ * Extract the newly acquired credentials from krb5_init_creds_context
+ * context.
+ *
+ * @param context A Kerberos 5 context.
+ * @param ctx
+ * @param cred credentials, free with krb5_free_cred_contents().
+ *
+ * @return 0 for sucess or An Kerberos error code, see krb5_get_error_message().
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
-krb5_get_init_creds(krb5_context context,
- krb5_creds *creds,
- krb5_principal client,
- krb5_prompter_fct prompter,
- void *data,
- krb5_deltat start_time,
- const char *in_tkt_service,
- krb5_get_init_creds_opt *options)
+krb5_init_creds_get_creds(krb5_context context,
+ krb5_init_creds_context ctx,
+ krb5_creds *cred)
{
- krb5_get_init_creds_ctx ctx;
- krb5_kdc_rep kdc_reply;
- krb5_error_code ret;
- char buf[BUFSIZ];
- int done;
+ return krb5_copy_creds_contents(context, &ctx->cred, cred);
+}
+
+/**
+ * Get the last error from the transaction.
+ *
+ * @return Returns 0 or an error code
+ *
+ * @ingroup krb5_credential
+ */
- memset(&kdc_reply, 0, sizeof(kdc_reply));
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_init_creds_get_error(krb5_context context,
+ krb5_init_creds_context ctx,
+ KRB_ERROR *error)
+{
+ krb5_error_code ret;
- ret = get_init_creds_common(context, client, start_time,
- in_tkt_service, options, &ctx);
+ ret = copy_KRB_ERROR(&ctx->error, error);
if (ret)
- goto out;
+ krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
- done = 0;
- while(!done) {
- memset(&kdc_reply, 0, sizeof(kdc_reply));
-
- ret = init_cred_loop(context,
- options,
- prompter,
- data,
- &ctx,
- &ctx.cred,
- &kdc_reply);
-
- switch (ret) {
- case 0 :
- done = 1;
- break;
- case KRB5KDC_ERR_KEY_EXPIRED :
- /* try to avoid recursion */
+ return ret;
+}
- /* don't try to change password where then where none */
- if (prompter == NULL || ctx.password == NULL)
- goto out;
+/**
+ * Free the krb5_init_creds_context allocated by krb5_init_creds_init().
+ *
+ * @param context A Kerberos 5 context.
+ * @param ctx The krb5_init_creds_context to free.
+ *
+ * @ingroup krb5_credential
+ */
- krb5_clear_error_message (context);
+void KRB5_LIB_FUNCTION
+krb5_init_creds_free(krb5_context context,
+ krb5_init_creds_context ctx)
+{
+ free_init_creds_ctx(context, ctx);
+ free(ctx);
+}
- if (ctx.in_tkt_service != NULL
- && strcmp (ctx.in_tkt_service, "kadmin/changepw") == 0)
- goto out;
+/**
+ * Get new credentials as setup by the krb5_init_creds_context.
+ *
+ * @param context A Kerberos 5 context.
+ * @param ctx The krb5_init_creds_context to process.
+ *
+ * @ingroup krb5_credential
+ */
- ret = change_password (context,
- client,
- ctx.password,
- buf,
- sizeof(buf),
- prompter,
- data,
- options);
- if (ret)
- goto out;
- ctx.password = buf;
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_init_creds_get(krb5_context context, krb5_init_creds_context ctx)
+{
+ krb5_sendto_ctx stctx = NULL;
+ krb5_krbhst_info *hostinfo = NULL;
+ krb5_error_code ret;
+ krb5_data in, out;
+ unsigned int flags = 0;
+
+ krb5_data_zero(&in);
+ krb5_data_zero(&out);
+
+ ret = krb5_sendto_ctx_alloc(context, &stctx);
+ if (ret)
+ goto out;
+ krb5_sendto_ctx_set_func(stctx, _krb5_kdc_retry, NULL);
+
+ while (1) {
+ flags = 0;
+ ret = krb5_init_creds_step(context, ctx, &in, &out, hostinfo, &flags);
+ krb5_data_free(&in);
+ if (ret)
+ goto out;
+
+ if ((flags & 1) == 0)
break;
- default:
+
+ ret = krb5_sendto_context (context, stctx, &out,
+ ctx->cred.client->realm, &in);
+ if (ret)
goto out;
- }
- }
- if (prompter)
- print_expire (context,
- krb5_principal_get_realm (context, ctx.cred.client),
- &kdc_reply,
- prompter,
- data);
+ }
out:
- memset (buf, 0, sizeof(buf));
- free_init_creds_ctx(context, &ctx);
- krb5_free_kdc_rep (context, &kdc_reply);
- if (ret == 0)
- *creds = ctx.cred;
- else
- krb5_free_cred_contents (context, &ctx.cred);
+ if (stctx)
+ krb5_sendto_ctx_free(context, stctx);
return ret;
}
+/**
+ * Get new credentials using password.
+ *
+ * @ingroup krb5_credential
+ */
+
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_init_creds_password(krb5_context context,
krb5_creds *creds,
@@ -1487,29 +1775,23 @@ krb5_get_init_creds_password(krb5_context context,
void *data,
krb5_deltat start_time,
const char *in_tkt_service,
- krb5_get_init_creds_opt *in_options)
+ krb5_get_init_creds_opt *options)
{
- krb5_get_init_creds_opt *options;
+ krb5_init_creds_context ctx;
char buf[BUFSIZ];
krb5_error_code ret;
+ int chpw = 0;
- if (in_options == NULL) {
- const char *realm = krb5_principal_get_realm(context, client);
- ret = krb5_get_init_creds_opt_alloc(context, &options);
- if (ret == 0)
- krb5_get_init_creds_opt_set_default_flags(context,
- NULL,
- realm,
- options);
- } else
- ret = _krb5_get_init_creds_opt_copy(context, in_options, &options);
+ again:
+ ret = krb5_init_creds_init(context, client, prompter, data, start_time, options, &ctx);
if (ret)
- return ret;
+ goto out;
- if (password == NULL &&
- options->opt_private->password == NULL &&
- options->opt_private->pk_init_ctx == NULL)
- {
+ ret = krb5_init_creds_set_service(context, ctx, in_tkt_service);
+ if (ret)
+ goto out;
+
+ if (prompter != NULL && ctx->password == NULL && password == NULL) {
krb5_prompt prompt;
krb5_data password_data;
char *p, *q;
@@ -1528,40 +1810,67 @@ krb5_get_init_creds_password(krb5_context context,
free (q);
if (ret) {
memset (buf, 0, sizeof(buf));
- krb5_get_init_creds_opt_free(context, options);
ret = KRB5_LIBOS_PWDINTR;
krb5_clear_error_message (context);
- return ret;
+ goto out;
}
password = password_data.data;
}
- if (options->opt_private->password == NULL) {
- ret = krb5_get_init_creds_opt_set_pa_password(context, options,
- password, NULL);
- if (ret) {
- krb5_get_init_creds_opt_free(context, options);
- memset(buf, 0, sizeof(buf));
- return ret;
- }
+ if (password) {
+ ret = krb5_init_creds_set_password(context, ctx, password);
+ if (ret)
+ goto out;
}
- ret = krb5_get_init_creds(context, creds, client, prompter,
- data, start_time, in_tkt_service, options);
- krb5_get_init_creds_opt_free(context, options);
+ ret = krb5_init_creds_get(context, ctx);
+
+ if (ret == 0)
+ process_last_request(context, options, ctx);
+
+
+ if (ret == KRB5KDC_ERR_KEY_EXPIRED && chpw == 0) {
+ char buf[1024];
+
+ /* try to avoid recursion */
+ if (in_tkt_service != NULL && strcmp(in_tkt_service, "kadmin/changepw") == 0)
+ goto out;
+
+ /* don't try to change password where then where none */
+ if (prompter == NULL)
+ goto out;
+
+ ret = change_password (context,
+ client,
+ ctx->password,
+ buf,
+ sizeof(buf),
+ prompter,
+ data,
+ options);
+ if (ret)
+ goto out;
+ chpw = 1;
+ krb5_init_creds_free(context, ctx);
+ goto again;
+ }
+
+ out:
+ if (ret == 0)
+ krb5_init_creds_get_creds(context, ctx, creds);
+
+ if (ctx)
+ krb5_init_creds_free(context, ctx);
+
memset(buf, 0, sizeof(buf));
return ret;
}
-static krb5_error_code
-init_creds_keyblock_key_proc (krb5_context context,
- krb5_enctype type,
- krb5_salt salt,
- krb5_const_pointer keyseed,
- krb5_keyblock **key)
-{
- return krb5_copy_keyblock (context, keyseed, key);
-}
+/**
+ * Get new credentials using keyblock.
+ *
+ * @ingroup krb5_credential
+ */
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_init_creds_keyblock(krb5_context context,
@@ -1572,33 +1881,80 @@ krb5_get_init_creds_keyblock(krb5_context context,
const char *in_tkt_service,
krb5_get_init_creds_opt *options)
{
- struct krb5_get_init_creds_ctx ctx;
+ krb5_init_creds_context ctx;
krb5_error_code ret;
- ret = get_init_creds_common(context, client, start_time,
- in_tkt_service, options, &ctx);
+ memset(creds, 0, sizeof(*creds));
+
+ ret = krb5_init_creds_init(context, client, NULL, NULL, start_time, options, &ctx);
if (ret)
goto out;
- ret = krb5_get_in_cred (context,
- KDCOptions2int(ctx.flags),
- ctx.addrs,
- ctx.etypes,
- ctx.pre_auth_types,
- NULL,
- init_creds_keyblock_key_proc,
- keyblock,
- NULL,
- NULL,
- &ctx.cred,
- NULL);
-
- if (ret == 0 && creds)
- *creds = ctx.cred;
- else
- krb5_free_cred_contents (context, &ctx.cred);
+ ret = krb5_init_creds_set_service(context, ctx, in_tkt_service);
+ if (ret)
+ goto out;
+
+ ret = krb5_init_creds_set_keyblock(context, ctx, keyblock);
+ if (ret)
+ goto out;
+
+ ret = krb5_init_creds_get(context, ctx);
+
+ if (ret == 0)
+ process_last_request(context, options, ctx);
+
+ out:
+ if (ret == 0)
+ krb5_init_creds_get_creds(context, ctx, creds);
+
+ if (ctx)
+ krb5_init_creds_free(context, ctx);
+
+ return ret;
+}
+
+/**
+ * Get new credentials using keytab.
+ *
+ * @ingroup krb5_credential
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_init_creds_keytab(krb5_context context,
+ krb5_creds *creds,
+ krb5_principal client,
+ krb5_keytab keytab,
+ krb5_deltat start_time,
+ const char *in_tkt_service,
+ krb5_get_init_creds_opt *options)
+{
+ krb5_init_creds_context ctx;
+ krb5_error_code ret;
+
+ memset(creds, 0, sizeof(*creds));
+
+ ret = krb5_init_creds_init(context, client, NULL, NULL, start_time, options, &ctx);
+ if (ret)
+ goto out;
+
+ ret = krb5_init_creds_set_service(context, ctx, in_tkt_service);
+ if (ret)
+ goto out;
+
+ ret = krb5_init_creds_set_keytab(context, ctx, keytab);
+ if (ret)
+ goto out;
+
+ ret = krb5_init_creds_get(context, ctx);
+ if (ret == 0)
+ process_last_request(context, options, ctx);
out:
- free_init_creds_ctx(context, &ctx);
+ if (ret == 0)
+ krb5_init_creds_get_creds(context, ctx, creds);
+
+ if (ctx)
+ krb5_init_creds_free(context, ctx);
+
return ret;
}
diff --git a/source4/heimdal/lib/krb5/kcm.c b/source4/heimdal/lib/krb5/kcm.c
index 8a8f1efc11..f034341972 100644
--- a/source4/heimdal/lib/krb5/kcm.c
+++ b/source4/heimdal/lib/krb5/kcm.c
@@ -43,17 +43,24 @@
#include "kcm.h"
-RCSID("$Id$");
-
typedef struct krb5_kcmcache {
char *name;
struct sockaddr_un path;
char *door_path;
} krb5_kcmcache;
+typedef struct krb5_kcm_cursor {
+ unsigned long offset;
+ unsigned long length;
+ kcmuuid_t *uuids;
+} *krb5_kcm_cursor;
+
+
#define KCMCACHE(X) ((krb5_kcmcache *)(X)->data.data)
#define CACHENAME(X) (KCMCACHE(X)->name)
-#define KCMCURSOR(C) (*(uint32_t *)(C))
+#define KCMCURSOR(C) ((krb5_kcm_cursor)(C))
+
+#ifdef HAVE_DOOR_CREATE
static krb5_error_code
try_door(krb5_context context,
@@ -61,7 +68,6 @@ try_door(krb5_context context,
krb5_data *request_data,
krb5_data *response_data)
{
-#ifdef HAVE_DOOR_CREATE
door_arg_t arg;
int fd;
int ret;
@@ -91,10 +97,8 @@ try_door(krb5_context context,
return ret;
return 0;
-#else
- return KRB5_CC_IO;
-#endif
}
+#endif /* HAVE_DOOR_CREATE */
static krb5_error_code
try_unix_socket(krb5_context context,
@@ -143,9 +147,11 @@ kcm_send_request(krb5_context context,
ret = KRB5_CC_NOSUPP;
for (i = 0; i < context->max_retries; i++) {
+#ifdef HAVE_DOOR_CREATE
ret = try_door(context, k, &request_data, response_data);
if (ret == 0 && response_data->length != 0)
break;
+#endif
ret = try_unix_socket(context, k, &request_data, response_data);
if (ret == 0 && response_data->length != 0)
break;
@@ -207,7 +213,8 @@ kcm_alloc(krb5_context context, const char *name, krb5_ccache *id)
k = malloc(sizeof(*k));
if (k == NULL) {
- krb5_set_error_message(context, KRB5_CC_NOMEM, N_("malloc: out of memory", ""));
+ krb5_set_error_message(context, KRB5_CC_NOMEM,
+ N_("malloc: out of memory", ""));
return KRB5_CC_NOMEM;
}
@@ -309,8 +316,6 @@ kcm_free(krb5_context context, krb5_ccache *id)
memset(k, 0, sizeof(*k));
krb5_data_free(&(*id)->data);
}
-
- *id = NULL;
}
static const char *
@@ -609,10 +614,10 @@ kcm_get_first (krb5_context context,
krb5_cc_cursor *cursor)
{
krb5_error_code ret;
+ krb5_kcm_cursor c;
krb5_kcmcache *k = KCMCACHE(id);
krb5_storage *request, *response;
krb5_data response_data;
- int32_t tmp;
ret = kcm_storage_request(context, KCM_OP_GET_FIRST, &request);
if (ret)
@@ -625,27 +630,56 @@ kcm_get_first (krb5_context context,
}
ret = kcm_call(context, k, request, &response, &response_data);
- if (ret) {
- krb5_storage_free(request);
+ krb5_storage_free(request);
+ if (ret)
+ return ret;
+
+ c = calloc(1, sizeof(*c));
+ if (c == NULL) {
+ ret = ENOMEM;
+ krb5_set_error_message(context, ret,
+ N_("malloc: out of memory", ""));
return ret;
}
- ret = krb5_ret_int32(response, &tmp);
- if (ret || tmp < 0)
- ret = KRB5_CC_IO;
+ while (1) {
+ ssize_t sret;
+ kcmuuid_t uuid;
+ void *ptr;
+
+ sret = krb5_storage_read(response, &uuid, sizeof(uuid));
+ if (sret == 0) {
+ ret = 0;
+ break;
+ } else if (sret != sizeof(uuid)) {
+ ret = EINVAL;
+ break;
+ }
+
+ ptr = realloc(c->uuids, sizeof(c->uuids[0]) * (c->length + 1));
+ if (ptr == NULL) {
+ free(c->uuids);
+ free(c);
+ krb5_set_error_message(context, ENOMEM,
+ N_("malloc: out of memory", ""));
+ return ENOMEM;
+ }
+ c->uuids = ptr;
+
+ memcpy(&c->uuids[c->length], &uuid, sizeof(uuid));
+ c->length += 1;
+ }
- krb5_storage_free(request);
krb5_storage_free(response);
krb5_data_free(&response_data);
- if (ret)
+ if (ret) {
+ free(c->uuids);
+ free(c);
return ret;
+ }
- *cursor = malloc(sizeof(tmp));
- if (*cursor == NULL)
- return KRB5_CC_NOMEM;
-
- KCMCURSOR(*cursor) = tmp;
+ *cursor = c;
return 0;
}
@@ -666,8 +700,15 @@ kcm_get_next (krb5_context context,
{
krb5_error_code ret;
krb5_kcmcache *k = KCMCACHE(id);
+ krb5_kcm_cursor c = KCMCURSOR(*cursor);
krb5_storage *request, *response;
krb5_data response_data;
+ ssize_t sret;
+
+ again:
+
+ if (c->offset >= c->length)
+ return KRB5_CC_END;
ret = kcm_storage_request(context, KCM_OP_GET_NEXT, &request);
if (ret)
@@ -679,23 +720,26 @@ kcm_get_next (krb5_context context,
return ret;
}
- ret = krb5_store_int32(request, KCMCURSOR(*cursor));
- if (ret) {
+ sret = krb5_storage_write(request,
+ &c->uuids[c->offset],
+ sizeof(c->uuids[c->offset]));
+ c->offset++;
+ if (sret != sizeof(c->uuids[c->offset])) {
krb5_storage_free(request);
- return ret;
+ krb5_clear_error_message(context);
+ return ENOMEM;
}
ret = kcm_call(context, k, request, &response, &response_data);
- if (ret) {
- krb5_storage_free(request);
- return ret;
+ krb5_storage_free(request);
+ if (ret == KRB5_CC_END) {
+ goto again;
}
ret = krb5_ret_creds(response, creds);
if (ret)
ret = KRB5_CC_IO;
- krb5_storage_free(request);
krb5_storage_free(response);
krb5_data_free(&response_data);
@@ -717,6 +761,7 @@ kcm_end_get (krb5_context context,
{
krb5_error_code ret;
krb5_kcmcache *k = KCMCACHE(id);
+ krb5_kcm_cursor c = KCMCURSOR(*cursor);
krb5_storage *request;
ret = kcm_storage_request(context, KCM_OP_END_GET, &request);
@@ -729,22 +774,14 @@ kcm_end_get (krb5_context context,
return ret;
}
- ret = krb5_store_int32(request, KCMCURSOR(*cursor));
- if (ret) {
- krb5_storage_free(request);
- return ret;
- }
-
ret = kcm_call(context, k, request, NULL, NULL);
- if (ret) {
- krb5_storage_free(request);
+ krb5_storage_free(request);
+ if (ret)
return ret;
- }
- krb5_storage_free(request);
+ free(c->uuids);
+ free(c);
- KCMCURSOR(*cursor) = 0;
- free(*cursor);
*cursor = NULL;
return ret;
diff --git a/source4/heimdal/lib/krb5/keyblock.c b/source4/heimdal/lib/krb5/keyblock.c
index aa6353d7c8..57ed7875fc 100644
--- a/source4/heimdal/lib/krb5/keyblock.c
+++ b/source4/heimdal/lib/krb5/keyblock.c
@@ -33,7 +33,13 @@
#include "krb5_locl.h"
-RCSID("$Id$");
+/**
+ * Zero out a keyblock
+ *
+ * @param keyblock keyblock to zero out
+ *
+ * @ingroup krb5_crypto
+ */
void KRB5_LIB_FUNCTION
krb5_keyblock_zero(krb5_keyblock *keyblock)
@@ -42,6 +48,15 @@ krb5_keyblock_zero(krb5_keyblock *keyblock)
krb5_data_zero(&keyblock->keyvalue);
}
+/**
+ * Free a keyblock's content, also zero out the content of the keyblock.
+ *
+ * @param context a Kerberos 5 context
+ * @param keyblock keyblock content to free, NULL is valid argument
+ *
+ * @ingroup krb5_crypto
+ */
+
void KRB5_LIB_FUNCTION
krb5_free_keyblock_contents(krb5_context context,
krb5_keyblock *keyblock)
@@ -54,6 +69,16 @@ krb5_free_keyblock_contents(krb5_context context,
}
}
+/**
+ * Free a keyblock, also zero out the content of the keyblock, uses
+ * krb5_free_keyblock_contents() to free the content.
+ *
+ * @param context a Kerberos 5 context
+ * @param keyblock keyblock to free, NULL is valid argument
+ *
+ * @ingroup krb5_crypto
+ */
+
void KRB5_LIB_FUNCTION
krb5_free_keyblock(krb5_context context,
krb5_keyblock *keyblock)
@@ -64,6 +89,19 @@ krb5_free_keyblock(krb5_context context,
}
}
+/**
+ * Copy a keyblock, free the output keyblock with
+ * krb5_free_keyblock_contents().
+ *
+ * @param context a Kerberos 5 context
+ * @param inblock the key to copy
+ * @param to the output key.
+ *
+ * @param 0 on success or a Kerberos 5 error code
+ *
+ * @ingroup krb5_crypto
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_copy_keyblock_contents (krb5_context context,
const krb5_keyblock *inblock,
@@ -72,31 +110,62 @@ krb5_copy_keyblock_contents (krb5_context context,
return copy_EncryptionKey(inblock, to);
}
+/**
+ * Copy a keyblock, free the output keyblock with
+ * krb5_free_keyblock().
+ *
+ * @param context a Kerberos 5 context
+ * @param inblock the key to copy
+ * @param to the output key.
+ *
+ * @param 0 on success or a Kerberos 5 error code
+ *
+ * @ingroup krb5_crypto
+ */
+
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_copy_keyblock (krb5_context context,
const krb5_keyblock *inblock,
krb5_keyblock **to)
{
+ krb5_error_code ret;
krb5_keyblock *k;
+
+ *to = NULL;
- k = malloc (sizeof(*k));
+ k = calloc (1, sizeof(*k));
if (k == NULL) {
krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
return ENOMEM;
}
+
+ ret = krb5_copy_keyblock_contents (context, inblock, k);
+ if (ret) {
+ free(k);
+ return ret;
+ }
*to = k;
- return krb5_copy_keyblock_contents (context, inblock, k);
+ return 0;
}
+/**
+ * Get encryption type of a keyblock.
+ *
+ * @ingroup krb5_crypto
+ */
+
krb5_enctype
krb5_keyblock_get_enctype(const krb5_keyblock *block)
{
return block->keytype;
}
-/*
+/**
* Fill in `key' with key data of type `enctype' from `data' of length
- * `size'. Key should be freed using krb5_free_keyblock_contents.
+ * `size'. Key should be freed using krb5_free_keyblock_contents().
+ *
+ * @ingroup krb5_crypto
*/
krb5_error_code KRB5_LIB_FUNCTION
diff --git a/source4/heimdal/lib/krb5/keytab.c b/source4/heimdal/lib/krb5/keytab.c
index aa7c77ce46..fcc74e847e 100644
--- a/source4/heimdal/lib/krb5/keytab.c
+++ b/source4/heimdal/lib/krb5/keytab.c
@@ -33,11 +33,114 @@
#include "krb5_locl.h"
-RCSID("$Id$");
+/**
+ * @page krb5_keytab_intro The keytab handing functions
+ * @section section_krb5_keytab Kerberos Keytabs
+ *
+ * See the library functions here: @ref krb5_keytab
+ *
+ * Keytabs are long term key storage for servers, their equvalment of
+ * password files.
+ *
+ * Normally the only function that useful for server are to specify
+ * what keytab to use to other core functions like krb5_rd_req()
+ * krb5_kt_resolve(), and krb5_kt_close().
+ *
+ * @subsection krb5_keytab_names Keytab names
+ *
+ * A keytab name is on the form type:residual. The residual part is
+ * specific to each keytab-type.
+ *
+ * When a keytab-name is resolved, the type is matched with an internal
+ * list of keytab types. If there is no matching keytab type,
+ * the default keytab is used. The current default type is FILE.
+ *
+ * The default value can be changed in the configuration file
+ * /etc/krb5.conf by setting the variable
+ * [defaults]default_keytab_name.
+ *
+ * The keytab types that are implemented in Heimdal are:
+ * - file
+ * store the keytab in a file, the type's name is FILE . The
+ * residual part is a filename. For compatibility with other
+ * Kerberos implemtation WRFILE and JAVA14 is also accepted. WRFILE
+ * has the same format as FILE. JAVA14 have a format that is
+ * compatible with older versions of MIT kerberos and SUN's Java
+ * based installation. They store a truncted kvno, so when the knvo
+ * excess 255, they are truncted in this format.
+ *
+ * - keytab
+ * store the keytab in a AFS keyfile (usually /usr/afs/etc/KeyFile ),
+ * the type's name is AFSKEYFILE. The residual part is a filename.
+ *
+ * - krb4
+ * the keytab is a Kerberos 4 srvtab that is on-the-fly converted to
+ * a keytab. The type's name is krb4 The residual part is a
+ * filename.
+ *
+ * - memory
+ * The keytab is stored in a memory segment. This allows sensitive
+ * and/or temporary data not to be stored on disk. The type's name
+ * is MEMORY. Each MEMORY keytab is referenced counted by and
+ * opened by the residual name, so two handles can point to the
+ * same memory area. When the last user closes the entry, it
+ * disappears.
+ *
+ *
+ * @subsection krb5_keytab_example Keytab example
+ *
+ * This is a minimalistic version of ktutil.
+ *
+ * @code
+int
+main (int argc, char **argv)
+{
+ krb5_context context;
+ krb5_keytab keytab;
+ krb5_kt_cursor cursor;
+ krb5_keytab_entry entry;
+ krb5_error_code ret;
+ char *principal;
-/*
- * Register a new keytab in `ops'
- * Return 0 or an error.
+ if (krb5_init_context (&context) != 0)
+ errx(1, "krb5_context");
+
+ ret = krb5_kt_default (context, &keytab);
+ if (ret)
+ krb5_err(context, 1, ret, "krb5_kt_default");
+
+ ret = krb5_kt_start_seq_get(context, keytab, &cursor);
+ if (ret)
+ krb5_err(context, 1, ret, "krb5_kt_start_seq_get");
+ while((ret = krb5_kt_next_entry(context, keytab, &entry, &cursor)) == 0){
+ krb5_unparse_name_short(context, entry.principal, &principal);
+ printf("principal: %s\n", principal);
+ free(principal);
+ krb5_kt_free_entry(context, &entry);
+ }
+ ret = krb5_kt_end_seq_get(context, keytab, &cursor);
+ if (ret)
+ krb5_err(context, 1, ret, "krb5_kt_end_seq_get");
+ ret = krb5_kt_close(context, keytab);
+ if (ret)
+ krb5_err(context, 1, ret, "krb5_kt_close");
+ krb5_free_context(context);
+ return 0;
+}
+ * @endcode
+ *
+ */
+
+
+/**
+ * Register a new keytab backend.
+ *
+ * @param context a Keberos context.
+ * @param ops a backend to register.
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -55,7 +158,8 @@ krb5_kt_register(krb5_context context,
tmp = realloc(context->kt_types,
(context->num_kt_types + 1) * sizeof(*context->kt_types));
if(tmp == NULL) {
- krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
+ krb5_set_error_message(context, ENOMEM,
+ N_("malloc: out of memory", ""));
return ENOMEM;
}
memcpy(&tmp[context->num_kt_types], ops,
@@ -65,12 +169,20 @@ krb5_kt_register(krb5_context context,
return 0;
}
-/*
+/**
* Resolve the keytab name (of the form `type:residual') in `name'
* into a keytab in `id'.
- * Return 0 or an error
+ *
+ * @param context a Keberos context.
+ * @param name name to resolve
+ * @param id resulting keytab, free with krb5_kt_close().
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_kt_resolve(krb5_context context,
const char *name,
@@ -120,9 +232,16 @@ krb5_kt_resolve(krb5_context context,
return ret;
}
-/*
+/**
* copy the name of the default keytab into `name'.
- * Return 0 or KRB5_CONFIG_NOTENUFSPACE if `namesize' is too short.
+ *
+ * @param context a Keberos context.
+ * @param name buffer where the name will be written
+ * @param namesize length of name
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -135,9 +254,16 @@ krb5_kt_default_name(krb5_context context, char *name, size_t namesize)
return 0;
}
-/*
- * copy the name of the default modify keytab into `name'.
- * Return 0 or KRB5_CONFIG_NOTENUFSPACE if `namesize' is too short.
+/**
+ * Copy the name of the default modify keytab into `name'.
+ *
+ * @param context a Keberos context.
+ * @param name buffer where the name will be written
+ * @param namesize length of name
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -166,9 +292,15 @@ krb5_kt_default_modify_name(krb5_context context, char *name, size_t namesize)
return 0;
}
-/*
+/**
* Set `id' to the default keytab.
- * Return 0 or an error.
+ *
+ * @param context a Keberos context.
+ * @param id the new default keytab.
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -177,10 +309,20 @@ krb5_kt_default(krb5_context context, krb5_keytab *id)
return krb5_kt_resolve (context, context->default_keytab, id);
}
-/*
+/**
* Read the key identified by `(principal, vno, enctype)' from the
* keytab in `keyprocarg' (the default if == NULL) into `*key'.
- * Return 0 or an error.
+ *
+ * @param context a Keberos context.
+ * @param keyprocarg
+ * @param principal
+ * @param vno
+ * @param enctype
+ * @param key
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -212,9 +354,18 @@ krb5_kt_read_service_key(krb5_context context,
return ret;
}
-/*
+/**
* Return the type of the `keytab' in the string `prefix of length
* `prefixsize'.
+ *
+ * @param context a Keberos context.
+ * @param keytab the keytab to get the prefix for
+ * @param prefix prefix buffer
+ * @param prefixsize length of prefix buffer
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -227,9 +378,17 @@ krb5_kt_get_type(krb5_context context,
return 0;
}
-/*
+/**
* Retrieve the name of the keytab `keytab' into `name', `namesize'
- * Return 0 or an error.
+ *
+ * @param context a Keberos context.
+ * @param keytab the keytab to get the name for.
+ * @param name name buffer.
+ * @param namesize size of name buffer.
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -241,10 +400,18 @@ krb5_kt_get_name(krb5_context context,
return (*keytab->get_name)(context, keytab, name, namesize);
}
-/*
+/**
* Retrieve the full name of the keytab `keytab' and store the name in
- * `str'. `str' needs to be freed by the caller using free(3).
- * Returns 0 or an error. On error, *str is set to NULL.
+ * `str'.
+ *
+ * @param context a Keberos context.
+ * @param keytab keytab to get name for.
+ * @param str the name of the keytab name, usee krb5_xfree() to free
+ * the string. On error, *str is set to NULL.
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -275,9 +442,16 @@ krb5_kt_get_full_name(krb5_context context,
return 0;
}
-/*
+/**
* Finish using the keytab in `id'. All resources will be released,
- * even on errors. Return 0 or an error.
+ * even on errors.
+ *
+ * @param context a Keberos context.
+ * @param id keytab to close.
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -292,10 +466,61 @@ krb5_kt_close(krb5_context context,
return ret;
}
+/**
+ * Destroy (remove) the keytab in `id'. All resources will be released,
+ * even on errors, does the equvalment of krb5_kt_close() on the resources.
+ *
+ * @param context a Keberos context.
+ * @param id keytab to destroy.
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_destroy(krb5_context context,
+ krb5_keytab id)
+{
+ krb5_error_code ret;
+
+ ret = (*id->destroy)(context, id);
+ krb5_kt_close(context, id);
+ return ret;
+}
+
/*
+ * Match any aliases in keytab `entry' with `principal'.
+ */
+
+static krb5_boolean
+compare_aliseses(krb5_context context,
+ krb5_keytab_entry *entry,
+ krb5_const_principal principal)
+{
+ unsigned int i;
+ if (entry->aliases == NULL)
+ return FALSE;
+ for (i = 0; i < entry->aliases->len; i++)
+ if (krb5_principal_compare(context, &entry->aliases->val[i], principal))
+ return TRUE;
+ return FALSE;
+}
+
+/**
* Compare `entry' against `principal, vno, enctype'.
* Any of `principal, vno, enctype' might be 0 which acts as a wildcard.
* Return TRUE if they compare the same, FALSE otherwise.
+ *
+ * @param context a Keberos context.
+ * @param entry an entry to match with.
+ * @param principal principal to match, NULL matches all principals.
+ * @param vno key version to match, 0 matches all key version numbers.
+ * @param enctype encryption type to match, 0 matches all encryption types.
+ *
+ * @return Return TRUE or match, FALSE if not matched.
+ *
+ * @ingroup krb5_keytab
*/
krb5_boolean KRB5_LIB_FUNCTION
@@ -306,7 +531,8 @@ krb5_kt_compare(krb5_context context,
krb5_enctype enctype)
{
if(principal != NULL &&
- !krb5_principal_compare(context, entry->principal, principal))
+ !(krb5_principal_compare(context, entry->principal, principal) ||
+ compare_aliseses(context, entry, principal)))
return FALSE;
if(vno && vno != entry->vno)
return FALSE;
@@ -315,11 +541,53 @@ krb5_kt_compare(krb5_context context,
return TRUE;
}
-/*
+krb5_error_code
+_krb5_kt_principal_not_found(krb5_context context,
+ krb5_error_code ret,
+ krb5_keytab id,
+ krb5_const_principal principal,
+ krb5_enctype enctype,
+ int kvno)
+{
+ char princ[256], kvno_str[25], *kt_name;
+ char *enctype_str = NULL;
+
+ krb5_unparse_name_fixed (context, principal, princ, sizeof(princ));
+ krb5_kt_get_full_name (context, id, &kt_name);
+ krb5_enctype_to_string(context, enctype, &enctype_str);
+
+ if (kvno)
+ snprintf(kvno_str, sizeof(kvno_str), "(kvno %d)", kvno);
+ else
+ kvno_str[0] = '\0';
+
+ krb5_set_error_message (context, ret,
+ N_("Failed to find %s%s in keytab %s (%s)",
+ "principal, kvno, keytab file, enctype"),
+ princ,
+ kvno_str,
+ kt_name ? kt_name : "unknown keytab",
+ enctype_str ? enctype_str : "unknown enctype");
+ free(kt_name);
+ free(enctype_str);
+ return ret;
+}
+
+
+/**
* Retrieve the keytab entry for `principal, kvno, enctype' into `entry'
- * from the keytab `id'.
- * kvno == 0 is a wildcard and gives the keytab with the highest vno.
- * Return 0 or an error.
+ * from the keytab `id'. Matching is done like krb5_kt_compare().
+ *
+ * @param context a Keberos context.
+ * @param id a keytab.
+ * @param principal principal to match, NULL matches all principals.
+ * @param kvno key version to match, 0 matches all key version numbers.
+ * @param enctype encryption type to match, 0 matches all encryption types.
+ * @param entry the returned entry, free with krb5_kt_free_entry().
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -365,37 +633,23 @@ krb5_kt_get_entry(krb5_context context,
krb5_kt_free_entry(context, &tmp);
}
krb5_kt_end_seq_get (context, id, &cursor);
- if (entry->vno) {
- return 0;
- } else {
- char princ[256], kvno_str[25], *kt_name;
- char *enctype_str = NULL;
-
- krb5_unparse_name_fixed (context, principal, princ, sizeof(princ));
- krb5_kt_get_full_name (context, id, &kt_name);
- krb5_enctype_to_string(context, enctype, &enctype_str);
-
- if (kvno)
- snprintf(kvno_str, sizeof(kvno_str), "(kvno %d)", kvno);
- else
- kvno_str[0] = '\0';
-
- krb5_set_error_message (context, KRB5_KT_NOTFOUND,
- N_("Failed to find %s%s in keytab %s (%s)",
- "principal, kvno, keytab file, enctype"),
- princ,
- kvno_str,
- kt_name ? kt_name : "unknown keytab",
- enctype_str ? enctype_str : "unknown enctype");
- free(kt_name);
- free(enctype_str);
- return KRB5_KT_NOTFOUND;
- }
+ if (entry->vno == 0)
+ return _krb5_kt_principal_not_found(context, KRB5_KT_NOTFOUND,
+ id, principal, enctype, kvno);
+ return 0;
}
-/*
+/**
* Copy the contents of `in' into `out'.
- * Return 0 or an error. */
+ *
+ * @param context a Keberos context.
+ * @param in the keytab entry to copy.
+ * @param out the copy of the keytab entry, free with krb5_kt_free_entry().
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
+ */
krb5_error_code KRB5_LIB_FUNCTION
krb5_kt_copy_entry_contents(krb5_context context,
@@ -422,8 +676,15 @@ fail:
return ret;
}
-/*
+/**
* Free the contents of `entry'.
+ *
+ * @param context a Keberos context.
+ * @param entry the entry to free
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -436,9 +697,16 @@ krb5_kt_free_entry(krb5_context context,
return 0;
}
-/*
+/**
* Set `cursor' to point at the beginning of `id'.
- * Return 0 or an error.
+ *
+ * @param context a Keberos context.
+ * @param id a keytab.
+ * @param cursor a newly allocated cursor, free with krb5_kt_end_seq_get().
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -456,10 +724,18 @@ krb5_kt_start_seq_get(krb5_context context,
return (*id->start_seq_get)(context, id, cursor);
}
-/*
- * Get the next entry from `id' pointed to by `cursor' and advance the
- * `cursor'.
- * Return 0 or an error.
+/**
+ * Get the next entry from keytab, advance the cursor. On last entry
+ * the function will return KRB5_KT_END.
+ *
+ * @param context a Keberos context.
+ * @param id a keytab.
+ * @param entry the returned entry, free with krb5_kt_free_entry().
+ * @param cursor the cursor of the iteration.
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -478,8 +754,16 @@ krb5_kt_next_entry(krb5_context context,
return (*id->next_entry)(context, id, entry, cursor);
}
-/*
+/**
* Release all resources associated with `cursor'.
+ *
+ * @param context a Keberos context.
+ * @param id a keytab.
+ * @param cursor the cursor to free.
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -496,9 +780,16 @@ krb5_kt_end_seq_get(krb5_context context,
return (*id->end_seq_get)(context, id, cursor);
}
-/*
+/**
* Add the entry in `entry' to the keytab `id'.
- * Return 0 or an error.
+ *
+ * @param context a Keberos context.
+ * @param id a keytab.
+ * @param entry the entry to add
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -516,9 +807,17 @@ krb5_kt_add_entry(krb5_context context,
return (*id->add)(context, id,entry);
}
-/*
- * Remove the entry `entry' from the keytab `id'.
- * Return 0 or an error.
+/**
+ * Remove an entry from the keytab, matching is done using
+ * krb5_kt_compare().
+
+ * @param context a Keberos context.
+ * @param id a keytab.
+ * @param entry the entry to remove
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
krb5_error_code KRB5_LIB_FUNCTION
diff --git a/source4/heimdal/lib/krb5/keytab_any.c b/source4/heimdal/lib/krb5/keytab_any.c
index 7a2d9b9f70..02de8c8028 100644
--- a/source4/heimdal/lib/krb5/keytab_any.c
+++ b/source4/heimdal/lib/krb5/keytab_any.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
struct any_data {
krb5_keytab kt;
char *name;
@@ -253,6 +251,7 @@ const krb5_kt_ops krb5_any_ops = {
any_resolve,
any_get_name,
any_close,
+ NULL, /* destroy */
NULL, /* get */
any_start_seq_get,
any_next_entry,
diff --git a/source4/heimdal/lib/krb5/keytab_file.c b/source4/heimdal/lib/krb5/keytab_file.c
index f494cac253..819366443f 100644
--- a/source4/heimdal/lib/krb5/keytab_file.c
+++ b/source4/heimdal/lib/krb5/keytab_file.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
#define KRB5_KT_VNO_1 1
#define KRB5_KT_VNO_2 2
#define KRB5_KT_VNO KRB5_KT_VNO_2
@@ -332,6 +330,14 @@ fkt_close(krb5_context context, krb5_keytab id)
}
static krb5_error_code
+fkt_destroy(krb5_context context, krb5_keytab id)
+{
+ struct fkt_data *d = id->data;
+ _krb5_erase_file(context, d->filename);
+ return 0;
+}
+
+static krb5_error_code
fkt_get_name(krb5_context context,
krb5_keytab id,
char *name,
@@ -445,6 +451,7 @@ fkt_next_entry_int(krb5_context context,
int ret;
int8_t tmp8;
int32_t tmp32;
+ uint32_t utmp32;
off_t pos, curpos;
pos = krb5_storage_seek(cursor->sp, 0, SEEK_CUR);
@@ -459,8 +466,8 @@ loop:
ret = krb5_kt_ret_principal (context, d, cursor->sp, &entry->principal);
if (ret)
goto out;
- ret = krb5_ret_int32(cursor->sp, &tmp32);
- entry->timestamp = tmp32;
+ ret = krb5_ret_uint32(cursor->sp, &utmp32);
+ entry->timestamp = utmp32;
if (ret)
goto out;
ret = krb5_ret_int8(cursor->sp, &tmp8);
@@ -476,10 +483,19 @@ loop:
curpos = krb5_storage_seek(cursor->sp, 0, SEEK_CUR);
if(len + 4 + pos - curpos >= 4) {
ret = krb5_ret_int32(cursor->sp, &tmp32);
- if (ret == 0 && tmp32 != 0) {
+ if (ret == 0 && tmp32 != 0)
entry->vno = tmp32;
- }
}
+ /* there might be a flags field here */
+ if(len + 4 + pos - curpos >= 8) {
+ ret = krb5_ret_uint32(cursor->sp, &utmp32);
+ if (ret == 0)
+ entry->flags = tmp32;
+ } else
+ entry->flags = 0;
+
+ entry->aliases = NULL;
+
if(start) *start = pos;
if(end) *end = pos + 4 + len;
out:
@@ -653,6 +669,15 @@ fkt_add_entry(krb5_context context,
krb5_storage_free(emem);
goto out;
}
+ ret = krb5_store_uint32 (emem, entry->flags);
+ if (ret) {
+ krb5_set_error_message(context, ret,
+ N_("Failed storing extended kvno "
+ "in keytab %s", ""),
+ d->filename);
+ krb5_storage_free(emem);
+ goto out;
+ }
}
ret = krb5_storage_to_data(emem, &keytab);
@@ -744,6 +769,7 @@ const krb5_kt_ops krb5_fkt_ops = {
fkt_resolve,
fkt_get_name,
fkt_close,
+ fkt_destroy,
NULL, /* get */
fkt_start_seq_get,
fkt_next_entry,
@@ -757,6 +783,7 @@ const krb5_kt_ops krb5_wrfkt_ops = {
fkt_resolve,
fkt_get_name,
fkt_close,
+ fkt_destroy,
NULL, /* get */
fkt_start_seq_get,
fkt_next_entry,
@@ -770,6 +797,7 @@ const krb5_kt_ops krb5_javakt_ops = {
fkt_resolve_java14,
fkt_get_name,
fkt_close,
+ fkt_destroy,
NULL, /* get */
fkt_start_seq_get,
fkt_next_entry,
diff --git a/source4/heimdal/lib/krb5/keytab_keyfile.c b/source4/heimdal/lib/krb5/keytab_keyfile.c
index 71d3d89d58..54666c7d44 100644
--- a/source4/heimdal/lib/krb5/keytab_keyfile.c
+++ b/source4/heimdal/lib/krb5/keytab_keyfile.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
#ifndef HEIMDAL_SMALLER
/* afs keyfile operations --------------------------------------- */
@@ -275,6 +273,8 @@ akf_next_entry(krb5_context context,
ret = 0;
entry->timestamp = time(NULL);
+ entry->flags = 0;
+ entry->aliases = NULL;
out:
krb5_storage_seek(cursor->sp, pos + 4 + 8, SEEK_SET);
@@ -440,6 +440,7 @@ const krb5_kt_ops krb5_akf_ops = {
akf_resolve,
akf_get_name,
akf_close,
+ NULL, /* destroy */
NULL, /* get */
akf_start_seq_get,
akf_next_entry,
diff --git a/source4/heimdal/lib/krb5/keytab_memory.c b/source4/heimdal/lib/krb5/keytab_memory.c
index defd10d67c..73ffa1c67d 100644
--- a/source4/heimdal/lib/krb5/keytab_memory.c
+++ b/source4/heimdal/lib/krb5/keytab_memory.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
/* memory operations -------------------------------------------- */
struct mkt_data {
@@ -228,6 +226,7 @@ const krb5_kt_ops krb5_mkt_ops = {
mkt_resolve,
mkt_get_name,
mkt_close,
+ NULL, /* destroy */
NULL, /* get */
mkt_start_seq_get,
mkt_next_entry,
diff --git a/source4/heimdal/lib/krb5/krb5.h b/source4/heimdal/lib/krb5/krb5.h
index 0ba4e7b54a..13dafacf21 100644
--- a/source4/heimdal/lib/krb5/krb5.h
+++ b/source4/heimdal/lib/krb5/krb5.h
@@ -51,6 +51,10 @@
#define KRB5KDC_ERR_KEY_EXP KRB5KDC_ERR_KEY_EXPIRED
#endif
+#ifndef KRB5_DEPRECATED
+#define KRB5_DEPRECATED __attribute__((deprecated))
+#endif
+
/* simple constants */
#ifndef TRUE
@@ -92,6 +96,8 @@ typedef Checksum krb5_checksum;
typedef ENCTYPE krb5_enctype;
+typedef struct krb5_get_init_creds_ctx *krb5_init_creds_context;
+
typedef heim_octet_string krb5_data;
/* PKINIT related forward declarations */
@@ -219,6 +225,8 @@ 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_PA_PKINIT_KX = 44,
+ /* Encryption type of the kdc session contribution in pk-init */
KRB5_KU_DIGEST_ENCRYPT = -18,
/* Encryption key usage used in the digest encryption field */
KRB5_KU_DIGEST_OPAQUE = -19,
@@ -272,13 +280,13 @@ typedef HostAddress krb5_address;
typedef HostAddresses krb5_addresses;
typedef enum krb5_keytype {
- KEYTYPE_NULL = 0,
- KEYTYPE_DES = 1,
- KEYTYPE_DES3 = 7,
- KEYTYPE_AES128 = 17,
- KEYTYPE_AES256 = 18,
- KEYTYPE_ARCFOUR = 23,
- KEYTYPE_ARCFOUR_56 = 24
+ KEYTYPE_NULL = ETYPE_NULL,
+ KEYTYPE_DES = ETYPE_DES_CBC_CRC,
+ KEYTYPE_DES3 = ETYPE_OLD_DES3_CBC_SHA1,
+ KEYTYPE_AES128 = ETYPE_AES128_CTS_HMAC_SHA1_96,
+ KEYTYPE_AES256 = ETYPE_AES256_CTS_HMAC_SHA1_96,
+ KEYTYPE_ARCFOUR = ETYPE_ARCFOUR_HMAC_MD5,
+ KEYTYPE_ARCFOUR_56 = ETYPE_ARCFOUR_HMAC_MD5_56
} krb5_keytype;
typedef EncryptionKey krb5_keyblock;
@@ -317,6 +325,7 @@ typedef const char *krb5_const_realm; /* stupid language */
typedef Principal krb5_principal_data;
typedef struct Principal *krb5_principal;
typedef const struct Principal *krb5_const_principal;
+typedef struct Principals *krb5_principals;
typedef time_t krb5_deltat;
typedef time_t krb5_timestamp;
@@ -478,6 +487,8 @@ typedef struct krb5_keytab_entry {
krb5_kvno vno;
krb5_keyblock keyblock;
uint32_t timestamp;
+ uint32_t flags;
+ krb5_principals aliases;
} krb5_keytab_entry;
typedef struct krb5_kt_cursor {
@@ -497,6 +508,7 @@ struct krb5_keytab_data {
krb5_error_code (*resolve)(krb5_context, const char*, krb5_keytab);
krb5_error_code (*get_name)(krb5_context, krb5_keytab, char*, size_t);
krb5_error_code (*close)(krb5_context, krb5_keytab);
+ krb5_error_code (*destroy)(krb5_context, krb5_keytab);
krb5_error_code (*get)(krb5_context, krb5_keytab, krb5_const_principal,
krb5_kvno, krb5_enctype, krb5_keytab_entry*);
krb5_error_code (*start_seq_get)(krb5_context, krb5_keytab, krb5_kt_cursor*);
@@ -593,7 +605,8 @@ typedef EncAPRepPart krb5_ap_rep_enc_part;
#define KRB5_TGS_NAME_SIZE (6)
#define KRB5_TGS_NAME ("krbtgt")
-
+#define KRB5_WELLKNOWN_NAME ("WELLKNOWN")
+#define KRB5_ANON_NAME ("ANONYMOUS")
#define KRB5_DIGEST_NAME ("digest")
typedef enum {
@@ -636,7 +649,7 @@ typedef krb5_error_code (*krb5_s2k_proc)(krb5_context /*context*/,
struct _krb5_get_init_creds_opt_private;
-typedef struct _krb5_get_init_creds_opt {
+struct _krb5_get_init_creds_opt {
krb5_flags flags;
krb5_deltat tkt_life;
krb5_deltat renew_life;
@@ -652,7 +665,9 @@ typedef struct _krb5_get_init_creds_opt {
int preauth_list_length;
krb5_data *salt;
struct _krb5_get_init_creds_opt_private *opt_private;
-} krb5_get_init_creds_opt;
+};
+
+typedef struct _krb5_get_init_creds_opt krb5_get_init_creds_opt;
#define KRB5_GET_INIT_CREDS_OPT_TKT_LIFE 0x0001
#define KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE 0x0002
@@ -661,7 +676,7 @@ typedef struct _krb5_get_init_creds_opt {
#define KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST 0x0010
#define KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST 0x0020
#define KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST 0x0040
-#define KRB5_GET_INIT_CREDS_OPT_SALT 0x0080
+#define KRB5_GET_INIT_CREDS_OPT_SALT 0x0080 /* no supported */
#define KRB5_GET_INIT_CREDS_OPT_ANONYMOUS 0x0100
#define KRB5_GET_INIT_CREDS_OPT_DISABLE_TRANSITED_CHECK 0x0200
@@ -727,22 +742,22 @@ enum {
typedef krb5_error_code (*krb5_send_to_kdc_func)(krb5_context,
void *,
krb5_krbhst_info *,
- time_t timeout,
+ time_t,
const krb5_data *,
krb5_data *);
-/* flags for krb5_parse_name_flags */
+/** flags for krb5_parse_name_flags */
enum {
- KRB5_PRINCIPAL_PARSE_NO_REALM = 1,
- KRB5_PRINCIPAL_PARSE_MUST_REALM = 2,
- KRB5_PRINCIPAL_PARSE_ENTERPRISE = 4
+ KRB5_PRINCIPAL_PARSE_NO_REALM = 1, /**< Require that there are no realm */
+ KRB5_PRINCIPAL_PARSE_REQUIRE_REALM = 2, /**< Require a realm present */
+ KRB5_PRINCIPAL_PARSE_ENTERPRISE = 4 /**< Parse as a NT-ENTERPRISE name */
};
-/* flags for krb5_unparse_name_flags */
+/** flags for krb5_unparse_name_flags */
enum {
- KRB5_PRINCIPAL_UNPARSE_SHORT = 1,
- KRB5_PRINCIPAL_UNPARSE_NO_REALM = 2,
- KRB5_PRINCIPAL_UNPARSE_DISPLAY = 4
+ KRB5_PRINCIPAL_UNPARSE_SHORT = 1, /**< No realm if it is the default realm */
+ KRB5_PRINCIPAL_UNPARSE_NO_REALM = 2, /**< No realm */
+ KRB5_PRINCIPAL_UNPARSE_DISPLAY = 4 /**< No quoting */
};
typedef struct krb5_sendto_ctx_data *krb5_sendto_ctx;
@@ -787,6 +802,20 @@ typedef struct krb5_crypto_iov {
} krb5_crypto_iov;
+/* Glue for MIT */
+
+typedef struct {
+ int32_t lr_type;
+ krb5_timestamp value;
+} krb5_last_req_entry;
+
+typedef krb5_error_code
+(*krb5_gic_process_last_req)(krb5_context, krb5_last_req_entry **, void *);
+
+/*
+ *
+ */
+
#include <krb5-protos.h>
/* variables */
@@ -810,5 +839,11 @@ extern KRB5_LIB_VARIABLE const krb5_kt_ops krb4_fkt_ops;
extern KRB5_LIB_VARIABLE const krb5_kt_ops krb5_srvtab_fkt_ops;
extern KRB5_LIB_VARIABLE const krb5_kt_ops krb5_any_ops;
+extern KRB5_LIB_VARIABLE const char *krb5_cc_type_api;
+extern KRB5_LIB_VARIABLE const char *krb5_cc_type_file;
+extern KRB5_LIB_VARIABLE const char *krb5_cc_type_memory;
+extern KRB5_LIB_VARIABLE const char *krb5_cc_type_kcm;
+extern KRB5_LIB_VARIABLE const char *krb5_cc_type_scc;
+
#endif /* __KRB5_H__ */
diff --git a/source4/heimdal/lib/krb5/krb5_ccapi.h b/source4/heimdal/lib/krb5/krb5_ccapi.h
index ec0cb3bc0b..5a7fe6a413 100644
--- a/source4/heimdal/lib/krb5/krb5_ccapi.h
+++ b/source4/heimdal/lib/krb5/krb5_ccapi.h
@@ -38,6 +38,10 @@
#include <krb5-types.h>
+ #ifdef __APPLE__
+#pragma pack(push,2)
+#endif
+
enum {
cc_credentials_v5 = 2
};
@@ -92,7 +96,7 @@ typedef struct cc_credentials_v5_t cc_credentials_v5_t;
typedef struct cc_credentials_t *cc_credentials_t;
typedef struct cc_credentials_iterator_t *cc_credentials_iterator_t;
typedef struct cc_string_t *cc_string_t;
-typedef time_t cc_time_t;
+typedef cc_uint32 cc_time_t;
typedef struct cc_data {
cc_uint32 type;
@@ -227,4 +231,9 @@ struct cc_context_t {
typedef cc_int32
(*cc_initialize_func)(cc_context_t*, cc_int32, cc_int32 *, char const **);
+#ifdef __APPLE__
+#pragma pack(pop)
+#endif
+
+
#endif /* KRB5_CCAPI_H */
diff --git a/source4/heimdal/lib/krb5/krb5_err.et b/source4/heimdal/lib/krb5/krb5_err.et
index c076992d0b..098e04b959 100644
--- a/source4/heimdal/lib/krb5/krb5_err.et
+++ b/source4/heimdal/lib/krb5/krb5_err.et
@@ -106,7 +106,13 @@ error_code PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED, "Public key encryption not suppo
#error_code ERR_KDC_NOT_FOUND, "IAKERB proxy could not find a KDC"
#error_code ERR_KDC_NO_RESPONSE, "IAKERB proxy never reeived a response from a KDC"
-# 82-127 are reserved
+# 82-93 are reserved
+
+index 94
+error_code INVALID_HASH_ALG, "Invalid OTP digest algorithm"
+error_code INVALID_ITERATION_COUNT, "Invalid OTP iteration count"
+
+# 97-127 are reserved
index 128
prefix
diff --git a/source4/heimdal/lib/krb5/krb5_locl.h b/source4/heimdal/lib/krb5/krb5_locl.h
index ced722f2d9..2d8bc07de3 100644
--- a/source4/heimdal/lib/krb5/krb5_locl.h
+++ b/source4/heimdal/lib/krb5/krb5_locl.h
@@ -36,9 +36,7 @@
#ifndef __KRB5_LOCL_H__
#define __KRB5_LOCL_H__
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include <errno.h>
#include <ctype.h>
@@ -214,11 +212,14 @@ struct _krb5_get_init_creds_opt_private {
krb5_get_init_creds_tristate req_pac;
/* PKINIT */
krb5_pk_init_ctx pk_init_ctx;
- KRB_ERROR *error;
krb5_get_init_creds_tristate addressless;
int flags;
#define KRB5_INIT_CREDS_CANONICALIZE 1
#define KRB5_INIT_CREDS_NO_C_CANON_CHECK 2
+ struct {
+ krb5_gic_process_last_req func;
+ void *ctx;
+ } lr;
};
typedef struct krb5_context_data {
@@ -261,6 +262,7 @@ typedef struct krb5_context_data {
int flags;
#define KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME 1
#define KRB5_CTX_F_CHECK_PAC 2
+#define KRB5_CTX_F_HOMEDIR_ACCESS 4
struct send_to_kdc *send_to_kdc;
} krb5_context_data;
@@ -295,6 +297,7 @@ struct krb5_pk_identity {
hx509_context hx509ctx;
hx509_verify_ctx verify_ctx;
hx509_certs certs;
+ hx509_cert cert;
hx509_certs anchors;
hx509_certs certpool;
hx509_revoke_ctx revokectx;
diff --git a/source4/heimdal/lib/krb5/krbhst.c b/source4/heimdal/lib/krb5/krbhst.c
index 7348ac3f00..e9111abec9 100644
--- a/source4/heimdal/lib/krb5/krbhst.c
+++ b/source4/heimdal/lib/krb5/krbhst.c
@@ -35,8 +35,6 @@
#include <resolve.h>
#include "locate_plugin.h"
-RCSID("$Id$");
-
static int
string_to_proto(const char *string)
{
@@ -61,8 +59,8 @@ srv_find_realm(krb5_context context, krb5_krbhst_info ***res, int *count,
const char *proto, const char *service, int port)
{
char domain[1024];
- struct dns_reply *r;
- struct resource_record *rr;
+ struct rk_dns_reply *r;
+ struct rk_resource_record *rr;
int num_srv;
int proto_num;
int def_port;
@@ -87,32 +85,32 @@ srv_find_realm(krb5_context context, krb5_krbhst_info ***res, int *count,
snprintf(domain, sizeof(domain), "_%s._%s.%s.", service, proto, realm);
- r = dns_lookup(domain, dns_type);
+ r = rk_dns_lookup(domain, dns_type);
if(r == NULL)
return KRB5_KDC_UNREACH;
for(num_srv = 0, rr = r->head; rr; rr = rr->next)
- if(rr->type == T_SRV)
+ if(rr->type == rk_ns_t_srv)
num_srv++;
*res = malloc(num_srv * sizeof(**res));
if(*res == NULL) {
- dns_free_data(r);
+ rk_dns_free_data(r);
krb5_set_error_message(context, ENOMEM,
N_("malloc: out of memory", ""));
return ENOMEM;
}
- dns_srv_order(r);
+ rk_dns_srv_order(r);
for(num_srv = 0, rr = r->head; rr; rr = rr->next)
- if(rr->type == T_SRV) {
+ if(rr->type == rk_ns_t_srv) {
krb5_krbhst_info *hi;
size_t len = strlen(rr->u.srv->target);
hi = calloc(1, sizeof(*hi) + len);
if(hi == NULL) {
- dns_free_data(r);
+ rk_dns_free_data(r);
while(--num_srv >= 0)
free((*res)[num_srv]);
free(*res);
@@ -134,7 +132,7 @@ srv_find_realm(krb5_context context, krb5_krbhst_info ***res, int *count,
*count = num_srv;
- dns_free_data(r);
+ rk_dns_free_data(r);
return 0;
}
@@ -948,7 +946,7 @@ gethostlist(krb5_context context, const char *realm,
return ENOMEM;
}
}
- (*hostlist)[nhost++] = NULL;
+ (*hostlist)[nhost] = NULL;
krb5_krbhst_free(context, handle);
return 0;
}
diff --git a/source4/heimdal/lib/krb5/locate_plugin.h b/source4/heimdal/lib/krb5/locate_plugin.h
index 529488ddfd..b1b1f0ef23 100644
--- a/source4/heimdal/lib/krb5/locate_plugin.h
+++ b/source4/heimdal/lib/krb5/locate_plugin.h
@@ -36,9 +36,7 @@
#ifndef HEIMDAL_KRB5_LOCATE_PLUGIN_H
#define HEIMDAL_KRB5_LOCATE_PLUGIN_H 1
-#include <krb5.h>
-
-#define KRB5_PLUGIN_LOCATE "resolve"
+#define KRB5_PLUGIN_LOCATE "service_locator"
enum locate_service_type {
locate_service_kdc = 1,
diff --git a/source4/heimdal/lib/krb5/log.c b/source4/heimdal/lib/krb5/log.c
index 587cf7ed97..31d267320f 100644
--- a/source4/heimdal/lib/krb5/log.c
+++ b/source4/heimdal/lib/krb5/log.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
struct facility {
int min;
int max;
diff --git a/source4/heimdal/lib/krb5/mcache.c b/source4/heimdal/lib/krb5/mcache.c
index 752608069d..78ef68db3d 100644
--- a/source4/heimdal/lib/krb5/mcache.c
+++ b/source4/heimdal/lib/krb5/mcache.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
typedef struct krb5_mcache {
char *name;
unsigned int refcnt;
diff --git a/source4/heimdal/lib/krb5/misc.c b/source4/heimdal/lib/krb5/misc.c
index 4cee5e22e1..e47383880c 100644
--- a/source4/heimdal/lib/krb5/misc.c
+++ b/source4/heimdal/lib/krb5/misc.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
krb5_error_code KRB5_LIB_FUNCTION
_krb5_s4u2self_to_checksumdata(krb5_context context,
const PA_S4U2Self *self,
diff --git a/source4/heimdal/lib/krb5/mit_glue.c b/source4/heimdal/lib/krb5/mit_glue.c
index f8f13922f5..dab5c6046a 100644
--- a/source4/heimdal/lib/krb5/mit_glue.c
+++ b/source4/heimdal/lib/krb5/mit_glue.c
@@ -31,8 +31,9 @@
* SUCH DAMAGE.
*/
+#define KRB5_DEPRECATED
+
#include "krb5_locl.h"
-RCSID("$Id$");
#ifndef HEIMDAL_SMALLER
@@ -315,8 +316,9 @@ krb5_c_enctype_compare(krb5_context context,
krb5_enctype e1,
krb5_enctype e2,
krb5_boolean *similar)
+ KRB5_DEPRECATED
{
- *similar = krb5_enctypes_compatible_keys(context, e1, e2);
+ *similar = (e1 == e2);
return 0;
}
@@ -370,4 +372,18 @@ krb5_c_prf(krb5_context context,
return ret;
}
+/**
+ * MIT compat glue
+ *
+ * @ingroup krb5_ccache
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_copy_creds(krb5_context context,
+ const krb5_ccache from,
+ krb5_ccache to)
+{
+ return krb5_cc_copy_cache(context, from, to);
+}
+
#endif /* HEIMDAL_SMALLER */
diff --git a/source4/heimdal/lib/krb5/mk_error.c b/source4/heimdal/lib/krb5/mk_error.c
index 989aa23d75..f623fc495b 100644
--- a/source4/heimdal/lib/krb5/mk_error.c
+++ b/source4/heimdal/lib/krb5/mk_error.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
krb5_error_code KRB5_LIB_FUNCTION
krb5_mk_error(krb5_context context,
krb5_error_code error_code,
diff --git a/source4/heimdal/lib/krb5/mk_priv.c b/source4/heimdal/lib/krb5/mk_priv.c
index 86a6b669b1..40f09ae33f 100644
--- a/source4/heimdal/lib/krb5/mk_priv.c
+++ b/source4/heimdal/lib/krb5/mk_priv.c
@@ -33,9 +33,6 @@
#include <krb5_locl.h>
-RCSID("$Id$");
-
-
krb5_error_code KRB5_LIB_FUNCTION
krb5_mk_priv(krb5_context context,
krb5_auth_context auth_context,
diff --git a/source4/heimdal/lib/krb5/mk_rep.c b/source4/heimdal/lib/krb5/mk_rep.c
index bba276183a..8eef0ea652 100644
--- a/source4/heimdal/lib/krb5/mk_rep.c
+++ b/source4/heimdal/lib/krb5/mk_rep.c
@@ -33,8 +33,6 @@
#include <krb5_locl.h>
-RCSID("$Id$");
-
krb5_error_code KRB5_LIB_FUNCTION
krb5_mk_rep(krb5_context context,
krb5_auth_context auth_context,
diff --git a/source4/heimdal/lib/krb5/mk_req.c b/source4/heimdal/lib/krb5/mk_req.c
index 1570637738..c87fa61293 100644
--- a/source4/heimdal/lib/krb5/mk_req.c
+++ b/source4/heimdal/lib/krb5/mk_req.c
@@ -33,8 +33,6 @@
#include <krb5_locl.h>
-RCSID("$Id$");
-
krb5_error_code KRB5_LIB_FUNCTION
krb5_mk_req_exact(krb5_context context,
krb5_auth_context *auth_context,
diff --git a/source4/heimdal/lib/krb5/mk_req_ext.c b/source4/heimdal/lib/krb5/mk_req_ext.c
index aba804716c..d130272aa1 100644
--- a/source4/heimdal/lib/krb5/mk_req_ext.c
+++ b/source4/heimdal/lib/krb5/mk_req_ext.c
@@ -33,8 +33,6 @@
#include <krb5_locl.h>
-RCSID("$Id$");
-
krb5_error_code
_krb5_mk_req_internal(krb5_context context,
krb5_auth_context *auth_context,
diff --git a/source4/heimdal/lib/krb5/n-fold.c b/source4/heimdal/lib/krb5/n-fold.c
index fa45b09f18..0623f6aae1 100644
--- a/source4/heimdal/lib/krb5/n-fold.c
+++ b/source4/heimdal/lib/krb5/n-fold.c
@@ -32,8 +32,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
static krb5_error_code
rr13(unsigned char *buf, size_t len)
{
@@ -109,8 +107,10 @@ _krb5_n_fold(const void *str, size_t len, void *key, size_t size)
unsigned char *tmp = malloc(maxlen);
unsigned char *buf = malloc(len);
- if (tmp == NULL || buf == NULL)
- return ENOMEM;
+ if (tmp == NULL || buf == NULL) {
+ ret = ENOMEM;
+ goto out;
+ }
memcpy(buf, str, len);
memset(key, 0, size);
@@ -129,9 +129,13 @@ _krb5_n_fold(const void *str, size_t len, void *key, size_t size)
}
} while(l != 0);
out:
- memset(buf, 0, len);
- free(buf);
- memset(tmp, 0, maxlen);
- free(tmp);
+ if (buf) {
+ memset(buf, 0, len);
+ free(buf);
+ }
+ if (tmp) {
+ memset(tmp, 0, maxlen);
+ free(tmp);
+ }
return ret;
}
diff --git a/source4/heimdal/lib/krb5/pac.c b/source4/heimdal/lib/krb5/pac.c
index 3c55eb3dc3..b66e79960d 100644
--- a/source4/heimdal/lib/krb5/pac.c
+++ b/source4/heimdal/lib/krb5/pac.c
@@ -34,8 +34,6 @@
#include "krb5_locl.h"
#include <wind.h>
-RCSID("$Id$");
-
struct PAC_INFO_BUFFER {
uint32_t type;
uint32_t buffersize;
@@ -613,6 +611,7 @@ verify_logonname(krb5_context context,
ret = wind_ucs2utf8(ucs2, ucs2len, s, &u8len);
free(ucs2);
if (ret) {
+ free(s);
krb5_set_error_message(context, ret, "Failed to convert to UTF-8");
return ret;
}
diff --git a/source4/heimdal/lib/krb5/padata.c b/source4/heimdal/lib/krb5/padata.c
index 022260e709..aa08248ed1 100644
--- a/source4/heimdal/lib/krb5/padata.c
+++ b/source4/heimdal/lib/krb5/padata.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
PA_DATA *
krb5_find_padata(PA_DATA *val, unsigned len, int type, int *idx)
{
diff --git a/source4/heimdal/lib/krb5/pkinit.c b/source4/heimdal/lib/krb5/pkinit.c
index de5e90a68e..18b5b5e017 100644
--- a/source4/heimdal/lib/krb5/pkinit.c
+++ b/source4/heimdal/lib/krb5/pkinit.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
struct krb5_dh_moduli {
char *name;
unsigned long bits;
@@ -60,7 +58,13 @@ struct krb5_pk_cert {
struct krb5_pk_init_ctx_data {
struct krb5_pk_identity *id;
- DH *dh;
+ enum { USE_RSA, USE_DH, USE_ECDH } keyex;
+ union {
+ DH *dh;
+#ifdef HAVE_OPENSSL
+ EC_KEY *eckey;
+#endif
+ } u;
krb5_data *clientDHNonce;
struct krb5_dh_moduli **m;
hx509_peer_info peer;
@@ -122,6 +126,45 @@ integer_to_BN(krb5_context context, const char *field, const heim_integer *f)
return bn;
}
+static krb5_error_code
+select_dh_group(krb5_context context, DH *dh, unsigned long bits,
+ struct krb5_dh_moduli **moduli)
+{
+ const struct krb5_dh_moduli *m;
+
+ 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_message(context, EINVAL,
+ N_("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)
+ return ENOMEM;
+ dh->g = integer_to_BN(context, "g", &m->g);
+ if (dh->g == NULL)
+ return ENOMEM;
+ dh->q = integer_to_BN(context, "q", &m->q);
+ if (dh->q == NULL)
+ return ENOMEM;
+
+ return 0;
+}
+
struct certfind {
const char *type;
const heim_oid *oid;
@@ -139,12 +182,12 @@ find_cert(krb5_context context, struct krb5_pk_identity *id,
struct certfind cf[3] = {
{ "PKINIT EKU" },
{ "MS EKU" },
- { "no" }
+ { "any (or no)" }
};
int i, ret;
- cf[0].oid = oid_id_pkekuoid();
- cf[1].oid = oid_id_pkinit_ms_eku();
+ cf[0].oid = &asn1_oid_id_pkekuoid;
+ cf[1].oid = &asn1_oid_id_pkinit_ms_eku;
cf[2].oid = NULL;
for (i = 0; i < sizeof(cf)/sizeof(cf[0]); i++) {
@@ -159,7 +202,7 @@ find_cert(krb5_context context, struct krb5_pk_identity *id,
if (ret == 0)
break;
pk_copy_error(context, id->hx509ctx, ret,
- "Failed cert for finding %s OID", cf[i].type);
+ "Failed finding certificate with %s OID", cf[i].type);
}
return ret;
}
@@ -173,37 +216,22 @@ create_signature(krb5_context context,
hx509_peer_info peer,
krb5_data *sd_data)
{
- hx509_cert cert = NULL;
- hx509_query *q = NULL;
- int ret;
-
- ret = hx509_query_alloc(id->hx509ctx, &q);
- if (ret) {
- pk_copy_error(context, id->hx509ctx, ret,
- "Allocate query to find signing certificate");
- return ret;
- }
+ int ret, flags = 0;
- hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
- hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE);
-
- ret = find_cert(context, id, q, &cert);
- hx509_query_free(id->hx509ctx, q);
- if (ret)
- return ret;
+ if (id->cert == NULL)
+ flags |= HX509_CMS_SIGNATURE_NO_SIGNER;
ret = hx509_cms_create_signed_1(id->hx509ctx,
- 0,
+ flags,
eContentType,
eContent->data,
eContent->length,
NULL,
- cert,
+ id->cert,
peer,
NULL,
id->certs,
sd_data);
- hx509_cert_free(cert);
if (ret) {
pk_copy_error(context, id->hx509ctx, ret,
"Create CMS signedData");
@@ -222,6 +250,9 @@ cert2epi(hx509_context context, void *ctx, hx509_cert c)
void *p;
int ret;
+ if (ids->len > 10)
+ return 0;
+
memset(&id, 0, sizeof(id));
ret = hx509_cert_get_subject(c, &subject);
@@ -319,7 +350,6 @@ static krb5_error_code
build_auth_pack(krb5_context context,
unsigned nonce,
krb5_pk_init_ctx ctx,
- DH *dh,
const KDC_REQ_BODY *body,
AuthPack *a)
{
@@ -368,12 +398,49 @@ build_auth_pack(krb5_context context,
if (ret)
return ret;
- if (dh) {
- DomainParameters dp;
- heim_integer dh_pub_key;
+ if (ctx->keyex == USE_DH || ctx->keyex == USE_ECDH) {
+ const char *moduli_file;
+ unsigned long dh_min_bits;
krb5_data dhbuf;
size_t size;
+ krb5_data_zero(&dhbuf);
+
+
+
+ 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, &ctx->m);
+ if (ret)
+ return ret;
+
+ ctx->u.dh = DH_new();
+ if (ctx->u.dh == NULL) {
+ krb5_set_error_message(context, ENOMEM,
+ N_("malloc: out of memory", ""));
+ return ENOMEM;
+ }
+
+ ret = select_dh_group(context, ctx->u.dh, dh_min_bits, ctx->m);
+ if (ret)
+ return ret;
+
+ if (DH_generate_key(ctx->u.dh) != 1) {
+ krb5_set_error_message(context, ENOMEM,
+ N_("pkinit: failed to generate DH key", ""));
+ return ENOMEM;
+ }
+
+
if (1 /* support_cached_dh */) {
ALLOC(a->clientDHNonce, 1);
if (a->clientDHNonce == NULL) {
@@ -385,7 +452,7 @@ build_auth_pack(krb5_context context,
krb5_clear_error_message(context);
return ret;
}
- memset(a->clientDHNonce->data, 0, a->clientDHNonce->length);
+ RAND_bytes(a->clientDHNonce->data, a->clientDHNonce->length);
ret = krb5_copy_data(context, a->clientDHNonce,
&ctx->clientDHNonce);
if (ret)
@@ -395,64 +462,135 @@ build_auth_pack(krb5_context context,
ALLOC(a->clientPublicValue, 1);
if (a->clientPublicValue == NULL)
return ENOMEM;
- ret = der_copy_oid(oid_id_dhpublicnumber(),
- &a->clientPublicValue->algorithm.algorithm);
- if (ret)
- return ret;
-
- memset(&dp, 0, sizeof(dp));
- ret = BN_to_integer(context, dh->p, &dp.p);
- if (ret) {
- free_DomainParameters(&dp);
- return ret;
- }
- ret = BN_to_integer(context, dh->g, &dp.g);
- if (ret) {
- free_DomainParameters(&dp);
- return ret;
- }
- ret = BN_to_integer(context, dh->q, &dp.q);
- if (ret) {
- free_DomainParameters(&dp);
- return ret;
- }
- dp.j = NULL;
- dp.validationParms = NULL;
+ if (ctx->keyex == USE_DH) {
+ DH *dh = ctx->u.dh;
+ DomainParameters dp;
+ heim_integer dh_pub_key;
- a->clientPublicValue->algorithm.parameters =
- malloc(sizeof(*a->clientPublicValue->algorithm.parameters));
- if (a->clientPublicValue->algorithm.parameters == NULL) {
+ ret = der_copy_oid(&asn1_oid_id_dhpublicnumber,
+ &a->clientPublicValue->algorithm.algorithm);
+ if (ret)
+ return ret;
+
+ memset(&dp, 0, sizeof(dp));
+
+ ret = BN_to_integer(context, dh->p, &dp.p);
+ if (ret) {
+ free_DomainParameters(&dp);
+ return ret;
+ }
+ ret = BN_to_integer(context, dh->g, &dp.g);
+ if (ret) {
+ free_DomainParameters(&dp);
+ return ret;
+ }
+ ret = BN_to_integer(context, dh->q, &dp.q);
+ if (ret) {
+ free_DomainParameters(&dp);
+ return ret;
+ }
+ dp.j = NULL;
+ dp.validationParms = NULL;
+
+ a->clientPublicValue->algorithm.parameters =
+ malloc(sizeof(*a->clientPublicValue->algorithm.parameters));
+ if (a->clientPublicValue->algorithm.parameters == NULL) {
+ free_DomainParameters(&dp);
+ return ret;
+ }
+
+ ASN1_MALLOC_ENCODE(DomainParameters,
+ a->clientPublicValue->algorithm.parameters->data,
+ a->clientPublicValue->algorithm.parameters->length,
+ &dp, &size, ret);
free_DomainParameters(&dp);
- return ret;
- }
+ if (ret)
+ return ret;
+ if (size != a->clientPublicValue->algorithm.parameters->length)
+ krb5_abortx(context, "Internal ASN1 encoder error");
+
+ ret = BN_to_integer(context, dh->pub_key, &dh_pub_key);
+ if (ret)
+ return ret;
+
+ ASN1_MALLOC_ENCODE(DHPublicKey, dhbuf.data, dhbuf.length,
+ &dh_pub_key, &size, ret);
+ der_free_heim_integer(&dh_pub_key);
+ if (ret)
+ return ret;
+ if (size != dhbuf.length)
+ krb5_abortx(context, "asn1 internal error");
+ } else if (ctx->keyex == USE_ECDH) {
+#ifdef HAVE_OPENSSL
+ ECParameters ecp;
+ unsigned char *p;
+ int len;
+
+ /* copy in public key, XXX find the best curve that the server support or use the clients curve if possible */
+
+ ecp.element = choice_ECParameters_namedCurve;
+ ret = der_copy_oid(&asn1_oid_id_ec_group_secp256r1,
+ &ecp.u.namedCurve);
+ if (ret)
+ return ret;
- ASN1_MALLOC_ENCODE(DomainParameters,
- a->clientPublicValue->algorithm.parameters->data,
- a->clientPublicValue->algorithm.parameters->length,
- &dp, &size, ret);
- free_DomainParameters(&dp);
- if (ret)
- return ret;
- if (size != a->clientPublicValue->algorithm.parameters->length)
- krb5_abortx(context, "Internal ASN1 encoder error");
+ ALLOC(a->clientPublicValue->algorithm.parameters, 1);
+ if (a->clientPublicValue->algorithm.parameters == NULL) {
+ free_ECParameters(&ecp);
+ return ENOMEM;
+ }
+ ASN1_MALLOC_ENCODE(ECParameters, p, len, &ecp, &size, ret);
+ free_ECParameters(&ecp);
+ if (ret)
+ return ret;
+ if (size != len)
+ krb5_abortx(context, "asn1 internal error");
+
+ a->clientPublicValue->algorithm.parameters->data = p;
+ a->clientPublicValue->algorithm.parameters->length = size;
- ret = BN_to_integer(context, dh->pub_key, &dh_pub_key);
- if (ret)
- return ret;
+ /* copy in public key */
- ASN1_MALLOC_ENCODE(DHPublicKey, dhbuf.data, dhbuf.length,
- &dh_pub_key, &size, ret);
- der_free_heim_integer(&dh_pub_key);
- if (ret)
- return ret;
- if (size != dhbuf.length)
- krb5_abortx(context, "asn1 internal error");
+ ret = der_copy_oid(&asn1_oid_id_ecPublicKey,
+ &a->clientPublicValue->algorithm.algorithm);
+ if (ret)
+ return ret;
+
+ ctx->u.eckey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
+ if (ctx->u.eckey == NULL)
+ return ENOMEM;
+
+ ret = EC_KEY_generate_key(ctx->u.eckey);
+ if (ret != 1)
+ return EINVAL;
+ /* encode onto dhkey */
+
+ len = i2o_ECPublicKey(ctx->u.eckey, NULL);
+ if (len <= 0)
+ abort();
+
+ dhbuf.data = malloc(len);
+ if (dhbuf.data == NULL)
+ abort();
+ dhbuf.length = len;
+ p = dhbuf.data;
+
+ len = i2o_ECPublicKey(ctx->u.eckey, &p);
+ if (len <= 0)
+ abort();
+
+ /* XXX verify that this is right with RFC3279 */
+#else
+ return EINVAL;
+#endif
+ } else
+ krb5_abortx(context, "internal error");
a->clientPublicValue->subjectPublicKey.length = dhbuf.length * 8;
a->clientPublicValue->subjectPublicKey.data = dhbuf.data;
}
-
+
{
a->supportedCMSTypes = calloc(1, sizeof(*a->supportedCMSTypes));
if (a->supportedCMSTypes == NULL)
@@ -546,13 +684,13 @@ pk_mk_padata(krb5_context context,
if (buf.length != size)
krb5_abortx(context, "internal ASN1 encoder error");
- oid = oid_id_pkcs7_data();
+ oid = &asn1_oid_id_pkcs7_data;
} else if (ctx->type == PKINIT_27) {
AuthPack ap;
memset(&ap, 0, sizeof(ap));
- ret = build_auth_pack(context, nonce, ctx, ctx->dh, req_body, &ap);
+ ret = build_auth_pack(context, nonce, ctx, req_body, &ap);
if (ret) {
free_AuthPack(&ap);
goto out;
@@ -569,7 +707,7 @@ pk_mk_padata(krb5_context context,
if (buf.length != size)
krb5_abortx(context, "internal ASN1 encoder error");
- oid = oid_id_pkauthdata();
+ oid = &asn1_oid_id_pkauthdata;
} else
krb5_abortx(context, "internal pkinit error");
@@ -579,7 +717,7 @@ pk_mk_padata(krb5_context context,
if (ret)
goto out;
- ret = hx509_cms_wrap_ContentInfo(oid_id_pkcs7_signedData(), &sd_buf, &buf);
+ ret = hx509_cms_wrap_ContentInfo(&asn1_oid_id_pkcs7_signedData, &sd_buf, &buf);
krb5_data_free(&sd_buf);
if (ret) {
krb5_set_error_message(context, ret,
@@ -648,8 +786,8 @@ pk_mk_padata(krb5_context context,
if (ret)
free(buf.data);
- if (ret == 0 && ctx->type == PKINIT_WIN2K)
- krb5_padata_add(context, md, KRB5_PADATA_PK_AS_09_BINDING, NULL, 0);
+ if (ret == 0)
+ krb5_padata_add(context, md, KRB5_PADATA_PK_AS_09_BINDING, NULL, 0);
out:
free_ContentInfo(&content_info);
@@ -721,14 +859,14 @@ _krb5_pk_mk_padata(krb5_context context,
return pk_mk_padata(context, ctx, req_body, nonce, md);
}
-krb5_error_code KRB5_LIB_FUNCTION
-_krb5_pk_verify_sign(krb5_context context,
- const void *data,
- size_t length,
- struct krb5_pk_identity *id,
- heim_oid *contentType,
- krb5_data *content,
- struct krb5_pk_cert **signer)
+static krb5_error_code
+pk_verify_sign(krb5_context context,
+ const void *data,
+ size_t length,
+ struct krb5_pk_identity *id,
+ heim_oid *contentType,
+ krb5_data *content,
+ struct krb5_pk_cert **signer)
{
hx509_certs signer_certs;
int ret;
@@ -737,6 +875,7 @@ _krb5_pk_verify_sign(krb5_context context,
ret = hx509_cms_verify_signed(id->hx509ctx,
id->verify_ctx,
+ HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH|HX509_CMS_VS_NO_KU_CHECK,
data,
length,
NULL,
@@ -902,7 +1041,7 @@ pk_verify_host(krb5_context context,
if (ctx->require_eku) {
ret = hx509_cert_check_eku(ctx->id->hx509ctx, host->cert,
- oid_id_pkkdcekuoid(), 0);
+ &asn1_oid_id_pkkdcekuoid, 0);
if (ret) {
krb5_set_error_message(context, ret,
N_("No PK-INIT KDC EKU in kdc certificate", ""));
@@ -915,7 +1054,7 @@ pk_verify_host(krb5_context context,
ret = hx509_cert_find_subjectAltName_otherName(ctx->id->hx509ctx,
host->cert,
- oid_id_pkinit_san(),
+ &asn1_oid_id_pkinit_san,
&list);
if (ret) {
krb5_set_error_message(context, ret,
@@ -995,16 +1134,20 @@ pk_rd_pa_reply_enckey(krb5_context context,
struct krb5_pk_cert *host = NULL;
krb5_data content;
heim_oid contentType = { 0, NULL };
+ int flags = HX509_CMS_UE_DONT_REQUIRE_KU_ENCIPHERMENT;
- if (der_heim_oid_cmp(oid_id_pkcs7_envelopedData(), dataType)) {
+ if (der_heim_oid_cmp(&asn1_oid_id_pkcs7_envelopedData, dataType)) {
krb5_set_error_message(context, EINVAL,
N_("PKINIT: Invalid content type", ""));
return EINVAL;
}
+ if (ctx->type == PKINIT_WIN2K)
+ flags |= HX509_CMS_UE_ALLOW_WEAK;
+
ret = hx509_cms_unenvelope(ctx->id->hx509ctx,
ctx->id->certs,
- HX509_CMS_UE_DONT_REQUIRE_KU_ENCIPHERMENT,
+ flags,
indata->data,
indata->length,
NULL,
@@ -1042,7 +1185,9 @@ pk_rd_pa_reply_enckey(krb5_context context,
heim_octet_string out;
ret = hx509_cms_unwrap_ContentInfo(&content, &type, &out, NULL);
- if (der_heim_oid_cmp(&type, oid_id_pkcs7_signedData())) {
+ if (ret)
+ goto out;
+ if (der_heim_oid_cmp(&type, &asn1_oid_id_pkcs7_signedData)) {
ret = EINVAL; /* XXX */
krb5_set_error_message(context, ret,
N_("PKINIT: Invalid content type", ""));
@@ -1061,13 +1206,13 @@ pk_rd_pa_reply_enckey(krb5_context context,
}
}
- ret = _krb5_pk_verify_sign(context,
- content.data,
- content.length,
- ctx->id,
- &contentType,
- &content,
- &host);
+ ret = pk_verify_sign(context,
+ content.data,
+ content.length,
+ ctx->id,
+ &contentType,
+ &content,
+ &host);
if (ret)
goto out;
@@ -1079,13 +1224,13 @@ pk_rd_pa_reply_enckey(krb5_context context,
#if 0
if (type == PKINIT_WIN2K) {
- if (der_heim_oid_cmp(&contentType, oid_id_pkcs7_data()) != 0) {
+ if (der_heim_oid_cmp(&contentType, &asn1_oid_id_pkcs7_data) != 0) {
ret = KRB5KRB_AP_ERR_MSG_TYPE;
krb5_set_error_message(context, ret, "PKINIT: reply key, wrong oid");
goto out;
}
} else {
- if (der_heim_oid_cmp(&contentType, oid_id_pkrkeydata()) != 0) {
+ if (der_heim_oid_cmp(&contentType, &asn1_oid_id_pkrkeydata) != 0) {
ret = KRB5KRB_AP_ERR_MSG_TYPE;
krb5_set_error_message(context, ret, "PKINIT: reply key, wrong oid");
goto out;
@@ -1131,32 +1276,33 @@ pk_rd_pa_reply_dh(krb5_context context,
PA_DATA *pa,
krb5_keyblock **key)
{
- unsigned char *p, *dh_gen_key = NULL;
+ const unsigned char *p;
+ unsigned char *dh_gen_key = NULL;
struct krb5_pk_cert *host = NULL;
BIGNUM *kdc_dh_pubkey = NULL;
KDCDHKeyInfo kdc_dh_info;
heim_oid contentType = { 0, NULL };
krb5_data content;
krb5_error_code ret;
- int dh_gen_keylen;
+ int dh_gen_keylen = 0;
size_t size;
krb5_data_zero(&content);
memset(&kdc_dh_info, 0, sizeof(kdc_dh_info));
- if (der_heim_oid_cmp(oid_id_pkcs7_signedData(), dataType)) {
+ if (der_heim_oid_cmp(&asn1_oid_id_pkcs7_signedData, dataType)) {
krb5_set_error_message(context, EINVAL,
N_("PKINIT: Invalid content type", ""));
return EINVAL;
}
- ret = _krb5_pk_verify_sign(context,
- indata->data,
- indata->length,
- ctx->id,
- &contentType,
- &content,
- &host);
+ ret = pk_verify_sign(context,
+ indata->data,
+ indata->length,
+ ctx->id,
+ &contentType,
+ &content,
+ &host);
if (ret)
goto out;
@@ -1165,7 +1311,7 @@ pk_rd_pa_reply_dh(krb5_context context,
if (ret)
goto out;
- if (der_heim_oid_cmp(&contentType, oid_id_pkdhkeydata())) {
+ if (der_heim_oid_cmp(&contentType, &asn1_oid_id_pkdhkeydata)) {
ret = KRB5KRB_AP_ERR_MSG_TYPE;
krb5_set_error_message(context, ret,
N_("pkinit - dh reply contains wrong oid", ""));
@@ -1221,7 +1367,7 @@ pk_rd_pa_reply_dh(krb5_context context,
p = kdc_dh_info.subjectPublicKey.data;
size = (kdc_dh_info.subjectPublicKey.length + 7) / 8;
- {
+ if (ctx->keyex == USE_DH) {
DHPublicKey k;
ret = decode_DHPublicKey(p, size, &k, NULL);
if (ret) {
@@ -1237,30 +1383,78 @@ pk_rd_pa_reply_dh(krb5_context context,
ret = ENOMEM;
goto out;
}
- }
- dh_gen_keylen = DH_size(ctx->dh);
- size = BN_num_bytes(ctx->dh->p);
- if (size < dh_gen_keylen)
- size = dh_gen_keylen;
- dh_gen_key = malloc(size);
- if (dh_gen_key == NULL) {
- ret = ENOMEM;
- krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
- goto out;
- }
- memset(dh_gen_key, 0, size - dh_gen_keylen);
+ dh_gen_keylen = DH_size(ctx->u.dh);
+ size = BN_num_bytes(ctx->u.dh->p);
+ if (size < dh_gen_keylen)
+ size = dh_gen_keylen;
- dh_gen_keylen = DH_compute_key(dh_gen_key + (size - dh_gen_keylen),
- kdc_dh_pubkey, ctx->dh);
- if (dh_gen_keylen == -1) {
- ret = KRB5KRB_ERR_GENERIC;
- krb5_set_error_message(context, ret,
- N_("PKINIT: Can't compute Diffie-Hellman key", ""));
- goto out;
- }
+ dh_gen_key = malloc(size);
+ if (dh_gen_key == NULL) {
+ ret = ENOMEM;
+ krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
+ goto out;
+ }
+ memset(dh_gen_key, 0, size - dh_gen_keylen);
+
+ dh_gen_keylen = DH_compute_key(dh_gen_key + (size - dh_gen_keylen),
+ kdc_dh_pubkey, ctx->u.dh);
+ if (dh_gen_keylen == -1) {
+ ret = KRB5KRB_ERR_GENERIC;
+ krb5_set_error_message(context, ret,
+ N_("PKINIT: Can't compute Diffie-Hellman key", ""));
+ goto out;
+ }
+ } else {
+#ifdef HAVE_OPENSSL
+ const EC_GROUP *group;
+ EC_KEY *public = NULL;
+
+ group = EC_KEY_get0_group(ctx->u.eckey);
+
+ public = EC_KEY_new();
+ if (public == NULL) {
+ ret = ENOMEM;
+ goto out;
+ }
+ if (EC_KEY_set_group(public, group) != 1) {
+ EC_KEY_free(public);
+ ret = ENOMEM;
+ goto out;
+ }
+ if (o2i_ECPublicKey(&public, &p, size) == NULL) {
+ EC_KEY_free(public);
+ ret = KRB5KRB_ERR_GENERIC;
+ krb5_set_error_message(context, ret,
+ N_("PKINIT: Can't parse ECDH public key", ""));
+ goto out;
+ }
+
+ size = (EC_GROUP_get_degree(group) + 7) / 8;
+ dh_gen_key = malloc(size);
+ if (dh_gen_key == NULL) {
+ EC_KEY_free(public);
+ ret = ENOMEM;
+ krb5_set_error_message(context, ret,
+ N_("malloc: out of memory", ""));
+ goto out;
+ }
+ dh_gen_keylen = ECDH_compute_key(dh_gen_key, size,
+ EC_KEY_get0_public_key(public), ctx->u.eckey, NULL);
+ EC_KEY_free(public);
+ if (dh_gen_keylen == -1) {
+ ret = KRB5KRB_ERR_GENERIC;
+ krb5_set_error_message(context, ret,
+ N_("PKINIT: Can't compute ECDH public key", ""));
+ goto out;
+ }
+#else
+ ret = EINVAL;
+#endif
+ }
+
*key = malloc (sizeof (**key));
if (*key == NULL) {
ret = ENOMEM;
@@ -1286,7 +1480,7 @@ pk_rd_pa_reply_dh(krb5_context context,
if (kdc_dh_pubkey)
BN_free(kdc_dh_pubkey);
if (dh_gen_key) {
- memset(dh_gen_key, 0, DH_size(ctx->dh));
+ memset(dh_gen_key, 0, dh_gen_keylen);
free(dh_gen_key);
}
if (host)
@@ -1343,12 +1537,42 @@ _krb5_pk_rd_pa_reply(krb5_context context,
case choice_PA_PK_AS_REP_encKeyPack:
os = rep.u.encKeyPack;
break;
- default:
+ default: {
+ PA_PK_AS_REP_BTMM btmm;
free_PA_PK_AS_REP(&rep);
- krb5_set_error_message(context, EINVAL,
- N_("PKINIT: -27 reply "
- "invalid content type", ""));
- return EINVAL;
+ memset(&rep, 0, sizeof(rep));
+
+ ret = decode_PA_PK_AS_REP_BTMM(pa->padata_value.data,
+ pa->padata_value.length,
+ &btmm,
+ &size);
+ if (ret) {
+ krb5_set_error_message(context, EINVAL,
+ N_("PKINIT: -27 reply "
+ "invalid content type", ""));
+ return EINVAL;
+ }
+
+ if (btmm.dhSignedData || btmm.encKeyPack == NULL) {
+ free_PA_PK_AS_REP_BTMM(&btmm);
+ ret = EINVAL;
+ krb5_set_error_message(context, ret,
+ N_("DH mode not supported for BTMM mode", ""));
+ return ret;
+ }
+
+ /*
+ * Transform to IETF style PK-INIT reply so that free works below
+ */
+
+ rep.element = choice_PA_PK_AS_REP_encKeyPack;
+ rep.u.encKeyPack.data = btmm.encKeyPack->data;
+ rep.u.encKeyPack.length = btmm.encKeyPack->length;
+ btmm.encKeyPack->data = NULL;
+ btmm.encKeyPack->length = 0;
+ free_PA_PK_AS_REP_BTMM(&btmm);
+ os = rep.u.encKeyPack;
+ }
}
ret = hx509_cms_unwrap_ContentInfo(&os, &oid, &data, NULL);
@@ -1484,18 +1708,10 @@ hx_pass_prompter(void *data, const hx509_prompt *prompter)
return 0;
}
-
-void KRB5_LIB_FUNCTION
-_krb5_pk_allow_proxy_certificate(struct krb5_pk_identity *id,
- int boolean)
-{
- hx509_verify_set_proxy_certificate(id->verify_ctx, boolean);
-}
-
-
krb5_error_code KRB5_LIB_FUNCTION
_krb5_pk_load_id(krb5_context context,
struct krb5_pk_identity **ret_id,
+ int flags,
const char *user_id,
const char *anchor_id,
char * const *chain_list,
@@ -1517,7 +1733,7 @@ _krb5_pk_load_id(krb5_context context,
return HEIM_PKINIT_NO_VALID_CA;
}
- if (user_id == NULL) {
+ if (user_id == NULL && (flags & 4) == 0) {
krb5_set_error_message(context, HEIM_PKINIT_NO_PRIVATE_KEY,
N_("PKINIT: No user certificate given", ""));
return HEIM_PKINIT_NO_PRIVATE_KEY;
@@ -1537,6 +1753,11 @@ _krb5_pk_load_id(krb5_context context,
goto out;
ret = hx509_lock_init(id->hx509ctx, &lock);
+ if (ret) {
+ pk_copy_error(context, id->hx509ctx, ret, "Failed init lock");
+ goto out;
+ }
+
if (password && password[0])
hx509_lock_add_password(lock, password);
@@ -1550,11 +1771,15 @@ _krb5_pk_load_id(krb5_context context,
goto out;
}
- ret = hx509_certs_init(id->hx509ctx, user_id, 0, lock, &id->certs);
- if (ret) {
- pk_copy_error(context, id->hx509ctx, ret,
- "Failed to init cert certs");
- goto out;
+ if (user_id) {
+ ret = hx509_certs_init(id->hx509ctx, user_id, 0, lock, &id->certs);
+ if (ret) {
+ pk_copy_error(context, id->hx509ctx, ret,
+ "Failed to init cert certs");
+ goto out;
+ }
+ } else {
+ id->certs = NULL;
}
ret = hx509_certs_init(id->hx509ctx, anchor_id, 0, NULL, &id->anchors);
@@ -1628,50 +1853,12 @@ _krb5_pk_load_id(krb5_context context,
} else
*ret_id = id;
- hx509_lock_free(lock);
+ if (lock)
+ hx509_lock_free(lock);
return ret;
}
-static krb5_error_code
-select_dh_group(krb5_context context, DH *dh, unsigned long bits,
- struct krb5_dh_moduli **moduli)
-{
- const struct krb5_dh_moduli *m;
-
- 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_message(context, EINVAL,
- N_("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)
- return ENOMEM;
- dh->g = integer_to_BN(context, "g", &m->g);
- if (dh->g == NULL)
- return ENOMEM;
- dh->q = integer_to_BN(context, "q", &m->q);
- if (dh->q == NULL)
- return ENOMEM;
-
- return 0;
-}
-
/*
*
*/
@@ -1752,8 +1939,10 @@ _krb5_parse_moduli_line(krb5_context context,
while (isspace((unsigned char)*p))
p++;
- if (*p == '#')
+ if (*p == '#') {
+ free(m1);
return 0;
+ }
ret = EINVAL;
p1 = strsep(&p, " \t");
@@ -1764,7 +1953,7 @@ _krb5_parse_moduli_line(krb5_context context,
goto out;
}
m1->name = strdup(p1);
- if (p1 == NULL) {
+ if (m1->name == NULL) {
ret = ENOMEM;
krb5_set_error_message(context, ret, N_("malloc: out of memeory", ""));
goto out;
@@ -2002,12 +2191,22 @@ _krb5_get_init_creds_opt_free_pkinit(krb5_get_init_creds_opt *opt)
if (opt->opt_private == NULL || opt->opt_private->pk_init_ctx == NULL)
return;
ctx = opt->opt_private->pk_init_ctx;
- if (ctx->dh)
- DH_free(ctx->dh);
- ctx->dh = NULL;
+ switch (ctx->keyex) {
+ case USE_DH:
+ DH_free(ctx->u.dh);
+ break;
+ case USE_RSA:
+ break;
+ case USE_ECDH:
+#ifdef HAVE_OPENSSL
+ EC_KEY_free(ctx->u.eckey);
+#endif
+ break;
+ }
if (ctx->id) {
hx509_verify_destroy_ctx(ctx->id->verify_ctx);
hx509_certs_free(&ctx->id->certs);
+ hx509_cert_free(ctx->id->cert);
hx509_certs_free(&ctx->id->anchors);
hx509_certs_free(&ctx->id->certpool);
hx509_context_free(&ctx->id->hx509ctx);
@@ -2056,9 +2255,6 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context,
N_("malloc: out of memory", ""));
return ENOMEM;
}
- opt->opt_private->pk_init_ctx->dh = NULL;
- opt->opt_private->pk_init_ctx->id = NULL;
- opt->opt_private->pk_init_ctx->clientDHNonce = NULL;
opt->opt_private->pk_init_ctx->require_binding = 0;
opt->opt_private->pk_init_ctx->require_eku = 1;
opt->opt_private->pk_init_ctx->require_krbtgt_otherName = 1;
@@ -2086,6 +2282,7 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context,
ret = _krb5_pk_load_id(context,
&opt->opt_private->pk_init_ctx->id,
+ flags,
user_id,
x509_anchors,
pool,
@@ -2099,50 +2296,58 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context,
return ret;
}
- if ((flags & 2) == 0) {
- const char *moduli_file;
- unsigned long dh_min_bits;
-
- moduli_file = krb5_config_get_string(context, NULL,
- "libdefaults",
- "moduli",
- NULL);
+ if (opt->opt_private->pk_init_ctx->id->certs) {
+ hx509_query *q = NULL;
+ hx509_cert cert = NULL;
+ hx509_context hx509ctx = opt->opt_private->pk_init_ctx->id->hx509ctx;
- 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);
+ ret = hx509_query_alloc(hx509ctx, &q);
if (ret) {
- _krb5_get_init_creds_opt_free_pkinit(opt);
+ pk_copy_error(context, hx509ctx, ret,
+ "Allocate query to find signing certificate");
return ret;
}
- opt->opt_private->pk_init_ctx->dh = DH_new();
- if (opt->opt_private->pk_init_ctx->dh == NULL) {
- _krb5_get_init_creds_opt_free_pkinit(opt);
- krb5_set_error_message(context, ENOMEM,
- N_("malloc: out of memory", ""));
- return ENOMEM;
- }
-
- 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);
+ hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
+ hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE);
+
+ ret = find_cert(context, opt->opt_private->pk_init_ctx->id, q, &cert);
+ hx509_query_free(hx509ctx, q);
+ if (ret)
return ret;
- }
- if (DH_generate_key(opt->opt_private->pk_init_ctx->dh) != 1) {
- _krb5_get_init_creds_opt_free_pkinit(opt);
- krb5_set_error_message(context, ENOMEM,
- N_("pkinit: failed to generate DH key", ""));
- return ENOMEM;
+ opt->opt_private->pk_init_ctx->id->cert = cert;
+ } else
+ opt->opt_private->pk_init_ctx->id->cert = NULL;
+
+ if ((flags & 2) == 0) {
+ hx509_context hx509ctx = opt->opt_private->pk_init_ctx->id->hx509ctx;
+ hx509_cert cert = opt->opt_private->pk_init_ctx->id->cert;
+
+ opt->opt_private->pk_init_ctx->keyex = USE_DH;
+
+ /*
+ * If its a ECDSA certs, lets select ECDSA as the keyex algorithm.
+ */
+ if (cert) {
+ AlgorithmIdentifier alg;
+
+ ret = hx509_cert_get_SPKI_AlgorithmIdentifier(hx509ctx, cert, &alg);
+ if (ret == 0) {
+ if (der_heim_oid_cmp(&alg.algorithm, &asn1_oid_id_ecPublicKey) == 0)
+ opt->opt_private->pk_init_ctx->keyex = USE_ECDH;
+ free_AlgorithmIdentifier(&alg);
+ }
}
+
+ } else {
+ opt->opt_private->pk_init_ctx->keyex = USE_RSA;
+
+ if (opt->opt_private->pk_init_ctx->id->certs == NULL) {
+ krb5_set_error_message(context, EINVAL,
+ N_("No anonymous pkinit support in RSA mode", ""));
+ return EINVAL;
+ }
}
return 0;
@@ -2152,3 +2357,122 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context,
return EINVAL;
#endif
}
+
+#ifdef PKINIT
+
+static int
+get_ms_san(hx509_context context, hx509_cert cert, char **upn)
+{
+ hx509_octet_string_list list;
+ int ret;
+
+ *upn = NULL;
+
+ ret = hx509_cert_find_subjectAltName_otherName(context,
+ cert,
+ &asn1_oid_id_pkinit_ms_san,
+ &list);
+ if (ret)
+ return 0;
+
+ if (list.len > 0 && list.val[0].length > 0)
+ ret = decode_MS_UPN_SAN(list.val[0].data, list.val[0].length,
+ upn, NULL);
+ else
+ ret = 1;
+ hx509_free_octet_string_list(&list);
+
+ return ret;
+}
+
+static int
+find_ms_san(hx509_context context, hx509_cert cert, void *ctx)
+{
+ char *upn;
+ int ret;
+
+ ret = get_ms_san(context, cert, &upn);
+ if (ret == 0)
+ free(upn);
+ return ret;
+}
+
+
+
+#endif
+
+/*
+ * Private since it need to be redesigned using krb5_get_init_creds()
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_pk_enterprise_cert(krb5_context context,
+ const char *user_id,
+ krb5_const_realm realm,
+ krb5_principal *principal)
+{
+#ifdef PKINIT
+ krb5_error_code ret;
+ hx509_context hx509ctx;
+ hx509_certs certs, result;
+ hx509_cert cert;
+ hx509_query *q;
+ char *name;
+
+ *principal = NULL;
+
+ if (user_id == NULL)
+ return ENOENT;
+
+ ret = hx509_context_init(&hx509ctx);
+ if (ret)
+ return ret;
+
+ ret = hx509_certs_init(hx509ctx, user_id, 0, NULL, &certs);
+ if (ret) {
+ pk_copy_error(context, hx509ctx, ret,
+ "Failed to init cert certs");
+ return ret;
+ }
+
+ ret = hx509_query_alloc(hx509ctx, &q);
+ if (ret) {
+ hx509_certs_free(&certs);
+ return ret;
+ }
+
+ hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
+ hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE);
+ hx509_query_match_eku(q, &asn1_oid_id_pkinit_ms_eku);
+ hx509_query_match_cmp_func(q, find_ms_san, NULL);
+
+ ret = hx509_certs_filter(hx509ctx, certs, q, &result);
+ hx509_query_free(hx509ctx, q);
+ hx509_certs_free(&certs);
+ if (ret)
+ return ret;
+
+ ret = hx509_get_one_cert(hx509ctx, result, &cert);
+ hx509_certs_free(&result);
+ if (ret)
+ return ret;
+
+ ret = get_ms_san(hx509ctx, cert, &name);
+ if (ret)
+ return ret;
+
+ ret = krb5_make_principal(context, principal, realm, name, NULL);
+ free(name);
+ hx509_context_free(&hx509ctx);
+ if (ret)
+ return ret;
+
+ krb5_principal_set_type(context, *principal, KRB5_NT_ENTERPRISE_PRINCIPAL);
+
+ return ret;
+#else
+ krb5_set_error_message(context, EINVAL,
+ N_("no support for PKINIT compiled in", ""));
+ return EINVAL;
+#endif
+}
diff --git a/source4/heimdal/lib/krb5/plugin.c b/source4/heimdal/lib/krb5/plugin.c
index a71dd8b6f7..844cb7ab88 100644
--- a/source4/heimdal/lib/krb5/plugin.c
+++ b/source4/heimdal/lib/krb5/plugin.c
@@ -32,7 +32,7 @@
*/
#include "krb5_locl.h"
-RCSID("$Id$");
+
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
#endif
@@ -54,7 +54,13 @@ struct plugin {
static HEIMDAL_MUTEX plugin_mutex = HEIMDAL_MUTEX_INITIALIZER;
static struct plugin *registered = NULL;
-static const char *plugin_dir = LIBDIR "/plugin/krb5";
+static const char *sysplugin_dirs[] = {
+ LIBDIR "/plugin/krb5",
+#ifdef __APPLE__
+ "/System/Library/KerberosPlugins/KerberosFrameworkPlugins",
+#endif
+ NULL
+};
/*
*
@@ -94,8 +100,11 @@ loadlib(krb5_context context,
#ifndef RTLD_LAZY
#define RTLD_LAZY 0
#endif
+#ifndef RTLD_LOCAL
+#define RTLD_LOCAL 0
+#endif
- (*e)->dsohandle = dlopen(lib, RTLD_LAZY);
+ (*e)->dsohandle = dlopen(lib, RTLD_LOCAL|RTLD_LAZY);
if ((*e)->dsohandle == NULL) {
free(*e);
*e = NULL;
@@ -173,7 +182,6 @@ _krb5_plugin_find(krb5_context context,
struct krb5_plugin *e;
struct plugin *p;
krb5_error_code ret;
- char *sysdirs[2] = { NULL, NULL };
char **dirs = NULL, **di;
struct dirent *entry;
char *path;
@@ -205,10 +213,8 @@ _krb5_plugin_find(krb5_context context,
dirs = krb5_config_get_strings(context, NULL, "libdefaults",
"plugin_dir", NULL);
- if (dirs == NULL) {
- sysdirs[0] = rk_UNCONST(plugin_dir);
- dirs = sysdirs;
- }
+ if (dirs == NULL)
+ dirs = rk_UNCONST(sysplugin_dirs);
for (di = dirs; *di != NULL; di++) {
@@ -218,7 +224,23 @@ _krb5_plugin_find(krb5_context context,
rk_cloexec(dirfd(d));
while ((entry = readdir(d)) != NULL) {
- asprintf(&path, "%s/%s", *di, entry->d_name);
+ char *n = entry->d_name;
+
+ /* skip . and .. */
+ if (n[0] == '.' && (n[1] == '\0' || (n[1] == '.' && n[2] == '\0')))
+ continue;
+
+ path = NULL;
+#ifdef __APPLE__
+ { /* support loading bundles on MacOS */
+ size_t len = strlen(n);
+ if (len > 7 && strcmp(&n[len - 7], ".bundle") == 0)
+ asprintf(&path, "%s/%s/Contents/MacOS/%.*s", *di, n, (int)(len - 7), n);
+ }
+#endif
+ if (path == NULL)
+ asprintf(&path, "%s/%s", *di, n);
+
if (path == NULL) {
ret = ENOMEM;
krb5_set_error_message(context, ret, "malloc: out of memory");
@@ -234,7 +256,7 @@ _krb5_plugin_find(krb5_context context,
}
closedir(d);
}
- if (dirs != sysdirs)
+ if (dirs != rk_UNCONST(sysplugin_dirs))
krb5_config_free_strings(dirs);
#endif /* HAVE_DLOPEN */
@@ -246,7 +268,7 @@ _krb5_plugin_find(krb5_context context,
return 0;
out:
- if (dirs && dirs != sysdirs)
+ if (dirs != rk_UNCONST(sysplugin_dirs))
krb5_config_free_strings(dirs);
if (d)
closedir(d);
diff --git a/source4/heimdal/lib/krb5/principal.c b/source4/heimdal/lib/krb5/principal.c
index f27355f2d8..50b7bb8813 100644
--- a/source4/heimdal/lib/krb5/principal.c
+++ b/source4/heimdal/lib/krb5/principal.c
@@ -32,7 +32,7 @@
*/
/**
- * @page page_principal The principal handing functions.
+ * @page krb5_principal_intro The principal handing functions.
*
* A Kerberos principal is a email address looking string that
* contains to parts separeted by a @. The later part is the kerbero
@@ -57,8 +57,6 @@ host/admin@H5L.ORG
#include <fnmatch.h>
#include "resolve.h"
-RCSID("$Id$");
-
#define princ_num_comp(P) ((P)->name.name_string.len)
#define princ_type(P) ((P)->name.name_type)
#define princ_comp(P) ((P)->name.name_string.val)
@@ -78,8 +76,6 @@ RCSID("$Id$");
* @ingroup krb5_principal
*/
-
-
void KRB5_LIB_FUNCTION
krb5_free_principal(krb5_context context,
krb5_principal p)
@@ -90,6 +86,18 @@ krb5_free_principal(krb5_context context,
}
}
+/**
+ * Set the type of the principal
+ *
+ * @param context A Kerberos context.
+ * @param principal principal to set the type for
+ * @param type the new type
+ *
+ * @return An krb5 error code, see krb5_get_error_message().
+ *
+ * @ingroup krb5_principal
+ */
+
void KRB5_LIB_FUNCTION
krb5_principal_set_type(krb5_context context,
krb5_principal principal,
@@ -127,8 +135,10 @@ krb5_principal_get_comp_string(krb5_context context,
*
* @param context Kerberos 5 context
* @param principal principal to query
+ *
* @return number of components in string
- * @ingroup krb5
+ *
+ * @ingroup krb5_principal
*/
unsigned int KRB5_LIB_FUNCTION
@@ -162,7 +172,7 @@ krb5_parse_name_flags(krb5_context context,
*principal = NULL;
-#define RFLAGS (KRB5_PRINCIPAL_PARSE_NO_REALM|KRB5_PRINCIPAL_PARSE_MUST_REALM)
+#define RFLAGS (KRB5_PRINCIPAL_PARSE_NO_REALM|KRB5_PRINCIPAL_PARSE_REQUIRE_REALM)
if ((flags & RFLAGS) == RFLAGS) {
krb5_set_error_message(context, KRB5_ERR_NO_SERVICE,
@@ -276,7 +286,7 @@ krb5_parse_name_flags(krb5_context context,
memcpy(realm, start, q - start);
realm[q - start] = 0;
}else{
- if (flags & KRB5_PRINCIPAL_PARSE_MUST_REALM) {
+ if (flags & KRB5_PRINCIPAL_PARSE_REQUIRE_REALM) {
ret = KRB5_PARSE_MALFORMED;
krb5_set_error_message(context, ret,
N_("realm NOT found in principal "
@@ -524,22 +534,6 @@ krb5_unparse_name_ext(krb5_context context,
#endif
-krb5_realm * KRB5_LIB_FUNCTION
-krb5_princ_realm(krb5_context context,
- krb5_principal principal)
-{
- return &princ_realm(principal);
-}
-
-
-void KRB5_LIB_FUNCTION
-krb5_princ_set_realm(krb5_context context,
- krb5_principal principal,
- krb5_realm *realm)
-{
- princ_realm(principal) = *realm;
-}
-
krb5_error_code KRB5_LIB_FUNCTION
krb5_principal_set_realm(krb5_context context,
krb5_principal principal,
@@ -821,6 +815,7 @@ krb5_principal_match(krb5_context context,
return TRUE;
}
+#if defined(KRB4) || !defined(HEIMDAL_SMALLER)
static struct v4_name_convert {
const char *from;
@@ -835,6 +830,10 @@ static struct v4_name_convert {
{ NULL, NULL }
};
+#endif
+
+#ifdef KRB4
+
/*
* return the converted instance name of `name' in `realm'.
* look in the configuration file and then in the default set above.
@@ -925,6 +924,8 @@ krb5_425_conv_principal_ext2(krb5_context context,
if(p){
instance = p;
ret = krb5_make_principal(context, &pr, realm, name, instance, NULL);
+ if (ret)
+ return ret;
if(func == NULL || (*func)(context, funcctx, pr)){
*princ = pr;
return 0;
@@ -938,23 +939,23 @@ krb5_425_conv_principal_ext2(krb5_context context,
krb5_boolean passed = FALSE;
char *inst = NULL;
#ifdef USE_RESOLVER
- struct dns_reply *r;
+ struct rk_dns_reply *r;
- r = dns_lookup(instance, "aaaa");
+ r = rk_dns_lookup(instance, "aaaa");
if (r) {
- if (r->head && r->head->type == T_AAAA) {
+ if (r->head && r->head->type == rk_ns_t_aaaa) {
inst = strdup(r->head->domain);
passed = TRUE;
}
- dns_free_data(r);
+ rk_dns_free_data(r);
} else {
- r = dns_lookup(instance, "a");
+ r = rk_dns_lookup(instance, "a");
if (r) {
- if(r->head && r->head->type == T_A) {
+ if(r->head && r->head->type == rk_ns_t_a) {
inst = strdup(r->head->domain);
passed = TRUE;
}
- dns_free_data(r);
+ rk_dns_free_data(r);
}
}
#else
@@ -998,6 +999,8 @@ krb5_425_conv_principal_ext2(krb5_context context,
snprintf(host, sizeof(host), "%s.%s", instance, realm);
strlwr(host);
ret = krb5_make_principal(context, &pr, realm, name, host, NULL);
+ if (ret)
+ return ret;
if((*func)(context, funcctx, pr)){
*princ = pr;
return 0;
@@ -1025,6 +1028,10 @@ krb5_425_conv_principal_ext2(krb5_context context,
for(d = domains; d && *d; d++){
snprintf(host, sizeof(host), "%s.%s", instance, *d);
ret = krb5_make_principal(context, &pr, realm, name, host, NULL);
+ if (ret) {
+ krb5_config_free_strings(domains);
+ return ret;
+ }
if(func == NULL || (*func)(context, funcctx, pr)){
*princ = pr;
krb5_config_free_strings(domains);
@@ -1049,6 +1056,8 @@ krb5_425_conv_principal_ext2(krb5_context context,
snprintf(host, sizeof(host), "%s.%s", instance, p);
local_host:
ret = krb5_make_principal(context, &pr, realm, name, host, NULL);
+ if (ret)
+ return ret;
if(func == NULL || (*func)(context, funcctx, pr)){
*princ = pr;
return 0;
@@ -1075,6 +1084,8 @@ no_host:
name = p;
ret = krb5_make_principal(context, &pr, realm, name, instance, NULL);
+ if (ret)
+ return ret;
if(func == NULL || (*func)(context, funcctx, pr)){
*princ = pr;
return 0;
@@ -1084,51 +1095,9 @@ no_host:
return HEIM_ERR_V4_PRINC_NO_CONV;
}
-static krb5_boolean
-convert_func(krb5_context conxtext, void *funcctx, krb5_principal principal)
-{
- krb5_boolean (*func)(krb5_context, krb5_principal) = funcctx;
- return (*func)(conxtext, principal);
-}
-
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_425_conv_principal_ext(krb5_context context,
- const char *name,
- const char *instance,
- const char *realm,
- krb5_boolean (*func)(krb5_context, krb5_principal),
- krb5_boolean resolve,
- krb5_principal *principal)
-{
- return krb5_425_conv_principal_ext2(context,
- name,
- instance,
- realm,
- func ? convert_func : NULL,
- func,
- resolve,
- principal);
-}
-
-
-
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_425_conv_principal(krb5_context context,
- const char *name,
- const char *instance,
- const char *realm,
- krb5_principal *princ)
-{
- krb5_boolean resolve = krb5_config_get_bool(context,
- NULL,
- "libdefaults",
- "v4_instance_resolve",
- NULL);
-
- return krb5_425_conv_principal_ext(context, name, instance, realm,
- NULL, resolve, princ);
-}
+#endif /* KRB4 */
+#ifndef HEIMDAL_SMALLER
static int
check_list(const krb5_config_binding *l, const char *name, const char **out)
@@ -1186,6 +1155,7 @@ name_convert(krb5_context context, const char *name, const char *realm,
return KRB5_NT_UNKNOWN;
/* didn't find it in config file, try built-in list */
+#ifdef KRB4
{
struct v4_name_convert *q;
for(q = default_v4_name_convert; q->from; q++) {
@@ -1195,6 +1165,7 @@ name_convert(krb5_context context, const char *name, const char *realm,
}
}
}
+#endif
return -1;
}
@@ -1273,6 +1244,8 @@ krb5_524_conv_principal(krb5_context context,
return 0;
}
+#endif /* !HEIMDAL_SMALLER */
+
/**
* Create a principal for the service running on hostname. If
* KRB5_NT_SRV_HST is used, the hostname is canonization using DNS (or
diff --git a/source4/heimdal/lib/krb5/prog_setup.c b/source4/heimdal/lib/krb5/prog_setup.c
index b368573b8d..4c060973d6 100644
--- a/source4/heimdal/lib/krb5/prog_setup.c
+++ b/source4/heimdal/lib/krb5/prog_setup.c
@@ -35,8 +35,6 @@
#include <getarg.h>
#include <err.h>
-RCSID("$Id$");
-
void KRB5_LIB_FUNCTION
krb5_std_usage(int code, struct getargs *args, int num_args)
{
diff --git a/source4/heimdal/lib/krb5/prompter_posix.c b/source4/heimdal/lib/krb5/prompter_posix.c
index 7d63935423..05deaff525 100644
--- a/source4/heimdal/lib/krb5/prompter_posix.c
+++ b/source4/heimdal/lib/krb5/prompter_posix.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
int KRB5_LIB_FUNCTION
krb5_prompter_posix (krb5_context context,
void *data,
diff --git a/source4/heimdal/lib/krb5/rd_cred.c b/source4/heimdal/lib/krb5/rd_cred.c
index dc51033019..f41edfa2b5 100644
--- a/source4/heimdal/lib/krb5/rd_cred.c
+++ b/source4/heimdal/lib/krb5/rd_cred.c
@@ -33,8 +33,6 @@
#include <krb5_locl.h>
-RCSID("$Id$");
-
static krb5_error_code
compare_addrs(krb5_context context,
krb5_address *a,
@@ -149,15 +147,18 @@ krb5_rd_cred(krb5_context context,
goto out;
}
- ret = krb5_decode_EncKrbCredPart (context,
- enc_krb_cred_part_data.data,
- enc_krb_cred_part_data.length,
- &enc_krb_cred_part,
- &len);
+ ret = decode_EncKrbCredPart(enc_krb_cred_part_data.data,
+ enc_krb_cred_part_data.length,
+ &enc_krb_cred_part,
+ &len);
if (enc_krb_cred_part_data.data != cred.enc_part.cipher.data)
krb5_data_free(&enc_krb_cred_part_data);
- if (ret)
+ if (ret) {
+ krb5_set_error_message(context, ret,
+ N_("Failed to decode "
+ "encrypte credential part", ""));
goto out;
+ }
/* check sender address */
diff --git a/source4/heimdal/lib/krb5/rd_error.c b/source4/heimdal/lib/krb5/rd_error.c
index 75ae8b1e8a..1561188fad 100644
--- a/source4/heimdal/lib/krb5/rd_error.c
+++ b/source4/heimdal/lib/krb5/rd_error.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
krb5_error_code KRB5_LIB_FUNCTION
krb5_rd_error(krb5_context context,
const krb5_data *msg,
diff --git a/source4/heimdal/lib/krb5/rd_priv.c b/source4/heimdal/lib/krb5/rd_priv.c
index 6778ccad88..fb6cfcee4f 100644
--- a/source4/heimdal/lib/krb5/rd_priv.c
+++ b/source4/heimdal/lib/krb5/rd_priv.c
@@ -33,8 +33,6 @@
#include <krb5_locl.h>
-RCSID("$Id$");
-
krb5_error_code KRB5_LIB_FUNCTION
krb5_rd_priv(krb5_context context,
krb5_auth_context auth_context,
diff --git a/source4/heimdal/lib/krb5/rd_rep.c b/source4/heimdal/lib/krb5/rd_rep.c
index 010726b180..2d5792cd40 100644
--- a/source4/heimdal/lib/krb5/rd_rep.c
+++ b/source4/heimdal/lib/krb5/rd_rep.c
@@ -33,8 +33,6 @@
#include <krb5_locl.h>
-RCSID("$Id$");
-
krb5_error_code KRB5_LIB_FUNCTION
krb5_rd_rep(krb5_context context,
krb5_auth_context auth_context,
@@ -48,7 +46,6 @@ krb5_rd_rep(krb5_context context,
krb5_crypto crypto;
krb5_data_zero (&data);
- ret = 0;
ret = decode_AP_REP(inbuf->data, inbuf->length, &ap_rep, &len);
if (ret)
@@ -82,13 +79,11 @@ krb5_rd_rep(krb5_context context,
krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
goto out;
}
- ret = krb5_decode_EncAPRepPart(context,
- data.data,
- data.length,
- *repl,
- &len);
- if (ret)
+ ret = decode_EncAPRepPart(data.data, data.length, *repl, &len);
+ if (ret) {
+ krb5_set_error_message(context, ret, N_("Failed to decode EncAPRepPart", ""));
return ret;
+ }
if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) {
if ((*repl)->ctime != auth_context->authenticator->ctime ||
diff --git a/source4/heimdal/lib/krb5/rd_req.c b/source4/heimdal/lib/krb5/rd_req.c
index a416f90c10..784427fe40 100644
--- a/source4/heimdal/lib/krb5/rd_req.c
+++ b/source4/heimdal/lib/krb5/rd_req.c
@@ -33,8 +33,6 @@
#include <krb5_locl.h>
-RCSID("$Id$");
-
static krb5_error_code
decrypt_tkt_enc_part (krb5_context context,
krb5_keyblock *key,
@@ -58,8 +56,11 @@ decrypt_tkt_enc_part (krb5_context context,
if (ret)
return ret;
- ret = krb5_decode_EncTicketPart(context, plain.data, plain.length,
- decr_part, &len);
+ ret = decode_EncTicketPart(plain.data, plain.length, decr_part, &len);
+ if (ret)
+ krb5_set_error_message(context, ret,
+ N_("Failed to decode encrypted "
+ "ticket part", ""));
krb5_data_free (&plain);
return ret;
}
@@ -95,8 +96,8 @@ decrypt_authenticator (krb5_context context,
if (ret)
return ret;
- ret = krb5_decode_Authenticator(context, plain.data, plain.length,
- authenticator, &len);
+ ret = decode_Authenticator(plain.data, plain.length,
+ authenticator, &len);
krb5_data_free (&plain);
return ret;
}
@@ -521,10 +522,20 @@ struct krb5_rd_req_out_ctx_data {
krb5_keyblock *keyblock;
krb5_flags ap_req_options;
krb5_ticket *ticket;
+ krb5_principal server;
};
-/*
+/**
+ * Allocate a krb5_rd_req_in_ctx as an input parameter to
+ * krb5_rd_req_ctx(). The caller should free the context with
+ * krb5_rd_req_in_ctx_free() when done with the context.
+ *
+ * @param context Keberos 5 context.
+ * @param ctx in ctx to krb5_rd_req_ctx().
+ *
+ * @return Kerberos 5 error code, see krb5_get_error_message().
*
+ * @ingroup krb5_auth
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -540,12 +551,26 @@ krb5_rd_req_in_ctx_alloc(krb5_context context, krb5_rd_req_in_ctx *ctx)
return 0;
}
+/**
+ * Set the keytab that krb5_rd_req_ctx() will use.
+ *
+ * @param context Keberos 5 context.
+ * @param in in ctx to krb5_rd_req_ctx().
+ * @param keytab keytab that krb5_rd_req_ctx() will use, only copy the
+ * pointer, so the caller must free they keytab after
+ * krb5_rd_req_in_ctx_free() is called.
+ *
+ * @return Kerberos 5 error code, see krb5_get_error_message().
+ *
+ * @ingroup krb5_auth
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_rd_req_in_set_keytab(krb5_context context,
krb5_rd_req_in_ctx in,
krb5_keytab keytab)
{
- in->keytab = keytab; /* XXX should make copy */
+ in->keytab = keytab;
return 0;
}
@@ -558,7 +583,7 @@ krb5_rd_req_in_set_keytab(krb5_context context,
*
* @return Kerberos 5 error code, see krb5_get_error_message().
*
- * @ingroup krb5
+ * @ingroup krb5_auth
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -605,28 +630,50 @@ krb5_rd_req_out_get_keyblock(krb5_context context,
return krb5_copy_keyblock(context, out->keyblock, keyblock);
}
+/**
+ * Get the principal that was used in the request from the
+ * client. Might not match whats in the ticket if krb5_rd_req_ctx()
+ * searched in the keytab for a matching key.
+ *
+ * @param context a Kerberos 5 context.
+ * @param out a krb5_rd_req_out_ctx from krb5_rd_req_ctx().
+ * @param principal return principal, free with krb5_free_principal().
+ *
+ * @ingroup krb5_auth
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_rd_req_out_get_server(krb5_context context,
+ krb5_rd_req_out_ctx out,
+ krb5_principal *principal)
+{
+ return krb5_copy_principal(context, out->server, principal);
+}
+
void KRB5_LIB_FUNCTION
krb5_rd_req_in_ctx_free(krb5_context context, krb5_rd_req_in_ctx ctx)
{
free(ctx);
}
-krb5_error_code KRB5_LIB_FUNCTION
-_krb5_rd_req_out_ctx_alloc(krb5_context context, krb5_rd_req_out_ctx *ctx)
-{
- *ctx = calloc(1, sizeof(**ctx));
- if (*ctx == NULL) {
- krb5_set_error_message(context, ENOMEM,
- N_("malloc: out of memory", ""));
- return ENOMEM;
- }
- return 0;
-}
+/**
+ * Free the krb5_rd_req_out_ctx.
+ *
+ * @param context Keberos 5 context.
+ * @param ctx krb5_rd_req_out_ctx context to free.
+ *
+ * @ingroup krb5_auth
+ */
void KRB5_LIB_FUNCTION
krb5_rd_req_out_ctx_free(krb5_context context, krb5_rd_req_out_ctx ctx)
{
- krb5_free_keyblock(context, ctx->keyblock);
+ if (ctx->ticket)
+ krb5_free_ticket(context, ctx->ticket);
+ if (ctx->keyblock)
+ krb5_free_keyblock(context, ctx->keyblock);
+ if (ctx->server)
+ krb5_free_principal(context, ctx->server);
free(ctx);
}
@@ -726,7 +773,6 @@ out:
static krb5_error_code
get_key_from_keytab(krb5_context context,
- krb5_auth_context *auth_context,
krb5_ap_req *ap_req,
krb5_const_principal server,
krb5_keytab keytab,
@@ -764,8 +810,28 @@ out:
return ret;
}
-/*
+/**
+ * The core server function that verify application authentication
+ * requests from clients.
+ *
+ * @param context Keberos 5 context.
+ * @param auth_context the authentication context, can be NULL, then
+ * default values for the authentication context will used.
+ * @param inbuf the (AP-REQ) authentication buffer
+ *
+ * @param server the server with authenticate as, if NULL the function
+ * will try to find any avaiable credentintial in the keytab
+ * that will verify the reply. The function will prefer the
+ * server the server client specified in the AP-REQ, but if
+ * there is no mach, it will try all keytab entries for a
+ * match. This have serious performance issues for larger keytabs.
*
+ * @param inctx control the behavior of the function, if NULL, the
+ * default behavior is used.
+ * @param outctx the return outctx, free with krb5_rd_req_out_ctx_free().
+ * @return Kerberos 5 error code, see krb5_get_error_message().
+ *
+ * @ingroup krb5_auth
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -778,12 +844,18 @@ krb5_rd_req_ctx(krb5_context context,
{
krb5_error_code ret;
krb5_ap_req ap_req;
- krb5_principal service = NULL;
krb5_rd_req_out_ctx o = NULL;
+ krb5_keytab id = NULL, keytab = NULL;
+ krb5_principal service = NULL;
- ret = _krb5_rd_req_out_ctx_alloc(context, &o);
- if (ret)
- goto out;
+ *outctx = NULL;
+
+ o = calloc(1, sizeof(*o));
+ if (o == NULL) {
+ krb5_set_error_message(context, ENOMEM,
+ N_("malloc: out of memory", ""));
+ return ENOMEM;
+ }
if (*auth_context == NULL) {
ret = krb5_auth_con_init(context, auth_context);
@@ -795,15 +867,14 @@ krb5_rd_req_ctx(krb5_context context,
if(ret)
goto out;
- if(server == NULL){
- ret = _krb5_principalname2krb5_principal(context,
- &service,
- ap_req.ticket.sname,
- ap_req.ticket.realm);
- if (ret)
- goto out;
- server = service;
- }
+ /* Save that principal that was in the request */
+ ret = _krb5_principalname2krb5_principal(context,
+ &o->server,
+ ap_req.ticket.sname,
+ ap_req.ticket.realm);
+ if (ret)
+ goto out;
+
if (ap_req.ap_options.use_session_key &&
(*auth_context)->keyblock == NULL) {
ret = KRB5KRB_AP_ERR_NOKEY;
@@ -813,49 +884,155 @@ krb5_rd_req_ctx(krb5_context context,
goto out;
}
+ if (inctx && inctx->keytab)
+ id = inctx->keytab;
+
if((*auth_context)->keyblock){
ret = krb5_copy_keyblock(context,
(*auth_context)->keyblock,
&o->keyblock);
if (ret)
goto out;
- } else if(inctx->keyblock){
+ } else if(inctx && inctx->keyblock){
ret = krb5_copy_keyblock(context,
inctx->keyblock,
&o->keyblock);
if (ret)
goto out;
} else {
- krb5_keytab keytab = NULL;
- if (inctx && inctx->keytab)
- keytab = inctx->keytab;
+ if(id == NULL) {
+ krb5_kt_default(context, &keytab);
+ id = keytab;
+ }
+ if (id == NULL)
+ goto out;
+
+ if (server == NULL) {
+ ret = _krb5_principalname2krb5_principal(context,
+ &service,
+ ap_req.ticket.sname,
+ ap_req.ticket.realm);
+ if (ret)
+ goto out;
+ server = service;
+ }
ret = get_key_from_keytab(context,
- auth_context,
&ap_req,
server,
- keytab,
+ id,
&o->keyblock);
- if(ret)
- goto out;
+ if (ret) {
+ /* If caller specified a server, fail. */
+ if (service == NULL)
+ goto out;
+ /* Otherwise, fall back to iterating over the keytab. This
+ * have serious performace issues for larger keytab.
+ */
+ o->keyblock = NULL;
+ }
}
- ret = krb5_verify_ap_req2(context,
- auth_context,
- &ap_req,
- server,
- o->keyblock,
- 0,
- &o->ap_req_options,
- &o->ticket,
- KRB5_KU_AP_REQ_AUTH);
+ if (o->keyblock) {
+ /*
+ * We got an exact keymatch, use that.
+ */
- if (ret)
- goto out;
+ ret = krb5_verify_ap_req2(context,
+ auth_context,
+ &ap_req,
+ server,
+ o->keyblock,
+ 0,
+ &o->ap_req_options,
+ &o->ticket,
+ KRB5_KU_AP_REQ_AUTH);
+
+ if (ret)
+ goto out;
+
+ } else {
+ /*
+ * Interate over keytab to find a key that can decrypt the request.
+ */
+
+ krb5_keytab_entry entry;
+ krb5_kt_cursor cursor;
+ int done = 0, kvno = 0;
+
+ memset(&cursor, 0, sizeof(cursor));
+
+ if (ap_req.ticket.enc_part.kvno)
+ kvno = *ap_req.ticket.enc_part.kvno;
+
+ ret = krb5_kt_start_seq_get(context, id, &cursor);
+ if (ret)
+ goto out;
+
+ done = 0;
+ while (!done) {
+ krb5_principal p;
+
+ ret = krb5_kt_next_entry(context, id, &entry, &cursor);
+ if (ret) {
+ _krb5_kt_principal_not_found(context, ret, id, o->server,
+ ap_req.ticket.enc_part.etype,
+ kvno);
+ goto out;
+ }
+
+ if (entry.keyblock.keytype != ap_req.ticket.enc_part.etype ||
+ (kvno && kvno != entry.vno)) {
+ krb5_kt_free_entry (context, &entry);
+ continue;
+ }
+
+ ret = krb5_verify_ap_req2(context,
+ auth_context,
+ &ap_req,
+ server,
+ &entry.keyblock,
+ 0,
+ &o->ap_req_options,
+ &o->ticket,
+ KRB5_KU_AP_REQ_AUTH);
+ if (ret) {
+ krb5_kt_free_entry (context, &entry);
+ continue;
+ }
+
+ /*
+ * Found a match, save the keyblock for PAC processing,
+ * and update the service principal in the ticket to match
+ * whatever is in the keytab.
+ */
+
+ ret = krb5_copy_keyblock(context,
+ &entry.keyblock,
+ &o->keyblock);
+ if (ret) {
+ krb5_kt_free_entry (context, &entry);
+ goto out;
+ }
+
+ ret = krb5_copy_principal(context, entry.principal, &p);
+ if (ret) {
+ krb5_kt_free_entry (context, &entry);
+ goto out;
+ }
+ krb5_free_principal(context, o->ticket->server);
+ o->ticket->server = p;
+
+ krb5_kt_free_entry (context, &entry);
+
+ done = 1;
+ }
+ krb5_kt_end_seq_get (context, id, &cursor);
+ }
/* If there is a PAC, verify its server signature */
- if (inctx->check_pac) {
+ if (inctx == NULL || inctx->check_pac) {
krb5_pac pac;
krb5_data data;
@@ -878,17 +1055,23 @@ krb5_rd_req_ctx(krb5_context context,
krb5_pac_free(context, pac);
if (ret)
goto out;
- }
- ret = 0;
+ } else
+ ret = 0;
}
out:
+
if (ret || outctx == NULL) {
krb5_rd_req_out_ctx_free(context, o);
} else
*outctx = o;
free_AP_REQ(&ap_req);
- if(service)
+
+ if (service)
krb5_free_principal(context, service);
+
+ if (keytab)
+ krb5_kt_close(context, keytab);
+
return ret;
}
diff --git a/source4/heimdal/lib/krb5/replay.c b/source4/heimdal/lib/krb5/replay.c
index 25a6da0262..37556cfbc5 100644
--- a/source4/heimdal/lib/krb5/replay.c
+++ b/source4/heimdal/lib/krb5/replay.c
@@ -34,8 +34,6 @@
#include "krb5_locl.h"
#include <vis.h>
-RCSID("$Id$");
-
struct krb5_rcache_data {
char *name;
};
diff --git a/source4/heimdal/lib/krb5/send_to_kdc.c b/source4/heimdal/lib/krb5/send_to_kdc.c
index 53c4a69a3f..50b42f2f10 100644
--- a/source4/heimdal/lib/krb5/send_to_kdc.c
+++ b/source4/heimdal/lib/krb5/send_to_kdc.c
@@ -34,8 +34,6 @@
#include "krb5_locl.h"
#include "send_to_kdc_plugin.h"
-RCSID("$Id$");
-
struct send_to_kdc {
krb5_send_to_kdc_func func;
void *data;
@@ -384,8 +382,8 @@ krb5_sendto (krb5_context context,
if (context->send_to_kdc) {
struct send_to_kdc *s = context->send_to_kdc;
- ret = (*s->func)(context, s->data,
- hi, context->kdc_timeout, send_data, receive);
+ ret = (*s->func)(context, s->data, hi,
+ context->kdc_timeout, send_data, receive);
if (ret == 0 && receive->length != 0)
goto out;
continue;
diff --git a/source4/heimdal/lib/krb5/set_default_realm.c b/source4/heimdal/lib/krb5/set_default_realm.c
index 6907b11d10..91201eeb53 100644
--- a/source4/heimdal/lib/krb5/set_default_realm.c
+++ b/source4/heimdal/lib/krb5/set_default_realm.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
/*
* Convert the simple string `s' into a NULL-terminated and freshly allocated
* list in `list'. Return an error code.
diff --git a/source4/heimdal/lib/krb5/store-int.h b/source4/heimdal/lib/krb5/store-int.h
index 8489f98453..0b7accb860 100644
--- a/source4/heimdal/lib/krb5/store-int.h
+++ b/source4/heimdal/lib/krb5/store-int.h
@@ -39,6 +39,7 @@ struct krb5_storage_data {
ssize_t (*fetch)(struct krb5_storage_data*, void*, size_t);
ssize_t (*store)(struct krb5_storage_data*, const void*, size_t);
off_t (*seek)(struct krb5_storage_data*, off_t, int);
+ int (*trunc)(struct krb5_storage_data*, off_t);
void (*free)(struct krb5_storage_data*);
krb5_flags flags;
int eof_code;
diff --git a/source4/heimdal/lib/krb5/store.c b/source4/heimdal/lib/krb5/store.c
index 47f9abe1de..2ba83ef0d5 100644
--- a/source4/heimdal/lib/krb5/store.c
+++ b/source4/heimdal/lib/krb5/store.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Kungliga Tekniska Högskolan
+ * Copyright (c) 1997-2008 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -34,8 +34,6 @@
#include "krb5_locl.h"
#include "store-int.h"
-RCSID("$Id$");
-
#define BYTEORDER_IS(SP, V) (((SP)->flags & KRB5_STORAGE_BYTEORDER_MASK) == (V))
#define BYTEORDER_IS_LE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_LE)
#define BYTEORDER_IS_BE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_BE)
@@ -54,12 +52,36 @@ krb5_storage_clear_flags(krb5_storage *sp, krb5_flags flags)
sp->flags &= ~flags;
}
+/**
+ * Return true or false depending on if the storage flags is set or
+ * not. NB testing for the flag 0 always return true.
+ *
+ * @param sp the storage buffer to check flags on
+ * @param flags The flags to test for
+ *
+ * @return true if all the flags are set, false if not.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_boolean KRB5_LIB_FUNCTION
krb5_storage_is_flags(krb5_storage *sp, krb5_flags flags)
{
return (sp->flags & flags) == flags;
}
+/**
+ * Set the new byte order of the storage buffer.
+ *
+ * @param sp the storage buffer to set the byte order for.
+ * @param byteorder the new byte order.
+ *
+ * The byte order are: KRB5_STORAGE_BYTEORDER_BE,
+ * KRB5_STORAGE_BYTEORDER_LE and KRB5_STORAGE_BYTEORDER_HOST.
+ *
+ * @ingroup krb5_storage
+ */
+
void KRB5_LIB_FUNCTION
krb5_storage_set_byteorder(krb5_storage *sp, krb5_flags byteorder)
{
@@ -67,36 +89,121 @@ krb5_storage_set_byteorder(krb5_storage *sp, krb5_flags byteorder)
sp->flags |= byteorder;
}
+/**
+ * Return the current byteorder for the buffer. See krb5_storage_set_byteorder() for the list or byte order contants.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_flags KRB5_LIB_FUNCTION
-krb5_storage_get_byteorder(krb5_storage *sp, krb5_flags byteorder)
+krb5_storage_get_byteorder(krb5_storage *sp)
{
return sp->flags & KRB5_STORAGE_BYTEORDER_MASK;
}
+/**
+ * Seek to a new offset.
+ *
+ * @param sp the storage buffer to seek in.
+ * @param offset the offset to seek
+ * @param whence relateive searching, SEEK_CUR from the current
+ * position, SEEK_END from the end, SEEK_SET absolute from the start.
+ *
+ * @return The new current offset
+ *
+ * @ingroup krb5_storage
+ */
+
off_t KRB5_LIB_FUNCTION
krb5_storage_seek(krb5_storage *sp, off_t offset, int whence)
{
return (*sp->seek)(sp, offset, whence);
}
+/**
+ * Truncate the storage buffer in sp to offset.
+ *
+ * @param sp the storage buffer to truncate.
+ * @param offset the offset to truncate too.
+ *
+ * @return An Kerberos 5 error code.
+ *
+ * @ingroup krb5_storage
+ */
+
+int KRB5_LIB_FUNCTION
+krb5_storage_truncate(krb5_storage *sp, off_t offset)
+{
+ return (*sp->trunc)(sp, offset);
+}
+
+/**
+ * Read to the storage buffer.
+ *
+ * @param sp the storage buffer to read from
+ * @param buf the buffer to store the data in
+ * @param len the length to read
+ *
+ * @return The length of data read (can be shorter then len), or negative on error.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_ssize_t KRB5_LIB_FUNCTION
krb5_storage_read(krb5_storage *sp, void *buf, size_t len)
{
return sp->fetch(sp, buf, len);
}
+/**
+ * Write to the storage buffer.
+ *
+ * @param sp the storage buffer to write to
+ * @param buf the buffer to write to the storage buffer
+ * @param len the length to write
+ *
+ * @return The length of data written (can be shorter then len), or negative on error.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_ssize_t KRB5_LIB_FUNCTION
krb5_storage_write(krb5_storage *sp, const void *buf, size_t len)
{
return sp->store(sp, buf, len);
}
+/**
+ * Set the return code that will be used when end of storage is reached.
+ *
+ * @param sp the storage
+ * @param code the error code to return on end of storage
+ *
+ * @ingroup krb5_storage
+ */
+
void KRB5_LIB_FUNCTION
krb5_storage_set_eof_code(krb5_storage *sp, int code)
{
sp->eof_code = code;
}
+/**
+ * Get the return code that will be used when end of storage is reached.
+ *
+ * @param sp the storage
+ *
+ * @return storage error code
+ *
+ * @ingroup krb5_storage
+ */
+
+int KRB5_LIB_FUNCTION
+krb5_storage_get_eof_code(krb5_storage *sp)
+{
+ return sp->eof_code;
+}
+
krb5_ssize_t KRB5_LIB_FUNCTION
_krb5_put_int(void *buffer, unsigned long value, size_t size)
{
@@ -121,6 +228,16 @@ _krb5_get_int(void *buffer, unsigned long *value, size_t size)
return size;
}
+/**
+ * Free a krb5 storage.
+ *
+ * @param sp the storage to free.
+ *
+ * @return An Kerberos 5 error code.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_storage_free(krb5_storage *sp)
{
@@ -131,15 +248,29 @@ krb5_storage_free(krb5_storage *sp)
return 0;
}
+/**
+ * Copy the contnent of storage
+ *
+ * @param sp the storage to copy to a data
+ * @param data the copied data, free with krb5_data_free()
+ *
+ * @return 0 for success, or a Kerberos 5 error code on failure.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_storage_to_data(krb5_storage *sp, krb5_data *data)
{
- off_t pos;
- size_t size;
+ off_t pos, size;
krb5_error_code ret;
pos = sp->seek(sp, 0, SEEK_CUR);
+ if (pos < 0)
+ return HEIM_ERR_NOT_SEEKABLE;
size = (size_t)sp->seek(sp, 0, SEEK_END);
+ if (size > (size_t)-1)
+ return HEIM_ERR_TOO_BIG;
ret = krb5_data_alloc (data, size);
if (ret) {
sp->seek(sp, pos, SEEK_SET);
@@ -170,6 +301,18 @@ krb5_store_int(krb5_storage *sp,
return 0;
}
+/**
+ * Store a int32 to storage, byte order is controlled by the settings
+ * on the storage, see krb5_storage_set_byteorder().
+ *
+ * @param sp the storage to write too
+ * @param value the value to store
+ *
+ * @return 0 for success, or a Kerberos 5 error code on failure.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_store_int32(krb5_storage *sp,
int32_t value)
@@ -181,6 +324,18 @@ krb5_store_int32(krb5_storage *sp,
return krb5_store_int(sp, value, 4);
}
+/**
+ * Store a uint32 to storage, byte order is controlled by the settings
+ * on the storage, see krb5_storage_set_byteorder().
+ *
+ * @param sp the storage to write too
+ * @param value the value to store
+ *
+ * @return 0 for success, or a Kerberos 5 error code on failure.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_store_uint32(krb5_storage *sp,
uint32_t value)
@@ -232,6 +387,18 @@ krb5_ret_uint32(krb5_storage *sp,
return ret;
}
+/**
+ * Store a int16 to storage, byte order is controlled by the settings
+ * on the storage, see krb5_storage_set_byteorder().
+ *
+ * @param sp the storage to write too
+ * @param value the value to store
+ *
+ * @return 0 for success, or a Kerberos 5 error code on failure.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_store_int16(krb5_storage *sp,
int16_t value)
@@ -243,6 +410,18 @@ krb5_store_int16(krb5_storage *sp,
return krb5_store_int(sp, value, 2);
}
+/**
+ * Store a uint16 to storage, byte order is controlled by the settings
+ * on the storage, see krb5_storage_set_byteorder().
+ *
+ * @param sp the storage to write too
+ * @param value the value to store
+ *
+ * @return 0 for success, or a Kerberos 5 error code on failure.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_store_uint16(krb5_storage *sp,
uint16_t value)
@@ -281,6 +460,17 @@ krb5_ret_uint16(krb5_storage *sp,
return ret;
}
+/**
+ * Store a int8 to storage.
+ *
+ * @param sp the storage to write too
+ * @param value the value to store
+ *
+ * @return 0 for success, or a Kerberos 5 error code on failure.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_store_int8(krb5_storage *sp,
int8_t value)
@@ -293,6 +483,17 @@ krb5_store_int8(krb5_storage *sp,
return 0;
}
+/**
+ * Store a uint8 to storage.
+ *
+ * @param sp the storage to write too
+ * @param value the value to store
+ *
+ * @return 0 for success, or a Kerberos 5 error code on failure.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_store_uint8(krb5_storage *sp,
uint8_t value)
@@ -326,6 +527,17 @@ krb5_ret_uint8(krb5_storage *sp,
return ret;
}
+/**
+ * Store a data to the storage.
+ *
+ * @param sp the storage buffer to write to
+ * @param data the buffer to store.
+ *
+ * @return 0 on success, a Kerberos 5 error code on failure.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_store_data(krb5_storage *sp,
krb5_data data)
@@ -343,6 +555,17 @@ krb5_store_data(krb5_storage *sp,
return 0;
}
+/**
+ * Parse a data from the storage.
+ *
+ * @param sp the storage buffer to read from
+ * @param data the parsed data
+ *
+ * @return 0 on success, a Kerberos 5 error code on failure.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_ret_data(krb5_storage *sp,
krb5_data *data)
@@ -594,6 +817,17 @@ krb5_ret_principal(krb5_storage *sp,
return 0;
}
+/**
+ * Store a keyblock to the storage.
+ *
+ * @param sp the storage buffer to write to
+ * @param p the keyblock to write
+ *
+ * @return 0 on success, a Kerberos 5 error code on failure.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_store_keyblock(krb5_storage *sp, krb5_keyblock p)
{
@@ -612,6 +846,17 @@ krb5_store_keyblock(krb5_storage *sp, krb5_keyblock p)
return ret;
}
+/**
+ * Read a keyblock from the storage.
+ *
+ * @param sp the storage buffer to write to
+ * @param p the keyblock read from storage, free using krb5_free_keyblock()
+ *
+ * @return 0 on success, a Kerberos 5 error code on failure.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_ret_keyblock(krb5_storage *sp, krb5_keyblock *p)
{
@@ -631,6 +876,17 @@ krb5_ret_keyblock(krb5_storage *sp, krb5_keyblock *p)
return ret;
}
+/**
+ * Write a times block to storage.
+ *
+ * @param sp the storage buffer to write to
+ * @param times the times block to write.
+ *
+ * @return 0 on success, a Kerberos 5 error code on failure.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_store_times(krb5_storage *sp, krb5_times times)
{
@@ -645,6 +901,17 @@ krb5_store_times(krb5_storage *sp, krb5_times times)
return ret;
}
+/**
+ * Read a times block from the storage.
+ *
+ * @param sp the storage buffer to write to
+ * @param times the times block read from storage
+ *
+ * @return 0 on success, a Kerberos 5 error code on failure.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_ret_times(krb5_storage *sp, krb5_times *times)
{
@@ -903,6 +1170,8 @@ krb5_store_creds_tag(krb5_storage *sp, krb5_creds *creds)
header |= SC_ADDRESSES;
ret = krb5_store_int32(sp, header);
+ if (ret)
+ return ret;
if (creds->client) {
ret = krb5_store_principal(sp, creds->client);
diff --git a/source4/heimdal/lib/krb5/store_emem.c b/source4/heimdal/lib/krb5/store_emem.c
index 8a587600fd..4be89b6564 100644
--- a/source4/heimdal/lib/krb5/store_emem.c
+++ b/source4/heimdal/lib/krb5/store_emem.c
@@ -34,8 +34,6 @@
#include "krb5_locl.h"
#include "store-int.h"
-RCSID("$Id$");
-
typedef struct emem_storage{
unsigned char *base;
size_t size;
@@ -67,7 +65,7 @@ emem_store(krb5_storage *sp, const void *data, size_t size)
sz *= 2;
base = realloc(s->base, sz);
if(base == NULL)
- return 0;
+ return -1;
s->size = sz;
s->base = base;
s->ptr = (unsigned char*)base + off;
@@ -104,6 +102,34 @@ emem_seek(krb5_storage *sp, off_t offset, int whence)
return s->ptr - s->base;
}
+static int
+emem_trunc(krb5_storage *sp, off_t offset)
+{
+ emem_storage *s = (emem_storage*)sp->data;
+ /*
+ * If offset is larget then current size, or current size is
+ * shrunk more then half of the current size, adjust buffer.
+ */
+ if (offset > s->size || (s->size / 2) > offset) {
+ void *base;
+ size_t off;
+ off = s->ptr - s->base;
+ base = realloc(s->base, offset);
+ if(base == NULL)
+ return ENOMEM;
+ if (offset > s->size)
+ memset((char *)base + s->size, 0, offset - s->size);
+ s->size = offset;
+ s->base = base;
+ s->ptr = (unsigned char *)base + off;
+ }
+ s->len = offset;
+ if ((s->ptr - s->base) > offset)
+ s->ptr = s->base + offset;
+ return 0;
+}
+
+
static void
emem_free(krb5_storage *sp)
{
@@ -112,6 +138,21 @@ emem_free(krb5_storage *sp)
free(s->base);
}
+/**
+ * Create a elastic (allocating) memory storage backend. Memory is
+ * allocated on demand. Free returned krb5_storage with
+ * krb5_storage_free().
+ *
+ * @return A krb5_storage on success, or NULL on out of memory error.
+ *
+ * @ingroup krb5_storage
+ *
+ * @sa krb5_storage_from_mem()
+ * @sa krb5_storage_from_readonly_mem()
+ * @sa krb5_storage_from_fd()
+ * @sa krb5_storage_from_data()
+ */
+
krb5_storage * KRB5_LIB_FUNCTION
krb5_storage_emem(void)
{
@@ -142,6 +183,7 @@ krb5_storage_emem(void)
sp->fetch = emem_fetch;
sp->store = emem_store;
sp->seek = emem_seek;
+ sp->trunc = emem_trunc;
sp->free = emem_free;
return sp;
}
diff --git a/source4/heimdal/lib/krb5/store_fd.c b/source4/heimdal/lib/krb5/store_fd.c
index fe3c513ee9..38d67ae4d3 100644
--- a/source4/heimdal/lib/krb5/store_fd.c
+++ b/source4/heimdal/lib/krb5/store_fd.c
@@ -34,8 +34,6 @@
#include "krb5_locl.h"
#include "store-int.h"
-RCSID("$Id$");
-
typedef struct fd_storage {
int fd;
} fd_storage;
@@ -60,12 +58,33 @@ fd_seek(krb5_storage * sp, off_t offset, int whence)
return lseek(FD(sp), offset, whence);
}
+static int
+fd_trunc(krb5_storage * sp, off_t offset)
+{
+ if (ftruncate(FD(sp), offset) == -1)
+ return errno;
+ return 0;
+}
+
static void
fd_free(krb5_storage * sp)
{
close(FD(sp));
}
+/**
+ *
+ *
+ * @return A krb5_storage on success, or NULL on out of memory error.
+ *
+ * @ingroup krb5_storage
+ *
+ * @sa krb5_storage_from_emem()
+ * @sa krb5_storage_from_mem()
+ * @sa krb5_storage_from_readonly_mem()
+ * @sa krb5_storage_from_data()
+ */
+
krb5_storage * KRB5_LIB_FUNCTION
krb5_storage_from_fd(int fd)
{
@@ -93,6 +112,7 @@ krb5_storage_from_fd(int fd)
sp->fetch = fd_fetch;
sp->store = fd_store;
sp->seek = fd_seek;
+ sp->trunc = fd_trunc;
sp->free = fd_free;
return sp;
}
diff --git a/source4/heimdal/lib/krb5/store_mem.c b/source4/heimdal/lib/krb5/store_mem.c
index 5c7cd17fba..db1abc1e90 100644
--- a/source4/heimdal/lib/krb5/store_mem.c
+++ b/source4/heimdal/lib/krb5/store_mem.c
@@ -34,8 +34,6 @@
#include "krb5_locl.h"
#include "store-int.h"
-RCSID("$Id$");
-
typedef struct mem_storage{
unsigned char *base;
size_t size;
@@ -93,6 +91,37 @@ mem_seek(krb5_storage *sp, off_t offset, int whence)
return s->ptr - s->base;
}
+static int
+mem_trunc(krb5_storage *sp, off_t offset)
+{
+ mem_storage *s = (mem_storage*)sp->data;
+ if(offset > s->size)
+ return ERANGE;
+ s->size = offset;
+ if ((s->ptr - s->base) > offset)
+ s->ptr = s->base + offset;
+ return 0;
+}
+
+static int
+mem_no_trunc(krb5_storage *sp, off_t offset)
+{
+ return EINVAL;
+}
+
+/**
+ *
+ *
+ * @return A krb5_storage on success, or NULL on out of memory error.
+ *
+ * @ingroup krb5_storage
+ *
+ * @sa krb5_storage_from_emem()
+ * @sa krb5_storage_from_readonly_mem()
+ * @sa krb5_storage_from_data()
+ * @sa krb5_storage_from_fd()
+ */
+
krb5_storage * KRB5_LIB_FUNCTION
krb5_storage_from_mem(void *buf, size_t len)
{
@@ -114,16 +143,43 @@ krb5_storage_from_mem(void *buf, size_t len)
sp->fetch = mem_fetch;
sp->store = mem_store;
sp->seek = mem_seek;
+ sp->trunc = mem_trunc;
sp->free = NULL;
return sp;
}
+/**
+ *
+ *
+ * @return A krb5_storage on success, or NULL on out of memory error.
+ *
+ * @ingroup krb5_storage
+ *
+ * @sa krb5_storage_from_emem()
+ * @sa krb5_storage_from_mem()
+ * @sa krb5_storage_from_readonly_mem()
+ * @sa krb5_storage_from_fd()
+ */
+
krb5_storage * KRB5_LIB_FUNCTION
krb5_storage_from_data(krb5_data *data)
{
return krb5_storage_from_mem(data->data, data->length);
}
+/**
+ *
+ *
+ * @return A krb5_storage on success, or NULL on out of memory error.
+ *
+ * @ingroup krb5_storage
+ *
+ * @sa krb5_storage_from_emem()
+ * @sa krb5_storage_from_mem()
+ * @sa krb5_storage_from_data()
+ * @sa krb5_storage_from_fd()
+ */
+
krb5_storage * KRB5_LIB_FUNCTION
krb5_storage_from_readonly_mem(const void *buf, size_t len)
{
@@ -145,6 +201,7 @@ krb5_storage_from_readonly_mem(const void *buf, size_t len)
sp->fetch = mem_fetch;
sp->store = mem_no_store;
sp->seek = mem_seek;
+ sp->trunc = mem_no_trunc;
sp->free = NULL;
return sp;
}
diff --git a/source4/heimdal/lib/krb5/ticket.c b/source4/heimdal/lib/krb5/ticket.c
index db78626570..86c4924506 100644
--- a/source4/heimdal/lib/krb5/ticket.c
+++ b/source4/heimdal/lib/krb5/ticket.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
krb5_error_code KRB5_LIB_FUNCTION
krb5_free_ticket(krb5_context context,
krb5_ticket *ticket)
@@ -301,3 +299,485 @@ krb5_ticket_get_authorization_data_type(krb5_context context,
}
return 0;
}
+
+static krb5_error_code
+check_server_referral(krb5_context context,
+ krb5_kdc_rep *rep,
+ unsigned flags,
+ krb5_const_principal requested,
+ krb5_const_principal returned,
+ krb5_keyblock * key)
+{
+ krb5_error_code ret;
+ PA_ServerReferralData ref;
+ krb5_crypto session;
+ EncryptedData ed;
+ size_t len;
+ krb5_data data;
+ PA_DATA *pa;
+ int i = 0, cmp;
+
+ if (rep->kdc_rep.padata == NULL)
+ goto noreferral;
+
+ pa = krb5_find_padata(rep->kdc_rep.padata->val,
+ rep->kdc_rep.padata->len,
+ KRB5_PADATA_SERVER_REFERRAL, &i);
+ if (pa == NULL)
+ goto noreferral;
+
+ memset(&ed, 0, sizeof(ed));
+ memset(&ref, 0, sizeof(ref));
+
+ ret = decode_EncryptedData(pa->padata_value.data,
+ pa->padata_value.length,
+ &ed, &len);
+ if (ret)
+ return ret;
+ if (len != pa->padata_value.length) {
+ free_EncryptedData(&ed);
+ krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
+ N_("Referral EncryptedData wrong for realm %s",
+ "realm"), requested->realm);
+ return KRB5KRB_AP_ERR_MODIFIED;
+ }
+
+ ret = krb5_crypto_init(context, key, 0, &session);
+ if (ret) {
+ free_EncryptedData(&ed);
+ return ret;
+ }
+
+ ret = krb5_decrypt_EncryptedData(context, session,
+ KRB5_KU_PA_SERVER_REFERRAL,
+ &ed, &data);
+ free_EncryptedData(&ed);
+ krb5_crypto_destroy(context, session);
+ if (ret)
+ return ret;
+
+ ret = decode_PA_ServerReferralData(data.data, data.length, &ref, &len);
+ if (ret) {
+ krb5_data_free(&data);
+ return ret;
+ }
+ krb5_data_free(&data);
+
+ if (strcmp(requested->realm, returned->realm) != 0) {
+ free_PA_ServerReferralData(&ref);
+ krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
+ N_("server ref realm mismatch, "
+ "requested realm %s got back %s", ""),
+ requested->realm, returned->realm);
+ return KRB5KRB_AP_ERR_MODIFIED;
+ }
+
+ if (returned->name.name_string.len == 2 &&
+ strcmp(returned->name.name_string.val[0], KRB5_TGS_NAME) == 0)
+ {
+ const char *realm = returned->name.name_string.val[1];
+
+ if (ref.referred_realm == NULL
+ || strcmp(*ref.referred_realm, realm) != 0)
+ {
+ free_PA_ServerReferralData(&ref);
+ krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
+ N_("tgt returned with wrong ref", ""));
+ return KRB5KRB_AP_ERR_MODIFIED;
+ }
+ } else if (krb5_principal_compare(context, returned, requested) == 0) {
+ free_PA_ServerReferralData(&ref);
+ krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
+ N_("req princ no same as returned", ""));
+ return KRB5KRB_AP_ERR_MODIFIED;
+ }
+
+ if (ref.requested_principal_name) {
+ cmp = _krb5_principal_compare_PrincipalName(context,
+ requested,
+ ref.requested_principal_name);
+ if (!cmp) {
+ free_PA_ServerReferralData(&ref);
+ krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
+ N_("referred principal not same "
+ "as requested", ""));
+ return KRB5KRB_AP_ERR_MODIFIED;
+ }
+ } else if (flags & EXTRACT_TICKET_AS_REQ) {
+ free_PA_ServerReferralData(&ref);
+ krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
+ N_("Requested principal missing on AS-REQ", ""));
+ return KRB5KRB_AP_ERR_MODIFIED;
+ }
+
+ free_PA_ServerReferralData(&ref);
+
+ return ret;
+noreferral:
+ if (krb5_principal_compare(context, requested, returned) == FALSE) {
+ krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
+ N_("Not same server principal returned "
+ "as requested", ""));
+ return KRB5KRB_AP_ERR_MODIFIED;
+ }
+ return 0;
+}
+
+
+/*
+ * Verify referral data
+ */
+
+
+static krb5_error_code
+check_client_referral(krb5_context context,
+ krb5_kdc_rep *rep,
+ krb5_const_principal requested,
+ krb5_const_principal mapped,
+ krb5_keyblock const * key)
+{
+ krb5_error_code ret;
+ PA_ClientCanonicalized canon;
+ krb5_crypto crypto;
+ krb5_data data;
+ PA_DATA *pa;
+ size_t len;
+ int i = 0;
+
+ if (rep->kdc_rep.padata == NULL)
+ goto noreferral;
+
+ pa = krb5_find_padata(rep->kdc_rep.padata->val,
+ rep->kdc_rep.padata->len,
+ KRB5_PADATA_CLIENT_CANONICALIZED, &i);
+ if (pa == NULL)
+ goto noreferral;
+
+ ret = decode_PA_ClientCanonicalized(pa->padata_value.data,
+ pa->padata_value.length,
+ &canon, &len);
+ if (ret) {
+ krb5_set_error_message(context, ret,
+ N_("Failed to decode ClientCanonicalized "
+ "from realm %s", ""), requested->realm);
+ return ret;
+ }
+
+ ASN1_MALLOC_ENCODE(PA_ClientCanonicalizedNames, data.data, data.length,
+ &canon.names, &len, ret);
+ if (ret) {
+ free_PA_ClientCanonicalized(&canon);
+ return ret;
+ }
+ if (data.length != len)
+ krb5_abortx(context, "internal asn.1 error");
+
+ ret = krb5_crypto_init(context, key, 0, &crypto);
+ if (ret) {
+ free(data.data);
+ free_PA_ClientCanonicalized(&canon);
+ return ret;
+ }
+
+ ret = krb5_verify_checksum(context, crypto, KRB5_KU_CANONICALIZED_NAMES,
+ data.data, data.length,
+ &canon.canon_checksum);
+ krb5_crypto_destroy(context, crypto);
+ free(data.data);
+ if (ret) {
+ krb5_set_error_message(context, ret,
+ N_("Failed to verify client canonicalized "
+ "data from realm %s", ""),
+ requested->realm);
+ free_PA_ClientCanonicalized(&canon);
+ return ret;
+ }
+
+ if (!_krb5_principal_compare_PrincipalName(context,
+ requested,
+ &canon.names.requested_name))
+ {
+ free_PA_ClientCanonicalized(&canon);
+ krb5_set_error_message(context, KRB5_PRINC_NOMATCH,
+ N_("Requested name doesn't match"
+ " in client referral", ""));
+ return KRB5_PRINC_NOMATCH;
+ }
+ if (!_krb5_principal_compare_PrincipalName(context,
+ mapped,
+ &canon.names.mapped_name))
+ {
+ free_PA_ClientCanonicalized(&canon);
+ krb5_set_error_message(context, KRB5_PRINC_NOMATCH,
+ N_("Mapped name doesn't match"
+ " in client referral", ""));
+ return KRB5_PRINC_NOMATCH;
+ }
+
+ return 0;
+
+noreferral:
+ if (krb5_principal_compare(context, requested, mapped) == FALSE) {
+ krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
+ N_("Not same client principal returned "
+ "as requested", ""));
+ return KRB5KRB_AP_ERR_MODIFIED;
+ }
+ return 0;
+}
+
+
+static krb5_error_code
+decrypt_tkt (krb5_context context,
+ krb5_keyblock *key,
+ krb5_key_usage usage,
+ krb5_const_pointer decrypt_arg,
+ krb5_kdc_rep *dec_rep)
+{
+ krb5_error_code ret;
+ krb5_data data;
+ size_t size;
+ krb5_crypto crypto;
+
+ ret = krb5_crypto_init(context, key, 0, &crypto);
+ if (ret)
+ return ret;
+
+ ret = krb5_decrypt_EncryptedData (context,
+ crypto,
+ usage,
+ &dec_rep->kdc_rep.enc_part,
+ &data);
+ krb5_crypto_destroy(context, crypto);
+
+ if (ret)
+ return ret;
+
+ ret = decode_EncASRepPart(data.data,
+ data.length,
+ &dec_rep->enc_part,
+ &size);
+ if (ret)
+ ret = decode_EncTGSRepPart(data.data,
+ data.length,
+ &dec_rep->enc_part,
+ &size);
+ krb5_data_free (&data);
+ if (ret) {
+ krb5_set_error_message(context, ret,
+ N_("Failed to decode encpart in ticket", ""));
+ return ret;
+ }
+ return 0;
+}
+
+int
+_krb5_extract_ticket(krb5_context context,
+ krb5_kdc_rep *rep,
+ krb5_creds *creds,
+ krb5_keyblock *key,
+ krb5_const_pointer keyseed,
+ krb5_key_usage key_usage,
+ krb5_addresses *addrs,
+ unsigned nonce,
+ unsigned flags,
+ krb5_decrypt_proc decrypt_proc,
+ krb5_const_pointer decryptarg)
+{
+ krb5_error_code ret;
+ krb5_principal tmp_principal;
+ size_t len;
+ time_t tmp_time;
+ krb5_timestamp sec_now;
+
+ /* decrypt */
+
+ if (decrypt_proc == NULL)
+ decrypt_proc = decrypt_tkt;
+
+ ret = (*decrypt_proc)(context, key, key_usage, decryptarg, rep);
+ if (ret)
+ goto out;
+
+ /* save session key */
+
+ creds->session.keyvalue.length = 0;
+ creds->session.keyvalue.data = NULL;
+ creds->session.keytype = rep->enc_part.key.keytype;
+ ret = krb5_data_copy (&creds->session.keyvalue,
+ rep->enc_part.key.keyvalue.data,
+ rep->enc_part.key.keyvalue.length);
+ if (ret) {
+ krb5_clear_error_message(context);
+ goto out;
+ }
+
+ /*
+ * HACK:
+ * this is really a ugly hack, to support using the Netbios Domain Name
+ * as realm against windows KDC's, they always return the full realm
+ * based on the DNS Name.
+ */
+ flags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH;
+ flags |= EXTRACT_TICKET_ALLOW_CNAME_MISMATCH;
+
+ /* compare client and save */
+ ret = _krb5_principalname2krb5_principal (context,
+ &tmp_principal,
+ rep->kdc_rep.cname,
+ rep->kdc_rep.crealm);
+ if (ret)
+ goto out;
+
+ /* check client referral and save principal */
+ /* anonymous here ? */
+ if((flags & EXTRACT_TICKET_ALLOW_CNAME_MISMATCH) == 0) {
+ ret = check_client_referral(context, rep,
+ creds->client,
+ tmp_principal,
+ &creds->session);
+ if (ret) {
+ krb5_free_principal (context, tmp_principal);
+ goto out;
+ }
+ }
+ krb5_free_principal (context, creds->client);
+ creds->client = tmp_principal;
+
+ /* check server referral and save principal */
+ ret = _krb5_principalname2krb5_principal (context,
+ &tmp_principal,
+ rep->kdc_rep.ticket.sname,
+ rep->kdc_rep.ticket.realm);
+ if (ret)
+ goto out;
+ if((flags & EXTRACT_TICKET_ALLOW_SERVER_MISMATCH) == 0){
+ ret = check_server_referral(context,
+ rep,
+ flags,
+ creds->server,
+ tmp_principal,
+ &creds->session);
+ if (ret) {
+ krb5_free_principal (context, tmp_principal);
+ goto out;
+ }
+ }
+ krb5_free_principal(context, creds->server);
+ creds->server = tmp_principal;
+
+ /* verify names */
+ if(flags & EXTRACT_TICKET_MATCH_REALM){
+ const char *srealm = krb5_principal_get_realm(context, creds->server);
+ const char *crealm = krb5_principal_get_realm(context, creds->client);
+
+ if (strcmp(rep->enc_part.srealm, srealm) != 0 ||
+ strcmp(rep->enc_part.srealm, crealm) != 0)
+ {
+ ret = KRB5KRB_AP_ERR_MODIFIED;
+ krb5_clear_error_message(context);
+ goto out;
+ }
+ }
+
+ /* compare nonces */
+
+ if (nonce != rep->enc_part.nonce) {
+ ret = KRB5KRB_AP_ERR_MODIFIED;
+ krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
+ goto out;
+ }
+
+ /* set kdc-offset */
+
+ krb5_timeofday (context, &sec_now);
+ if (rep->enc_part.flags.initial
+ && context->kdc_sec_offset == 0
+ && krb5_config_get_bool (context, NULL,
+ "libdefaults",
+ "kdc_timesync",
+ NULL)) {
+ context->kdc_sec_offset = rep->enc_part.authtime - sec_now;
+ krb5_timeofday (context, &sec_now);
+ }
+
+ /* check all times */
+
+ if (rep->enc_part.starttime) {
+ tmp_time = *rep->enc_part.starttime;
+ } else
+ tmp_time = rep->enc_part.authtime;
+
+ if (creds->times.starttime == 0
+ && abs(tmp_time - sec_now) > context->max_skew) {
+ ret = KRB5KRB_AP_ERR_SKEW;
+ krb5_set_error_message (context, ret,
+ N_("time skew (%d) larger than max (%d)", ""),
+ abs(tmp_time - sec_now),
+ (int)context->max_skew);
+ goto out;
+ }
+
+ if (creds->times.starttime != 0
+ && tmp_time != creds->times.starttime) {
+ krb5_clear_error_message (context);
+ ret = KRB5KRB_AP_ERR_MODIFIED;
+ goto out;
+ }
+
+ creds->times.starttime = tmp_time;
+
+ if (rep->enc_part.renew_till) {
+ tmp_time = *rep->enc_part.renew_till;
+ } else
+ tmp_time = 0;
+
+ if (creds->times.renew_till != 0
+ && tmp_time > creds->times.renew_till) {
+ krb5_clear_error_message (context);
+ ret = KRB5KRB_AP_ERR_MODIFIED;
+ goto out;
+ }
+
+ creds->times.renew_till = tmp_time;
+
+ creds->times.authtime = rep->enc_part.authtime;
+
+ if (creds->times.endtime != 0
+ && rep->enc_part.endtime > creds->times.endtime) {
+ krb5_clear_error_message (context);
+ ret = KRB5KRB_AP_ERR_MODIFIED;
+ goto out;
+ }
+
+ creds->times.endtime = rep->enc_part.endtime;
+
+ if(rep->enc_part.caddr)
+ krb5_copy_addresses (context, rep->enc_part.caddr, &creds->addresses);
+ else if(addrs)
+ krb5_copy_addresses (context, addrs, &creds->addresses);
+ else {
+ creds->addresses.len = 0;
+ creds->addresses.val = NULL;
+ }
+ creds->flags.b = rep->enc_part.flags;
+
+ creds->authdata.len = 0;
+ creds->authdata.val = NULL;
+
+ /* extract ticket */
+ ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length,
+ &rep->kdc_rep.ticket, &len, ret);
+ if(ret)
+ goto out;
+ if (creds->ticket.length != len)
+ krb5_abortx(context, "internal error in ASN.1 encoder");
+ creds->second_ticket.length = 0;
+ creds->second_ticket.data = NULL;
+
+
+out:
+ memset (rep->enc_part.key.keyvalue.data, 0,
+ rep->enc_part.key.keyvalue.length);
+ return ret;
+}
diff --git a/source4/heimdal/lib/krb5/time.c b/source4/heimdal/lib/krb5/time.c
index cd786fedde..ed235783a2 100644
--- a/source4/heimdal/lib/krb5/time.c
+++ b/source4/heimdal/lib/krb5/time.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
/**
* Set the absolute time that the caller knows the kdc has so the
* kerberos library can calculate the relative diffrence beteen the
diff --git a/source4/heimdal/lib/krb5/transited.c b/source4/heimdal/lib/krb5/transited.c
index 7e11d5579a..196ef447ee 100644
--- a/source4/heimdal/lib/krb5/transited.c
+++ b/source4/heimdal/lib/krb5/transited.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
/* this is an attempt at one of the most horrible `compression'
schemes that has ever been invented; it's so amazingly brain-dead
that words can not describe it, and all this just to save a few
diff --git a/source4/heimdal/lib/krb5/v4_glue.c b/source4/heimdal/lib/krb5/v4_glue.c
index 6911cb20f8..168268ceab 100644
--- a/source4/heimdal/lib/krb5/v4_glue.c
+++ b/source4/heimdal/lib/krb5/v4_glue.c
@@ -32,7 +32,6 @@
*/
#include "krb5_locl.h"
-RCSID("$Id$");
#include "krb5-v4compat.h"
@@ -217,14 +216,16 @@ write_v4_cc(krb5_context context, const char *tkfile,
ret = write(fd, data.data, data.length);
if (ret != data.length)
ret = KRB5_CC_IO;
+ else
+ ret = 0;
- krb5_free_data_contents(context, &data);
+ krb5_data_free(&data);
flock(fd, LOCK_UN);
free(path);
close(fd);
- return 0;
+ return ret;
}
/*
diff --git a/source4/heimdal/lib/krb5/version.c b/source4/heimdal/lib/krb5/version.c
index d43b83e26e..a0e750604e 100644
--- a/source4/heimdal/lib/krb5/version.c
+++ b/source4/heimdal/lib/krb5/version.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
/* this is just to get a version stamp in the library file */
#define heimdal_version __heimdal_version
diff --git a/source4/heimdal/lib/krb5/warn.c b/source4/heimdal/lib/krb5/warn.c
index a00ae80697..58fb73189e 100644
--- a/source4/heimdal/lib/krb5/warn.c
+++ b/source4/heimdal/lib/krb5/warn.c
@@ -34,8 +34,6 @@
#include "krb5_locl.h"
#include <err.h>
-RCSID("$Id$");
-
static krb5_error_code _warnerr(krb5_context context, int do_errtext,
krb5_error_code code, int level, const char *fmt, va_list ap)
__attribute__((__format__(__printf__, 5, 0)));
@@ -96,6 +94,18 @@ _warnerr(krb5_context context, int do_errtext,
#undef __attribute__
#define __attribute__(X)
+/**
+ * Log a warning to the log, default stderr, include the error from
+ * the last failure.
+ *
+ * @param context A Kerberos 5 context.
+ * @param code error code of the last error
+ * @param fmt message to print
+ * @param ap arguments
+ *
+ * @ingroup krb5_error
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_vwarn(krb5_context context, krb5_error_code code,
const char *fmt, va_list ap)
@@ -104,6 +114,16 @@ krb5_vwarn(krb5_context context, krb5_error_code code,
return _warnerr(context, 1, code, 1, fmt, ap);
}
+/**
+ * Log a warning to the log, default stderr, include the error from
+ * the last failure.
+ *
+ * @param context A Kerberos 5 context.
+ * @param code error code of the last error
+ * @param fmt message to print
+ *
+ * @ingroup krb5_error
+ */
krb5_error_code KRB5_LIB_FUNCTION
krb5_warn(krb5_context context, krb5_error_code code, const char *fmt, ...)
@@ -113,6 +133,16 @@ krb5_warn(krb5_context context, krb5_error_code code, const char *fmt, ...)
return ret;
}
+/**
+ * Log a warning to the log, default stderr.
+ *
+ * @param context A Kerberos 5 context.
+ * @param fmt message to print
+ * @param ap arguments
+ *
+ * @ingroup krb5_error
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_vwarnx(krb5_context context, const char *fmt, va_list ap)
__attribute__ ((format (printf, 2, 0)))
@@ -120,6 +150,15 @@ krb5_vwarnx(krb5_context context, const char *fmt, va_list ap)
return _warnerr(context, 0, 0, 1, fmt, ap);
}
+/**
+ * Log a warning to the log, default stderr.
+ *
+ * @param context A Kerberos 5 context.
+ * @param fmt message to print
+ *
+ * @ingroup krb5_error
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_warnx(krb5_context context, const char *fmt, ...)
__attribute__ ((format (printf, 2, 3)))
@@ -128,6 +167,19 @@ krb5_warnx(krb5_context context, const char *fmt, ...)
return ret;
}
+/**
+ * Log a warning to the log, default stderr, include bthe error from
+ * the last failure and then exit.
+ *
+ * @param context A Kerberos 5 context
+ * @param eval the exit code to exit with
+ * @param code error code of the last error
+ * @param fmt message to print
+ * @param ap arguments
+ *
+ * @ingroup krb5_error
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_verr(krb5_context context, int eval, krb5_error_code code,
const char *fmt, va_list ap)
@@ -137,6 +189,17 @@ krb5_verr(krb5_context context, int eval, krb5_error_code code,
exit(eval);
}
+/**
+ * Log a warning to the log, default stderr, include bthe error from
+ * the last failure and then exit.
+ *
+ * @param context A Kerberos 5 context
+ * @param eval the exit code to exit with
+ * @param code error code of the last error
+ * @param fmt message to print
+ *
+ * @ingroup krb5_error
+ */
krb5_error_code KRB5_LIB_FUNCTION
krb5_err(krb5_context context, int eval, krb5_error_code code,
@@ -147,6 +210,17 @@ krb5_err(krb5_context context, int eval, krb5_error_code code,
exit(eval);
}
+/**
+ * Log a warning to the log, default stderr, and then exit.
+ *
+ * @param context A Kerberos 5 context
+ * @param eval the exit code to exit with
+ * @param fmt message to print
+ * @param ap arguments
+ *
+ * @ingroup krb5_error
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_verrx(krb5_context context, int eval, const char *fmt, va_list ap)
__attribute__ ((noreturn, format (printf, 3, 0)))
@@ -155,6 +229,16 @@ krb5_verrx(krb5_context context, int eval, const char *fmt, va_list ap)
exit(eval);
}
+/**
+ * Log a warning to the log, default stderr, and then exit.
+ *
+ * @param context A Kerberos 5 context
+ * @param eval the exit code to exit with
+ * @param fmt message to print
+ *
+ * @ingroup krb5_error
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_errx(krb5_context context, int eval, const char *fmt, ...)
__attribute__ ((noreturn, format (printf, 3, 4)))
@@ -163,6 +247,18 @@ krb5_errx(krb5_context context, int eval, const char *fmt, ...)
exit(eval);
}
+/**
+ * Log a warning to the log, default stderr, include bthe error from
+ * the last failure and then abort.
+ *
+ * @param context A Kerberos 5 context
+ * @param code error code of the last error
+ * @param fmt message to print
+ * @param ap arguments
+ *
+ * @ingroup krb5_error
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_vabort(krb5_context context, krb5_error_code code,
const char *fmt, va_list ap)
@@ -172,6 +268,16 @@ krb5_vabort(krb5_context context, krb5_error_code code,
abort();
}
+/**
+ * Log a warning to the log, default stderr, include bthe error from
+ * the last failure and then abort.
+ *
+ * @param context A Kerberos 5 context
+ * @param code error code of the last error
+ * @param fmt message to print
+ *
+ * @ingroup krb5_error
+ */
krb5_error_code KRB5_LIB_FUNCTION
krb5_abort(krb5_context context, krb5_error_code code, const char *fmt, ...)
@@ -189,6 +295,16 @@ krb5_vabortx(krb5_context context, const char *fmt, va_list ap)
abort();
}
+/**
+ * Log a warning to the log, default stderr, and then abort.
+ *
+ * @param context A Kerberos 5 context
+ * @param code error code of the last error
+ * @param fmt message to print
+ *
+ * @ingroup krb5_error
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_abortx(krb5_context context, const char *fmt, ...)
__attribute__ ((noreturn, format (printf, 2, 3)))
@@ -197,6 +313,15 @@ krb5_abortx(krb5_context context, const char *fmt, ...)
abort();
}
+/**
+ * Set the default logging facility.
+ *
+ * @param context A Kerberos 5 context
+ * @param fac Facility to use for logging.
+ *
+ * @ingroup krb5_error
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_set_warn_dest(krb5_context context, krb5_log_facility *fac)
{
@@ -204,6 +329,14 @@ krb5_set_warn_dest(krb5_context context, krb5_log_facility *fac)
return 0;
}
+/**
+ * Get the default logging facility.
+ *
+ * @param context A Kerberos 5 context
+ *
+ * @ingroup krb5_error
+ */
+
krb5_log_facility * KRB5_LIB_FUNCTION
krb5_get_warn_dest(krb5_context context)
{