heimdal Extra files required for merge up to current heimdal
authorAndrew Bartlett <abartlet@samba.org>
Fri, 12 Nov 2010 04:27:43 +0000 (15:27 +1100)
committerAndrew Bartlett <abartlet@samba.org>
Mon, 15 Nov 2010 01:25:06 +0000 (01:25 +0000)
31 files changed:
source4/heimdal/base/array.c [new file with mode: 0644]
source4/heimdal/base/baselocl.h [new file with mode: 0644]
source4/heimdal/base/bool.c [new file with mode: 0644]
source4/heimdal/base/dict.c [new file with mode: 0644]
source4/heimdal/base/heimbase.c [new file with mode: 0644]
source4/heimdal/base/heimbasepriv.h [new file with mode: 0644]
source4/heimdal/base/heimqueue.h [new file with mode: 0644]
source4/heimdal/base/null.c [new file with mode: 0644]
source4/heimdal/base/number.c [new file with mode: 0644]
source4/heimdal/base/string.c [new file with mode: 0644]
source4/heimdal/lib/hx509/lex.yy.c [new file with mode: 0644]
source4/heimdal/lib/krb5/crypto-aes.c [new file with mode: 0644]
source4/heimdal/lib/krb5/crypto-algs.c [new file with mode: 0644]
source4/heimdal/lib/krb5/crypto-arcfour.c [new file with mode: 0644]
source4/heimdal/lib/krb5/crypto-des-common.c [new file with mode: 0644]
source4/heimdal/lib/krb5/crypto-des.c [new file with mode: 0644]
source4/heimdal/lib/krb5/crypto-des3.c [new file with mode: 0644]
source4/heimdal/lib/krb5/crypto-evp.c [new file with mode: 0644]
source4/heimdal/lib/krb5/crypto-null.c [new file with mode: 0644]
source4/heimdal/lib/krb5/crypto-pk.c [new file with mode: 0644]
source4/heimdal/lib/krb5/crypto-rand.c [new file with mode: 0644]
source4/heimdal/lib/krb5/crypto-stubs.c [new file with mode: 0644]
source4/heimdal/lib/krb5/crypto.h [new file with mode: 0644]
source4/heimdal/lib/krb5/salt-aes.c [new file with mode: 0644]
source4/heimdal/lib/krb5/salt-arcfour.c [new file with mode: 0644]
source4/heimdal/lib/krb5/salt-des.c [new file with mode: 0644]
source4/heimdal/lib/krb5/salt-des3.c [new file with mode: 0644]
source4/heimdal/lib/krb5/store-int.c [new file with mode: 0644]
source4/heimdal/lib/ntlm/ntlm_err.et [new file with mode: 0644]
source4/heimdal_build/kpasswdd-glue.h [deleted file]
source4/heimdal_build/wscript_build

diff --git a/source4/heimdal/base/array.c b/source4/heimdal/base/array.c
new file mode 100644 (file)
index 0000000..7b0d77b
--- /dev/null
@@ -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 (file)
index 0000000..3932378
--- /dev/null
@@ -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 (file)
index 0000000..72edcc7
--- /dev/null
@@ -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 (file)
index 0000000..2eb57aa
--- /dev/null
@@ -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 (file)
index 0000000..a6caad2
--- /dev/null
@@ -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 (file)
index 0000000..7729625
--- /dev/null
@@ -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 (file)
index 0000000..423a684
--- /dev/null
@@ -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 (file)
index 0000000..66731aa
--- /dev/null
@@ -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 (file)
index 0000000..72631a5
--- /dev/null
@@ -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 (file)
index 0000000..414a916
--- /dev/null
@@ -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 (file)
index 0000000..4ee5a26
--- /dev/null
@@ -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 (file)
index 0000000..25c675c
--- /dev/null
@@ -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 (file)
index 0000000..5bd14ce
--- /dev/null
@@ -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 (file)
index 0000000..d098561
--- /dev/null
@@ -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 (file)
index 0000000..82d344f
--- /dev/null
@@ -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 (file)
index 0000000..f6c09ba
--- /dev/null
@@ -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 (file)
index 0000000..1ff692b
--- /dev/null
@@ -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 (file)
index 0000000..69d1e26
--- /dev/null
@@ -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 (file)
index 0000000..3a5c6b6
--- /dev/null
@@ -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 (file)
index 0000000..21e729c
--- /dev/null
@@ -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 (file)
index 0000000..49bd679
--- /dev/null
@@ -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 (file)
index 0000000..b462680
--- /dev/null
@@ -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 (file)
index 0000000..c57221b
--- /dev/null
@@ -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 (file)
index 0000000..1c40b54
--- /dev/null
@@ -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 (file)
index 0000000..b222b47
--- /dev/null
@@ -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 (file)
index 0000000..6939b6b
--- /dev/null
@@ -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 (file)
index 0000000..79140a2
--- /dev/null
@@ -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 (file)
index 0000000..0a18d0d
--- /dev/null
@@ -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 (file)
index 0000000..0fd6e00
--- /dev/null
@@ -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
diff --git a/source4/heimdal_build/kpasswdd-glue.h b/source4/heimdal_build/kpasswdd-glue.h
deleted file mode 100644 (file)
index 47ac26d..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-/* TODO: remove this file */
-struct _krb5_krb_auth_data;
-struct krb5_dh_moduli;
-struct AlgorithmIdentifier;
-#include "heimdal/lib/hcrypto/evp.h"
-#include "heimdal/lib/krb5/krb5-private.h"
index 058541e7a1320b15411111ebc68fd022f7b7a1fd..4d8459e02eb6d28a3ff70f9baa72c573bef596b5 100644 (file)
@@ -494,12 +494,14 @@ KDC_SOURCE='kdc/default_config.c kdc/kerberos5.c kdc/krb5tgs.c kdc/pkinit.c kdc/
 
 HEIMDAL_LIBRARY('kdc', source=KDC_SOURCE,
                     includes='../heimdal/kdc',
-                    deps='roken krb5 hdb asn1 HEIMDAL_DIGEST_ASN1 HEIMDAL_KX509_ASN1 heimntlm HEIMDAL_HCRYPTO com_err wind',
-                    vnum='2.0.0',
-                    )
+                    deps='roken krb5 hdb asn1 HEIMDAL_DIGEST_ASN1 HEIMDAL_KX509_ASN1 heimntlm HEIMDAL_HCRYPTO com_err wind HEIMDAL_BASE',
+                    vnum='2.0.0')
 HEIMDAL_AUTOPROTO('kdc/kdc-protos.h', KDC_SOURCE)
 HEIMDAL_AUTOPROTO_PRIVATE('kdc/kdc-private.h', KDC_SOURCE)
 
+HEIMDAL_ERRTABLE('HEIMNTLM_ET',
+                 'lib/ntlm/ntlm_err.et')
+
 HEIMNTLM_SOURCE = 'lib/ntlm/ntlm.c'
 HEIMDAL_LIBRARY('heimntlm',
                     source=HEIMNTLM_SOURCE,
@@ -580,10 +582,10 @@ lib/gssapi/mech/gss_set_cred_option.c  lib/gssapi/mech/gss_pseudo_random.c ../he
 
 # expand_path.c needs some of the install paths
 HEIMDAL_SUBSYSTEM('HEIMDAL_CONFIG',
-                  'lib/krb5/expand_path.c lib/krb5/plugin.c',
+                  'lib/krb5/expand_path.c lib/krb5/plugin.c lib/krb5/context.c',
                   includes='../heimdal/lib/krb5 ../heimdal/lib/asn1 ../heimdal/include',
                   cflags=bld.dynconfig_cflags('LIBDIR BINDIR LIBEXECDIR SBINDIR'),
-                  deps='HEIMDAL_HCRYPTO wind hx509 com_err'
+                  deps='HEIMDAL_HCRYPTO HEIMDAL_BASE wind hx509 com_err'
                   )
 
 KRB5_SOURCE = [os.path.join('lib/krb5/', x) for x in to_list(
@@ -592,9 +594,13 @@ KRB5_SOURCE = [os.path.join('lib/krb5/', x) for x in to_list(
                                asn1_glue.c auth_context.c
                                build_ap_req.c build_auth.c cache.c
                                changepw.c codec.c config_file.c
-                               constants.c context.c convert_creds.c
+                               constants.c convert_creds.c
                                copy_host_realm.c crc.c creds.c
-                               crypto.c data.c eai_to_heim_errno.c
+                               crypto.c crypto-aes.c crypto-algs.c
+                               crypto-arcfour.c crypto-des3.c crypto-des.c
+                               crypto-des-common.c crypto-evp.c
+                               crypto-null.c crypto-pk.c crypto-rand.c
+                               data.c eai_to_heim_errno.c
                                error_string.c expand_hostname.c
                                fcache.c free.c free_host_realm.c
                                generate_seq_number.c generate_subkey.c
@@ -612,18 +618,19 @@ KRB5_SOURCE = [os.path.join('lib/krb5/', x) for x in to_list(
                                principal.c prog_setup.c pac.c
                                pcache.c prompter_posix.c rd_cred.c rd_error.c
                                rd_priv.c rd_rep.c rd_req.c replay.c
+                               salt.c salt-aes.c salt-arcfour.c salt-des3.c salt-des.c
                                send_to_kdc.c set_default_realm.c
-                               store.c store_emem.c store_fd.c
+                               store.c store-int.c store_emem.c store_fd.c
                                store_mem.c ticket.c time.c transited.c
                                v4_glue.c version.c warn.c krb5_err.c
                                heim_err.c k524_err.c krb_err.c''')]  + ["../heimdal_build/krb5-glue.c"]
 
 HEIMDAL_LIBRARY('krb5', KRB5_SOURCE,
                     includes='../heimdal/lib/krb5 ../heimdal/lib/asn1 ../heimdal/include',
-            deps='roken HEIMDAL_PKINIT_ASN1 wind HEIMDAL_KRB5_ASN1 hx509 HEIMDAL_HCRYPTO samba-hostconfig intl com_err HEIMDAL_CONFIG',
+            deps='roken HEIMDAL_PKINIT_ASN1 wind HEIMDAL_KRB5_ASN1 hx509 HEIMDAL_HCRYPTO samba-hostconfig intl com_err HEIMDAL_CONFIG HEIMDAL_BASE',
             vnum='26.0.0',
                     )
-KRB5_PROTO_SOURCE = KRB5_SOURCE + ['lib/krb5/expand_path.c', 'lib/krb5/plugin.c']
+KRB5_PROTO_SOURCE = KRB5_SOURCE + ['lib/krb5/expand_path.c', 'lib/krb5/plugin.c', 'lib/krb5/context.c']
 
 HEIMDAL_AUTOPROTO_PRIVATE('lib/krb5/krb5-private.h', KRB5_PROTO_SOURCE)
 HEIMDAL_AUTOPROTO('lib/krb5/krb5-protos.h', KRB5_PROTO_SOURCE,
@@ -663,11 +670,6 @@ if not bld.CONFIG_SET("USING_SYSTEM_ASN1"):
             vnum='8.0.0')
 
 
-HEIMDAL_SUBSYSTEM('HEIMDAL_HCRYPTO_IMATH',
-    'lib/hcrypto/imath/imath.c lib/hcrypto/imath/iprime.c',
-    includes='../heimdal/lib/hcrypto/imath',
-    deps='roken'
-    )
 if not bld.CONFIG_SET("USING_SYSTEM_TOMMATH"):
     HEIMDAL_SUBSYSTEM('tommath',
         'lib/hcrypto/libtommath/bncore.c lib/hcrypto/libtommath/bn_mp_init.c lib/hcrypto/libtommath/bn_mp_clear.c lib/hcrypto/libtommath/bn_mp_exch.c lib/hcrypto/libtommath/bn_mp_grow.c lib/hcrypto/libtommath/bn_mp_shrink.c lib/hcrypto/libtommath/bn_mp_clamp.c lib/hcrypto/libtommath/bn_mp_zero.c lib/hcrypto/libtommath/bn_mp_zero_multi.c lib/hcrypto/libtommath/bn_mp_set.c lib/hcrypto/libtommath/bn_mp_set_int.c lib/hcrypto/libtommath/bn_mp_init_size.c lib/hcrypto/libtommath/bn_mp_copy.c lib/hcrypto/libtommath/bn_mp_init_copy.c lib/hcrypto/libtommath/bn_mp_abs.c lib/hcrypto/libtommath/bn_mp_neg.c lib/hcrypto/libtommath/bn_mp_cmp_mag.c lib/hcrypto/libtommath/bn_mp_cmp.c lib/hcrypto/libtommath/bn_mp_cmp_d.c lib/hcrypto/libtommath/bn_mp_rshd.c lib/hcrypto/libtommath/bn_mp_lshd.c lib/hcrypto/libtommath/bn_mp_mod_2d.c lib/hcrypto/libtommath/bn_mp_div_2d.c lib/hcrypto/libtommath/bn_mp_mul_2d.c lib/hcrypto/libtommath/bn_mp_div_2.c lib/hcrypto/libtommath/bn_mp_mul_2.c lib/hcrypto/libtommath/bn_s_mp_add.c lib/hcrypto/libtommath/bn_s_mp_sub.c lib/hcrypto/libtommath/bn_fast_s_mp_mul_digs.c lib/hcrypto/libtommath/bn_s_mp_mul_digs.c lib/hcrypto/libtommath/bn_fast_s_mp_mul_high_digs.c lib/hcrypto/libtommath/bn_s_mp_mul_high_digs.c lib/hcrypto/libtommath/bn_fast_s_mp_sqr.c lib/hcrypto/libtommath/bn_s_mp_sqr.c lib/hcrypto/libtommath/bn_mp_add.c lib/hcrypto/libtommath/bn_mp_sub.c lib/hcrypto/libtommath/bn_mp_karatsuba_mul.c lib/hcrypto/libtommath/bn_mp_mul.c lib/hcrypto/libtommath/bn_mp_karatsuba_sqr.c lib/hcrypto/libtommath/bn_mp_sqr.c lib/hcrypto/libtommath/bn_mp_div.c lib/hcrypto/libtommath/bn_mp_mod.c lib/hcrypto/libtommath/bn_mp_add_d.c lib/hcrypto/libtommath/bn_mp_sub_d.c lib/hcrypto/libtommath/bn_mp_mul_d.c lib/hcrypto/libtommath/bn_mp_div_d.c lib/hcrypto/libtommath/bn_mp_mod_d.c lib/hcrypto/libtommath/bn_mp_expt_d.c lib/hcrypto/libtommath/bn_mp_addmod.c lib/hcrypto/libtommath/bn_mp_submod.c lib/hcrypto/libtommath/bn_mp_mulmod.c lib/hcrypto/libtommath/bn_mp_sqrmod.c lib/hcrypto/libtommath/bn_mp_gcd.c lib/hcrypto/libtommath/bn_mp_lcm.c lib/hcrypto/libtommath/bn_fast_mp_invmod.c lib/hcrypto/libtommath/bn_mp_invmod.c lib/hcrypto/libtommath/bn_mp_reduce.c lib/hcrypto/libtommath/bn_mp_montgomery_setup.c lib/hcrypto/libtommath/bn_fast_mp_montgomery_reduce.c lib/hcrypto/libtommath/bn_mp_montgomery_reduce.c lib/hcrypto/libtommath/bn_mp_exptmod_fast.c lib/hcrypto/libtommath/bn_mp_exptmod.c lib/hcrypto/libtommath/bn_mp_2expt.c lib/hcrypto/libtommath/bn_mp_n_root.c lib/hcrypto/libtommath/bn_mp_jacobi.c lib/hcrypto/libtommath/bn_reverse.c lib/hcrypto/libtommath/bn_mp_count_bits.c lib/hcrypto/libtommath/bn_mp_read_unsigned_bin.c lib/hcrypto/libtommath/bn_mp_read_signed_bin.c lib/hcrypto/libtommath/bn_mp_to_unsigned_bin.c lib/hcrypto/libtommath/bn_mp_to_signed_bin.c lib/hcrypto/libtommath/bn_mp_unsigned_bin_size.c lib/hcrypto/libtommath/bn_mp_signed_bin_size.c lib/hcrypto/libtommath/bn_mp_xor.c lib/hcrypto/libtommath/bn_mp_and.c lib/hcrypto/libtommath/bn_mp_or.c lib/hcrypto/libtommath/bn_mp_rand.c lib/hcrypto/libtommath/bn_mp_montgomery_calc_normalization.c lib/hcrypto/libtommath/bn_mp_prime_is_divisible.c lib/hcrypto/libtommath/bn_prime_tab.c lib/hcrypto/libtommath/bn_mp_prime_fermat.c lib/hcrypto/libtommath/bn_mp_prime_miller_rabin.c lib/hcrypto/libtommath/bn_mp_prime_is_prime.c lib/hcrypto/libtommath/bn_mp_prime_next_prime.c lib/hcrypto/libtommath/bn_mp_find_prime.c lib/hcrypto/libtommath/bn_mp_isprime.c lib/hcrypto/libtommath/bn_mp_dr_reduce.c lib/hcrypto/libtommath/bn_mp_dr_is_modulus.c lib/hcrypto/libtommath/bn_mp_dr_setup.c lib/hcrypto/libtommath/bn_mp_reduce_setup.c lib/hcrypto/libtommath/bn_mp_toom_mul.c lib/hcrypto/libtommath/bn_mp_toom_sqr.c lib/hcrypto/libtommath/bn_mp_div_3.c lib/hcrypto/libtommath/bn_s_mp_exptmod.c lib/hcrypto/libtommath/bn_mp_reduce_2k.c lib/hcrypto/libtommath/bn_mp_reduce_is_2k.c lib/hcrypto/libtommath/bn_mp_reduce_2k_setup.c lib/hcrypto/libtommath/bn_mp_reduce_2k_l.c lib/hcrypto/libtommath/bn_mp_reduce_is_2k_l.c lib/hcrypto/libtommath/bn_mp_reduce_2k_setup_l.c lib/hcrypto/libtommath/bn_mp_radix_smap.c lib/hcrypto/libtommath/bn_mp_read_radix.c lib/hcrypto/libtommath/bn_mp_toradix.c lib/hcrypto/libtommath/bn_mp_radix_size.c lib/hcrypto/libtommath/bn_mp_fread.c lib/hcrypto/libtommath/bn_mp_fwrite.c lib/hcrypto/libtommath/bn_mp_cnt_lsb.c lib/hcrypto/libtommath/bn_error.c lib/hcrypto/libtommath/bn_mp_init_multi.c lib/hcrypto/libtommath/bn_mp_clear_multi.c lib/hcrypto/libtommath/bn_mp_exteuclid.c lib/hcrypto/libtommath/bn_mp_toradix_n.c lib/hcrypto/libtommath/bn_mp_prime_random_ex.c lib/hcrypto/libtommath/bn_mp_get_int.c lib/hcrypto/libtommath/bn_mp_sqrt.c lib/hcrypto/libtommath/bn_mp_is_square.c lib/hcrypto/libtommath/bn_mp_init_set.c lib/hcrypto/libtommath/bn_mp_init_set_int.c lib/hcrypto/libtommath/bn_mp_invmod_slow.c lib/hcrypto/libtommath/bn_mp_prime_rabin_miller_trials.c lib/hcrypto/libtommath/bn_mp_to_signed_bin_n.c lib/hcrypto/libtommath/bn_mp_to_unsigned_bin_n.c',
@@ -675,9 +677,15 @@ if not bld.CONFIG_SET("USING_SYSTEM_TOMMATH"):
         )
 
 HEIMDAL_SUBSYSTEM('HEIMDAL_HCRYPTO',
-    'lib/hcrypto/aes.c lib/hcrypto/bn.c lib/hcrypto/dh.c lib/hcrypto/dh-ltm.c lib/hcrypto/dh-imath.c lib/hcrypto/des.c lib/hcrypto/dsa.c lib/hcrypto/engine.c lib/hcrypto/md2.c lib/hcrypto/md4.c lib/hcrypto/md5.c lib/hcrypto/rsa.c lib/hcrypto/rsa-ltm.c lib/hcrypto/rsa-imath.c lib/hcrypto/rc2.c lib/hcrypto/rc4.c lib/hcrypto/rijndael-alg-fst.c lib/hcrypto/rnd_keys.c lib/hcrypto/sha.c lib/hcrypto/sha256.c lib/hcrypto/sha512.c lib/hcrypto/ui.c lib/hcrypto/evp.c lib/hcrypto/evp-hcrypto.c lib/hcrypto/pkcs5.c lib/hcrypto/pkcs12.c lib/hcrypto/rand.c lib/hcrypto/rand-egd.c lib/hcrypto/rand-unix.c lib/hcrypto/rand-fortuna.c lib/hcrypto/rand-timer.c lib/hcrypto/hmac.c lib/hcrypto/camellia.c lib/hcrypto/camellia-ntt.c lib/hcrypto/common.c lib/hcrypto/validate.c',
+    'lib/hcrypto/aes.c lib/hcrypto/bn.c lib/hcrypto/dh.c lib/hcrypto/dh-ltm.c lib/hcrypto/des.c lib/hcrypto/dsa.c lib/hcrypto/engine.c lib/hcrypto/md2.c lib/hcrypto/md4.c lib/hcrypto/md5.c lib/hcrypto/rsa.c lib/hcrypto/rsa-ltm.c lib/hcrypto/rc2.c lib/hcrypto/rc4.c lib/hcrypto/rijndael-alg-fst.c lib/hcrypto/rnd_keys.c lib/hcrypto/sha.c lib/hcrypto/sha256.c lib/hcrypto/sha512.c lib/hcrypto/ui.c lib/hcrypto/evp.c lib/hcrypto/evp-hcrypto.c lib/hcrypto/pkcs5.c lib/hcrypto/pkcs12.c lib/hcrypto/rand.c lib/hcrypto/rand-egd.c lib/hcrypto/rand-unix.c lib/hcrypto/rand-fortuna.c lib/hcrypto/rand-timer.c lib/hcrypto/hmac.c lib/hcrypto/camellia.c lib/hcrypto/camellia-ntt.c lib/hcrypto/common.c lib/hcrypto/validate.c',
     includes='../heimdal/lib/hcrypto ../heimdal/lib ../heimdal/include',
-    deps='roken asn1 HEIMDAL_HCRYPTO_IMATH HEIMDAL_RFC2459_ASN1 tommath'
+    deps='roken asn1 HEIMDAL_RFC2459_ASN1 tommath'
+    )
+
+HEIMDAL_SUBSYSTEM('HEIMDAL_BASE',
+    'base/array.c base/bool.c base/dict.c base/heimbase.c base/string.c base/number.c base/null.c',
+    includes='../heimdal/base',
+    deps='roken'
     )