Add attribute macros for Heimdal to use
authorAndrew Bartlett <abartlet@samba.org>
Fri, 12 Nov 2010 02:14:00 +0000 (13:14 +1100)
committerAndrew Bartlett <abartlet@samba.org>
Mon, 15 Nov 2010 01:25:06 +0000 (01:25 +0000)
Heimdal uses HEIMDAL_NORETURN_ATTRIBUTE and HEIMDAL_PRINTF_ATTRIBUTE,
and we need to provide a link between these and Samba's function
attribute handling.

Andrew Bartlett

lib/util/attr.h
source4/heimdal/base/heimbase.h [new file with mode: 0644]
source4/heimdal/lib/krb5/salt.c [new file with mode: 0644]
source4/heimdal_build/config.h

index 9b346459b60746c61f55b4131db556d26cd99677..a2690613fb14a1fc35eeea954809fa3018419866 100644 (file)
 #endif
 #endif
 
+#ifndef FORMAT_ATTRIBUTE
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
+/** Use gcc attribute to check printf fns.  a1 is argument to format()
+ * in the above macro.  This is needed to support Heimdal's printf
+ * decorations. Note that some gcc 2.x versions don't handle this
+ * properly, and as such I've used the same minimum from heimdal: GCC 3.1 **/
+#define FORMAT_ATTRIBUTE(a) __attribute__ ((format a))
+#else
+#define FORMAT_ATTRIBUTE(a)
+#endif
+#endif
+
 #endif /* __UTIL_ATTR_H__ */
diff --git a/source4/heimdal/base/heimbase.h b/source4/heimdal/base/heimbase.h
new file mode 100644 (file)
index 0000000..17eb12e
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ * 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.
+ */
+
+#ifndef HEIM_BASE_H
+#define HEIM_BASE_H 1
+
+#include <sys/types.h>
+#include <krb5-types.h>
+#include <stdarg.h>
+#include <stdbool.h>
+
+typedef void * heim_object_t;
+typedef unsigned int heim_tid_t;
+typedef heim_object_t heim_bool_t;
+typedef heim_object_t heim_null_t;
+#define HEIM_BASE_ONCE_INIT 0
+typedef long heim_base_once_t; /* XXX arch dependant */
+
+void * heim_retain(heim_object_t);
+void   heim_release(heim_object_t);
+
+typedef void (*heim_type_dealloc)(void *);
+
+void *
+heim_alloc(size_t size, const char *name, heim_type_dealloc dealloc);
+
+heim_tid_t
+heim_get_tid(heim_object_t object);
+
+int
+heim_cmp(heim_object_t a, heim_object_t b);
+
+unsigned long
+heim_get_hash(heim_object_t ptr);
+
+void
+heim_base_once_f(heim_base_once_t *, void *, void (*)(void *));
+
+void
+heim_abort(const char *fmt, ...)
+    HEIMDAL_NORETURN_ATTRIBUTE
+    HEIMDAL_PRINTF_ATTRIBUTE((printf, 1, 2));
+
+void
+heim_abortv(const char *fmt, va_list ap)
+    HEIMDAL_NORETURN_ATTRIBUTE
+    HEIMDAL_PRINTF_ATTRIBUTE((printf, 1, 0));
+
+#define heim_assert(e,t) \
+    (__builtin_expect(!(e), 0) ? heim_abort(t ":" #e) : (void)0)
+
+/*
+ *
+ */
+
+heim_null_t
+heim_null_create(void);
+
+heim_bool_t
+heim_bool_create(int);
+
+int
+heim_bool_val(heim_bool_t);
+
+/*
+ * Array
+ */
+
+typedef struct heim_array_data *heim_array_t;
+
+heim_array_t heim_array_create(void);
+heim_tid_t heim_array_get_type_id(void);
+
+typedef void (*heim_array_iterator_f_t)(heim_object_t, void *);
+
+int    heim_array_append_value(heim_array_t, heim_object_t);
+void   heim_array_iterate_f(heim_array_t, heim_array_iterator_f_t, void *);
+#ifdef __BLOCKS__
+void   heim_array_iterate(heim_array_t, void (^)(heim_object_t));
+#endif
+size_t heim_array_get_length(heim_array_t);
+heim_object_t
+       heim_array_copy_value(heim_array_t, size_t);
+void   heim_array_delete_value(heim_array_t, size_t);
+#ifdef __BLOCKS__
+void   heim_array_filter(heim_array_t, bool (^)(heim_object_t));
+#endif
+
+/*
+ * Dict
+ */
+
+typedef struct heim_dict_data *heim_dict_t;
+
+heim_dict_t heim_dict_create(size_t size);
+heim_tid_t heim_dict_get_type_id(void);
+
+typedef void (*heim_dict_iterator_f_t)(heim_object_t, heim_object_t, void *);
+
+int    heim_dict_add_value(heim_dict_t, heim_object_t, heim_object_t);
+void   heim_dict_iterate_f(heim_dict_t, heim_dict_iterator_f_t, void *);
+#ifdef __BLOCKS__
+void   heim_dict_iterate(heim_dict_t, void (^)(heim_object_t, heim_object_t));
+#endif
+
+heim_object_t
+       heim_dict_copy_value(heim_dict_t, heim_object_t);
+void   heim_dict_delete_key(heim_dict_t, heim_object_t);
+
+/*
+ * String
+ */
+
+typedef struct heim_string_data *heim_string_t;
+
+heim_string_t heim_string_create(const char *);
+heim_string_t heim_string_create_with_static(const char *);
+heim_tid_t heim_string_get_type_id(void);
+const char * heim_string_get_utf8(heim_string_t);
+
+/*
+ * Number
+ */
+
+typedef struct heim_number_data *heim_number_t;
+
+heim_number_t heim_number_create(int);
+heim_tid_t heim_number_get_type_id(void);
+int heim_number_get_int(heim_number_t);
+
+/*
+ *
+ */
+
+typedef struct heim_auto_release * heim_auto_release_t;
+
+heim_auto_release_t heim_auto_release_create(void);
+void heim_auto_release_drain(heim_auto_release_t);
+void heim_auto_release(heim_object_t);
+
+#endif /* HEIM_BASE_H */
diff --git a/source4/heimdal/lib/krb5/salt.c b/source4/heimdal/lib/krb5/salt.c
new file mode 100644 (file)
index 0000000..69375f6
--- /dev/null
@@ -0,0 +1,304 @@
+/*
+ * 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_error_code KRB5_LIB_CALL
+krb5_salttype_to_string (krb5_context context,
+                        krb5_enctype etype,
+                        krb5_salttype stype,
+                        char **string)
+{
+    struct encryption_type *e;
+    struct salt_type *st;
+
+    e = _krb5_find_enctype (etype);
+    if (e == NULL) {
+       krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
+                              "encryption type %d not supported",
+                              etype);
+       return KRB5_PROG_ETYPE_NOSUPP;
+    }
+    for (st = e->keytype->string_to_key; st && st->type; st++) {
+       if (st->type == stype) {
+           *string = strdup (st->name);
+           if (*string == NULL) {
+               krb5_set_error_message (context, ENOMEM,
+                                       N_("malloc: out of memory", ""));
+               return ENOMEM;
+           }
+           return 0;
+       }
+    }
+    krb5_set_error_message (context, HEIM_ERR_SALTTYPE_NOSUPP,
+                           "salttype %d not supported", stype);
+    return HEIM_ERR_SALTTYPE_NOSUPP;
+}
+
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+krb5_string_to_salttype (krb5_context context,
+                        krb5_enctype etype,
+                        const char *string,
+                        krb5_salttype *salttype)
+{
+    struct encryption_type *e;
+    struct salt_type *st;
+
+    e = _krb5_find_enctype (etype);
+    if (e == NULL) {
+       krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
+                              N_("encryption type %d not supported", ""),
+                              etype);
+       return KRB5_PROG_ETYPE_NOSUPP;
+    }
+    for (st = e->keytype->string_to_key; st && st->type; st++) {
+       if (strcasecmp (st->name, string) == 0) {
+           *salttype = st->type;
+           return 0;
+       }
+    }
+    krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP,
+                          N_("salttype %s not supported", ""), string);
+    return HEIM_ERR_SALTTYPE_NOSUPP;
+}
+
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+krb5_get_pw_salt(krb5_context context,
+                krb5_const_principal principal,
+                krb5_salt *salt)
+{
+    size_t len;
+    int i;
+    krb5_error_code ret;
+    char *p;
+
+    salt->salttype = KRB5_PW_SALT;
+    len = strlen(principal->realm);
+    for (i = 0; i < principal->name.name_string.len; ++i)
+       len += strlen(principal->name.name_string.val[i]);
+    ret = krb5_data_alloc (&salt->saltvalue, len);
+    if (ret)
+       return ret;
+    p = salt->saltvalue.data;
+    memcpy (p, principal->realm, strlen(principal->realm));
+    p += strlen(principal->realm);
+    for (i = 0; i < principal->name.name_string.len; ++i) {
+       memcpy (p,
+               principal->name.name_string.val[i],
+               strlen(principal->name.name_string.val[i]));
+       p += strlen(principal->name.name_string.val[i]);
+    }
+    return 0;
+}
+
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+krb5_free_salt(krb5_context context,
+              krb5_salt salt)
+{
+    krb5_data_free(&salt.saltvalue);
+    return 0;
+}
+
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+krb5_string_to_key_data (krb5_context context,
+                        krb5_enctype enctype,
+                        krb5_data password,
+                        krb5_principal principal,
+                        krb5_keyblock *key)
+{
+    krb5_error_code ret;
+    krb5_salt salt;
+
+    ret = krb5_get_pw_salt(context, principal, &salt);
+    if(ret)
+       return ret;
+    ret = krb5_string_to_key_data_salt(context, enctype, password, salt, key);
+    krb5_free_salt(context, salt);
+    return ret;
+}
+
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+krb5_string_to_key (krb5_context context,
+                   krb5_enctype enctype,
+                   const char *password,
+                   krb5_principal principal,
+                   krb5_keyblock *key)
+{
+    krb5_data pw;
+    pw.data = rk_UNCONST(password);
+    pw.length = strlen(password);
+    return krb5_string_to_key_data(context, enctype, pw, principal, key);
+}
+
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+krb5_string_to_key_data_salt (krb5_context context,
+                             krb5_enctype enctype,
+                             krb5_data password,
+                             krb5_salt salt,
+                             krb5_keyblock *key)
+{
+    krb5_data opaque;
+    krb5_data_zero(&opaque);
+    return krb5_string_to_key_data_salt_opaque(context, enctype, password,
+                                              salt, opaque, key);
+}
+
+/*
+ * Do a string -> key for encryption type `enctype' operation on
+ * `password' (with salt `salt' and the enctype specific data string
+ * `opaque'), returning the resulting key in `key'
+ */
+
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+krb5_string_to_key_data_salt_opaque (krb5_context context,
+                                    krb5_enctype enctype,
+                                    krb5_data password,
+                                    krb5_salt salt,
+                                    krb5_data opaque,
+                                    krb5_keyblock *key)
+{
+    struct encryption_type *et =_krb5_find_enctype(enctype);
+    struct salt_type *st;
+    if(et == NULL) {
+       krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
+                              N_("encryption type %d not supported", ""),
+                              enctype);
+       return KRB5_PROG_ETYPE_NOSUPP;
+    }
+    for(st = et->keytype->string_to_key; st && st->type; st++)
+       if(st->type == salt.salttype)
+           return (*st->string_to_key)(context, enctype, password,
+                                       salt, opaque, key);
+    krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP,
+                          N_("salt type %d not supported", ""),
+                          salt.salttype);
+    return HEIM_ERR_SALTTYPE_NOSUPP;
+}
+
+/*
+ * Do a string -> key for encryption type `enctype' operation on the
+ * string `password' (with salt `salt'), returning the resulting key
+ * in `key'
+ */
+
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+krb5_string_to_key_salt (krb5_context context,
+                        krb5_enctype enctype,
+                        const char *password,
+                        krb5_salt salt,
+                        krb5_keyblock *key)
+{
+    krb5_data pw;
+    pw.data = rk_UNCONST(password);
+    pw.length = strlen(password);
+    return krb5_string_to_key_data_salt(context, enctype, pw, salt, key);
+}
+
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+krb5_string_to_key_salt_opaque (krb5_context context,
+                               krb5_enctype enctype,
+                               const char *password,
+                               krb5_salt salt,
+                               krb5_data opaque,
+                               krb5_keyblock *key)
+{
+    krb5_data pw;
+    pw.data = rk_UNCONST(password);
+    pw.length = strlen(password);
+    return krb5_string_to_key_data_salt_opaque(context, enctype,
+                                              pw, salt, opaque, key);
+}
+
+
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+krb5_string_to_key_derived(krb5_context context,
+                          const void *str,
+                          size_t len,
+                          krb5_enctype etype,
+                          krb5_keyblock *key)
+{
+    struct encryption_type *et = _krb5_find_enctype(etype);
+    krb5_error_code ret;
+    struct key_data kd;
+    size_t keylen;
+    u_char *tmp;
+
+    if(et == NULL) {
+       krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
+                               N_("encryption type %d not supported", ""),
+                               etype);
+       return KRB5_PROG_ETYPE_NOSUPP;
+    }
+    keylen = et->keytype->bits / 8;
+
+    ALLOC(kd.key, 1);
+    if(kd.key == NULL) {
+       krb5_set_error_message (context, ENOMEM,
+                               N_("malloc: out of memory", ""));
+       return ENOMEM;
+    }
+    ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
+    if(ret) {
+       free(kd.key);
+       return ret;
+    }
+    kd.key->keytype = etype;
+    tmp = malloc (keylen);
+    if(tmp == NULL) {
+       krb5_free_keyblock(context, kd.key);
+       krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
+       return ENOMEM;
+    }
+    ret = _krb5_n_fold(str, len, tmp, keylen);
+    if (ret) {
+       free(tmp);
+       krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
+       return ret;
+    }
+    kd.schedule = NULL;
+    _krb5_DES3_random_to_key(context, kd.key, tmp, keylen);
+    memset(tmp, 0, keylen);
+    free(tmp);
+    ret = _krb5_derive_key(context,
+                          et,
+                          &kd,
+                          "kerberos", /* XXX well known constant */
+                          strlen("kerberos"));
+    if (ret) {
+       _krb5_free_key_data(context, &kd, et);
+       return ret;
+    }
+    ret = krb5_copy_keyblock_contents(context, kd.key, key);
+    _krb5_free_key_data(context, &kd, et);
+    return ret;
+}
index 611bf2fe0c90344aee4bad2819962a6481cc740f..71ef3e983f9fa072161ab03e87f137564a5d0fa5 100644 (file)
@@ -8,7 +8,9 @@
 
 #include "include/config.h"
 #include "../replace/replace.h"
-
+#include "../lib/util/attr.h"
+#define HEIMDAL_NORETURN_ATTRIBUTE _NORETURN_
+#define HEIMDAL_PRINTF_ATTRIBUTE(x) FORMAT_ATTRIBUTE(x)
 #define VERSIONLIST {"Lorikeet-Heimdal, Modified for Samba4"}
 
 #define VERSION "Samba"