summaryrefslogtreecommitdiff
path: root/source4/heimdal
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2010-11-12 15:27:43 +1100
committerAndrew Bartlett <abartlet@samba.org>2010-11-15 01:25:06 +0000
commit6a27fbbfc4c51ae1635b8a5fa51c470ebc9f01e2 (patch)
tree67429e7173cb2e524bcb340e233008b33241dc77 /source4/heimdal
parent192a555c9ab425fa8e18ee5bed84a8c2fd527200 (diff)
downloadsamba-6a27fbbfc4c51ae1635b8a5fa51c470ebc9f01e2.tar.gz
samba-6a27fbbfc4c51ae1635b8a5fa51c470ebc9f01e2.tar.bz2
samba-6a27fbbfc4c51ae1635b8a5fa51c470ebc9f01e2.zip
heimdal Extra files required for merge up to current heimdal
Diffstat (limited to 'source4/heimdal')
-rw-r--r--source4/heimdal/base/array.c234
-rw-r--r--source4/heimdal/base/baselocl.h90
-rw-r--r--source4/heimdal/base/bool.c58
-rw-r--r--source4/heimdal/base/dict.c282
-rw-r--r--source4/heimdal/base/heimbase.c559
-rw-r--r--source4/heimdal/base/heimbasepriv.h91
-rw-r--r--source4/heimdal/base/heimqueue.h167
-rw-r--r--source4/heimdal/base/null.c52
-rw-r--r--source4/heimdal/base/number.c127
-rw-r--r--source4/heimdal/base/string.c146
-rw-r--r--source4/heimdal/lib/hx509/lex.yy.c1923
-rw-r--r--source4/heimdal/lib/krb5/crypto-aes.c170
-rw-r--r--source4/heimdal/lib/krb5/crypto-algs.c87
-rw-r--r--source4/heimdal/lib/krb5/crypto-arcfour.c325
-rw-r--r--source4/heimdal/lib/krb5/crypto-des-common.c152
-rw-r--r--source4/heimdal/lib/krb5/crypto-des.c375
-rw-r--r--source4/heimdal/lib/krb5/crypto-des3.c226
-rw-r--r--source4/heimdal/lib/krb5/crypto-evp.c182
-rw-r--r--source4/heimdal/lib/krb5/crypto-null.c97
-rw-r--r--source4/heimdal/lib/krb5/crypto-pk.c292
-rw-r--r--source4/heimdal/lib/krb5/crypto-rand.c109
-rw-r--r--source4/heimdal/lib/krb5/crypto-stubs.c102
-rw-r--r--source4/heimdal/lib/krb5/crypto.h182
-rw-r--r--source4/heimdal/lib/krb5/salt-aes.c103
-rw-r--r--source4/heimdal/lib/krb5/salt-arcfour.c112
-rw-r--r--source4/heimdal/lib/krb5/salt-des.c224
-rw-r--r--source4/heimdal/lib/krb5/salt-des3.c150
-rw-r--r--source4/heimdal/lib/krb5/store-int.c58
-rw-r--r--source4/heimdal/lib/ntlm/ntlm_err.et24
29 files changed, 6699 insertions, 0 deletions
diff --git a/source4/heimdal/base/array.c b/source4/heimdal/base/array.c
new file mode 100644
index 0000000000..7b0d77b1cc
--- /dev/null
+++ b/source4/heimdal/base/array.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2010 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2010 Apple Inc. 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 "baselocl.h"
+
+/*
+ *
+ */
+
+struct heim_array_data {
+ size_t len;
+ heim_object_t *val;
+};
+
+static void
+array_dealloc(heim_object_t ptr)
+{
+ heim_array_t array = ptr;
+ size_t n;
+ for (n = 0; n < array->len; n++)
+ heim_release(array->val[n]);
+ free(array->val);
+}
+
+struct heim_type_data array_object = {
+ HEIM_TID_ARRAY,
+ "dict-object",
+ NULL,
+ array_dealloc,
+ NULL,
+ NULL,
+ NULL
+};
+
+/**
+ * Allocate an array
+ *
+ * @return A new allocated array, free with heim_release()
+ */
+
+heim_array_t
+heim_array_create(void)
+{
+ heim_array_t array;
+
+ array = _heim_alloc_object(&array_object, sizeof(*array));
+ if (array == NULL)
+ return NULL;
+
+ array->val = NULL;
+ array->len = 0;
+
+ return array;
+}
+
+/**
+ * Get type id of an dict
+ *
+ * @return the type id
+ */
+
+heim_tid_t
+heim_array_get_type_id(void)
+{
+ return HEIM_TID_ARRAY;
+}
+
+/**
+ * Append object to array
+ *
+ * @param array array to add too
+ * @param object the object to add
+ *
+ * @return zero if added, errno otherwise
+ */
+
+int
+heim_array_append_value(heim_array_t array, heim_object_t object)
+{
+ heim_object_t *ptr;
+
+ ptr = realloc(array->val, (array->len + 1) * sizeof(array->val[0]));
+ if (ptr == NULL)
+ return ENOMEM;
+ array->val = ptr;
+ array->val[array->len++] = heim_retain(object);
+
+ return 0;
+}
+
+/**
+ * Iterate over all objects in array
+ *
+ * @param array array to iterate over
+ * @param fn function to call on each object
+ * @param ctx context passed to fn
+ */
+
+void
+heim_array_iterate_f(heim_array_t array, heim_array_iterator_f_t fn, void *ctx)
+{
+ size_t n;
+ for (n = 0; n < array->len; n++)
+ fn(array->val[n], ctx);
+}
+
+#ifdef __BLOCKS__
+/**
+ * Iterate over all objects in array
+ *
+ * @param array array to iterate over
+ * @param fn block to call on each object
+ */
+
+void
+heim_array_iterate(heim_array_t array, void (^fn)(heim_object_t))
+{
+ size_t n;
+ for (n = 0; n < array->len; n++)
+ fn(array->val[n]);
+}
+#endif
+
+/**
+ * Get length of array
+ *
+ * @param array array to get length of
+ *
+ * @return length of array
+ */
+
+size_t
+heim_array_get_length(heim_array_t array)
+{
+ return array->len;
+}
+
+/**
+ * Copy value of array
+ *
+ * @param array array copy object from
+ * @param idx index of object, 0 based, must be smaller then
+ * heim_array_get_length()
+ *
+ * @return a retained copy of the object
+ */
+
+heim_object_t
+heim_array_copy_value(heim_array_t array, size_t idx)
+{
+ if (idx >= array->len)
+ heim_abort("index too large");
+ return heim_retain(array->val[idx]);
+}
+
+/**
+ * Delete value at idx
+ *
+ * @param array the array to modify
+ * @param idx the key to delete
+ */
+
+void
+heim_array_delete_value(heim_array_t array, size_t idx)
+{
+ heim_object_t obj;
+ if (idx >= array->len)
+ heim_abort("index too large");
+ obj = array->val[idx];
+
+ array->len--;
+
+ if (idx < array->len)
+ memmove(&array->val[idx], &array->val[idx + 1],
+ (array->len - idx) * sizeof(array->val[0]));
+
+ heim_release(obj);
+}
+
+#ifdef __BLOCKS__
+/**
+ * Get value at idx
+ *
+ * @param array the array to modify
+ * @param idx the key to delete
+ */
+
+void
+heim_array_filter(heim_array_t array, bool (^block)(heim_object_t))
+{
+ size_t n = 0;
+
+ while (n < array->len) {
+ if (block(array->val[n])) {
+ heim_array_delete_value(array, n);
+ } else {
+ n++;
+ }
+ }
+}
+
+#endif /* __BLOCKS__ */
diff --git a/source4/heimdal/base/baselocl.h b/source4/heimdal/base/baselocl.h
new file mode 100644
index 0000000000..3932378b2d
--- /dev/null
+++ b/source4/heimdal/base/baselocl.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2010 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2010 Apple Inc. 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 <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+#include <unistd.h>
+
+#include "config.h"
+
+#include "heimqueue.h"
+#include "heim_threads.h"
+#include "heimbase.h"
+#include "heimbasepriv.h"
+
+#ifdef HAVE_DISPATCH_DISPATCH_H
+#include <dispatch/dispatch.h>
+#endif
+
+#ifdef __GNUC__
+#define heim_base_atomic_inc(x) __sync_add_and_fetch((x), 1)
+#define heim_base_atomic_dec(x) __sync_sub_and_fetch((x), 1)
+#define heim_base_atomic_type unsigned int
+#define heim_base_atomic_max UINT_MAX
+
+#define heim_base_exchange_pointer(t,v) __sync_lock_test_and_set((t), (v))
+
+#elif 0 /* windows */
+
+#define heim_base_exchange_pointer(t,v) InterlockedExchangePointer((t),(v))
+
+#else
+#error "provide atomic integer operations for your compiler"
+#endif
+
+/* tagged strings/object/XXX */
+#define heim_base_is_tagged(x) (((uintptr_t)(x)) & 0x3)
+
+#define heim_base_is_tagged_string(x) ((((uintptr_t)(x)) & 0x3) == 2)
+#define heim_base_make_tagged_string_ptr(x) ((heim_object_t)(((uintptr_t)(x)) | 2))
+#define heim_base_tagged_string_ptr(x) ((char *)(((uintptr_t)(x)) & (~3)))
+
+
+#define heim_base_is_tagged_object(x) ((((uintptr_t)(x)) & 0x3) == 1)
+#define heim_base_make_tagged_object(x, tid) \
+ ((heim_object_t)((((uintptr_t)(x)) << 5) | ((tid) << 2) | 0x1))
+#define heim_base_tagged_object_tid(x) ((((uintptr_t)(x)) & 0x1f) >> 2)
+#define heim_base_tagged_object_value(x) (((uintptr_t)(x)) >> 5)
+
+/*
+ *
+ */
+
+#undef HEIMDAL_NORETURN_ATTRIBUTE
+#define HEIMDAL_NORETURN_ATTRIBUTE
+#undef HEIMDAL_PRINTF_ATTRIBUTE
+#define HEIMDAL_PRINTF_ATTRIBUTE(x)
diff --git a/source4/heimdal/base/bool.c b/source4/heimdal/base/bool.c
new file mode 100644
index 0000000000..72edcc71ed
--- /dev/null
+++ b/source4/heimdal/base/bool.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2010 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2010 Apple Inc. 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 "baselocl.h"
+
+struct heim_type_data _heim_bool_object = {
+ HEIM_TID_BOOL,
+ "bool-object",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+heim_bool_t
+heim_bool_create(int val)
+{
+ return heim_base_make_tagged_object(!!val, HEIM_TID_BOOL);
+}
+
+int
+heim_bool_val(heim_bool_t ptr)
+{
+ return heim_base_tagged_object_value(ptr);
+}
diff --git a/source4/heimdal/base/dict.c b/source4/heimdal/base/dict.c
new file mode 100644
index 0000000000..2eb57aa938
--- /dev/null
+++ b/source4/heimdal/base/dict.c
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 2002, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2010 Apple Inc. 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 "baselocl.h"
+
+struct hashentry {
+ struct hashentry **prev;
+ struct hashentry *next;
+ heim_object_t key;
+ heim_object_t value;
+};
+
+struct heim_dict_data {
+ size_t size;
+ struct hashentry **tab;
+};
+
+static void
+dict_dealloc(void *ptr)
+{
+ heim_dict_t dict = ptr;
+ struct hashentry **h, *g, *i;
+
+ for (h = dict->tab; h < &dict->tab[dict->size]; ++h) {
+ for (g = h[0]; g; g = i) {
+ i = g->next;
+ heim_release(g->key);
+ heim_release(g->value);
+ free(g);
+ }
+ }
+ free(dict->tab);
+}
+
+struct heim_type_data dict_object = {
+ HEIM_TID_DICT,
+ "dict-object",
+ NULL,
+ dict_dealloc,
+ NULL,
+ NULL,
+ NULL
+};
+
+static size_t
+isprime(size_t p)
+{
+ int q, i;
+
+ for(i = 2 ; i < p; i++) {
+ q = p / i;
+
+ if (i * q == p)
+ return 0;
+ if (i * i > p)
+ return 1;
+ }
+ return 1;
+}
+
+static size_t
+findprime(size_t p)
+{
+ if (p % 2 == 0)
+ p++;
+
+ while (isprime(p) == 0)
+ p += 2;
+
+ return p;
+}
+
+/**
+ * Allocate an array
+ *
+ * @return A new allocated array, free with heim_release()
+ */
+
+heim_dict_t
+heim_dict_create(size_t size)
+{
+ heim_dict_t dict;
+
+ dict = _heim_alloc_object(&dict_object, sizeof(*dict));
+
+ dict->size = findprime(size);
+ if (dict->size == 0) {
+ heim_release(dict);
+ return NULL;
+ }
+
+ dict->tab = calloc(dict->size, sizeof(dict->tab[0]));
+ if (dict->tab == NULL) {
+ dict->size = 0;
+ heim_release(dict);
+ return NULL;
+ }
+
+ return dict;
+}
+
+/**
+ * Get type id of an dict
+ *
+ * @return the type id
+ */
+
+heim_tid_t
+heim_dict_get_type_id(void)
+{
+ return HEIM_TID_DICT;
+}
+
+/* Intern search function */
+
+static struct hashentry *
+_search(heim_dict_t dict, heim_object_t ptr)
+{
+ unsigned long v = heim_get_hash(ptr);
+ struct hashentry *p;
+
+ for (p = dict->tab[v % dict->size]; p != NULL; p = p->next)
+ if (heim_cmp(ptr, p->key) == 0)
+ return p;
+
+ return NULL;
+}
+
+/**
+ * Search for element in hash table
+ *
+ * @value dict the dict to search in
+ * @value key the key to search for
+ *
+ * @return a retained copy of the value for key or NULL if not found
+ */
+
+heim_object_t
+heim_dict_copy_value(heim_dict_t dict, heim_object_t key)
+{
+ struct hashentry *p;
+ p = _search(dict, key);
+ if (p == NULL)
+ return NULL;
+
+ return heim_retain(p->value);
+}
+
+/**
+ * Add key and value to dict
+ *
+ * @value dict the dict to add too
+ * @value key the key to add
+ * @value value the value to add
+ *
+ * @return 0 if added, errno if not
+ */
+
+int
+heim_dict_add_value(heim_dict_t dict, heim_object_t key, heim_object_t value)
+{
+ struct hashentry **tabptr, *h;
+
+ h = _search(dict, key);
+ if (h) {
+ heim_release(h->value);
+ h->value = heim_retain(value);
+ } else {
+ unsigned long v;
+
+ h = malloc(sizeof(*h));
+ if (h == NULL)
+ return ENOMEM;
+
+ h->key = heim_retain(key);
+ h->value = heim_retain(value);
+
+ v = heim_get_hash(key);
+
+ tabptr = &dict->tab[v % dict->size];
+ h->next = *tabptr;
+ *tabptr = h;
+ h->prev = tabptr;
+ if (h->next)
+ h->next->prev = &h->next;
+ }
+
+ return 0;
+}
+
+/**
+ * Delete element with key key
+ *
+ * @value dict the dict to delete from
+ * @value key the key to delete
+ */
+
+void
+heim_dict_delete_key(heim_dict_t dict, heim_object_t key)
+{
+ struct hashentry *h = _search(dict, key);
+
+ if (h == NULL)
+ return;
+
+ heim_release(h->key);
+ heim_release(h->value);
+
+ if ((*(h->prev) = h->next) != NULL)
+ h->next->prev = h->prev;
+
+ free(h);
+}
+
+/**
+ * Do something for each element
+ *
+ * @value dict the dict to interate over
+ * @value func the function to search for
+ * @value arg argument to func
+ */
+
+void
+heim_dict_iterate_f(heim_dict_t dict, heim_dict_iterator_f_t func, void *arg)
+{
+ struct hashentry **h, *g;
+
+ for (h = dict->tab; h < &dict->tab[dict->size]; ++h)
+ for (g = *h; g; g = g->next)
+ func(g->key, g->value, arg);
+}
+
+#ifdef __BLOCKS__
+/**
+ * Do something for each element
+ *
+ * @value dict the dict to interate over
+ * @value func the function to search for
+ */
+
+void
+heim_dict_iterate(heim_dict_t dict, void (^func)(heim_object_t, heim_object_t))
+{
+ struct hashentry **h, *g;
+
+ for (h = dict->tab; h < &dict->tab[dict->size]; ++h)
+ for (g = *h; g; g = g->next)
+ func(g->key, g->value);
+}
+#endif
diff --git a/source4/heimdal/base/heimbase.c b/source4/heimdal/base/heimbase.c
new file mode 100644
index 0000000000..a6caad2baf
--- /dev/null
+++ b/source4/heimdal/base/heimbase.c
@@ -0,0 +1,559 @@
+/*
+ * Copyright (c) 2010 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2010 Apple Inc. 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 "baselocl.h"
+#include <syslog.h>
+
+static heim_base_atomic_type tidglobal = HEIM_TID_USER;
+
+struct heim_base {
+ heim_type_t isa;
+ heim_base_atomic_type ref_cnt;
+ HEIM_TAILQ_ENTRY(heim_base) autorel;
+ heim_auto_release_t autorelpool;
+ uintptr_t isaextra[3];
+};
+
+/* specialized version of base */
+struct heim_base_mem {
+ heim_type_t isa;
+ heim_base_atomic_type ref_cnt;
+ HEIM_TAILQ_ENTRY(heim_base) autorel;
+ heim_auto_release_t autorelpool;
+ const char *name;
+ void (*dealloc)(void *);
+ uintptr_t isaextra[1];
+};
+
+#define PTR2BASE(ptr) (((struct heim_base *)ptr) - 1)
+#define BASE2PTR(ptr) ((void *)(((struct heim_base *)ptr) + 1))
+
+/*
+ * Auto release structure
+ */
+
+struct heim_auto_release {
+ HEIM_TAILQ_HEAD(, heim_base) pool;
+ HEIMDAL_MUTEX pool_mutex;
+ struct heim_auto_release *parent;
+};
+
+
+/**
+ * Retain object
+ *
+ * @param object to be released, NULL is ok
+ *
+ * @return the same object as passed in
+ */
+
+void *
+heim_retain(void *ptr)
+{
+ struct heim_base *p = PTR2BASE(ptr);
+
+ if (ptr == NULL || heim_base_is_tagged(ptr))
+ return ptr;
+
+ if (p->ref_cnt == heim_base_atomic_max)
+ return ptr;
+
+ if ((heim_base_atomic_inc(&p->ref_cnt) - 1) == 0)
+ heim_abort("resurection");
+ return ptr;
+}
+
+/**
+ * Release object, free is reference count reaches zero
+ *
+ * @param object to be released
+ */
+
+void
+heim_release(void *ptr)
+{
+ heim_base_atomic_type old;
+ struct heim_base *p = PTR2BASE(ptr);
+
+ if (ptr == NULL || heim_base_is_tagged(ptr))
+ return;
+
+ if (p->ref_cnt == heim_base_atomic_max)
+ return;
+
+ old = heim_base_atomic_dec(&p->ref_cnt) + 1;
+
+ if (old > 1)
+ return;
+
+ if (old == 1) {
+ heim_auto_release_t ar = p->autorelpool;
+ /* remove from autorel pool list */
+ if (ar) {
+ p->autorelpool = NULL;
+ HEIMDAL_MUTEX_lock(&ar->pool_mutex);
+ HEIM_TAILQ_REMOVE(&ar->pool, p, autorel);
+ HEIMDAL_MUTEX_unlock(&ar->pool_mutex);
+ }
+ if (p->isa->dealloc)
+ p->isa->dealloc(ptr);
+ free(p);
+ } else
+ heim_abort("over release");
+}
+
+static heim_type_t tagged_isa[9] = {
+ &_heim_number_object,
+ &_heim_null_object,
+ &_heim_bool_object,
+
+ NULL,
+ NULL,
+ NULL,
+
+ NULL,
+ NULL,
+ NULL
+};
+
+heim_type_t
+_heim_get_isa(heim_object_t ptr)
+{
+ struct heim_base *p;
+ if (heim_base_is_tagged(ptr)) {
+ if (heim_base_is_tagged_object(ptr))
+ return tagged_isa[heim_base_tagged_object_tid(ptr)];
+ if (heim_base_is_tagged_string(ptr))
+ return &_heim_string_object;
+ heim_abort("not a supported tagged type");
+ }
+ p = PTR2BASE(ptr);
+ return p->isa;
+}
+
+/**
+ * Get type ID of object
+ *
+ * @param object object to get type id of
+ *
+ * @return type id of object
+ */
+
+heim_tid_t
+heim_get_tid(heim_object_t ptr)
+{
+ heim_type_t isa = _heim_get_isa(ptr);
+ return isa->tid;
+}
+
+/**
+ * Get hash value of object
+ *
+ * @param object object to get hash value for
+ *
+ * @return a hash value
+ */
+
+unsigned long
+heim_get_hash(heim_object_t ptr)
+{
+ heim_type_t isa = _heim_get_isa(ptr);
+ if (isa->hash)
+ return isa->hash(ptr);
+ return (unsigned long)ptr;
+}
+
+/**
+ * Compare two objects, returns 0 if equal, can use used for qsort()
+ * and friends.
+ *
+ * @param a first object to compare
+ * @param b first object to compare
+ *
+ * @return 0 if objects are equal
+ */
+
+int
+heim_cmp(heim_object_t a, heim_object_t b)
+{
+ heim_tid_t ta, tb;
+ heim_type_t isa;
+
+ ta = heim_get_tid(a);
+ tb = heim_get_tid(b);
+
+ if (ta != tb)
+ return ta - tb;
+
+ isa = _heim_get_isa(a);
+
+ if (isa->cmp)
+ return isa->cmp(a, b);
+
+ return (uintptr_t)a - (uintptr_t)b;
+}
+
+/*
+ * Private - allocates an memory object
+ */
+
+static void
+memory_dealloc(void *ptr)
+{
+ struct heim_base_mem *p = (struct heim_base_mem *)PTR2BASE(ptr);
+ if (p->dealloc)
+ p->dealloc(ptr);
+}
+
+struct heim_type_data memory_object = {
+ HEIM_TID_MEMORY,
+ "memory-object",
+ NULL,
+ memory_dealloc,
+ NULL,
+ NULL,
+ NULL
+};
+
+void *
+heim_alloc(size_t size, const char *name, heim_type_dealloc dealloc)
+{
+ /* XXX use posix_memalign */
+
+ struct heim_base_mem *p = calloc(1, size + sizeof(*p));
+ if (p == NULL)
+ return NULL;
+ p->isa = &memory_object;
+ p->ref_cnt = 1;
+ p->name = name;
+ p->dealloc = dealloc;
+ return BASE2PTR(p);
+}
+
+heim_type_t
+_heim_create_type(const char *name,
+ heim_type_init init,
+ heim_type_dealloc dealloc,
+ heim_type_copy copy,
+ heim_type_cmp cmp,
+ heim_type_hash hash)
+{
+ heim_type_t type;
+
+ type = calloc(1, sizeof(*type));
+ if (type == NULL)
+ return NULL;
+
+ type->tid = heim_base_atomic_inc(&tidglobal);
+ type->name = name;
+ type->init = init;
+ type->dealloc = dealloc;
+ type->copy = copy;
+ type->cmp = cmp;
+ type->hash = hash;
+
+ return type;
+}
+
+heim_object_t
+_heim_alloc_object(heim_type_t type, size_t size)
+{
+ /* XXX should use posix_memalign */
+ struct heim_base *p = calloc(1, size + sizeof(*p));
+ if (p == NULL)
+ return NULL;
+ p->isa = type;
+ p->ref_cnt = 1;
+
+ return BASE2PTR(p);
+}
+
+heim_tid_t
+_heim_type_get_tid(heim_type_t type)
+{
+ return type->tid;
+}
+
+/**
+ * Call func once and only once
+ *
+ * @param once pointer to a heim_base_once_t
+ * @param ctx context passed to func
+ * @param func function to be called
+ */
+
+void
+heim_base_once_f(heim_base_once_t *once, void *ctx, void (*func)(void *))
+{
+#ifdef HAVE_DISPATCH_DISPATCH_H
+ dispatch_once_f(once, ctx, func);
+#else
+ static HEIMDAL_MUTEX mutex = HEIMDAL_MUTEX_INITIALIZER;
+ HEIMDAL_MUTEX_lock(&mutex);
+ if (*once == 0) {
+ *once = 1;
+ HEIMDAL_MUTEX_unlock(&mutex);
+ func(ctx);
+ HEIMDAL_MUTEX_lock(&mutex);
+ *once = 2;
+ HEIMDAL_MUTEX_unlock(&mutex);
+ } else if (*once == 2) {
+ HEIMDAL_MUTEX_unlock(&mutex);
+ } else {
+ HEIMDAL_MUTEX_unlock(&mutex);
+ while (1) {
+ struct timeval tv = { 0, 1000 };
+ HEIMDAL_MUTEX_lock(&mutex);
+ if (*once == 2)
+ break;
+ HEIMDAL_MUTEX_unlock(&mutex);
+ }
+ HEIMDAL_MUTEX_unlock(&mutex);
+ }
+#endif
+}
+
+/**
+ * Abort and log the failure (using syslog)
+ */
+
+void
+heim_abort(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ heim_abortv(fmt, ap);
+ va_end(ap);
+}
+
+/**
+ * Abort and log the failure (using syslog)
+ */
+
+void
+heim_abortv(const char *fmt, va_list ap)
+{
+ char *str = NULL;
+ int ret;
+
+ ret = vasprintf(&str, fmt, ap);
+ if (ret > 0 && str) {
+ syslog(LOG_ERR, "heim_abort: %s", str);
+ }
+ abort();
+}
+
+/*
+ *
+ */
+
+static int ar_created = 0;
+static HEIMDAL_thread_key ar_key;
+
+struct ar_tls {
+ struct heim_auto_release *head;
+ struct heim_auto_release *current;
+ HEIMDAL_MUTEX tls_mutex;
+};
+
+static void
+ar_tls_delete(void *ptr)
+{
+ struct ar_tls *tls = ptr;
+ if (tls->head)
+ heim_release(tls->head);
+ free(tls);
+}
+
+static void
+init_ar_tls(void *ptr)
+{
+ int ret;
+ HEIMDAL_key_create(&ar_key, ar_tls_delete, ret);
+ if (ret == 0)
+ ar_created = 1;
+}
+
+static struct ar_tls *
+autorel_tls(void)
+{
+ static heim_base_once_t once = HEIM_BASE_ONCE_INIT;
+ struct ar_tls *arp;
+ int ret;
+
+ heim_base_once_f(&once, NULL, init_ar_tls);
+ if (!ar_created)
+ return NULL;
+
+ arp = HEIMDAL_getspecific(ar_key);
+ if (arp == NULL) {
+
+ arp = calloc(1, sizeof(*arp));
+ if (arp == NULL)
+ return NULL;
+ HEIMDAL_setspecific(ar_key, arp, ret);
+ if (ret) {
+ free(arp);
+ return NULL;
+ }
+ }
+ return arp;
+
+}
+
+static void
+autorel_dealloc(void *ptr)
+{
+ heim_auto_release_t ar = ptr;
+ struct ar_tls *tls;
+
+ tls = autorel_tls();
+ if (tls == NULL)
+ heim_abort("autorelease pool released on thread w/o autorelease inited");
+
+ heim_auto_release_drain(ar);
+
+ if (!HEIM_TAILQ_EMPTY(&ar->pool))
+ heim_abort("pool not empty after draining");
+
+ HEIMDAL_MUTEX_lock(&tls->tls_mutex);
+ if (tls->current != ptr)
+ heim_abort("autorelease not releaseing top pool");
+
+ if (tls->current != tls->head)
+ tls->current = ar->parent;
+ HEIMDAL_MUTEX_unlock(&tls->tls_mutex);
+}
+
+static int
+autorel_cmp(void *a, void *b)
+{
+ return (a == b);
+}
+
+static unsigned long
+autorel_hash(void *ptr)
+{
+ return (unsigned long)ptr;
+}
+
+
+static struct heim_type_data _heim_autorel_object = {
+ HEIM_TID_AUTORELEASE,
+ "autorelease-pool",
+ NULL,
+ autorel_dealloc,
+ NULL,
+ autorel_cmp,
+ autorel_hash
+};
+
+/**
+ *
+ */
+
+heim_auto_release_t
+heim_auto_release_create(void)
+{
+ struct ar_tls *tls = autorel_tls();
+ heim_auto_release_t ar;
+
+ if (tls == NULL)
+ heim_abort("Failed to create/get autorelease head");
+
+ ar = _heim_alloc_object(&_heim_autorel_object, sizeof(struct heim_auto_release));
+ if (ar) {
+ HEIMDAL_MUTEX_lock(&tls->tls_mutex);
+ if (tls->head == NULL)
+ tls->head = ar;
+ ar->parent = tls->current;
+ tls->current = ar;
+ HEIMDAL_MUTEX_unlock(&tls->tls_mutex);
+ }
+
+ return ar;
+}
+
+/**
+ * Mark the current object as a
+ */
+
+void
+heim_auto_release(heim_object_t ptr)
+{
+ struct heim_base *p = PTR2BASE(ptr);
+ struct ar_tls *tls = autorel_tls();
+ heim_auto_release_t ar;
+
+ if (ptr == NULL || heim_base_is_tagged(ptr))
+ return;
+
+ /* drop from old pool */
+ if ((ar = p->autorelpool) != NULL) {
+ HEIMDAL_MUTEX_lock(&ar->pool_mutex);
+ HEIM_TAILQ_REMOVE(&ar->pool, p, autorel);
+ p->autorelpool = NULL;
+ HEIMDAL_MUTEX_unlock(&ar->pool_mutex);
+ }
+
+ if (tls == NULL || (ar = tls->current) == NULL)
+ heim_abort("no auto relase pool in place, would leak");
+
+ HEIMDAL_MUTEX_lock(&ar->pool_mutex);
+ HEIM_TAILQ_INSERT_HEAD(&ar->pool, p, autorel);
+ p->autorelpool = ar;
+ HEIMDAL_MUTEX_unlock(&ar->pool_mutex);
+}
+
+/**
+ *
+ */
+
+void
+heim_auto_release_drain(heim_auto_release_t autorel)
+{
+ heim_object_t obj;
+
+ /* release all elements on the tail queue */
+
+ HEIMDAL_MUTEX_lock(&autorel->pool_mutex);
+ while(!HEIM_TAILQ_EMPTY(&autorel->pool)) {
+ obj = HEIM_TAILQ_FIRST(&autorel->pool);
+ HEIMDAL_MUTEX_unlock(&autorel->pool_mutex);
+ heim_release(BASE2PTR(obj));
+ HEIMDAL_MUTEX_lock(&autorel->pool_mutex);
+ }
+ HEIMDAL_MUTEX_unlock(&autorel->pool_mutex);
+}
diff --git a/source4/heimdal/base/heimbasepriv.h b/source4/heimdal/base/heimbasepriv.h
new file mode 100644
index 0000000000..772962548f
--- /dev/null
+++ b/source4/heimdal/base/heimbasepriv.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2010 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2010 Apple Inc. 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.
+ */
+
+typedef void (*heim_type_init)(void *);
+typedef heim_object_t (*heim_type_copy)(void *);
+typedef int (*heim_type_cmp)(void *, void *);
+typedef unsigned long (*heim_type_hash)(void *);
+
+typedef struct heim_type_data *heim_type_t;
+
+enum {
+ HEIM_TID_NUMBER = 0,
+ HEIM_TID_NULL = 1,
+ HEIM_TID_BOOL = 2,
+ HEIM_TID_TAGGED_UNUSED2 = 3,
+ HEIM_TID_TAGGED_UNUSED3 = 4,
+ HEIM_TID_TAGGED_UNUSED4 = 5,
+ HEIM_TID_TAGGED_UNUSED5 = 6,
+ HEIM_TID_TAGGED_UNUSED6 = 7,
+ HEIM_TID_MEMORY = 128,
+ HEIM_TID_ARRAY = 129,
+ HEIM_TID_DICT = 130,
+ HEIM_TID_STRING = 131,
+ HEIM_TID_AUTORELEASE = 132,
+ HEIM_TID_USER = 255
+
+};
+
+struct heim_type_data {
+ heim_tid_t tid;
+ const char *name;
+ heim_type_init init;
+ heim_type_dealloc dealloc;
+ heim_type_copy copy;
+ heim_type_cmp cmp;
+ heim_type_hash hash;
+};
+
+heim_type_t _heim_get_isa(heim_object_t);
+
+heim_type_t
+_heim_create_type(const char *name,
+ heim_type_init init,
+ heim_type_dealloc dealloc,
+ heim_type_copy copy,
+ heim_type_cmp cmp,
+ heim_type_hash hash);
+
+heim_object_t
+_heim_alloc_object(heim_type_t type, size_t size);
+
+heim_tid_t
+_heim_type_get_tid(heim_type_t type);
+
+/* tagged tid */
+extern struct heim_type_data _heim_null_object;
+extern struct heim_type_data _heim_bool_object;
+extern struct heim_type_data _heim_number_object;
+extern struct heim_type_data _heim_string_object;
diff --git a/source4/heimdal/base/heimqueue.h b/source4/heimdal/base/heimqueue.h
new file mode 100644
index 0000000000..423a684787
--- /dev/null
+++ b/source4/heimdal/base/heimqueue.h
@@ -0,0 +1,167 @@
+/* $NetBSD: queue.h,v 1.38 2004/04/18 14:12:05 lukem Exp $ */
+/* $Id$ */
+
+/*
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. 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 University 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 REGENTS 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 REGENTS 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.
+ *
+ * @(#)queue.h 8.5 (Berkeley) 8/20/94
+ */
+
+#ifndef _HEIM_QUEUE_H_
+#define _HEIM_QUEUE_H_
+
+/*
+ * Tail queue definitions.
+ */
+#define HEIM_TAILQ_HEAD(name, type) \
+struct name { \
+ struct type *tqh_first; /* first element */ \
+ struct type **tqh_last; /* addr of last next element */ \
+}
+
+#define HEIM_TAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).tqh_first }
+#define HEIM_TAILQ_ENTRY(type) \
+struct { \
+ struct type *tqe_next; /* next element */ \
+ struct type **tqe_prev; /* address of previous next element */ \
+}
+
+/*
+ * Tail queue functions.
+ */
+#if defined(_KERNEL) && defined(QUEUEDEBUG)
+#define QUEUEDEBUG_HEIM_TAILQ_INSERT_HEAD(head, elm, field) \
+ if ((head)->tqh_first && \
+ (head)->tqh_first->field.tqe_prev != &(head)->tqh_first) \
+ panic("HEIM_TAILQ_INSERT_HEAD %p %s:%d", (head), __FILE__, __LINE__);
+#define QUEUEDEBUG_HEIM_TAILQ_INSERT_TAIL(head, elm, field) \
+ if (*(head)->tqh_last != NULL) \
+ panic("HEIM_TAILQ_INSERT_TAIL %p %s:%d", (head), __FILE__, __LINE__);
+#define QUEUEDEBUG_HEIM_TAILQ_OP(elm, field) \
+ if ((elm)->field.tqe_next && \
+ (elm)->field.tqe_next->field.tqe_prev != \
+ &(elm)->field.tqe_next) \
+ panic("HEIM_TAILQ_* forw %p %s:%d", (elm), __FILE__, __LINE__);\
+ if (*(elm)->field.tqe_prev != (elm)) \
+ panic("HEIM_TAILQ_* back %p %s:%d", (elm), __FILE__, __LINE__);
+#define QUEUEDEBUG_HEIM_TAILQ_PREREMOVE(head, elm, field) \
+ if ((elm)->field.tqe_next == NULL && \
+ (head)->tqh_last != &(elm)->field.tqe_next) \
+ panic("HEIM_TAILQ_PREREMOVE head %p elm %p %s:%d", \
+ (head), (elm), __FILE__, __LINE__);
+#define QUEUEDEBUG_HEIM_TAILQ_POSTREMOVE(elm, field) \
+ (elm)->field.tqe_next = (void *)1L; \
+ (elm)->field.tqe_prev = (void *)1L;
+#else
+#define QUEUEDEBUG_HEIM_TAILQ_INSERT_HEAD(head, elm, field)
+#define QUEUEDEBUG_HEIM_TAILQ_INSERT_TAIL(head, elm, field)
+#define QUEUEDEBUG_HEIM_TAILQ_OP(elm, field)
+#define QUEUEDEBUG_HEIM_TAILQ_PREREMOVE(head, elm, field)
+#define QUEUEDEBUG_HEIM_TAILQ_POSTREMOVE(elm, field)
+#endif
+
+#define HEIM_TAILQ_INIT(head) do { \
+ (head)->tqh_first = NULL; \
+ (head)->tqh_last = &(head)->tqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define HEIM_TAILQ_INSERT_HEAD(head, elm, field) do { \
+ QUEUEDEBUG_HEIM_TAILQ_INSERT_HEAD((head), (elm), field) \
+ if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
+ (head)->tqh_first->field.tqe_prev = \
+ &(elm)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+ (head)->tqh_first = (elm); \
+ (elm)->field.tqe_prev = &(head)->tqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define HEIM_TAILQ_INSERT_TAIL(head, elm, field) do { \
+ QUEUEDEBUG_HEIM_TAILQ_INSERT_TAIL((head), (elm), field) \
+ (elm)->field.tqe_next = NULL; \
+ (elm)->field.tqe_prev = (head)->tqh_last; \
+ *(head)->tqh_last = (elm); \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define HEIM_TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ QUEUEDEBUG_HEIM_TAILQ_OP((listelm), field) \
+ if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
+ (elm)->field.tqe_next->field.tqe_prev = \
+ &(elm)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+ (listelm)->field.tqe_next = (elm); \
+ (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define HEIM_TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
+ QUEUEDEBUG_HEIM_TAILQ_OP((listelm), field) \
+ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
+ (elm)->field.tqe_next = (listelm); \
+ *(listelm)->field.tqe_prev = (elm); \
+ (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define HEIM_TAILQ_REMOVE(head, elm, field) do { \
+ QUEUEDEBUG_HEIM_TAILQ_PREREMOVE((head), (elm), field) \
+ QUEUEDEBUG_HEIM_TAILQ_OP((elm), field) \
+ if (((elm)->field.tqe_next) != NULL) \
+ (elm)->field.tqe_next->field.tqe_prev = \
+ (elm)->field.tqe_prev; \
+ else \
+ (head)->tqh_last = (elm)->field.tqe_prev; \
+ *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
+ QUEUEDEBUG_HEIM_TAILQ_POSTREMOVE((elm), field); \
+} while (/*CONSTCOND*/0)
+
+#define HEIM_TAILQ_FOREACH(var, head, field) \
+ for ((var) = ((head)->tqh_first); \
+ (var); \
+ (var) = ((var)->field.tqe_next))
+
+#define HEIM_TAILQ_FOREACH_REVERSE(var, head, headname, field) \
+ for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \
+ (var); \
+ (var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last)))
+
+/*
+ * Tail queue access methods.
+ */
+#define HEIM_TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
+#define HEIM_TAILQ_FIRST(head) ((head)->tqh_first)
+#define HEIM_TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+
+#define HEIM_TAILQ_LAST(head, headname) \
+ (*(((struct headname *)((head)->tqh_last))->tqh_last))
+#define HEIM_TAILQ_PREV(elm, headname, field) \
+ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+
+
+#endif /* !_HEIM_QUEUE_H_ */
diff --git a/source4/heimdal/base/null.c b/source4/heimdal/base/null.c
new file mode 100644
index 0000000000..66731aad26
--- /dev/null
+++ b/source4/heimdal/base/null.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2010 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2010 Apple Inc. 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 "baselocl.h"
+
+struct heim_type_data _heim_null_object = {
+ HEIM_TID_NULL,
+ "null-object",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+heim_null_t
+heim_null_create(void)
+{
+ return heim_base_make_tagged_object(0, HEIM_TID_NULL);
+}
diff --git a/source4/heimdal/base/number.c b/source4/heimdal/base/number.c
new file mode 100644
index 0000000000..72631a531c
--- /dev/null
+++ b/source4/heimdal/base/number.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2010 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2010 Apple Inc. 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 "baselocl.h"
+
+static void
+number_dealloc(void *ptr)
+{
+}
+
+static int
+number_cmp(void *a, void *b)
+{
+ int na, nb;
+
+ if (heim_base_is_tagged_object(a))
+ na = heim_base_tagged_object_value(a);
+ else
+ na = *(int *)a;
+
+ if (heim_base_is_tagged_object(b))
+ nb = heim_base_tagged_object_value(b);
+ else
+ nb = *(int *)b;
+
+ return na - nb;
+}
+
+static unsigned long
+number_hash(void *ptr)
+{
+ if (heim_base_is_tagged_object(ptr))
+ return heim_base_tagged_object_value(ptr);
+ return (unsigned long)*(int *)ptr;
+}
+
+struct heim_type_data _heim_number_object = {
+ HEIM_TID_NUMBER,
+ "number-object",
+ NULL,
+ number_dealloc,
+ NULL,
+ number_cmp,
+ number_hash
+};
+
+/**
+ * Create a number object
+ *
+ * @param the number to contain in the object
+ *
+ * @return a number object
+ */
+
+heim_number_t
+heim_number_create(int number)
+{
+ heim_number_t n;
+
+ if (number < 0xffffff && number >= 0)
+ return heim_base_make_tagged_object(number, HEIM_TID_NUMBER);
+
+ n = _heim_alloc_object(&_heim_number_object, sizeof(int));
+ if (n)
+ *((int *)n) = number;
+ return n;
+}
+
+/**
+ * Return the type ID of number objects
+ *
+ * @return type id of number objects
+ */
+
+heim_tid_t
+heim_number_get_type_id(void)
+{
+ return HEIM_TID_NUMBER;
+}
+
+/**
+ * Get the int value of the content
+ *
+ * @param number the number object to get the value from
+ *
+ * @return an int
+ */
+
+int
+heim_number_get_int(heim_number_t number)
+{
+ if (heim_base_is_tagged_object(number))
+ return heim_base_tagged_object_value(number);
+ return *(int *)number;
+}
diff --git a/source4/heimdal/base/string.c b/source4/heimdal/base/string.c
new file mode 100644
index 0000000000..414a9161fa
--- /dev/null
+++ b/source4/heimdal/base/string.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2010 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2010 Apple Inc. 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 "baselocl.h"
+#include <string.h>
+
+static void
+string_dealloc(void *ptr)
+{
+}
+
+static int
+string_cmp(void *a, void *b)
+{
+ if (heim_base_is_tagged_string(a))
+ a = heim_base_tagged_string_ptr(a);
+ if (heim_base_is_tagged_string(b))
+ b = heim_base_tagged_string_ptr(b);
+
+ return strcmp(a, b);
+}
+
+static unsigned long
+string_hash(void *ptr)
+{
+ const char *s;
+ unsigned long n;
+
+ if (heim_base_is_tagged_string(ptr))
+ s = heim_base_tagged_string_ptr(ptr);
+ else
+ s = ptr;
+
+ for (n = 0; *s; ++s)
+ n += *s;
+ return n;
+}
+
+
+struct heim_type_data _heim_string_object = {
+ HEIM_TID_STRING,
+ "string-object",
+ NULL,
+ string_dealloc,
+ NULL,
+ string_cmp,
+ string_hash
+};
+
+/**
+ * Create a string object
+ *
+ * @param string the string to create, must be an utf8 string
+ *
+ * @return string object
+ */
+
+heim_string_t
+heim_string_create(const char *string)
+{
+ size_t len = strlen(string);
+ heim_string_t s;
+
+ s = _heim_alloc_object(&_heim_string_object, len + 1);
+ if (s)
+ memcpy(s, string, len + 1);
+ return s;
+}
+
+/**
+ * Create a string object from a strings allocated in the text segment.
+ *
+ * Note that static string object wont be auto released with
+ * heim_auto_release(), the allocation policy of the string must
+ * be manged separately from the returned object. This make this
+ * function not very useful for strings in allocated from heap or
+ * stack. In that case you should use heim_string_create().
+ *
+ * @param string the string to create, must be an utf8 string
+ *
+ * @return string object
+ */
+
+heim_string_t
+heim_string_create_with_static(const char *string)
+{
+ return heim_base_make_tagged_string_ptr(string);
+}
+
+/**
+ * Return the type ID of string objects
+ *
+ * @return type id of string objects
+ */
+
+heim_tid_t
+heim_string_get_type_id(void)
+{
+ return HEIM_TID_STRING;
+}
+
+/**
+ * Get the string value of the content.
+ *
+ * @param string the string object to get the value from
+ *
+ * @return a utf8 string
+ */
+
+const char *
+heim_string_get_utf8(heim_string_t string)
+{
+ return (const char *)string;
+}
diff --git a/source4/heimdal/lib/hx509/lex.yy.c b/source4/heimdal/lib/hx509/lex.yy.c
new file mode 100644
index 0000000000..4ee5a26820
--- /dev/null
+++ b/source4/heimdal/lib/hx509/lex.yy.c
@@ -0,0 +1,1923 @@
+
+#line 3 "lex.yy.c"
+
+#define YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types.
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t;
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX (4294967295U)
+#endif
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif /* defined (__STDC__) */
+#endif /* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index. If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN (yy_start) = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart(yyin )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+extern int yyleng;
+
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+ #define YY_LESS_LINENO(n)
+
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ *yy_cp = (yy_hold_char); \
+ YY_RESTORE_YY_MORE_OFFSET \
+ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+ } \
+ while ( 0 )
+
+#define unput(c) yyunput( c, (yytext_ptr) )
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ int yy_bs_lineno; /**< The line count. */
+ int yy_bs_column; /**< The column count. */
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via yyrestart()), so that the user can continue scanning by
+ * just pointing yyin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+
+ };
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+ : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+static int yy_n_chars; /* number of characters read into yy_ch_buf */
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 0; /* whether we need to initialize */
+static int yy_start = 0; /* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin. A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart (FILE *input_file );
+void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer );
+YY_BUFFER_STATE yy_create_buffer (FILE *file,int size );
+void yy_delete_buffer (YY_BUFFER_STATE b );
+void yy_flush_buffer (YY_BUFFER_STATE b );
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer );
+void yypop_buffer_state (void );
+
+static void yyensure_buffer_stack (void );
+static void yy_load_buffer_state (void );
+static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file );
+
+#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
+
+YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size );
+YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str );
+YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len );
+
+void *yyalloc (yy_size_t );
+void *yyrealloc (void *,yy_size_t );
+void yyfree (void * );
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){ \
+ yyensure_buffer_stack (); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ yy_create_buffer(yyin,YY_BUF_SIZE ); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+ }
+
+#define yy_set_bol(at_bol) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){\
+ yyensure_buffer_stack (); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ yy_create_buffer(yyin,YY_BUF_SIZE ); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+ }
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+typedef unsigned char YY_CHAR;
+
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+
+typedef int yy_state_type;
+
+extern int yylineno;
+
+int yylineno = 1;
+
+extern char *yytext;
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state (void );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state );
+static int yy_get_next_buffer (void );
+static void yy_fatal_error (yyconst char msg[] );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+ (yytext_ptr) = yy_bp; \
+ yyleng = (size_t) (yy_cp - yy_bp); \
+ (yy_hold_char) = *yy_cp; \
+ *yy_cp = '\0'; \
+ (yy_c_buf_p) = yy_cp;
+
+#define YY_NUM_RULES 12
+#define YY_END_OF_BUFFER 13
+/* This struct is not used in this scanner,
+ but its presence is necessary. */
+struct yy_trans_info
+ {
+ flex_int32_t yy_verify;
+ flex_int32_t yy_nxt;
+ };
+static yyconst flex_int16_t yy_accept[36] =
+ { 0,
+ 0, 0, 13, 12, 11, 9, 10, 8, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 5, 4, 7,
+ 7, 3, 7, 7, 7, 7, 7, 1, 2, 7,
+ 7, 7, 7, 6, 0
+ } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 4, 5, 1, 1, 4, 1, 1, 4,
+ 4, 1, 1, 4, 6, 4, 1, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 1, 1, 1,
+ 4, 1, 1, 1, 7, 8, 9, 10, 11, 12,
+ 8, 13, 14, 8, 8, 15, 16, 17, 18, 8,
+ 8, 19, 20, 21, 22, 8, 8, 8, 8, 8,
+ 1, 1, 1, 1, 6, 1, 8, 8, 8, 8,
+
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 4, 1, 4, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+ } ;
+
+static yyconst flex_int32_t yy_meta[23] =
+ { 0,
+ 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2
+ } ;
+
+static yyconst flex_int16_t yy_base[37] =
+ { 0,
+ 0, 0, 43, 44, 44, 44, 44, 44, 25, 0,
+ 34, 23, 20, 16, 0, 28, 22, 0, 0, 22,
+ 12, 0, 13, 17, 20, 19, 13, 0, 0, 21,
+ 6, 17, 12, 0, 44, 22
+ } ;
+
+static yyconst flex_int16_t yy_def[37] =
+ { 0,
+ 35, 1, 35, 35, 35, 35, 35, 35, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 0, 35
+ } ;
+
+static yyconst flex_int16_t yy_nxt[67] =
+ { 0,
+ 4, 5, 6, 7, 8, 4, 9, 10, 10, 10,
+ 10, 11, 10, 12, 10, 10, 10, 13, 10, 10,
+ 14, 10, 20, 15, 34, 33, 32, 31, 30, 29,
+ 28, 27, 26, 25, 21, 24, 23, 22, 19, 18,
+ 17, 16, 35, 3, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35
+ } ;
+
+static yyconst flex_int16_t yy_chk[67] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 14, 36, 33, 32, 31, 30, 27, 26,
+ 25, 24, 23, 21, 14, 20, 17, 16, 13, 12,
+ 11, 9, 3, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35
+ } ;
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+extern int yy_flex_debug;
+int yy_flex_debug = 0;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+#line 1 "sel-lex.l"
+#line 2 "sel-lex.l"
+/*
+ * Copyright (c) 2004, 2008 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$ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#undef ECHO
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include "sel.h"
+#include "sel-gram.h"
+unsigned lineno = 1;
+
+static char * handle_string(void);
+static int lex_input(char *, int);
+
+struct hx_expr_input _hx509_expr_input;
+
+#ifndef YY_NULL
+#define YY_NULL 0
+#endif
+
+#define YY_NO_UNPUT 1
+
+#undef YY_INPUT
+#define YY_INPUT(buf,res,maxsize) (res = lex_input(buf, maxsize))
+
+#undef ECHO
+
+#line 538 "lex.yy.c"
+
+#define INITIAL 0
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+static int yy_init_globals (void );
+
+/* Accessor methods to globals.
+ These are made visible to non-reentrant scanners for convenience. */
+
+int yylex_destroy (void );
+
+int yyget_debug (void );
+
+void yyset_debug (int debug_flag );
+
+YY_EXTRA_TYPE yyget_extra (void );
+
+void yyset_extra (YY_EXTRA_TYPE user_defined );
+
+FILE *yyget_in (void );
+
+void yyset_in (FILE * in_str );
+
+FILE *yyget_out (void );
+
+void yyset_out (FILE * out_str );
+
+int yyget_leng (void );
+
+char *yyget_text (void );
+
+int yyget_lineno (void );
+
+void yyset_lineno (int line_number );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap (void );
+#else
+extern int yywrap (void );
+#endif
+#endif
+
+ static void yyunput (int c,char *buf_ptr );
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * );
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (void );
+#else
+static int input (void );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+ { \
+ int c = '*'; \
+ unsigned n; \
+ for ( n = 0; n < max_size && \
+ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+ buf[n] = (char) c; \
+ if ( c == '\n' ) \
+ buf[n++] = (char) c; \
+ if ( c == EOF && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ result = n; \
+ } \
+ else \
+ { \
+ errno=0; \
+ while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+ { \
+ if( errno != EINTR) \
+ { \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ break; \
+ } \
+ errno=0; \
+ clearerr(yyin); \
+ } \
+ }\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int yylex (void);
+
+#define YY_DECL int yylex (void)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+ YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp, *yy_bp;
+ register int yy_act;
+
+#line 68 "sel-lex.l"
+
+
+#line 723 "lex.yy.c"
+
+ if ( !(yy_init) )
+ {
+ (yy_init) = 1;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ if ( ! (yy_start) )
+ (yy_start) = 1; /* first start state */
+
+ if ( ! yyin )
+ yyin = stdin;
+
+ if ( ! yyout )
+ yyout = stdout;
+
+ if ( ! YY_CURRENT_BUFFER ) {
+ yyensure_buffer_stack ();
+ YY_CURRENT_BUFFER_LVALUE =
+ yy_create_buffer(yyin,YY_BUF_SIZE );
+ }
+
+ yy_load_buffer_state( );
+ }
+
+ while ( 1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = (yy_c_buf_p);
+
+ /* Support of yytext. */
+ *yy_cp = (yy_hold_char);
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = (yy_start);
+yy_match:
+ do
+ {
+ register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ if ( yy_accept[yy_current_state] )
+ {
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 36 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ ++yy_cp;
+ }
+ while ( yy_base[yy_current_state] != 44 );
+
+yy_find_action:
+ yy_act = yy_accept[yy_current_state];
+ if ( yy_act == 0 )
+ { /* have to back up */
+ yy_cp = (yy_last_accepting_cpos);
+ yy_current_state = (yy_last_accepting_state);
+ yy_act = yy_accept[yy_current_state];
+ }
+
+ YY_DO_BEFORE_ACTION;
+
+do_action: /* This label is used only to access EOF actions. */
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+ case 0: /* must back up */
+ /* undo the effects of YY_DO_BEFORE_ACTION */
+ *yy_cp = (yy_hold_char);
+ yy_cp = (yy_last_accepting_cpos);
+ yy_current_state = (yy_last_accepting_state);
+ goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 70 "sel-lex.l"
+{ return kw_TRUE; }
+ YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 71 "sel-lex.l"
+{ return kw_FALSE; }
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 72 "sel-lex.l"
+{ return kw_AND; }
+ YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 73 "sel-lex.l"
+{ return kw_OR; }
+ YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 74 "sel-lex.l"
+{ return kw_IN; }
+ YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 75 "sel-lex.l"
+{ return kw_TAILMATCH; }
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 77 "sel-lex.l"
+{
+ yylval.string = strdup ((const char *)yytext);
+ return IDENTIFIER;
+ }
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 81 "sel-lex.l"
+{ yylval.string = handle_string(); return STRING; }
+ YY_BREAK
+case 9:
+/* rule 9 can match eol */
+YY_RULE_SETUP
+#line 82 "sel-lex.l"
+{ ++lineno; }
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 83 "sel-lex.l"
+{ return *yytext; }
+ YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 84 "sel-lex.l"
+;
+ YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 85 "sel-lex.l"
+ECHO;
+ YY_BREAK
+#line 870 "lex.yy.c"
+case YY_STATE_EOF(INITIAL):
+ yyterminate();
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = (yy_hold_char);
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed yyin at a new source and called
+ * yylex(). If so, then we have to assure
+ * consistency between YY_CURRENT_BUFFER and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( );
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+ yy_cp = ++(yy_c_buf_p);
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+ yy_cp = (yy_c_buf_p);
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer( ) )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ (yy_did_buffer_switch_on_eof) = 0;
+
+ if ( yywrap( ) )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * yytext, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! (yy_did_buffer_switch_on_eof) )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ (yy_c_buf_p) =
+ (yytext_ptr) + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( );
+
+ yy_cp = (yy_c_buf_p);
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ (yy_c_buf_p) =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+ yy_current_state = yy_get_previous_state( );
+
+ yy_cp = (yy_c_buf_p);
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+} /* end of yylex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (void)
+{
+ register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ register char *source = (yytext_ptr);
+ register int number_to_move, i;
+ int ret_val;
+
+ if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else
+ {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+ else
+ {
+ int num_to_read =
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+
+ /* just a shorter name for the current buffer */
+ YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+ int yy_c_buf_p_offset =
+ (int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+ if ( b->yy_is_our_buffer )
+ {
+ int new_size = b->yy_buf_size * 2;
+
+ if ( new_size <= 0 )
+ b->yy_buf_size += b->yy_buf_size / 8;
+ else
+ b->yy_buf_size *= 2;
+
+ b->yy_ch_buf = (char *)
+ /* Include room in for 2 EOB chars. */
+ yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 );
+ }
+ else
+ /* Can't grow it, we don't own it. */
+ b->yy_ch_buf = 0;
+
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR(
+ "fatal error - scanner input buffer overflow" );
+
+ (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+ num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+ number_to_move - 1;
+
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+ (yy_n_chars), (size_t) num_to_read );
+
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ if ( (yy_n_chars) == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ yyrestart(yyin );
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+ /* Extend the array by 50%, plus the number we really need. */
+ yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size );
+ if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+ }
+
+ (yy_n_chars) += number_to_move;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+ (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+ return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+ static yy_state_type yy_get_previous_state (void)
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp;
+
+ yy_current_state = (yy_start);
+
+ for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+ {
+ register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ if ( yy_accept[yy_current_state] )
+ {
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 36 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ }
+
+ return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state )
+{
+ register int yy_is_jam;
+ register char *yy_cp = (yy_c_buf_p);
+
+ register YY_CHAR yy_c = 1;
+ if ( yy_accept[yy_current_state] )
+ {
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 36 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ yy_is_jam = (yy_current_state == 35);
+
+ return yy_is_jam ? 0 : yy_current_state;
+}
+
+ static void yyunput (int c, register char * yy_bp )
+{
+ register char *yy_cp;
+
+ yy_cp = (yy_c_buf_p);
+
+ /* undo effects of setting up yytext */
+ *yy_cp = (yy_hold_char);
+
+ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+ { /* need to shift things up to make room */
+ /* +2 for EOB chars. */
+ register int number_to_move = (yy_n_chars) + 2;
+ register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+ register char *source =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+ while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ *--dest = *--source;
+
+ yy_cp += (int) (dest - source);
+ yy_bp += (int) (dest - source);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+ YY_FATAL_ERROR( "flex scanner push-back overflow" );
+ }
+
+ *--yy_cp = (char) c;
+
+ (yytext_ptr) = yy_bp;
+ (yy_hold_char) = *yy_cp;
+ (yy_c_buf_p) = yy_cp;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+ static int yyinput (void)
+#else
+ static int input (void)
+#endif
+
+{
+ int c;
+
+ *(yy_c_buf_p) = (yy_hold_char);
+
+ if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+ /* This was really a NUL. */
+ *(yy_c_buf_p) = '\0';
+
+ else
+ { /* need more input */
+ int offset = (yy_c_buf_p) - (yytext_ptr);
+ ++(yy_c_buf_p);
+
+ switch ( yy_get_next_buffer( ) )
+ {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ yyrestart(yyin );
+
+ /*FALLTHROUGH*/
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( yywrap( ) )
+ return EOF;
+
+ if ( ! (yy_did_buffer_switch_on_eof) )
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput();
+#else
+ return input();
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ (yy_c_buf_p) = (yytext_ptr) + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */
+ *(yy_c_buf_p) = '\0'; /* preserve yytext */
+ (yy_hold_char) = *++(yy_c_buf_p);
+
+ return c;
+}
+#endif /* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ *
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+ void yyrestart (FILE * input_file )
+{
+
+ if ( ! YY_CURRENT_BUFFER ){
+ yyensure_buffer_stack ();
+ YY_CURRENT_BUFFER_LVALUE =
+ yy_create_buffer(yyin,YY_BUF_SIZE );
+ }
+
+ yy_init_buffer(YY_CURRENT_BUFFER,input_file );
+ yy_load_buffer_state( );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ *
+ */
+ void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer )
+{
+
+ /* TODO. We should be able to replace this entire function body
+ * with
+ * yypop_buffer_state();
+ * yypush_buffer_state(new_buffer);
+ */
+ yyensure_buffer_stack ();
+ if ( YY_CURRENT_BUFFER == new_buffer )
+ return;
+
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *(yy_c_buf_p) = (yy_hold_char);
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+ yy_load_buffer_state( );
+
+ /* We don't actually know whether we did this switch during
+ * EOF (yywrap()) processing, but the only time this flag
+ * is looked at is after yywrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ (yy_did_buffer_switch_on_eof) = 1;
+}
+
+static void yy_load_buffer_state (void)
+{
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+ yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+ (yy_hold_char) = *(yy_c_buf_p);
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ *
+ * @return the allocated buffer state.
+ */
+ YY_BUFFER_STATE yy_create_buffer (FILE * file, int size )
+{
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ yy_init_buffer(b,file );
+
+ return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with yy_create_buffer()
+ *
+ */
+ void yy_delete_buffer (YY_BUFFER_STATE b )
+{
+
+ if ( ! b )
+ return;
+
+ if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+ yyfree((void *) b->yy_ch_buf );
+
+ yyfree((void *) b );
+}
+
+#ifndef __cplusplus
+extern int isatty (int );
+#endif /* __cplusplus */
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a yyrestart() or at EOF.
+ */
+ static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file )
+
+{
+ int oerrno = errno;
+
+ yy_flush_buffer(b );
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+ /* If b is the current buffer, then yy_init_buffer was _probably_
+ * called from yyrestart() or through yy_get_next_buffer.
+ * In that case, we don't want to reset the lineno or column.
+ */
+ if (b != YY_CURRENT_BUFFER){
+ b->yy_bs_lineno = 1;
+ b->yy_bs_column = 0;
+ }
+
+ b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+
+ errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ *
+ */
+ void yy_flush_buffer (YY_BUFFER_STATE b )
+{
+ if ( ! b )
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if ( b == YY_CURRENT_BUFFER )
+ yy_load_buffer_state( );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ * the current state. This function will allocate the stack
+ * if necessary.
+ * @param new_buffer The new state.
+ *
+ */
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+ if (new_buffer == NULL)
+ return;
+
+ yyensure_buffer_stack();
+
+ /* This block is copied from yy_switch_to_buffer. */
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *(yy_c_buf_p) = (yy_hold_char);
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ /* Only push if top exists. Otherwise, replace top. */
+ if (YY_CURRENT_BUFFER)
+ (yy_buffer_stack_top)++;
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+ /* copied from yy_switch_to_buffer. */
+ yy_load_buffer_state( );
+ (yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ * The next element becomes the new top.
+ *
+ */
+void yypop_buffer_state (void)
+{
+ if (!YY_CURRENT_BUFFER)
+ return;
+
+ yy_delete_buffer(YY_CURRENT_BUFFER );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ if ((yy_buffer_stack_top) > 0)
+ --(yy_buffer_stack_top);
+
+ if (YY_CURRENT_BUFFER) {
+ yy_load_buffer_state( );
+ (yy_did_buffer_switch_on_eof) = 1;
+ }
+}
+
+/* Allocates the stack if it does not exist.
+ * Guarantees space for at least one push.
+ */
+static void yyensure_buffer_stack (void)
+{
+ int num_to_alloc;
+
+ if (!(yy_buffer_stack)) {
+
+ /* First allocation is just for 2 elements, since we don't know if this
+ * scanner will even need a stack. We use 2 instead of 1 to avoid an
+ * immediate realloc on the next call.
+ */
+ num_to_alloc = 1;
+ (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
+ (num_to_alloc * sizeof(struct yy_buffer_state*)
+ );
+ if ( ! (yy_buffer_stack) )
+ YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+ memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+
+ (yy_buffer_stack_max) = num_to_alloc;
+ (yy_buffer_stack_top) = 0;
+ return;
+ }
+
+ if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+ /* Increase the buffer to prepare for a possible push. */
+ int grow_size = 8 /* arbitrary grow size */;
+
+ num_to_alloc = (yy_buffer_stack_max) + grow_size;
+ (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
+ ((yy_buffer_stack),
+ num_to_alloc * sizeof(struct yy_buffer_state*)
+ );
+ if ( ! (yy_buffer_stack) )
+ YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+ /* zero only the new slots.*/
+ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+ (yy_buffer_stack_max) = num_to_alloc;
+ }
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ *
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size )
+{
+ YY_BUFFER_STATE b;
+
+ if ( size < 2 ||
+ base[size-2] != YY_END_OF_BUFFER_CHAR ||
+ base[size-1] != YY_END_OF_BUFFER_CHAR )
+ /* They forgot to leave room for the EOB's. */
+ return 0;
+
+ b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+ b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = 0;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ yy_switch_to_buffer(b );
+
+ return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to yylex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ *
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ * yy_scan_bytes() instead.
+ */
+YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
+{
+
+ return yy_scan_bytes(yystr,strlen(yystr) );
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
+ * scan from a @e copy of @a bytes.
+ * @param bytes the byte buffer to scan
+ * @param len the number of bytes in the buffer pointed to by @a bytes.
+ *
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len )
+{
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = _yybytes_len + 2;
+ buf = (char *) yyalloc(n );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+ for ( i = 0; i < _yybytes_len; ++i )
+ buf[i] = yybytes[i];
+
+ buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+ b = yy_scan_buffer(buf,n );
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg )
+{
+ (void) fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ yytext[yyleng] = (yy_hold_char); \
+ (yy_c_buf_p) = yytext + yyless_macro_arg; \
+ (yy_hold_char) = *(yy_c_buf_p); \
+ *(yy_c_buf_p) = '\0'; \
+ yyleng = yyless_macro_arg; \
+ } \
+ while ( 0 )
+
+/* Accessor methods (get/set functions) to struct members. */
+
+/** Get the current line number.
+ *
+ */
+int yyget_lineno (void)
+{
+
+ return yylineno;
+}
+
+/** Get the input stream.
+ *
+ */
+FILE *yyget_in (void)
+{
+ return yyin;
+}
+
+/** Get the output stream.
+ *
+ */
+FILE *yyget_out (void)
+{
+ return yyout;
+}
+
+/** Get the length of the current token.
+ *
+ */
+int yyget_leng (void)
+{
+ return yyleng;
+}
+
+/** Get the current token.
+ *
+ */
+
+char *yyget_text (void)
+{
+ return yytext;
+}
+
+/** Set the current line number.
+ * @param line_number
+ *
+ */
+void yyset_lineno (int line_number )
+{
+
+ yylineno = line_number;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ *
+ * @see yy_switch_to_buffer
+ */
+void yyset_in (FILE * in_str )
+{
+ yyin = in_str ;
+}
+
+void yyset_out (FILE * out_str )
+{
+ yyout = out_str ;
+}
+
+int yyget_debug (void)
+{
+ return yy_flex_debug;
+}
+
+void yyset_debug (int bdebug )
+{
+ yy_flex_debug = bdebug ;
+}
+
+static int yy_init_globals (void)
+{
+ /* Initialization is the same as for the non-reentrant scanner.
+ * This function is called from yylex_destroy(), so don't allocate here.
+ */
+
+ (yy_buffer_stack) = 0;
+ (yy_buffer_stack_top) = 0;
+ (yy_buffer_stack_max) = 0;
+ (yy_c_buf_p) = (char *) 0;
+ (yy_init) = 0;
+ (yy_start) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+ yyin = stdin;
+ yyout = stdout;
+#else
+ yyin = (FILE *) 0;
+ yyout = (FILE *) 0;
+#endif
+
+ /* For future reference: Set errno on error, since we are called by
+ * yylex_init()
+ */
+ return 0;
+}
+
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_destroy (void)
+{
+
+ /* Pop the buffer stack, destroying each element. */
+ while(YY_CURRENT_BUFFER){
+ yy_delete_buffer(YY_CURRENT_BUFFER );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ yypop_buffer_state();
+ }
+
+ /* Destroy the stack itself. */
+ yyfree((yy_buffer_stack) );
+ (yy_buffer_stack) = NULL;
+
+ /* Reset the globals. This is important in a non-reentrant scanner so the next time
+ * yylex() is called, initialization will occur. */
+ yy_init_globals( );
+
+ return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+{
+ register int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s )
+{
+ register int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+}
+#endif
+
+void *yyalloc (yy_size_t size )
+{
+ return (void *) malloc( size );
+}
+
+void *yyrealloc (void * ptr, yy_size_t size )
+{
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return (void *) realloc( (char *) ptr, size );
+}
+
+void yyfree (void * ptr )
+{
+ free( (char *) ptr ); /* see yyrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 85 "sel-lex.l"
+
+
+
+static char *
+handle_string(void)
+{
+ char x[1024];
+ int i = 0;
+ int c;
+ int quote = 0;
+ while((c = input()) != EOF){
+ if(quote) {
+ x[i++] = '\\';
+ x[i++] = c;
+ quote = 0;
+ continue;
+ }
+ if(c == '\n'){
+ _hx509_sel_yyerror("unterminated string");
+ lineno++;
+ break;
+ }
+ if(c == '\\'){
+ quote++;
+ continue;
+ }
+ if(c == '\"')
+ break;
+ x[i++] = c;
+ }
+ x[i] = '\0';
+ return strdup(x);
+}
+
+int
+yywrap ()
+{
+ return 1;
+}
+
+static int
+lex_input(char *buf, int max_size)
+{
+ int n;
+
+ n = _hx509_expr_input.length - _hx509_expr_input.offset;
+ if (max_size < n)
+ n = max_size;
+ if (n <= 0)
+ return YY_NULL;
+
+ memcpy(buf, _hx509_expr_input.buf + _hx509_expr_input.offset, n);
+ _hx509_expr_input.offset += n;
+
+ return n;
+}
diff --git a/source4/heimdal/lib/krb5/crypto-aes.c b/source4/heimdal/lib/krb5/crypto-aes.c
new file mode 100644
index 0000000000..25c675c900
--- /dev/null
+++ b/source4/heimdal/lib/krb5/crypto-aes.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 1997 - 2008 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"
+
+/*
+ * AES
+ */
+
+static struct key_type keytype_aes128 = {
+ KEYTYPE_AES128,
+ "aes-128",
+ 128,
+ 16,
+ sizeof(struct evp_schedule),
+ NULL,
+ _krb5_evp_schedule,
+ _krb5_AES_salt,
+ NULL,
+ _krb5_evp_cleanup,
+ EVP_aes_128_cbc
+};
+
+static struct key_type keytype_aes256 = {
+ KEYTYPE_AES256,
+ "aes-256",
+ 256,
+ 32,
+ sizeof(struct evp_schedule),
+ NULL,
+ _krb5_evp_schedule,
+ _krb5_AES_salt,
+ NULL,
+ _krb5_evp_cleanup,
+ EVP_aes_256_cbc
+};
+
+struct checksum_type _krb5_checksum_hmac_sha1_aes128 = {
+ CKSUMTYPE_HMAC_SHA1_96_AES_128,
+ "hmac-sha1-96-aes128",
+ 64,
+ 12,
+ F_KEYED | F_CPROOF | F_DERIVED,
+ _krb5_SP_HMAC_SHA1_checksum,
+ NULL
+};
+
+struct checksum_type _krb5_checksum_hmac_sha1_aes256 = {
+ CKSUMTYPE_HMAC_SHA1_96_AES_256,
+ "hmac-sha1-96-aes256",
+ 64,
+ 12,
+ F_KEYED | F_CPROOF | F_DERIVED,
+ _krb5_SP_HMAC_SHA1_checksum,
+ NULL
+};
+
+static krb5_error_code
+AES_PRF(krb5_context context,
+ krb5_crypto crypto,
+ const krb5_data *in,
+ krb5_data *out)
+{
+ struct checksum_type *ct = crypto->et->checksum;
+ krb5_error_code ret;
+ Checksum result;
+ krb5_keyblock *derived;
+
+ result.cksumtype = ct->type;
+ ret = krb5_data_alloc(&result.checksum, ct->checksumsize);
+ if (ret) {
+ krb5_set_error_message(context, ret, N_("malloc: out memory", ""));
+ return ret;
+ }
+
+ ret = (*ct->checksum)(context, NULL, in->data, in->length, 0, &result);
+ if (ret) {
+ krb5_data_free(&result.checksum);
+ return ret;
+ }
+
+ if (result.checksum.length < crypto->et->blocksize)
+ krb5_abortx(context, "internal prf error");
+
+ derived = NULL;
+ ret = krb5_derive_key(context, crypto->key.key,
+ crypto->et->type, "prf", 3, &derived);
+ if (ret)
+ krb5_abortx(context, "krb5_derive_key");
+
+ ret = krb5_data_alloc(out, crypto->et->blocksize);
+ if (ret)
+ krb5_abortx(context, "malloc failed");
+
+ {
+ const EVP_CIPHER *c = (*crypto->et->keytype->evp)();
+ EVP_CIPHER_CTX ctx;
+
+ 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,
+ crypto->et->blocksize);
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ }
+
+ krb5_data_free(&result.checksum);
+ krb5_free_keyblock(context, derived);
+
+ return ret;
+}
+
+struct encryption_type _krb5_enctype_aes128_cts_hmac_sha1 = {
+ ETYPE_AES128_CTS_HMAC_SHA1_96,
+ "aes128-cts-hmac-sha1-96",
+ 16,
+ 1,
+ 16,
+ &keytype_aes128,
+ &_krb5_checksum_sha1,
+ &_krb5_checksum_hmac_sha1_aes128,
+ F_DERIVED,
+ _krb5_evp_encrypt_cts,
+ 16,
+ AES_PRF
+};
+
+struct encryption_type _krb5_enctype_aes256_cts_hmac_sha1 = {
+ ETYPE_AES256_CTS_HMAC_SHA1_96,
+ "aes256-cts-hmac-sha1-96",
+ 16,
+ 1,
+ 16,
+ &keytype_aes256,
+ &_krb5_checksum_sha1,
+ &_krb5_checksum_hmac_sha1_aes256,
+ F_DERIVED,
+ _krb5_evp_encrypt_cts,
+ 16,
+ AES_PRF
+};
diff --git a/source4/heimdal/lib/krb5/crypto-algs.c b/source4/heimdal/lib/krb5/crypto-algs.c
new file mode 100644
index 0000000000..5bd14ce09d
--- /dev/null
+++ b/source4/heimdal/lib/krb5/crypto-algs.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 1997 - 2008 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"
+
+#ifndef HEIMDAL_SMALLER
+#define DES3_OLD_ENCTYPE 1
+#endif
+
+struct checksum_type *_krb5_checksum_types[] = {
+ &_krb5_checksum_none,
+#ifdef HEIM_WEAK_CRYPTO
+ &_krb5_checksum_crc32,
+ &_krb5_checksum_rsa_md4,
+ &_krb5_checksum_rsa_md4_des,
+ &_krb5_checksum_rsa_md5_des,
+#endif
+#ifdef DES3_OLD_ENCTYPE
+ &_krb5_checksum_rsa_md5_des3,
+#endif
+ &_krb5_checksum_rsa_md5,
+ &_krb5_checksum_sha1,
+ &_krb5_checksum_hmac_sha1_des3,
+ &_krb5_checksum_hmac_sha1_aes128,
+ &_krb5_checksum_hmac_sha1_aes256,
+ &_krb5_checksum_hmac_md5
+};
+
+int _krb5_num_checksums
+ = sizeof(_krb5_checksum_types) / sizeof(_krb5_checksum_types[0]);
+
+/*
+ * these should currently be in reverse preference order.
+ * (only relevant for !F_PSEUDO) */
+
+struct encryption_type *_krb5_etypes[] = {
+ &_krb5_enctype_aes256_cts_hmac_sha1,
+ &_krb5_enctype_aes128_cts_hmac_sha1,
+ &_krb5_enctype_des3_cbc_sha1,
+ &_krb5_enctype_des3_cbc_none, /* used by the gss-api mech */
+ &_krb5_enctype_arcfour_hmac_md5,
+#ifdef DES3_OLD_ENCTYPE
+ &_krb5_enctype_des3_cbc_md5,
+ &_krb5_enctype_old_des3_cbc_sha1,
+#endif
+#ifdef HEIM_WEAK_CRYPTO
+ &_krb5_enctype_des_cbc_crc,
+ &_krb5_enctype_des_cbc_md4,
+ &_krb5_enctype_des_cbc_md5,
+ &_krb5_enctype_des_cbc_none,
+ &_krb5_enctype_des_cfb64_none,
+ &_krb5_enctype_des_pcbc_none,
+#endif
+ &_krb5_enctype_null
+};
+
+int _krb5_num_etypes = sizeof(_krb5_etypes) / sizeof(_krb5_etypes[0]);
diff --git a/source4/heimdal/lib/krb5/crypto-arcfour.c b/source4/heimdal/lib/krb5/crypto-arcfour.c
new file mode 100644
index 0000000000..d098561474
--- /dev/null
+++ b/source4/heimdal/lib/krb5/crypto-arcfour.c
@@ -0,0 +1,325 @@
+/*
+ * Copyright (c) 1997 - 2008 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.
+ */
+
+/*
+ * ARCFOUR
+ */
+
+#include "krb5_locl.h"
+
+static struct key_type keytype_arcfour = {
+ KEYTYPE_ARCFOUR,
+ "arcfour",
+ 128,
+ 16,
+ sizeof(struct evp_schedule),
+ NULL,
+ _krb5_evp_schedule,
+ _krb5_arcfour_salt,
+ NULL,
+ _krb5_evp_cleanup,
+ EVP_rc4
+};
+
+/*
+ * checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt
+ */
+
+krb5_error_code
+_krb5_HMAC_MD5_checksum(krb5_context context,
+ struct key_data *key,
+ const void *data,
+ size_t len,
+ unsigned usage,
+ Checksum *result)
+{
+ EVP_MD_CTX *m;
+ struct checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5);
+ const char signature[] = "signaturekey";
+ Checksum ksign_c;
+ struct key_data ksign;
+ krb5_keyblock kb;
+ unsigned char t[4];
+ unsigned char tmp[16];
+ unsigned char ksign_c_data[16];
+ krb5_error_code ret;
+
+ m = EVP_MD_CTX_create();
+ if (m == NULL) {
+ krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
+ return ENOMEM;
+ }
+ ksign_c.checksum.length = sizeof(ksign_c_data);
+ ksign_c.checksum.data = ksign_c_data;
+ ret = _krb5_internal_hmac(context, c, signature, sizeof(signature),
+ 0, key, &ksign_c);
+ if (ret) {
+ EVP_MD_CTX_destroy(m);
+ return ret;
+ }
+ ksign.key = &kb;
+ kb.keyvalue = ksign_c.checksum;
+ EVP_DigestInit_ex(m, EVP_md5(), NULL);
+ t[0] = (usage >> 0) & 0xFF;
+ t[1] = (usage >> 8) & 0xFF;
+ t[2] = (usage >> 16) & 0xFF;
+ t[3] = (usage >> 24) & 0xFF;
+ EVP_DigestUpdate(m, t, 4);
+ EVP_DigestUpdate(m, data, len);
+ EVP_DigestFinal_ex (m, tmp, NULL);
+ EVP_MD_CTX_destroy(m);
+
+ ret = _krb5_internal_hmac(context, c, tmp, sizeof(tmp), 0, &ksign, result);
+ if (ret)
+ return ret;
+ return 0;
+}
+
+struct checksum_type _krb5_checksum_hmac_md5 = {
+ CKSUMTYPE_HMAC_MD5,
+ "hmac-md5",
+ 64,
+ 16,
+ F_KEYED | F_CPROOF,
+ _krb5_HMAC_MD5_checksum,
+ NULL
+};
+
+/*
+ * section 6 of draft-brezak-win2k-krb-rc4-hmac-03
+ *
+ * warning: not for small children
+ */
+
+static krb5_error_code
+ARCFOUR_subencrypt(krb5_context context,
+ struct key_data *key,
+ void *data,
+ size_t len,
+ unsigned usage,
+ void *ivec)
+{
+ EVP_CIPHER_CTX ctx;
+ struct checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5);
+ Checksum k1_c, k2_c, k3_c, cksum;
+ struct key_data ke;
+ krb5_keyblock kb;
+ unsigned char t[4];
+ unsigned char *cdata = data;
+ unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
+ krb5_error_code ret;
+
+ t[0] = (usage >> 0) & 0xFF;
+ t[1] = (usage >> 8) & 0xFF;
+ t[2] = (usage >> 16) & 0xFF;
+ t[3] = (usage >> 24) & 0xFF;
+
+ k1_c.checksum.length = sizeof(k1_c_data);
+ k1_c.checksum.data = k1_c_data;
+
+ ret = _krb5_internal_hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
+ if (ret)
+ krb5_abortx(context, "hmac failed");
+
+ memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
+
+ k2_c.checksum.length = sizeof(k2_c_data);
+ k2_c.checksum.data = k2_c_data;
+
+ ke.key = &kb;
+ kb.keyvalue = k2_c.checksum;
+
+ cksum.checksum.length = 16;
+ cksum.checksum.data = data;
+
+ ret = _krb5_internal_hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
+ if (ret)
+ krb5_abortx(context, "hmac failed");
+
+ ke.key = &kb;
+ kb.keyvalue = k1_c.checksum;
+
+ k3_c.checksum.length = sizeof(k3_c_data);
+ k3_c.checksum.data = k3_c_data;
+
+ ret = _krb5_internal_hmac(NULL, c, data, 16, 0, &ke, &k3_c);
+ if (ret)
+ krb5_abortx(context, "hmac failed");
+
+ EVP_CIPHER_CTX_init(&ctx);
+
+ EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 1);
+ EVP_Cipher(&ctx, cdata + 16, cdata + 16, len - 16);
+ EVP_CIPHER_CTX_cleanup(&ctx);
+
+ memset (k1_c_data, 0, sizeof(k1_c_data));
+ memset (k2_c_data, 0, sizeof(k2_c_data));
+ memset (k3_c_data, 0, sizeof(k3_c_data));
+ return 0;
+}
+
+static krb5_error_code
+ARCFOUR_subdecrypt(krb5_context context,
+ struct key_data *key,
+ void *data,
+ size_t len,
+ unsigned usage,
+ void *ivec)
+{
+ EVP_CIPHER_CTX ctx;
+ struct checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5);
+ Checksum k1_c, k2_c, k3_c, cksum;
+ struct key_data ke;
+ krb5_keyblock kb;
+ unsigned char t[4];
+ unsigned char *cdata = data;
+ unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
+ unsigned char cksum_data[16];
+ krb5_error_code ret;
+
+ t[0] = (usage >> 0) & 0xFF;
+ t[1] = (usage >> 8) & 0xFF;
+ t[2] = (usage >> 16) & 0xFF;
+ t[3] = (usage >> 24) & 0xFF;
+
+ k1_c.checksum.length = sizeof(k1_c_data);
+ k1_c.checksum.data = k1_c_data;
+
+ ret = _krb5_internal_hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
+ if (ret)
+ krb5_abortx(context, "hmac failed");
+
+ memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
+
+ k2_c.checksum.length = sizeof(k2_c_data);
+ k2_c.checksum.data = k2_c_data;
+
+ ke.key = &kb;
+ kb.keyvalue = k1_c.checksum;
+
+ k3_c.checksum.length = sizeof(k3_c_data);
+ k3_c.checksum.data = k3_c_data;
+
+ ret = _krb5_internal_hmac(NULL, c, cdata, 16, 0, &ke, &k3_c);
+ if (ret)
+ krb5_abortx(context, "hmac failed");
+
+ EVP_CIPHER_CTX_init(&ctx);
+ EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 0);
+ EVP_Cipher(&ctx, cdata + 16, cdata + 16, len - 16);
+ EVP_CIPHER_CTX_cleanup(&ctx);
+
+ ke.key = &kb;
+ kb.keyvalue = k2_c.checksum;
+
+ cksum.checksum.length = 16;
+ cksum.checksum.data = cksum_data;
+
+ ret = _krb5_internal_hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
+ if (ret)
+ krb5_abortx(context, "hmac failed");
+
+ memset (k1_c_data, 0, sizeof(k1_c_data));
+ memset (k2_c_data, 0, sizeof(k2_c_data));
+ memset (k3_c_data, 0, sizeof(k3_c_data));
+
+ if (ct_memcmp (cksum.checksum.data, data, 16) != 0) {
+ krb5_clear_error_message (context);
+ return KRB5KRB_AP_ERR_BAD_INTEGRITY;
+ } else {
+ return 0;
+ }
+}
+
+/*
+ * convert the usage numbers used in
+ * draft-ietf-cat-kerb-key-derivation-00.txt to the ones in
+ * draft-brezak-win2k-krb-rc4-hmac-04.txt
+ */
+
+krb5_error_code
+_krb5_usage2arcfour(krb5_context context, unsigned *usage)
+{
+ switch (*usage) {
+ case KRB5_KU_AS_REP_ENC_PART : /* 3 */
+ *usage = 8;
+ return 0;
+ case KRB5_KU_USAGE_SEAL : /* 22 */
+ *usage = 13;
+ return 0;
+ case KRB5_KU_USAGE_SIGN : /* 23 */
+ *usage = 15;
+ return 0;
+ case KRB5_KU_USAGE_SEQ: /* 24 */
+ *usage = 0;
+ return 0;
+ default :
+ return 0;
+ }
+}
+
+static krb5_error_code
+ARCFOUR_encrypt(krb5_context context,
+ struct key_data *key,
+ void *data,
+ size_t len,
+ krb5_boolean encryptp,
+ int usage,
+ void *ivec)
+{
+ krb5_error_code ret;
+ unsigned keyusage = usage;
+
+ if((ret = _krb5_usage2arcfour (context, &keyusage)) != 0)
+ return ret;
+
+ if (encryptp)
+ return ARCFOUR_subencrypt (context, key, data, len, keyusage, ivec);
+ else
+ return ARCFOUR_subdecrypt (context, key, data, len, keyusage, ivec);
+}
+
+struct encryption_type _krb5_enctype_arcfour_hmac_md5 = {
+ ETYPE_ARCFOUR_HMAC_MD5,
+ "arcfour-hmac-md5",
+ 1,
+ 1,
+ 8,
+ &keytype_arcfour,
+ &_krb5_checksum_hmac_md5,
+ NULL,
+ F_SPECIAL,
+ ARCFOUR_encrypt,
+ 0,
+ NULL
+};
diff --git a/source4/heimdal/lib/krb5/crypto-des-common.c b/source4/heimdal/lib/krb5/crypto-des-common.c
new file mode 100644
index 0000000000..82d344f28f
--- /dev/null
+++ b/source4/heimdal/lib/krb5/crypto-des-common.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 1997 - 2008 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.
+ */
+
+/* Functions which are used by both single and triple DES enctypes */
+
+#include "krb5_locl.h"
+
+/*
+ * A = A xor B. A & B are 8 bytes.
+ */
+
+void
+_krb5_xor (DES_cblock *key, const unsigned char *b)
+{
+ unsigned char *a = (unsigned char*)key;
+ a[0] ^= b[0];
+ a[1] ^= b[1];
+ a[2] ^= b[2];
+ a[3] ^= b[3];
+ a[4] ^= b[4];
+ a[5] ^= b[5];
+ a[6] ^= b[6];
+ a[7] ^= b[7];
+}
+
+#if defined(DES3_OLD_ENCTYPE) || defined(HEIM_WEAK_CRYPTO)
+krb5_error_code
+_krb5_des_checksum(krb5_context context,
+ const EVP_MD *evp_md,
+ struct key_data *key,
+ const void *data,
+ size_t len,
+ Checksum *cksum)
+{
+ struct evp_schedule *ctx = key->schedule->data;
+ EVP_MD_CTX *m;
+ DES_cblock ivec;
+ unsigned char *p = cksum->checksum.data;
+
+ krb5_generate_random_block(p, 8);
+
+ m = EVP_MD_CTX_create();
+ if (m == NULL) {
+ krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
+ return ENOMEM;
+ }
+
+ EVP_DigestInit_ex(m, evp_md, NULL);
+ EVP_DigestUpdate(m, p, 8);
+ EVP_DigestUpdate(m, data, len);
+ EVP_DigestFinal_ex (m, p + 8, NULL);
+ EVP_MD_CTX_destroy(m);
+ memset (&ivec, 0, sizeof(ivec));
+ EVP_CipherInit_ex(&ctx->ectx, NULL, NULL, NULL, (void *)&ivec, -1);
+ EVP_Cipher(&ctx->ectx, p, p, 24);
+
+ return 0;
+}
+
+krb5_error_code
+_krb5_des_verify(krb5_context context,
+ const EVP_MD *evp_md,
+ struct key_data *key,
+ const void *data,
+ size_t len,
+ Checksum *C)
+{
+ struct evp_schedule *ctx = key->schedule->data;
+ EVP_MD_CTX *m;
+ unsigned char tmp[24];
+ unsigned char res[16];
+ DES_cblock ivec;
+ krb5_error_code ret = 0;
+
+ m = EVP_MD_CTX_create();
+ if (m == NULL) {
+ krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
+ return ENOMEM;
+ }
+
+ memset(&ivec, 0, sizeof(ivec));
+ EVP_CipherInit_ex(&ctx->dctx, NULL, NULL, NULL, (void *)&ivec, -1);
+ EVP_Cipher(&ctx->dctx, tmp, C->checksum.data, 24);
+
+ EVP_DigestInit_ex(m, evp_md, NULL);
+ EVP_DigestUpdate(m, tmp, 8); /* confounder */
+ EVP_DigestUpdate(m, data, len);
+ EVP_DigestFinal_ex (m, res, NULL);
+ EVP_MD_CTX_destroy(m);
+ if(ct_memcmp(res, tmp + 8, sizeof(res)) != 0) {
+ krb5_clear_error_message (context);
+ ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+ }
+ memset(tmp, 0, sizeof(tmp));
+ memset(res, 0, sizeof(res));
+ return ret;
+}
+
+#endif
+
+static krb5_error_code
+RSA_MD5_checksum(krb5_context context,
+ struct key_data *key,
+ const void *data,
+ size_t len,
+ unsigned usage,
+ Checksum *C)
+{
+ if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_md5(), NULL) != 1)
+ krb5_abortx(context, "md5 checksum failed");
+ return 0;
+}
+
+struct checksum_type _krb5_checksum_rsa_md5 = {
+ CKSUMTYPE_RSA_MD5,
+ "rsa-md5",
+ 64,
+ 16,
+ F_CPROOF,
+ RSA_MD5_checksum,
+ NULL
+};
diff --git a/source4/heimdal/lib/krb5/crypto-des.c b/source4/heimdal/lib/krb5/crypto-des.c
new file mode 100644
index 0000000000..f6c09ba40c
--- /dev/null
+++ b/source4/heimdal/lib/krb5/crypto-des.c
@@ -0,0 +1,375 @@
+/*
+ * Copyright (c) 1997 - 2008 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"
+
+#ifdef HEIM_WEAK_CRYPTO
+
+
+static void
+krb5_DES_random_key(krb5_context context,
+ krb5_keyblock *key)
+{
+ DES_cblock *k = key->keyvalue.data;
+ do {
+ krb5_generate_random_block(k, sizeof(DES_cblock));
+ DES_set_odd_parity(k);
+ } while(DES_is_weak_key(k));
+}
+
+static void
+krb5_DES_schedule_old(krb5_context context,
+ struct key_type *kt,
+ struct key_data *key)
+{
+ DES_set_key_unchecked(key->key->keyvalue.data, key->schedule->data);
+}
+
+static void
+krb5_DES_random_to_key(krb5_context context,
+ krb5_keyblock *key,
+ const void *data,
+ size_t size)
+{
+ DES_cblock *k = key->keyvalue.data;
+ memcpy(k, data, key->keyvalue.length);
+ DES_set_odd_parity(k);
+ if(DES_is_weak_key(k))
+ _krb5_xor(k, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
+}
+
+static struct key_type keytype_des_old = {
+ KEYTYPE_DES,
+ "des-old",
+ 56,
+ 8,
+ sizeof(DES_key_schedule),
+ krb5_DES_random_key,
+ krb5_DES_schedule_old,
+ _krb5_des_salt,
+ krb5_DES_random_to_key
+};
+
+static struct key_type keytype_des = {
+ KEYTYPE_DES,
+ "des",
+ 56,
+ 8,
+ sizeof(struct evp_schedule),
+ krb5_DES_random_key,
+ _krb5_evp_schedule,
+ _krb5_des_salt,
+ krb5_DES_random_to_key,
+ _krb5_evp_cleanup,
+ EVP_des_cbc
+};
+
+static krb5_error_code
+CRC32_checksum(krb5_context context,
+ struct key_data *key,
+ const void *data,
+ size_t len,
+ unsigned usage,
+ Checksum *C)
+{
+ uint32_t crc;
+ unsigned char *r = C->checksum.data;
+ _krb5_crc_init_table ();
+ crc = _krb5_crc_update (data, len, 0);
+ r[0] = crc & 0xff;
+ r[1] = (crc >> 8) & 0xff;
+ r[2] = (crc >> 16) & 0xff;
+ r[3] = (crc >> 24) & 0xff;
+ return 0;
+}
+
+static krb5_error_code
+RSA_MD4_checksum(krb5_context context,
+ struct key_data *key,
+ const void *data,
+ size_t len,
+ unsigned usage,
+ Checksum *C)
+{
+ if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_md4(), NULL) != 1)
+ krb5_abortx(context, "md4 checksum failed");
+ return 0;
+}
+
+static krb5_error_code
+RSA_MD4_DES_checksum(krb5_context context,
+ struct key_data *key,
+ const void *data,
+ size_t len,
+ unsigned usage,
+ Checksum *cksum)
+{
+ return _krb5_des_checksum(context, EVP_md4(), key, data, len, cksum);
+}
+
+static krb5_error_code
+RSA_MD4_DES_verify(krb5_context context,
+ struct key_data *key,
+ const void *data,
+ size_t len,
+ unsigned usage,
+ Checksum *C)
+{
+ return _krb5_des_verify(context, EVP_md4(), key, data, len, C);
+}
+
+static krb5_error_code
+RSA_MD5_DES_checksum(krb5_context context,
+ struct key_data *key,
+ const void *data,
+ size_t len,
+ unsigned usage,
+ Checksum *C)
+{
+ return _krb5_des_checksum(context, EVP_md5(), key, data, len, C);
+}
+
+static krb5_error_code
+RSA_MD5_DES_verify(krb5_context context,
+ struct key_data *key,
+ const void *data,
+ size_t len,
+ unsigned usage,
+ Checksum *C)
+{
+ return _krb5_des_verify(context, EVP_md5(), key, data, len, C);
+}
+
+struct checksum_type _krb5_checksum_crc32 = {
+ CKSUMTYPE_CRC32,
+ "crc32",
+ 1,
+ 4,
+ 0,
+ CRC32_checksum,
+ NULL
+};
+
+struct checksum_type _krb5_checksum_rsa_md4 = {
+ CKSUMTYPE_RSA_MD4,
+ "rsa-md4",
+ 64,
+ 16,
+ F_CPROOF,
+ RSA_MD4_checksum,
+ NULL
+};
+
+struct checksum_type _krb5_checksum_rsa_md4_des = {
+ CKSUMTYPE_RSA_MD4_DES,
+ "rsa-md4-des",
+ 64,
+ 24,
+ F_KEYED | F_CPROOF | F_VARIANT,
+ RSA_MD4_DES_checksum,
+ RSA_MD4_DES_verify
+};
+
+struct checksum_type _krb5_checksum_rsa_md5_des = {
+ CKSUMTYPE_RSA_MD5_DES,
+ "rsa-md5-des",
+ 64,
+ 24,
+ F_KEYED | F_CPROOF | F_VARIANT,
+ RSA_MD5_DES_checksum,
+ RSA_MD5_DES_verify
+};
+
+static krb5_error_code
+evp_des_encrypt_null_ivec(krb5_context context,
+ struct key_data *key,
+ void *data,
+ size_t len,
+ krb5_boolean encryptp,
+ int usage,
+ void *ignore_ivec)
+{
+ struct evp_schedule *ctx = key->schedule->data;
+ EVP_CIPHER_CTX *c;
+ DES_cblock ivec;
+ memset(&ivec, 0, sizeof(ivec));
+ c = encryptp ? &ctx->ectx : &ctx->dctx;
+ EVP_CipherInit_ex(c, NULL, NULL, NULL, (void *)&ivec, -1);
+ EVP_Cipher(c, data, data, len);
+ return 0;
+}
+
+static krb5_error_code
+evp_des_encrypt_key_ivec(krb5_context context,
+ struct key_data *key,
+ void *data,
+ size_t len,
+ krb5_boolean encryptp,
+ int usage,
+ void *ignore_ivec)
+{
+ struct evp_schedule *ctx = key->schedule->data;
+ EVP_CIPHER_CTX *c;
+ DES_cblock ivec;
+ memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
+ c = encryptp ? &ctx->ectx : &ctx->dctx;
+ EVP_CipherInit_ex(c, NULL, NULL, NULL, (void *)&ivec, -1);
+ EVP_Cipher(c, data, data, len);
+ return 0;
+}
+
+static krb5_error_code
+DES_CFB64_encrypt_null_ivec(krb5_context context,
+ struct key_data *key,
+ void *data,
+ size_t len,
+ krb5_boolean encryptp,
+ int usage,
+ void *ignore_ivec)
+{
+ DES_cblock ivec;
+ int num = 0;
+ DES_key_schedule *s = key->schedule->data;
+ memset(&ivec, 0, sizeof(ivec));
+
+ DES_cfb64_encrypt(data, data, len, s, &ivec, &num, encryptp);
+ return 0;
+}
+
+static krb5_error_code
+DES_PCBC_encrypt_key_ivec(krb5_context context,
+ struct key_data *key,
+ void *data,
+ size_t len,
+ krb5_boolean encryptp,
+ int usage,
+ void *ignore_ivec)
+{
+ DES_cblock ivec;
+ DES_key_schedule *s = key->schedule->data;
+ memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
+
+ DES_pcbc_encrypt(data, data, len, s, &ivec, encryptp);
+ return 0;
+}
+
+struct encryption_type _krb5_enctype_des_cbc_crc = {
+ ETYPE_DES_CBC_CRC,
+ "des-cbc-crc",
+ 8,
+ 8,
+ 8,
+ &keytype_des,
+ &_krb5_checksum_crc32,
+ NULL,
+ F_DISABLED|F_WEAK,
+ evp_des_encrypt_key_ivec,
+ 0,
+ NULL
+};
+
+struct encryption_type _krb5_enctype_des_cbc_md4 = {
+ ETYPE_DES_CBC_MD4,
+ "des-cbc-md4",
+ 8,
+ 8,
+ 8,
+ &keytype_des,
+ &_krb5_checksum_rsa_md4,
+ &_krb5_checksum_rsa_md4_des,
+ F_DISABLED|F_WEAK,
+ evp_des_encrypt_null_ivec,
+ 0,
+ NULL
+};
+
+struct encryption_type _krb5_enctype_des_cbc_md5 = {
+ ETYPE_DES_CBC_MD5,
+ "des-cbc-md5",
+ 8,
+ 8,
+ 8,
+ &keytype_des,
+ &_krb5_checksum_rsa_md5,
+ &_krb5_checksum_rsa_md5_des,
+ F_DISABLED|F_WEAK,
+ evp_des_encrypt_null_ivec,
+ 0,
+ NULL
+};
+
+struct encryption_type _krb5_enctype_des_cbc_none = {
+ ETYPE_DES_CBC_NONE,
+ "des-cbc-none",
+ 8,
+ 8,
+ 0,
+ &keytype_des,
+ &_krb5_checksum_none,
+ NULL,
+ F_PSEUDO|F_DISABLED|F_WEAK,
+ evp_des_encrypt_null_ivec,
+ 0,
+ NULL
+};
+
+struct encryption_type _krb5_enctype_des_cfb64_none = {
+ ETYPE_DES_CFB64_NONE,
+ "des-cfb64-none",
+ 1,
+ 1,
+ 0,
+ &keytype_des_old,
+ &_krb5_checksum_none,
+ NULL,
+ F_PSEUDO|F_DISABLED|F_WEAK,
+ DES_CFB64_encrypt_null_ivec,
+ 0,
+ NULL
+};
+
+struct encryption_type _krb5_enctype_des_pcbc_none = {
+ ETYPE_DES_PCBC_NONE,
+ "des-pcbc-none",
+ 8,
+ 8,
+ 0,
+ &keytype_des_old,
+ &_krb5_checksum_none,
+ NULL,
+ F_PSEUDO|F_DISABLED|F_WEAK,
+ DES_PCBC_encrypt_key_ivec,
+ 0,
+ NULL
+};
+#endif /* HEIM_WEAK_CRYPTO */
diff --git a/source4/heimdal/lib/krb5/crypto-des3.c b/source4/heimdal/lib/krb5/crypto-des3.c
new file mode 100644
index 0000000000..1ff692b520
--- /dev/null
+++ b/source4/heimdal/lib/krb5/crypto-des3.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 1997 - 2008 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"
+
+/*
+ *
+ */
+
+static void
+DES3_random_key(krb5_context context,
+ krb5_keyblock *key)
+{
+ DES_cblock *k = key->keyvalue.data;
+ do {
+ krb5_generate_random_block(k, 3 * sizeof(DES_cblock));
+ DES_set_odd_parity(&k[0]);
+ DES_set_odd_parity(&k[1]);
+ DES_set_odd_parity(&k[2]);
+ } while(DES_is_weak_key(&k[0]) ||
+ DES_is_weak_key(&k[1]) ||
+ DES_is_weak_key(&k[2]));
+}
+
+
+#ifdef DES3_OLD_ENCTYPE
+static struct key_type keytype_des3 = {
+ KEYTYPE_DES3,
+ "des3",
+ 168,
+ 24,
+ sizeof(struct evp_schedule),
+ DES3_random_key,
+ _krb5_evp_schedule,
+ _krb5_des3_salt,
+ _krb5_DES3_random_to_key,
+ _krb5_evp_cleanup,
+ EVP_des_ede3_cbc
+};
+#endif
+
+static struct key_type keytype_des3_derived = {
+ KEYTYPE_DES3,
+ "des3",
+ 168,
+ 24,
+ sizeof(struct evp_schedule),
+ DES3_random_key,
+ _krb5_evp_schedule,
+ _krb5_des3_salt_derived,
+ _krb5_DES3_random_to_key,
+ _krb5_evp_cleanup,
+ EVP_des_ede3_cbc
+};
+
+#ifdef DES3_OLD_ENCTYPE
+static krb5_error_code
+RSA_MD5_DES3_checksum(krb5_context context,
+ struct key_data *key,
+ const void *data,
+ size_t len,
+ unsigned usage,
+ Checksum *C)
+{
+ return _krb5_des_checksum(context, EVP_md5(), key, data, len, C);
+}
+
+static krb5_error_code
+RSA_MD5_DES3_verify(krb5_context context,
+ struct key_data *key,
+ const void *data,
+ size_t len,
+ unsigned usage,
+ Checksum *C)
+{
+ return _krb5_des_verify(context, EVP_md5(), key, data, len, C);
+}
+
+struct checksum_type _krb5_checksum_rsa_md5_des3 = {
+ CKSUMTYPE_RSA_MD5_DES3,
+ "rsa-md5-des3",
+ 64,
+ 24,
+ F_KEYED | F_CPROOF | F_VARIANT,
+ RSA_MD5_DES3_checksum,
+ RSA_MD5_DES3_verify
+};
+#endif
+
+struct checksum_type _krb5_checksum_hmac_sha1_des3 = {
+ CKSUMTYPE_HMAC_SHA1_DES3,
+ "hmac-sha1-des3",
+ 64,
+ 20,
+ F_KEYED | F_CPROOF | F_DERIVED,
+ _krb5_SP_HMAC_SHA1_checksum,
+ NULL
+};
+
+#ifdef DES3_OLD_ENCTYPE
+struct encryption_type _krb5_enctype_des3_cbc_md5 = {
+ ETYPE_DES3_CBC_MD5,
+ "des3-cbc-md5",
+ 8,
+ 8,
+ 8,
+ &keytype_des3,
+ &_krb5_checksum_rsa_md5,
+ &_krb5_checksum_rsa_md5_des3,
+ 0,
+ _krb5_evp_encrypt,
+ 0,
+ NULL
+};
+#endif
+
+struct encryption_type _krb5_enctype_des3_cbc_sha1 = {
+ ETYPE_DES3_CBC_SHA1,
+ "des3-cbc-sha1",
+ 8,
+ 8,
+ 8,
+ &keytype_des3_derived,
+ &_krb5_checksum_sha1,
+ &_krb5_checksum_hmac_sha1_des3,
+ F_DERIVED,
+ _krb5_evp_encrypt,
+ 0,
+ NULL
+};
+
+#ifdef DES3_OLD_ENCTYPE
+struct encryption_type _krb5_enctype_old_des3_cbc_sha1 = {
+ ETYPE_OLD_DES3_CBC_SHA1,
+ "old-des3-cbc-sha1",
+ 8,
+ 8,
+ 8,
+ &keytype_des3,
+ &_krb5_checksum_sha1,
+ &_krb5_checksum_hmac_sha1_des3,
+ 0,
+ _krb5_evp_encrypt,
+ 0,
+ NULL
+};
+#endif
+
+struct encryption_type _krb5_enctype_des3_cbc_none = {
+ ETYPE_DES3_CBC_NONE,
+ "des3-cbc-none",
+ 8,
+ 8,
+ 0,
+ &keytype_des3_derived,
+ &_krb5_checksum_none,
+ NULL,
+ F_PSEUDO,
+ _krb5_evp_encrypt,
+ 0,
+ NULL
+};
+
+void
+_krb5_DES3_random_to_key(krb5_context context,
+ krb5_keyblock *key,
+ const void *data,
+ size_t size)
+{
+ unsigned char *x = key->keyvalue.data;
+ const u_char *q = data;
+ DES_cblock *k;
+ int i, j;
+
+ memset(x, 0, sizeof(x));
+ for (i = 0; i < 3; ++i) {
+ unsigned char foo;
+ for (j = 0; j < 7; ++j) {
+ unsigned char b = q[7 * i + j];
+
+ x[8 * i + j] = b;
+ }
+ foo = 0;
+ for (j = 6; j >= 0; --j) {
+ foo |= q[7 * i + j] & 1;
+ foo <<= 1;
+ }
+ x[8 * i + 7] = foo;
+ }
+ k = key->keyvalue.data;
+ for (i = 0; i < 3; i++) {
+ DES_set_odd_parity(&k[i]);
+ if(DES_is_weak_key(&k[i]))
+ _krb5_xor(&k[i], (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
+ }
+}
diff --git a/source4/heimdal/lib/krb5/crypto-evp.c b/source4/heimdal/lib/krb5/crypto-evp.c
new file mode 100644
index 0000000000..69d1e2679d
--- /dev/null
+++ b/source4/heimdal/lib/krb5/crypto-evp.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 1997 - 2008 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"
+
+void
+_krb5_evp_schedule(krb5_context context,
+ struct key_type *kt,
+ struct key_data *kd)
+{
+ struct evp_schedule *key = kd->schedule->data;
+ const EVP_CIPHER *c = (*kt->evp)();
+
+ EVP_CIPHER_CTX_init(&key->ectx);
+ EVP_CIPHER_CTX_init(&key->dctx);
+
+ EVP_CipherInit_ex(&key->ectx, c, NULL, kd->key->keyvalue.data, NULL, 1);
+ EVP_CipherInit_ex(&key->dctx, c, NULL, kd->key->keyvalue.data, NULL, 0);
+}
+
+void
+_krb5_evp_cleanup(krb5_context context, struct key_data *kd)
+{
+ struct evp_schedule *key = kd->schedule->data;
+ EVP_CIPHER_CTX_cleanup(&key->ectx);
+ EVP_CIPHER_CTX_cleanup(&key->dctx);
+}
+
+krb5_error_code
+_krb5_evp_encrypt(krb5_context context,
+ struct key_data *key,
+ void *data,
+ size_t len,
+ krb5_boolean encryptp,
+ int usage,
+ void *ivec)
+{
+ struct evp_schedule *ctx = key->schedule->data;
+ EVP_CIPHER_CTX *c;
+ c = encryptp ? &ctx->ectx : &ctx->dctx;
+ if (ivec == NULL) {
+ /* alloca ? */
+ size_t len2 = EVP_CIPHER_CTX_iv_length(c);
+ void *loiv = malloc(len2);
+ if (loiv == NULL) {
+ krb5_clear_error_message(context);
+ return ENOMEM;
+ }
+ memset(loiv, 0, len2);
+ EVP_CipherInit_ex(c, NULL, NULL, NULL, loiv, -1);
+ free(loiv);
+ } else
+ EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1);
+ EVP_Cipher(c, data, data, len);
+ return 0;
+}
+
+static const unsigned char zero_ivec[EVP_MAX_BLOCK_LENGTH] = { 0 };
+
+krb5_error_code
+_krb5_evp_encrypt_cts(krb5_context context,
+ struct key_data *key,
+ void *data,
+ size_t len,
+ krb5_boolean encryptp,
+ int usage,
+ void *ivec)
+{
+ size_t i, blocksize;
+ struct evp_schedule *ctx = key->schedule->data;
+ char tmp[EVP_MAX_BLOCK_LENGTH], ivec2[EVP_MAX_BLOCK_LENGTH];
+ EVP_CIPHER_CTX *c;
+ unsigned char *p;
+
+ c = encryptp ? &ctx->ectx : &ctx->dctx;
+
+ blocksize = EVP_CIPHER_CTX_block_size(c);
+
+ if (len < blocksize) {
+ krb5_set_error_message(context, EINVAL,
+ "message block too short");
+ return EINVAL;
+ } else if (len == blocksize) {
+ EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
+ EVP_Cipher(c, data, data, len);
+ return 0;
+ }
+
+ if (ivec)
+ EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1);
+ else
+ EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
+
+ if (encryptp) {
+
+ p = data;
+ i = ((len - 1) / blocksize) * blocksize;
+ EVP_Cipher(c, p, p, i);
+ p += i - blocksize;
+ len -= i;
+ memcpy(ivec2, p, blocksize);
+
+ for (i = 0; i < len; i++)
+ tmp[i] = p[i + blocksize] ^ ivec2[i];
+ for (; i < blocksize; i++)
+ tmp[i] = 0 ^ ivec2[i];
+
+ EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
+ EVP_Cipher(c, p, tmp, blocksize);
+
+ memcpy(p + blocksize, ivec2, len);
+ if (ivec)
+ memcpy(ivec, p, blocksize);
+ } else {
+ char tmp2[EVP_MAX_BLOCK_LENGTH], tmp3[EVP_MAX_BLOCK_LENGTH];
+
+ p = data;
+ if (len > blocksize * 2) {
+ /* remove last two blocks and round up, decrypt this with cbc, then do cts dance */
+ i = ((((len - blocksize * 2) + blocksize - 1) / blocksize) * blocksize);
+ memcpy(ivec2, p + i - blocksize, blocksize);
+ EVP_Cipher(c, p, p, i);
+ p += i;
+ len -= i + blocksize;
+ } else {
+ if (ivec)
+ memcpy(ivec2, ivec, blocksize);
+ else
+ memcpy(ivec2, zero_ivec, blocksize);
+ len -= blocksize;
+ }
+
+ memcpy(tmp, p, blocksize);
+ EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
+ EVP_Cipher(c, tmp2, p, blocksize);
+
+ memcpy(tmp3, p + blocksize, len);
+ memcpy(tmp3 + len, tmp2 + len, blocksize - len); /* xor 0 */
+
+ for (i = 0; i < len; i++)
+ p[i + blocksize] = tmp2[i] ^ tmp3[i];
+
+ EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
+ EVP_Cipher(c, p, tmp3, blocksize);
+
+ for (i = 0; i < blocksize; i++)
+ p[i] ^= ivec2[i];
+ if (ivec)
+ memcpy(ivec, tmp, blocksize);
+ }
+ return 0;
+}
diff --git a/source4/heimdal/lib/krb5/crypto-null.c b/source4/heimdal/lib/krb5/crypto-null.c
new file mode 100644
index 0000000000..3a5c6b6cb3
--- /dev/null
+++ b/source4/heimdal/lib/krb5/crypto-null.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 1997 - 2008 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"
+
+#ifndef HEIMDAL_SMALLER
+#define DES3_OLD_ENCTYPE 1
+#endif
+
+static struct key_type keytype_null = {
+ KEYTYPE_NULL,
+ "null",
+ 0,
+ 0,
+ 0,
+ NULL,
+ NULL,
+ NULL
+};
+
+static krb5_error_code
+NONE_checksum(krb5_context context,
+ struct key_data *key,
+ const void *data,
+ size_t len,
+ unsigned usage,
+ Checksum *C)
+{
+ return 0;
+}
+
+struct checksum_type _krb5_checksum_none = {
+ CKSUMTYPE_NONE,
+ "none",
+ 1,
+ 0,
+ 0,
+ NONE_checksum,
+ NULL
+};
+
+static krb5_error_code
+NULL_encrypt(krb5_context context,
+ struct key_data *key,
+ void *data,
+ size_t len,
+ krb5_boolean encryptp,
+ int usage,
+ void *ivec)
+{
+ return 0;
+}
+
+struct encryption_type _krb5_enctype_null = {
+ ETYPE_NULL,
+ "null",
+ 1,
+ 1,
+ 0,
+ &keytype_null,
+ &_krb5_checksum_none,
+ NULL,
+ F_DISABLED,
+ NULL_encrypt,
+ 0,
+ NULL
+};
diff --git a/source4/heimdal/lib/krb5/crypto-pk.c b/source4/heimdal/lib/krb5/crypto-pk.c
new file mode 100644
index 0000000000..21e729c9e1
--- /dev/null
+++ b/source4/heimdal/lib/krb5/crypto-pk.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 1997 - 2008 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"
+
+#include <pkinit_asn1.h>
+
+krb5_error_code
+_krb5_pk_octetstring2key(krb5_context context,
+ krb5_enctype type,
+ const void *dhdata,
+ size_t dhsize,
+ const heim_octet_string *c_n,
+ const heim_octet_string *k_n,
+ krb5_keyblock *key)
+{
+ struct encryption_type *et = _krb5_find_enctype(type);
+ krb5_error_code ret;
+ size_t keylen, offset;
+ void *keydata;
+ unsigned char counter;
+ unsigned char shaoutput[SHA_DIGEST_LENGTH];
+ EVP_MD_CTX *m;
+
+ if(et == NULL) {
+ krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
+ N_("encryption type %d not supported", ""),
+ type);
+ return KRB5_PROG_ETYPE_NOSUPP;
+ }
+ keylen = (et->keytype->bits + 7) / 8;
+
+ keydata = malloc(keylen);
+ if (keydata == NULL) {
+ krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
+ return ENOMEM;
+ }
+
+ m = EVP_MD_CTX_create();
+ if (m == NULL) {
+ free(keydata);
+ krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
+ return ENOMEM;
+ }
+
+ counter = 0;
+ offset = 0;
+ do {
+
+ EVP_DigestInit_ex(m, EVP_sha1(), NULL);
+ EVP_DigestUpdate(m, &counter, 1);
+ EVP_DigestUpdate(m, dhdata, dhsize);
+
+ if (c_n)
+ EVP_DigestUpdate(m, c_n->data, c_n->length);
+ if (k_n)
+ EVP_DigestUpdate(m, k_n->data, k_n->length);
+
+ EVP_DigestFinal_ex(m, shaoutput, NULL);
+
+ memcpy((unsigned char *)keydata + offset,
+ shaoutput,
+ min(keylen - offset, sizeof(shaoutput)));
+
+ offset += sizeof(shaoutput);
+ counter++;
+ } while(offset < keylen);
+ memset(shaoutput, 0, sizeof(shaoutput));
+
+ EVP_MD_CTX_destroy(m);
+
+ ret = krb5_random_to_key(context, type, keydata, keylen, key);
+ memset(keydata, 0, sizeof(keylen));
+ free(keydata);
+ return ret;
+}
+
+static krb5_error_code
+encode_uvinfo(krb5_context context, krb5_const_principal p, krb5_data *data)
+{
+ KRB5PrincipalName pn;
+ krb5_error_code ret;
+ size_t size;
+
+ pn.principalName = p->name;
+ pn.realm = p->realm;
+
+ ASN1_MALLOC_ENCODE(KRB5PrincipalName, data->data, data->length,
+ &pn, &size, ret);
+ if (ret) {
+ krb5_data_zero(data);
+ krb5_set_error_message(context, ret,
+ N_("Failed to encode KRB5PrincipalName", ""));
+ return ret;
+ }
+ if (data->length != size)
+ krb5_abortx(context, "asn1 compiler internal error");
+ return 0;
+}
+
+static krb5_error_code
+encode_otherinfo(krb5_context context,
+ const AlgorithmIdentifier *ai,
+ krb5_const_principal client,
+ krb5_const_principal server,
+ krb5_enctype enctype,
+ const krb5_data *as_req,
+ const krb5_data *pk_as_rep,
+ const Ticket *ticket,
+ krb5_data *other)
+{
+ PkinitSP80056AOtherInfo otherinfo;
+ PkinitSuppPubInfo pubinfo;
+ krb5_error_code ret;
+ krb5_data pub;
+ size_t size;
+
+ krb5_data_zero(other);
+ memset(&otherinfo, 0, sizeof(otherinfo));
+ memset(&pubinfo, 0, sizeof(pubinfo));
+
+ pubinfo.enctype = enctype;
+ pubinfo.as_REQ = *as_req;
+ pubinfo.pk_as_rep = *pk_as_rep;
+ pubinfo.ticket = *ticket;
+ ASN1_MALLOC_ENCODE(PkinitSuppPubInfo, pub.data, pub.length,
+ &pubinfo, &size, ret);
+ if (ret) {
+ krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
+ return ret;
+ }
+ if (pub.length != size)
+ krb5_abortx(context, "asn1 compiler internal error");
+
+ ret = encode_uvinfo(context, client, &otherinfo.partyUInfo);
+ if (ret) {
+ free(pub.data);
+ return ret;
+ }
+ ret = encode_uvinfo(context, server, &otherinfo.partyVInfo);
+ if (ret) {
+ free(otherinfo.partyUInfo.data);
+ free(pub.data);
+ return ret;
+ }
+
+ otherinfo.algorithmID = *ai;
+ otherinfo.suppPubInfo = &pub;
+
+ ASN1_MALLOC_ENCODE(PkinitSP80056AOtherInfo, other->data, other->length,
+ &otherinfo, &size, ret);
+ free(otherinfo.partyUInfo.data);
+ free(otherinfo.partyVInfo.data);
+ free(pub.data);
+ if (ret) {
+ krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
+ return ret;
+ }
+ if (other->length != size)
+ krb5_abortx(context, "asn1 compiler internal error");
+
+ return 0;
+}
+
+krb5_error_code
+_krb5_pk_kdf(krb5_context context,
+ const struct AlgorithmIdentifier *ai,
+ const void *dhdata,
+ size_t dhsize,
+ krb5_const_principal client,
+ krb5_const_principal server,
+ krb5_enctype enctype,
+ const krb5_data *as_req,
+ const krb5_data *pk_as_rep,
+ const Ticket *ticket,
+ krb5_keyblock *key)
+{
+ struct encryption_type *et;
+ krb5_error_code ret;
+ krb5_data other;
+ size_t keylen, offset;
+ uint32_t counter;
+ unsigned char *keydata;
+ unsigned char shaoutput[SHA_DIGEST_LENGTH];
+ EVP_MD_CTX *m;
+
+ 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;
+ }
+ if (ai->parameters != NULL &&
+ (ai->parameters->length != 2 ||
+ memcmp(ai->parameters->data, "\x05\x00", 2) != 0))
+ {
+ krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
+ N_("kdf params not NULL or the NULL-type",
+ ""));
+ return KRB5_PROG_ETYPE_NOSUPP;
+ }
+
+ et = _krb5_find_enctype(enctype);
+ if(et == NULL) {
+ krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
+ N_("encryption type %d not supported", ""),
+ enctype);
+ return KRB5_PROG_ETYPE_NOSUPP;
+ }
+ keylen = (et->keytype->bits + 7) / 8;
+
+ keydata = malloc(keylen);
+ if (keydata == NULL) {
+ krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
+ return ENOMEM;
+ }
+
+ ret = encode_otherinfo(context, ai, client, server,
+ enctype, as_req, pk_as_rep, ticket, &other);
+ if (ret) {
+ free(keydata);
+ return ret;
+ }
+
+ m = EVP_MD_CTX_create();
+ if (m == NULL) {
+ free(keydata);
+ free(other.data);
+ krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
+ return ENOMEM;
+ }
+
+ offset = 0;
+ counter = 1;
+ do {
+ unsigned char cdata[4];
+
+ EVP_DigestInit_ex(m, EVP_sha1(), NULL);
+ _krb5_put_int(cdata, counter, 4);
+ EVP_DigestUpdate(m, cdata, 4);
+ EVP_DigestUpdate(m, dhdata, dhsize);
+ EVP_DigestUpdate(m, other.data, other.length);
+
+ EVP_DigestFinal_ex(m, shaoutput, NULL);
+
+ memcpy((unsigned char *)keydata + offset,
+ shaoutput,
+ min(keylen - offset, sizeof(shaoutput)));
+
+ offset += sizeof(shaoutput);
+ counter++;
+ } while(offset < keylen);
+ memset(shaoutput, 0, sizeof(shaoutput));
+
+ EVP_MD_CTX_destroy(m);
+ free(other.data);
+
+ ret = krb5_random_to_key(context, enctype, keydata, keylen, key);
+ memset(keydata, 0, sizeof(keylen));
+ free(keydata);
+
+ return ret;
+}
diff --git a/source4/heimdal/lib/krb5/crypto-rand.c b/source4/heimdal/lib/krb5/crypto-rand.c
new file mode 100644
index 0000000000..49bd679362
--- /dev/null
+++ b/source4/heimdal/lib/krb5/crypto-rand.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 1997 - 2008 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"
+
+#define ENTROPY_NEEDED 128
+
+static HEIMDAL_MUTEX crypto_mutex = HEIMDAL_MUTEX_INITIALIZER;
+
+static int
+seed_something(void)
+{
+ char buf[1024], seedfile[256];
+
+ /* If there is a seed file, load it. But such a file cannot be trusted,
+ so use 0 for the entropy estimate */
+ if (RAND_file_name(seedfile, sizeof(seedfile))) {
+ int fd;
+ fd = open(seedfile, O_RDONLY | O_BINARY | O_CLOEXEC);
+ if (fd >= 0) {
+ ssize_t ret;
+ rk_cloexec(fd);
+ ret = read(fd, buf, sizeof(buf));
+ if (ret > 0)
+ RAND_add(buf, ret, 0.0);
+ close(fd);
+ } else
+ seedfile[0] = '\0';
+ } else
+ seedfile[0] = '\0';
+
+ /* Calling RAND_status() will try to use /dev/urandom if it exists so
+ we do not have to deal with it. */
+ if (RAND_status() != 1) {
+#ifndef _WIN32
+ krb5_context context;
+ const char *p;
+
+ /* Try using egd */
+ if (!krb5_init_context(&context)) {
+ p = krb5_config_get_string(context, NULL, "libdefaults",
+ "egd_socket", NULL);
+ if (p != NULL)
+ RAND_egd_bytes(p, ENTROPY_NEEDED);
+ krb5_free_context(context);
+ }
+#else
+ /* TODO: Once a Windows CryptoAPI RAND method is defined, we
+ can use that and failover to another method. */
+#endif
+ }
+
+ if (RAND_status() == 1) {
+ /* Update the seed file */
+ if (seedfile[0])
+ RAND_write_file(seedfile);
+
+ return 0;
+ } else
+ return -1;
+}
+
+KRB5_LIB_FUNCTION void KRB5_LIB_CALL
+krb5_generate_random_block(void *buf, size_t len)
+{
+ static int rng_initialized = 0;
+
+ HEIMDAL_MUTEX_lock(&crypto_mutex);
+ if (!rng_initialized) {
+ if (seed_something())
+ krb5_abortx(NULL, "Fatal: could not seed the "
+ "random number generator");
+
+ rng_initialized = 1;
+ }
+ HEIMDAL_MUTEX_unlock(&crypto_mutex);
+ if (RAND_bytes(buf, len) <= 0)
+ krb5_abortx(NULL, "Failed to generate random block");
+}
diff --git a/source4/heimdal/lib/krb5/crypto-stubs.c b/source4/heimdal/lib/krb5/crypto-stubs.c
new file mode 100644
index 0000000000..b462680643
--- /dev/null
+++ b/source4/heimdal/lib/krb5/crypto-stubs.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 1997 - 2008 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>
+
+/* These are stub functions for the standalone RFC3961 crypto library */
+
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+krb5_init_context(krb5_context *context)
+{
+ krb5_context p;
+
+ *context = NULL;
+
+ /* should have a run_once */
+ bindtextdomain(HEIMDAL_TEXTDOMAIN, HEIMDAL_LOCALEDIR);
+
+ p = calloc(1, sizeof(*p));
+ if(!p)
+ return ENOMEM;
+
+ p->mutex = malloc(sizeof(HEIMDAL_MUTEX));
+ if (p->mutex == NULL) {
+ free(p);
+ return ENOMEM;
+ }
+ HEIMDAL_MUTEX_init(p->mutex);
+
+ *context = p;
+ return 0;
+}
+
+KRB5_LIB_FUNCTION void KRB5_LIB_CALL
+krb5_free_context(krb5_context context)
+{
+ krb5_clear_error_message(context);
+
+ HEIMDAL_MUTEX_destroy(context->mutex);
+ free(context->mutex);
+ if (context->flags & KRB5_CTX_F_SOCKETS_INITIALIZED) {
+ rk_SOCK_EXIT();
+ }
+
+ memset(context, 0, sizeof(*context));
+ free(context);
+}
+
+krb5_boolean
+_krb5_homedir_access(krb5_context context) {
+ return 0;
+}
+
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+krb5_log(krb5_context context,
+ krb5_log_facility *fac,
+ int level,
+ const char *fmt,
+ ...)
+{
+ return 0;
+}
+
+/* This function is currently just used to get the location of the EGD
+ * socket. If we're not using an EGD, then we can just return NULL */
+
+KRB5_LIB_FUNCTION const char* KRB5_LIB_CALL
+krb5_config_get_string (krb5_context context,
+ const krb5_config_section *c,
+ ...)
+{
+ return NULL;
+}
diff --git a/source4/heimdal/lib/krb5/crypto.h b/source4/heimdal/lib/krb5/crypto.h
new file mode 100644
index 0000000000..c57221b1e6
--- /dev/null
+++ b/source4/heimdal/lib/krb5/crypto.h
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 1997 - 2008 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.
+ */
+
+#ifndef HEIMDAL_SMALLER
+#define DES3_OLD_ENCTYPE 1
+#endif
+
+struct key_data {
+ krb5_keyblock *key;
+ krb5_data *schedule;
+};
+
+struct key_usage {
+ unsigned usage;
+ struct key_data key;
+};
+
+struct krb5_crypto_data {
+ struct encryption_type *et;
+ struct key_data key;
+ int num_key_usage;
+ struct key_usage *key_usage;
+};
+
+#define CRYPTO_ETYPE(C) ((C)->et->type)
+
+/* bits for `flags' below */
+#define F_KEYED 1 /* checksum is keyed */
+#define F_CPROOF 2 /* checksum is collision proof */
+#define F_DERIVED 4 /* uses derived keys */
+#define F_VARIANT 8 /* uses `variant' keys (6.4.3) */
+#define F_PSEUDO 16 /* not a real protocol type */
+#define F_SPECIAL 32 /* backwards */
+#define F_DISABLED 64 /* enctype/checksum disabled */
+#define F_WEAK 128 /* enctype is considered weak */
+
+struct salt_type {
+ krb5_salttype type;
+ const char *name;
+ krb5_error_code (*string_to_key)(krb5_context, krb5_enctype, krb5_data,
+ krb5_salt, krb5_data, krb5_keyblock*);
+};
+
+struct key_type {
+ krb5_keytype type; /* XXX */
+ const char *name;
+ size_t bits;
+ size_t size;
+ size_t schedule_size;
+ void (*random_key)(krb5_context, krb5_keyblock*);
+ void (*schedule)(krb5_context, struct key_type *, struct key_data *);
+ struct salt_type *string_to_key;
+ void (*random_to_key)(krb5_context, krb5_keyblock*, const void*, size_t);
+ void (*cleanup)(krb5_context, struct key_data *);
+ const EVP_CIPHER *(*evp)(void);
+};
+
+struct checksum_type {
+ krb5_cksumtype type;
+ const char *name;
+ size_t blocksize;
+ size_t checksumsize;
+ unsigned flags;
+ krb5_error_code (*checksum)(krb5_context context,
+ struct key_data *key,
+ const void *buf, size_t len,
+ unsigned usage,
+ Checksum *csum);
+ krb5_error_code (*verify)(krb5_context context,
+ struct key_data *key,
+ const void *buf, size_t len,
+ unsigned usage,
+ Checksum *csum);
+};
+
+struct encryption_type {
+ krb5_enctype type;
+ const char *name;
+ size_t blocksize;
+ size_t padsize;
+ size_t confoundersize;
+ struct key_type *keytype;
+ struct checksum_type *checksum;
+ struct checksum_type *keyed_checksum;
+ unsigned flags;
+ krb5_error_code (*encrypt)(krb5_context context,
+ struct key_data *key,
+ void *data, size_t len,
+ krb5_boolean encryptp,
+ int usage,
+ void *ivec);
+ size_t prf_length;
+ krb5_error_code (*prf)(krb5_context,
+ krb5_crypto, const krb5_data *, krb5_data *);
+};
+
+#define ENCRYPTION_USAGE(U) (((U) << 8) | 0xAA)
+#define INTEGRITY_USAGE(U) (((U) << 8) | 0x55)
+#define CHECKSUM_USAGE(U) (((U) << 8) | 0x99)
+
+/* Checksums */
+
+extern struct checksum_type _krb5_checksum_none;
+extern struct checksum_type _krb5_checksum_crc32;
+extern struct checksum_type _krb5_checksum_rsa_md4;
+extern struct checksum_type _krb5_checksum_rsa_md4_des;
+extern struct checksum_type _krb5_checksum_rsa_md5_des;
+extern struct checksum_type _krb5_checksum_rsa_md5_des3;
+extern struct checksum_type _krb5_checksum_rsa_md5;
+extern struct checksum_type _krb5_checksum_hmac_sha1_des3;
+extern struct checksum_type _krb5_checksum_hmac_sha1_aes128;
+extern struct checksum_type _krb5_checksum_hmac_sha1_aes256;
+extern struct checksum_type _krb5_checksum_hmac_md5;
+extern struct checksum_type _krb5_checksum_sha1;
+
+extern struct checksum_type *_krb5_checksum_types[];
+extern int _krb5_num_checksums;
+
+/* Salts */
+
+extern struct salt_type _krb5_AES_salt[];
+extern struct salt_type _krb5_arcfour_salt[];
+extern struct salt_type _krb5_des_salt[];
+extern struct salt_type _krb5_des3_salt[];
+extern struct salt_type _krb5_des3_salt_derived[];
+
+/* Encryption types */
+
+extern struct encryption_type _krb5_enctype_aes256_cts_hmac_sha1;
+extern struct encryption_type _krb5_enctype_aes128_cts_hmac_sha1;
+extern struct encryption_type _krb5_enctype_des3_cbc_sha1;
+extern struct encryption_type _krb5_enctype_des3_cbc_md5;
+extern struct encryption_type _krb5_enctype_des3_cbc_none;
+extern struct encryption_type _krb5_enctype_arcfour_hmac_md5;
+extern struct encryption_type _krb5_enctype_des_cbc_md5;
+extern struct encryption_type _krb5_enctype_old_des3_cbc_sha1;
+extern struct encryption_type _krb5_enctype_des_cbc_crc;
+extern struct encryption_type _krb5_enctype_des_cbc_md4;
+extern struct encryption_type _krb5_enctype_des_cbc_md5;
+extern struct encryption_type _krb5_enctype_des_cbc_none;
+extern struct encryption_type _krb5_enctype_des_cfb64_none;
+extern struct encryption_type _krb5_enctype_des_pcbc_none;
+extern struct encryption_type _krb5_enctype_null;
+
+extern struct encryption_type *_krb5_etypes[];
+extern int _krb5_num_etypes;
+
+/* Interface to the EVP crypto layer provided by hcrypto */
+struct evp_schedule {
+ EVP_CIPHER_CTX ectx;
+ EVP_CIPHER_CTX dctx;
+};
diff --git a/source4/heimdal/lib/krb5/salt-aes.c b/source4/heimdal/lib/krb5/salt-aes.c
new file mode 100644
index 0000000000..1c40b54f6b
--- /dev/null
+++ b/source4/heimdal/lib/krb5/salt-aes.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 1997 - 2008 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"
+
+int _krb5_AES_string_to_default_iterator = 4096;
+
+static krb5_error_code
+AES_string_to_key(krb5_context context,
+ krb5_enctype enctype,
+ krb5_data password,
+ krb5_salt salt,
+ krb5_data opaque,
+ krb5_keyblock *key)
+{
+ krb5_error_code ret;
+ uint32_t iter;
+ struct encryption_type *et;
+ struct key_data kd;
+
+ if (opaque.length == 0)
+ iter = _krb5_AES_string_to_default_iterator;
+ else if (opaque.length == 4) {
+ unsigned long v;
+ _krb5_get_int(opaque.data, &v, 4);
+ iter = ((uint32_t)v);
+ } else
+ return KRB5_PROG_KEYTYPE_NOSUPP; /* XXX */
+
+ et = _krb5_find_enctype(enctype);
+ if (et == NULL)
+ return KRB5_PROG_KEYTYPE_NOSUPP;
+
+ kd.schedule = NULL;
+ ALLOC(kd.key, 1);
+ if(kd.key == NULL) {
+ krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
+ return ENOMEM;
+ }
+ kd.key->keytype = enctype;
+ ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
+ if (ret) {
+ krb5_set_error_message (context, ret, N_("malloc: out of memory", ""));
+ return ret;
+ }
+
+ ret = PKCS5_PBKDF2_HMAC_SHA1(password.data, password.length,
+ salt.saltvalue.data, salt.saltvalue.length,
+ iter,
+ et->keytype->size, kd.key->keyvalue.data);
+ if (ret != 1) {
+ _krb5_free_key_data(context, &kd, et);
+ krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
+ "Error calculating s2k");
+ return KRB5_PROG_KEYTYPE_NOSUPP;
+ }
+
+ ret = _krb5_derive_key(context, et, &kd, "kerberos", strlen("kerberos"));
+ if (ret == 0)
+ ret = krb5_copy_keyblock_contents(context, kd.key, key);
+ _krb5_free_key_data(context, &kd, et);
+
+ return ret;
+}
+
+struct salt_type _krb5_AES_salt[] = {
+ {
+ KRB5_PW_SALT,
+ "pw-salt",
+ AES_string_to_key
+ },
+ { 0 }
+};
diff --git a/source4/heimdal/lib/krb5/salt-arcfour.c b/source4/heimdal/lib/krb5/salt-arcfour.c
new file mode 100644
index 0000000000..b222b47e16
--- /dev/null
+++ b/source4/heimdal/lib/krb5/salt-arcfour.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 1997 - 2008 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"
+
+static krb5_error_code
+ARCFOUR_string_to_key(krb5_context context,
+ krb5_enctype enctype,
+ krb5_data password,
+ krb5_salt salt,
+ krb5_data opaque,
+ krb5_keyblock *key)
+{
+ krb5_error_code ret;
+ uint16_t *s = NULL;
+ size_t len, i;
+ EVP_MD_CTX *m;
+
+ m = EVP_MD_CTX_create();
+ if (m == NULL) {
+ ret = ENOMEM;
+ krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
+ goto out;
+ }
+
+ EVP_DigestInit_ex(m, EVP_md4(), NULL);
+
+ ret = wind_utf8ucs2_length(password.data, &len);
+ if (ret) {
+ krb5_set_error_message (context, ret,
+ N_("Password not an UCS2 string", ""));
+ goto out;
+ }
+
+ s = malloc (len * sizeof(s[0]));
+ if (len != 0 && s == NULL) {
+ krb5_set_error_message (context, ENOMEM,
+ N_("malloc: out of memory", ""));
+ ret = ENOMEM;
+ goto out;
+ }
+
+ ret = wind_utf8ucs2(password.data, s, &len);
+ if (ret) {
+ krb5_set_error_message (context, ret,
+ N_("Password not an UCS2 string", ""));
+ goto out;
+ }
+
+ /* LE encoding */
+ for (i = 0; i < len; i++) {
+ unsigned char p;
+ p = (s[i] & 0xff);
+ EVP_DigestUpdate (m, &p, 1);
+ p = (s[i] >> 8) & 0xff;
+ EVP_DigestUpdate (m, &p, 1);
+ }
+
+ key->keytype = enctype;
+ ret = krb5_data_alloc (&key->keyvalue, 16);
+ if (ret) {
+ krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
+ goto out;
+ }
+ EVP_DigestFinal_ex (m, key->keyvalue.data, NULL);
+
+ out:
+ EVP_MD_CTX_destroy(m);
+ if (s)
+ memset (s, 0, len);
+ free (s);
+ return ret;
+}
+
+struct salt_type _krb5_arcfour_salt[] = {
+ {
+ KRB5_PW_SALT,
+ "pw-salt",
+ ARCFOUR_string_to_key
+ },
+ { 0 }
+};
diff --git a/source4/heimdal/lib/krb5/salt-des.c b/source4/heimdal/lib/krb5/salt-des.c
new file mode 100644
index 0000000000..6939b6b50b
--- /dev/null
+++ b/source4/heimdal/lib/krb5/salt-des.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 1997 - 2008 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"
+
+#ifdef HEIM_WEAK_CRYPTO
+
+#ifdef ENABLE_AFS_STRING_TO_KEY
+
+/* This defines the Andrew string_to_key function. It accepts a password
+ * string as input and converts it via a one-way encryption algorithm to a DES
+ * encryption key. It is compatible with the original Andrew authentication
+ * service password database.
+ */
+
+/*
+ * Short passwords, i.e 8 characters or less.
+ */
+static void
+krb5_DES_AFS3_CMU_string_to_key (krb5_data pw,
+ krb5_data cell,
+ DES_cblock *key)
+{
+ char password[8+1]; /* crypt is limited to 8 chars anyway */
+ int i;
+
+ for(i = 0; i < 8; i++) {
+ char c = ((i < pw.length) ? ((char*)pw.data)[i] : 0) ^
+ ((i < cell.length) ?
+ tolower(((unsigned char*)cell.data)[i]) : 0);
+ password[i] = c ? c : 'X';
+ }
+ password[8] = '\0';
+
+ memcpy(key, crypt(password, "p1") + 2, sizeof(DES_cblock));
+
+ /* parity is inserted into the LSB so left shift each byte up one
+ bit. This allows ascii characters with a zero MSB to retain as
+ much significance as possible. */
+ for (i = 0; i < sizeof(DES_cblock); i++)
+ ((unsigned char*)key)[i] <<= 1;
+ DES_set_odd_parity (key);
+}
+
+/*
+ * Long passwords, i.e 9 characters or more.
+ */
+static void
+krb5_DES_AFS3_Transarc_string_to_key (krb5_data pw,
+ krb5_data cell,
+ DES_cblock *key)
+{
+ DES_key_schedule schedule;
+ DES_cblock temp_key;
+ DES_cblock ivec;
+ char password[512];
+ size_t passlen;
+
+ memcpy(password, pw.data, min(pw.length, sizeof(password)));
+ if(pw.length < sizeof(password)) {
+ int len = min(cell.length, sizeof(password) - pw.length);
+ int i;
+
+ memcpy(password + pw.length, cell.data, len);
+ for (i = pw.length; i < pw.length + len; ++i)
+ password[i] = tolower((unsigned char)password[i]);
+ }
+ passlen = min(sizeof(password), pw.length + cell.length);
+ memcpy(&ivec, "kerberos", 8);
+ memcpy(&temp_key, "kerberos", 8);
+ DES_set_odd_parity (&temp_key);
+ DES_set_key_unchecked (&temp_key, &schedule);
+ DES_cbc_cksum ((void*)password, &ivec, passlen, &schedule, &ivec);
+
+ memcpy(&temp_key, &ivec, 8);
+ DES_set_odd_parity (&temp_key);
+ DES_set_key_unchecked (&temp_key, &schedule);
+ DES_cbc_cksum ((void*)password, key, passlen, &schedule, &ivec);
+ memset(&schedule, 0, sizeof(schedule));
+ memset(&temp_key, 0, sizeof(temp_key));
+ memset(&ivec, 0, sizeof(ivec));
+ memset(password, 0, sizeof(password));
+
+ DES_set_odd_parity (key);
+}
+
+static krb5_error_code
+DES_AFS3_string_to_key(krb5_context context,
+ krb5_enctype enctype,
+ krb5_data password,
+ krb5_salt salt,
+ krb5_data opaque,
+ krb5_keyblock *key)
+{
+ DES_cblock tmp;
+ if(password.length > 8)
+ krb5_DES_AFS3_Transarc_string_to_key(password, salt.saltvalue, &tmp);
+ else
+ krb5_DES_AFS3_CMU_string_to_key(password, salt.saltvalue, &tmp);
+ key->keytype = enctype;
+ krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
+ memset(&key, 0, sizeof(key));
+ return 0;
+}
+#endif /* ENABLE_AFS_STRING_TO_KEY */
+
+static void
+DES_string_to_key_int(unsigned char *data, size_t length, DES_cblock *key)
+{
+ DES_key_schedule schedule;
+ int i;
+ int reverse = 0;
+ unsigned char *p;
+
+ unsigned char swap[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
+ 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf };
+ memset(key, 0, 8);
+
+ p = (unsigned char*)key;
+ for (i = 0; i < length; i++) {
+ unsigned char tmp = data[i];
+ if (!reverse)
+ *p++ ^= (tmp << 1);
+ else
+ *--p ^= (swap[tmp & 0xf] << 4) | swap[(tmp & 0xf0) >> 4];
+ if((i % 8) == 7)
+ reverse = !reverse;
+ }
+ DES_set_odd_parity(key);
+ if(DES_is_weak_key(key))
+ (*key)[7] ^= 0xF0;
+ DES_set_key_unchecked(key, &schedule);
+ DES_cbc_cksum((void*)data, key, length, &schedule, key);
+ memset(&schedule, 0, sizeof(schedule));
+ DES_set_odd_parity(key);
+ if(DES_is_weak_key(key))
+ (*key)[7] ^= 0xF0;
+}
+
+static krb5_error_code
+krb5_DES_string_to_key(krb5_context context,
+ krb5_enctype enctype,
+ krb5_data password,
+ krb5_salt salt,
+ krb5_data opaque,
+ krb5_keyblock *key)
+{
+ unsigned char *s;
+ size_t len;
+ DES_cblock tmp;
+
+#ifdef ENABLE_AFS_STRING_TO_KEY
+ if (opaque.length == 1) {
+ unsigned long v;
+ _krb5_get_int(opaque.data, &v, 1);
+ if (v == 1)
+ return DES_AFS3_string_to_key(context, enctype, password,
+ salt, opaque, key);
+ }
+#endif
+
+ len = password.length + salt.saltvalue.length;
+ s = malloc(len);
+ if(len > 0 && s == NULL) {
+ krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
+ return ENOMEM;
+ }
+ memcpy(s, password.data, password.length);
+ memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
+ DES_string_to_key_int(s, len, &tmp);
+ key->keytype = enctype;
+ krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
+ memset(&tmp, 0, sizeof(tmp));
+ memset(s, 0, len);
+ free(s);
+ return 0;
+}
+
+struct salt_type _krb5_des_salt[] = {
+ {
+ KRB5_PW_SALT,
+ "pw-salt",
+ krb5_DES_string_to_key
+ },
+#ifdef ENABLE_AFS_STRING_TO_KEY
+ {
+ KRB5_AFS3_SALT,
+ "afs3-salt",
+ DES_AFS3_string_to_key
+ },
+#endif
+ { 0 }
+};
+#endif
diff --git a/source4/heimdal/lib/krb5/salt-des3.c b/source4/heimdal/lib/krb5/salt-des3.c
new file mode 100644
index 0000000000..79140a274f
--- /dev/null
+++ b/source4/heimdal/lib/krb5/salt-des3.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 1997 - 2008 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"
+
+#ifdef DES3_OLD_ENCTYPE
+static krb5_error_code
+DES3_string_to_key(krb5_context context,
+ krb5_enctype enctype,
+ krb5_data password,
+ krb5_salt salt,
+ krb5_data opaque,
+ krb5_keyblock *key)
+{
+ char *str;
+ size_t len;
+ unsigned char tmp[24];
+ DES_cblock keys[3];
+ krb5_error_code ret;
+
+ len = password.length + salt.saltvalue.length;
+ str = malloc(len);
+ if(len != 0 && str == NULL) {
+ krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
+ return ENOMEM;
+ }
+ memcpy(str, password.data, password.length);
+ memcpy(str + password.length, salt.saltvalue.data, salt.saltvalue.length);
+ {
+ DES_cblock ivec;
+ DES_key_schedule s[3];
+ int i;
+
+ ret = _krb5_n_fold(str, len, tmp, 24);
+ if (ret) {
+ memset(str, 0, len);
+ free(str);
+ krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
+ return ret;
+ }
+
+ for(i = 0; i < 3; i++){
+ memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
+ DES_set_odd_parity(keys + i);
+ if(DES_is_weak_key(keys + i))
+ _krb5_xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
+ DES_set_key_unchecked(keys + i, &s[i]);
+ }
+ memset(&ivec, 0, sizeof(ivec));
+ DES_ede3_cbc_encrypt(tmp,
+ tmp, sizeof(tmp),
+ &s[0], &s[1], &s[2], &ivec, DES_ENCRYPT);
+ memset(s, 0, sizeof(s));
+ memset(&ivec, 0, sizeof(ivec));
+ for(i = 0; i < 3; i++){
+ memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
+ DES_set_odd_parity(keys + i);
+ if(DES_is_weak_key(keys + i))
+ _krb5_xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
+ }
+ memset(tmp, 0, sizeof(tmp));
+ }
+ key->keytype = enctype;
+ krb5_data_copy(&key->keyvalue, keys, sizeof(keys));
+ memset(keys, 0, sizeof(keys));
+ memset(str, 0, len);
+ free(str);
+ return 0;
+}
+#endif
+
+static krb5_error_code
+DES3_string_to_key_derived(krb5_context context,
+ krb5_enctype enctype,
+ krb5_data password,
+ krb5_salt salt,
+ krb5_data opaque,
+ krb5_keyblock *key)
+{
+ krb5_error_code ret;
+ size_t len = password.length + salt.saltvalue.length;
+ char *s;
+
+ s = malloc(len);
+ if(len != 0 && s == NULL) {
+ krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
+ return ENOMEM;
+ }
+ memcpy(s, password.data, password.length);
+ memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
+ ret = krb5_string_to_key_derived(context,
+ s,
+ len,
+ enctype,
+ key);
+ memset(s, 0, len);
+ free(s);
+ return ret;
+}
+
+
+#ifdef DES3_OLD_ENCTYPE
+struct salt_type _krb5_des3_salt[] = {
+ {
+ KRB5_PW_SALT,
+ "pw-salt",
+ DES3_string_to_key
+ },
+ { 0 }
+};
+#endif
+
+struct salt_type _krb5_des3_salt_derived[] = {
+ {
+ KRB5_PW_SALT,
+ "pw-salt",
+ DES3_string_to_key_derived
+ },
+ { 0 }
+};
diff --git a/source4/heimdal/lib/krb5/store-int.c b/source4/heimdal/lib/krb5/store-int.c
new file mode 100644
index 0000000000..0a18d0dddf
--- /dev/null
+++ b/source4/heimdal/lib/krb5/store-int.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1997-2008 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"
+
+KRB5_LIB_FUNCTION krb5_ssize_t KRB5_LIB_CALL
+_krb5_put_int(void *buffer, unsigned long value, size_t size)
+{
+ unsigned char *p = buffer;
+ int i;
+ for (i = size - 1; i >= 0; i--) {
+ p[i] = value & 0xff;
+ value >>= 8;
+ }
+ return size;
+}
+
+KRB5_LIB_FUNCTION krb5_ssize_t KRB5_LIB_CALL
+_krb5_get_int(void *buffer, unsigned long *value, size_t size)
+{
+ unsigned char *p = buffer;
+ unsigned long v = 0;
+ int i;
+ for (i = 0; i < size; i++)
+ v = (v << 8) + p[i];
+ *value = v;
+ return size;
+}
diff --git a/source4/heimdal/lib/ntlm/ntlm_err.et b/source4/heimdal/lib/ntlm/ntlm_err.et
new file mode 100644
index 0000000000..0fd6e00a21
--- /dev/null
+++ b/source4/heimdal/lib/ntlm/ntlm_err.et
@@ -0,0 +1,24 @@
+#
+# Error messages for the ntlm library
+#
+# This might look like a com_err file, but is not
+#
+
+error_table ntlm
+
+prefix HNTLM_ERR
+error_code DECODE, "Failed to decode packet"
+error_code INVALID_LENGTH, "Input length invalid"
+error_code CRYPTO, "Failed crypto primitive"
+error_code RAND, "Random generator failed"
+error_code AUTH, "NTLM authentication failed"
+error_code TIME_SKEW, "Client time skewed to server"
+error_code OEM, "Client set OEM string"
+error_code MISSING_NAME_SEPARATOR, "missing @ or \ in name"
+error_code MISSING_BUFFER, "missing expected buffer"
+error_code INVALID_APOP, "Invalid APOP response"
+error_code INVALID_CRAM_MD5, "Invalid CRAM-MD5 response"
+error_code INVALID_DIGEST_MD5, "Invalid DIGEST-MD5 response"
+error_code INVALID_DIGEST_MD5_RSPAUTH, "Invalid DIGEST-MD5 rspauth"
+
+end