From 5a6288f45891be30bd8e22978f61faf487214de6 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 13 Nov 2006 03:19:59 +0000 Subject: r19681: Update to current lorikeet-heimdal. I'm looking at using the realm lookup plugin, the new PAC validation code as well as Heimdal's SPNEGO implementation. Andrew Bartlett (This used to be commit 05421f45ed7811697ea491e26c9d991a7faa1a64) --- source4/heimdal/lib/krb5/krb5-private.h | 54 +++++++ source4/heimdal/lib/krb5/krb5-protos.h | 27 +++- source4/heimdal/lib/krb5/krb5.h | 4 +- source4/heimdal/lib/krb5/krb5_locl.h | 6 + source4/heimdal/lib/krb5/krbhst.c | 97 ++++++++++++- source4/heimdal/lib/krb5/locate_plugin.h | 64 ++++++++ source4/heimdal/lib/krb5/mit_glue.c | 10 +- source4/heimdal/lib/krb5/plugin.c | 242 +++++++++++++++++++++++++++++++ 8 files changed, 491 insertions(+), 13 deletions(-) create mode 100644 source4/heimdal/lib/krb5/locate_plugin.h create mode 100644 source4/heimdal/lib/krb5/plugin.c (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/krb5-private.h b/source4/heimdal/lib/krb5/krb5-private.h index 0bf184a530..ba2f75ad22 100644 --- a/source4/heimdal/lib/krb5/krb5-private.h +++ b/source4/heimdal/lib/krb5/krb5-private.h @@ -299,6 +299,37 @@ _krb5_oid_to_enctype ( const heim_oid */*oid*/, krb5_enctype */*etype*/); +void +_krb5_pac_free ( + krb5_context /*context*/, + struct krb5_pac */*pac*/); + +krb5_error_code +_krb5_pac_parse ( + krb5_context /*context*/, + const void */*ptr*/, + size_t /*len*/, + struct krb5_pac **/*pac*/); + +krb5_error_code +_krb5_pac_sign ( + krb5_context /*context*/, + struct krb5_pac */*p*/, + time_t /*authtime*/, + krb5_principal /*principal*/, + krb5_keyblock */*server_key*/, + krb5_keyblock */*priv_key*/, + krb5_data */*data*/); + +krb5_error_code +_krb5_pac_verify ( + krb5_context /*context*/, + struct krb5_pac */*pac*/, + time_t /*authtime*/, + krb5_principal /*principal*/, + krb5_keyblock */*server*/, + krb5_keyblock */*privsvr*/); + krb5_error_code _krb5_parse_moduli ( krb5_context /*context*/, @@ -380,6 +411,29 @@ _krb5_pk_verify_sign ( krb5_data */*content*/, struct krb5_pk_cert **/*signer*/); +krb5_error_code +_krb5_plugin_find ( + krb5_context /*context*/, + enum plugin_type /*type*/, + const char */*name*/, + struct krb5_plugin **/*list*/); + +void +_krb5_plugin_free (struct krb5_plugin */*list*/); + +struct krb5_plugin * +_krb5_plugin_get_next (struct krb5_plugin */*p*/); + +void * +_krb5_plugin_get_symbol (struct krb5_plugin */*p*/); + +krb5_error_code +_krb5_plugin_register ( + krb5_context /*context*/, + enum plugin_type /*type*/, + const char */*name*/, + void */*symbol*/); + krb5_error_code KRB5_LIB_FUNCTION _krb5_principal2principalname ( PrincipalName */*p*/, diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h index 104f10bdf2..8b61e8d7d2 100644 --- a/source4/heimdal/lib/krb5/krb5-protos.h +++ b/source4/heimdal/lib/krb5/krb5-protos.h @@ -498,6 +498,12 @@ krb5_c_is_coll_proof_cksum (krb5_cksumtype /*ctype*/); krb5_boolean KRB5_LIB_FUNCTION krb5_c_is_keyed_cksum (krb5_cksumtype /*ctype*/); +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_keylength ( + krb5_context /*context*/, + krb5_enctype /*enctype*/, + size_t */*len*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_c_make_checksum ( krb5_context /*context*/, @@ -2165,6 +2171,9 @@ krb5_get_krbhst ( const krb5_realm */*realm*/, char ***/*hostlist*/); +time_t KRB5_LIB_FUNCTION +krb5_get_max_time_skew (krb5_context /*context*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_get_pw_salt ( krb5_context /*context*/, @@ -2177,9 +2186,6 @@ krb5_get_server_rcache ( const krb5_data */*piece*/, krb5_rcache */*id*/); -time_t KRB5_LIB_FUNCTION -krb5_get_time_wrap (krb5_context /*context*/); - krb5_boolean KRB5_LIB_FUNCTION krb5_get_use_admin_kdc (krb5_context /*context*/); @@ -3165,6 +3171,11 @@ krb5_set_ignore_addresses ( krb5_context /*context*/, const krb5_addresses */*addresses*/); +void KRB5_LIB_FUNCTION +krb5_set_max_time_skew ( + krb5_context /*context*/, + time_t /*t*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_set_password ( krb5_context /*context*/, @@ -3197,11 +3208,6 @@ krb5_set_send_to_kdc_func ( krb5_send_to_kdc_func /*func*/, void */*data*/); -void KRB5_LIB_FUNCTION -krb5_set_time_wrap ( - krb5_context /*context*/, - time_t /*t*/); - void KRB5_LIB_FUNCTION krb5_set_use_admin_kdc ( krb5_context /*context*/, @@ -3271,6 +3277,11 @@ krb5_storage_from_mem ( void */*buf*/, size_t /*len*/); +krb5_storage * KRB5_LIB_FUNCTION +krb5_storage_from_readonly_mem ( + const void */*buf*/, + size_t /*len*/); + krb5_flags KRB5_LIB_FUNCTION krb5_storage_get_byteorder ( krb5_storage */*sp*/, diff --git a/source4/heimdal/lib/krb5/krb5.h b/source4/heimdal/lib/krb5/krb5.h index f5c8b069de..1b26e8b3e7 100644 --- a/source4/heimdal/lib/krb5/krb5.h +++ b/source4/heimdal/lib/krb5/krb5.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5.h,v 1.254 2006/11/07 00:17:42 lha Exp $ */ +/* $Id: krb5.h,v 1.255 2006/11/12 08:33:07 lha Exp $ */ #ifndef __KRB5_H__ #define __KRB5_H__ @@ -78,6 +78,8 @@ typedef struct krb5_get_creds_opt_data *krb5_get_creds_opt; struct krb5_digest; typedef struct krb5_digest *krb5_digest; +struct krb5_pac; + typedef struct krb5_rd_req_in_ctx *krb5_rd_req_in_ctx; typedef struct krb5_rd_req_out_ctx *krb5_rd_req_out_ctx; diff --git a/source4/heimdal/lib/krb5/krb5_locl.h b/source4/heimdal/lib/krb5/krb5_locl.h index 89b3c6ad40..3fb5461b3c 100644 --- a/source4/heimdal/lib/krb5/krb5_locl.h +++ b/source4/heimdal/lib/krb5/krb5_locl.h @@ -148,6 +148,12 @@ struct krb5_dh_moduli; /* v4 glue */ struct _krb5_krb_auth_data; +struct krb5_plugin; +enum plugin_type { + PLUGIN_TYPE_DATA = 1, + PLUGIN_TYPE_FUNC +}; + #include #include diff --git a/source4/heimdal/lib/krb5/krbhst.c b/source4/heimdal/lib/krb5/krbhst.c index e7b2579229..f395f0d0c3 100644 --- a/source4/heimdal/lib/krb5/krbhst.c +++ b/source4/heimdal/lib/krb5/krbhst.c @@ -33,8 +33,9 @@ #include "krb5_locl.h" #include +#include "locate_plugin.h" -RCSID("$Id: krbhst.c,v 1.57 2006/10/06 17:11:02 lha Exp $"); +RCSID("$Id: krbhst.c,v 1.58 2006/11/12 20:05:20 lha Exp $"); static int string_to_proto(const char *string) @@ -147,6 +148,7 @@ struct krb5_krbhst_data { #define KD_FALLBACK 16 #define KD_CONFIG_EXISTS 32 #define KD_LARGE_MSG 64 +#define KD_PLUGIN 128 krb5_error_code (*get_next)(krb5_context, struct krb5_krbhst_data *, krb5_krbhst_info**); @@ -460,8 +462,8 @@ fallback_get_hosts(krb5_context context, struct krb5_krbhst_data *kd, hi->proto = proto; hi->port = hi->def_port = port; hi->ai = ai; - memmove(hi->hostname, host, hostlen - 1); - hi->hostname[hostlen - 1] = '\0'; + memmove(hi->hostname, host, hostlen); + hi->hostname[hostlen] = '\0'; free(host); append_host_hostinfo(kd, hi); kd->fallback_count++; @@ -469,6 +471,88 @@ fallback_get_hosts(krb5_context context, struct krb5_krbhst_data *kd, return 0; } +/* + * Fetch hosts from plugin + */ + +static krb5_error_code +add_locate(void *ctx, int type, struct sockaddr *addr) +{ + struct krb5_krbhst_info *hi; + struct krb5_krbhst_data *kd = ctx; + char host[NI_MAXHOST], port[NI_MAXSERV]; + struct addrinfo hints, *ai; + socklen_t socklen; + size_t hostlen; + int ret; + + socklen = socket_sockaddr_size(addr); + + ret = getnameinfo(addr, socklen, host, sizeof(host), port, sizeof(port), + NI_NUMERICHOST|NI_NUMERICSERV); + if (ret != 0) + return 0; + + memset(&hints, 0, sizeof(hints)); + ret = getaddrinfo(host, port, &hints, &ai); + if (ret) + return 0; + + hostlen = strlen(host); + + hi = calloc(1, sizeof(*hi) + hostlen); + if(hi == NULL) { + free(host); + return ENOMEM; + } + + hi->proto = krbhst_get_default_proto(kd); + hi->port = hi->def_port = socket_get_port(addr); + hi->ai = ai; + memmove(hi->hostname, host, hostlen); + hi->hostname[hostlen] = '\0'; + append_host_hostinfo(kd, hi); + + return 0; +} + +static void +plugin_get_hosts(krb5_context context, + struct krb5_krbhst_data *kd, + enum locate_service_type type) +{ + struct krb5_plugin *list, *e; + krb5_error_code ret; + + ret = _krb5_plugin_find(context, PLUGIN_TYPE_DATA, "resolve", &list); + if(ret != 0 || list == NULL) + return; + + kd->flags |= KD_CONFIG_EXISTS; + + for (e = list; e != NULL; e = _krb5_plugin_get_next(e)) { + krb5plugin_service_locate_ftable *service; + void *ctx; + + service = _krb5_plugin_get_symbol(e); + if (service->minor_version != 0) + continue; + + (*service->init)(context, &ctx); + ret = (*service->lookup)(ctx, type, kd->realm, 0, 0, add_locate, kd); + (*service->fini)(ctx); + if (ret) { + krb5_set_error_string(context, "Plugin failed to lookup"); + break; + } + } + _krb5_plugin_free(list); +} + +/* + * + */ + static krb5_error_code kdc_get_next(krb5_context context, struct krb5_krbhst_data *kd, @@ -476,6 +560,13 @@ kdc_get_next(krb5_context context, { krb5_error_code ret; + if ((kd->flags & KD_PLUGIN) == 0) { + plugin_get_hosts(context, kd, locate_service_kdc); + kd->flags |= KD_PLUGIN; + if(get_next(kd, host)) + return 0; + } + if((kd->flags & KD_CONFIG) == 0) { config_get_hosts(context, kd, "kdc"); kd->flags |= KD_CONFIG; diff --git a/source4/heimdal/lib/krb5/locate_plugin.h b/source4/heimdal/lib/krb5/locate_plugin.h new file mode 100644 index 0000000000..ec06d362cf --- /dev/null +++ b/source4/heimdal/lib/krb5/locate_plugin.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2006 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: locate_plugin.h,v 1.1 2006/11/12 19:00:03 lha Exp $ */ + +#ifndef HEIMDAL_KRB5_LOCATE_PLUGIN_H +#define HEIMDAL_KRB5_LOCATE_PLUGIN_H 1 + +#include + +enum locate_service_type { + locate_service_kdc = 1, + locate_service_master_kdc, + locate_service_kadmin, + locate_service_krb524, + locate_service_kpasswd +}; + +typedef krb5_error_code +(*krb5plugin_service_locate_lookup) (void *, enum locate_service_type, + const char *, int, int, + int (*)(void *,int,struct sockaddr *), + void *); + + +typedef struct krb5plugin_service_locate_ftable { + int minor_version; + krb5_error_code (*init)(krb5_context, void **); + void (*fini)(void *); + krb5plugin_service_locate_lookup lookup; +} krb5plugin_service_locate_ftable; + +#endif /* HEIMDAL_KRB5_LOCATE_PLUGIN_H */ + diff --git a/source4/heimdal/lib/krb5/mit_glue.c b/source4/heimdal/lib/krb5/mit_glue.c index b9075b3079..493c4cd845 100755 --- a/source4/heimdal/lib/krb5/mit_glue.c +++ b/source4/heimdal/lib/krb5/mit_glue.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: mit_glue.c,v 1.8 2006/10/14 09:51:02 lha Exp $"); +RCSID("$Id: mit_glue.c,v 1.9 2006/11/09 21:24:16 lha Exp $"); /* * Glue for MIT API @@ -325,3 +325,11 @@ krb5_c_make_random_key(krb5_context context, { return krb5_generate_random_keyblock(context, enctype, random_key); } + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_keylength(krb5_context context, + krb5_enctype enctype, + size_t *len) +{ + return krb5_enctype_keysize(context, enctype, len); +} diff --git a/source4/heimdal/lib/krb5/plugin.c b/source4/heimdal/lib/krb5/plugin.c new file mode 100644 index 0000000000..294807faab --- /dev/null +++ b/source4/heimdal/lib/krb5/plugin.c @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" +RCSID("$Id: plugin.c,v 1.2 2006/11/12 21:39:43 lha Exp $"); +#ifdef HAVE_DLFCN_H +#include +#endif +#include + +struct krb5_plugin { + void *symbol; + void *dsohandle; + struct krb5_plugin *next; +}; + +struct plugin { + enum plugin_type type; + void *name; + void *symbol; + struct plugin *next; +}; + +static HEIMDAL_MUTEX plugin_mutex = HEIMDAL_MUTEX_INITIALIZER; +static struct plugin *registered = NULL; + +static const char *plugin_dir = LIBDIR "/plugin/krb5"; + +/* + * + */ + +void * +_krb5_plugin_get_symbol(struct krb5_plugin *p) +{ + return p->symbol; +} + +struct krb5_plugin * +_krb5_plugin_get_next(struct krb5_plugin *p) +{ + return p->next; +} + +/* + * + */ + +static krb5_error_code +loadlib(krb5_context context, + enum plugin_type type, + const char *name, + const char *lib, + struct krb5_plugin **e) +{ + *e = calloc(1, sizeof(**e)); + if (*e == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + + (*e)->dsohandle = dlopen(lib, 0); + if ((*e)->dsohandle == NULL) { + free(*e); + krb5_set_error_string(context, "Failed to load %s: %s", + lib, dlerror()); + return ENOMEM; + } + + /* dlsym doesn't care about the type */ + (*e)->symbol = dlsym((*e)->dsohandle, name); + if ((*e)->symbol == NULL) { + dlclose((*e)->dsohandle); + free(*e); + krb5_clear_error_string(context); + return ENOMEM; + } + + return 0; +} + +krb5_error_code +_krb5_plugin_register(krb5_context context, + enum plugin_type type, + const char *name, + void *symbol) +{ + struct plugin *e; + + e = calloc(1, sizeof(*e)); + if (e == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + e->type = type; + e->name = strdup(name); + if (e->name == NULL) { + free(e); + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + e->symbol = symbol; + + HEIMDAL_MUTEX_lock(&plugin_mutex); + e->next = registered; + registered = e; + HEIMDAL_MUTEX_unlock(&plugin_mutex); + + return 0; +} + +krb5_error_code +_krb5_plugin_find(krb5_context context, + enum plugin_type type, + const char *name, + struct krb5_plugin **list) +{ + struct krb5_plugin *e; + struct plugin *p; + krb5_error_code ret; + char *sysdirs[2] = { NULL, NULL }; + char **dirs = NULL, **di; + struct dirent *entry; + char *path; + DIR *d = NULL; + + *list = NULL; + + HEIMDAL_MUTEX_lock(&plugin_mutex); + + for (p = registered; p != NULL; p = p->next) { + if (p->type != type || strcmp(p->name, name) != 0) + continue; + + e = calloc(1, sizeof(*e)); + if (e == NULL) { + HEIMDAL_MUTEX_unlock(&plugin_mutex); + krb5_set_error_string(context, "out of memory"); + ret = ENOMEM; + goto out; + } + e->symbol = p->symbol; + e->dsohandle = NULL; + e->next = *list; + *list = e; + } + HEIMDAL_MUTEX_unlock(&plugin_mutex); + + dirs = krb5_config_get_strings(context, NULL, "libdefaults", + "plugin_dir", NULL); + if (dirs == NULL) { + sysdirs[0] = rk_UNCONST(plugin_dir); + dirs = sysdirs; + } + + for (di = dirs; *di != NULL; di++) { + + d = opendir(*di); + if (d == NULL) + continue; + + while ((entry = readdir(d)) != NULL) { + asprintf(&path, "%s/%s", *di, entry->d_name); + if (path == NULL) { + krb5_set_error_string(context, "out of memory"); + ret = ENOMEM; + goto out; + } + ret = loadlib(context, type, name, path, &e); + free(path); + if (ret) + continue; + + e->next = *list; + *list = e; + } + closedir(d); + } + if (dirs != sysdirs) + krb5_config_free_strings(dirs); + + if (*list == NULL) { + krb5_set_error_string(context, "Did not find a plugin for %s", name); + return ENOENT; + } + + return 0; + +out: + if (dirs && dirs != sysdirs) + krb5_config_free_strings(dirs); + if (d) + closedir(d); + _krb5_plugin_free(*list); + *list = NULL; + + return ret; +} + +void +_krb5_plugin_free(struct krb5_plugin *list) +{ + struct krb5_plugin *next; + while (list) { + next = list->next; + if (list->dsohandle) + dlclose(list->dsohandle); + free(list); + list = next; + } +} + -- cgit