rewrite send to kdc to be more agressive, try kdcs in paralell and easier to configure behavior

This commit is contained in:
Love Hornquist Astrand
2013-02-10 19:02:52 -08:00
parent a952dc2c52
commit 58ff480763
17 changed files with 1550 additions and 740 deletions

View File

@@ -383,7 +383,7 @@ eval_kdestroy(heim_dict_t o)
*/
static void
eval_array_element(heim_object_t o, void *ptr)
eval_array_element(heim_object_t o, void *ptr, int *stop)
{
eval_object(o);
}

View File

@@ -255,8 +255,12 @@ void
heim_array_iterate_f(heim_array_t array, void *ctx, heim_array_iterator_f_t fn)
{
size_t n;
for (n = 0; n < array->len; n++)
fn(array->val[n], ctx);
int stop = 0;
for (n = 0; n < array->len; n++) {
fn(array->val[n], ctx, &stop);
if (stop)
return;
}
}
#ifdef __BLOCKS__
@@ -268,11 +272,15 @@ heim_array_iterate_f(heim_array_t array, void *ctx, heim_array_iterator_f_t fn)
*/
void
heim_array_iterate(heim_array_t array, void (^fn)(heim_object_t))
heim_array_iterate(heim_array_t array, void (^fn)(heim_object_t, int *))
{
size_t n;
for (n = 0; n < array->len; n++)
fn(array->val[n]);
int stop = 0;
for (n = 0; n < array->len; n++) {
fn(array->val[n], &stop);
if (stop)
return;
}
}
#endif
@@ -288,8 +296,13 @@ void
heim_array_iterate_reverse_f(heim_array_t array, void *ctx, heim_array_iterator_f_t fn)
{
size_t n;
for (n = array->len; n > 0; n--)
fn(array->val[n - 1], ctx);
int stop = 0;
for (n = array->len; n > 0; n--) {
fn(array->val[n - 1], ctx, &stop);
if (stop)
return;
}
}
#ifdef __BLOCKS__
@@ -301,11 +314,15 @@ heim_array_iterate_reverse_f(heim_array_t array, void *ctx, heim_array_iterator_
*/
void
heim_array_iterate_reverse(heim_array_t array, void (^fn)(heim_object_t))
heim_array_iterate_reverse(heim_array_t array, void (^fn)(heim_object_t, int *))
{
size_t n;
for (n = array->len; n > 0; n--)
fn(array->val[n - 1]);
int stop = 0;
for (n = array->len; n > 0; n--) {
fn(array->val[n - 1], &stop);
if (stop)
return;
}
}
#endif
@@ -414,12 +431,34 @@ heim_array_delete_value(heim_array_t array, size_t idx)
heim_release(obj);
}
#ifdef __BLOCKS__
/**
* Get value at idx
* Filter out entres of array when function return true
*
* @param array the array to modify
* @param idx the key to delete
* @param fn filter function
*/
void
heim_array_filter_f(heim_array_t array, void *ctx, heim_array_filter_f_t fn)
{
size_t n = 0;
while (n < array->len) {
if (fn(array->val[n], ctx)) {
heim_array_delete_value(array, n);
} else {
n++;
}
}
}
#ifdef __BLOCKS__
/**
* Filter out entres of array when block return true
*
* @param array the array to modify
* @param block filter block
*/
void

View File

@@ -41,6 +41,8 @@
#include <stdarg.h>
#include <stdbool.h>
#define HEIM_BASE_API_VERSION 20130210
typedef void * heim_object_t;
typedef unsigned int heim_tid_t;
typedef heim_object_t heim_bool_t;
@@ -121,15 +123,16 @@ 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 *);
typedef void (*heim_array_iterator_f_t)(heim_object_t, void *, int *);
typedef int (*heim_array_filter_f_t)(heim_object_t, void *);
int heim_array_append_value(heim_array_t, heim_object_t);
int heim_array_insert_value(heim_array_t, size_t idx, heim_object_t);
void heim_array_iterate_f(heim_array_t, void *, heim_array_iterator_f_t);
void heim_array_iterate_reverse_f(heim_array_t, void *, heim_array_iterator_f_t);
#ifdef __BLOCKS__
void heim_array_iterate(heim_array_t, void (^)(heim_object_t));
void heim_array_iterate_reverse(heim_array_t, void (^)(heim_object_t));
void heim_array_iterate(heim_array_t, void (^)(heim_object_t, int *));
void heim_array_iterate_reverse(heim_array_t, void (^)(heim_object_t, int *));
#endif
size_t heim_array_get_length(heim_array_t);
heim_object_t
@@ -138,6 +141,7 @@ heim_object_t
heim_array_copy_value(heim_array_t, size_t);
void heim_array_set_value(heim_array_t, size_t, heim_object_t);
void heim_array_delete_value(heim_array_t, size_t);
void heim_array_filter_f(heim_array_t, void *, heim_array_filter_f_t);
#ifdef __BLOCKS__
void heim_array_filter(heim_array_t, int (^)(heim_object_t));
#endif

View File

@@ -79,7 +79,7 @@ indent(struct twojson *j)
}
static void
array2json(heim_object_t value, void *ctx)
array2json(heim_object_t value, void *ctx, int *stop)
{
struct twojson *j = ctx;
if (j->ret)

View File

@@ -795,7 +795,7 @@ struct test_array_iter_ctx {
char buf[256];
};
static void test_array_iter(heim_object_t elt, void *arg)
static void test_array_iter(heim_object_t elt, void *arg, int *stop)
{
struct test_array_iter_ctx *iter_ctx = arg;

View File

@@ -178,23 +178,9 @@ _gsskrb5_set_sec_context_option
} else if (gss_oid_equal(desired_object, GSS_KRB5_SEND_TO_KDC_X)) {
if (value == NULL || value->length == 0) {
krb5_set_send_to_kdc_func(context, NULL, NULL);
} else {
struct gsskrb5_send_to_kdc c;
*minor_status = EINVAL;
return GSS_S_FAILURE;
if (value->length != sizeof(c)) {
*minor_status = EINVAL;
return GSS_S_FAILURE;
}
memcpy(&c, value->value, sizeof(c));
krb5_set_send_to_kdc_func(context,
(krb5_send_to_kdc_func)c.func,
c.ptr);
}
*minor_status = 0;
return GSS_S_COMPLETE;
} else if (gss_oid_equal(desired_object, GSS_KRB5_CCACHE_NAME_X)) {
char *str;

View File

@@ -100,7 +100,8 @@ init_context_from_config_file(krb5_context context)
krb5_enctype *tmptypes;
INIT_FIELD(context, time, max_skew, 5 * 60, "clockskew");
INIT_FIELD(context, time, kdc_timeout, 3, "kdc_timeout");
INIT_FIELD(context, time, kdc_timeout, 30, "kdc_timeout");
INIT_FIELD(context, time, host_timeout, 3, "host_timeout");
INIT_FIELD(context, int, max_retries, 3, "max_retries");
INIT_FIELD(context, string, http_proxy, NULL, "http_proxy");
@@ -220,6 +221,7 @@ init_context_from_config_file(krb5_context context)
INIT_FIELD(context, bool, srv_lookup, TRUE, "srv_lookup");
INIT_FIELD(context, bool, srv_lookup, context->srv_lookup, "dns_lookup_kdc");
INIT_FIELD(context, int, large_msg_size, 1400, "large_message_size");
INIT_FIELD(context, int, max_msg_size, 1000 * 1024, "maximum_message_size");
INIT_FLAG(context, flags, KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME, TRUE, "dns_canonicalize_hostname");
INIT_FLAG(context, flags, KRB5_CTX_F_CHECK_PAC, TRUE, "check_pac");
context->default_cc_name = NULL;

View File

@@ -648,4 +648,97 @@ krb5_have_error_string(krb5_context context)
return str != NULL;
}
struct send_to_kdc {
krb5_send_to_kdc_func func;
void *data;
};
/*
* Send the data `send' to one host from `handle` and get back the reply
* in `receive'.
*/
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_sendto (krb5_context context,
const krb5_data *send_data,
krb5_krbhst_handle handle,
krb5_data *receive)
{
krb5_error_code ret;
krb5_sendto_ctx ctx;
ret = krb5_sendto_ctx_alloc(context, &ctx);
if (ret)
return ret;
_krb5_sendto_ctx_set_krb5hst(context, ctx, handle);
ret = krb5_sendto_context(context, ctx, send_data, (char *)_krb5_krbhst_get_realm(handle), receive);
krb5_sendto_ctx_free(context, ctx);
return ret;
}
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_sendto_kdc(krb5_context context,
const krb5_data *send_data,
const krb5_realm *realm,
krb5_data *receive)
{
return krb5_sendto_kdc_flags(context, send_data, realm, receive, 0);
}
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_sendto_kdc_flags(krb5_context context,
const krb5_data *send_data,
const krb5_realm *realm,
krb5_data *receive,
int flags)
{
krb5_error_code ret;
krb5_sendto_ctx ctx;
ret = krb5_sendto_ctx_alloc(context, &ctx);
if (ret)
return ret;
krb5_sendto_ctx_add_flags(ctx, flags);
krb5_sendto_ctx_set_func(ctx, _krb5_kdc_retry, NULL);
ret = krb5_sendto_context(context, ctx, send_data, *realm, receive);
krb5_sendto_ctx_free(context, ctx);
return ret;
}
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_set_send_to_kdc_func(krb5_context context,
krb5_send_to_kdc_func func,
void *data)
{
free(context->send_to_kdc);
if (func == NULL) {
context->send_to_kdc = NULL;
return 0;
}
context->send_to_kdc = malloc(sizeof(*context->send_to_kdc));
if (context->send_to_kdc == NULL) {
krb5_set_error_message(context, ENOMEM,
N_("malloc: out of memory", ""));
return ENOMEM;
}
context->send_to_kdc->func = func;
context->send_to_kdc->data = data;
return 0;
}
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
_krb5_copy_send_to_kdc_func(krb5_context context, krb5_context to)
{
if (context->send_to_kdc)
return krb5_set_send_to_kdc_func(to,
context->send_to_kdc->func,
context->send_to_kdc->data);
else
return krb5_set_send_to_kdc_func(to, NULL, NULL);
}
#endif /* HEIMDAL_SMALLER */

View File

@@ -44,4 +44,9 @@ error_code NONAME, "nodename nor servname provided, or not known"
error_code SERVICE, "servname not supported for ai_socktype"
error_code SOCKTYPE, "ai_socktype not supported"
error_code SYSTEM, "system error returned in errno"
index 192
prefix HEIM_NET
error_code CONN_REFUSED, "connection refused"
end

View File

@@ -689,6 +689,13 @@ typedef EncAPRepPart krb5_ap_rep_enc_part;
#define KRB5_WELLKNOWN_ORG_H5L_REALM ("WELLKNOWN:ORG.H5L")
#define KRB5_DIGEST_NAME ("digest")
#define KRB5_PKU2U_REALM_NAME ("WELLKNOWN:PKU2U")
#define KRB5_LKDC_REALM_NAME ("WELLKNOWN:COM.APPLE.LKDC")
#define KRB5_GSS_HOSTBASED_SERVICE_NAME ("WELLKNOWN:ORG.H5L.HOSTBASED-SERVICE")
#define KRB5_GSS_REFERALS_REALM_NAME ("WELLKNOWN:ORG.H5L.REFERALS-REALM")
typedef enum {
KRB5_PROMPT_TYPE_PASSWORD = 0x1,
KRB5_PROMPT_TYPE_NEW_PASSWORD = 0x2,
@@ -822,6 +829,7 @@ enum {
KRB5_KRBHST_FLAGS_LARGE_MSG = 2
};
typedef krb5_error_code (*krb5_sendto_prexmit)(krb5_context, int, void *, int, krb5_data *);
typedef krb5_error_code
(KRB5_CALLCONV * krb5_send_to_kdc_func)(krb5_context, void *, krb5_krbhst_info *, time_t,
const krb5_data *, krb5_data *);
@@ -843,8 +851,13 @@ enum {
typedef struct krb5_sendto_ctx_data *krb5_sendto_ctx;
#define KRB5_SENDTO_DONE 0
#define KRB5_SENDTO_RESTART 1
#define KRB5_SENDTO_RESET 1
#define KRB5_SENDTO_CONTINUE 2
#define KRB5_SENDTO_TIMEOUT 3
#define KRB5_SENDTO_INITIAL 4
#define KRB5_SENDTO_FILTER 5
#define KRB5_SENDTO_FAILED 6
#define KRB5_SENDTO_KRBHST 7
typedef krb5_error_code
(KRB5_CALLCONV * krb5_sendto_ctx_func)(krb5_context, krb5_sendto_ctx, void *,

View File

@@ -261,6 +261,7 @@ typedef struct krb5_context_data {
char **default_realms;
time_t max_skew;
time_t kdc_timeout;
time_t host_timeout;
unsigned max_retries;
int32_t kdc_sec_offset;
int32_t kdc_usec_offset;
@@ -293,6 +294,8 @@ typedef struct krb5_context_data {
int default_cc_name_set;
void *mutex; /* protects error_string */
int large_msg_size;
int max_msg_size;
int tgs_negative_timeout; /* timeout for TGS negative cache */
int flags;
#define KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME 1
#define KRB5_CTX_F_CHECK_PAC 2
@@ -303,6 +306,7 @@ typedef struct krb5_context_data {
#ifdef PKINIT
hx509_context hx509ctx;
#endif
unsigned int num_kdc_requests;
} krb5_context_data;
#ifndef KRB5_USE_PATH_TOKENS
@@ -340,6 +344,14 @@ typedef struct krb5_context_data {
#define KRB5_FORWARDABLE_DEFAULT TRUE
#endif
#ifndef KRB5_CONFIGURATION_CHANGE_NOTIFY_NAME
#define KRB5_CONFIGURATION_CHANGE_NOTIFY_NAME "org.h5l.Kerberos.configuration-changed"
#endif
#ifndef KRB5_FALLBACK_DEFAULT
#define KRB5_FALLBACK_DEFAULT TRUE
#endif
#ifdef PKINIT
struct krb5_pk_identity {

View File

@@ -3,6 +3,8 @@
* (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:
@@ -153,9 +155,11 @@ struct krb5_krbhst_data {
#define KD_CONFIG_EXISTS 32
#define KD_LARGE_MSG 64
#define KD_PLUGIN 128
#define KD_HOSTNAMES 256
krb5_error_code (*get_next)(krb5_context, struct krb5_krbhst_data *,
krb5_krbhst_info**);
char *hostname;
unsigned int fallback_count;
struct krb5_krbhst_info *hosts, **index, **end;
@@ -179,6 +183,12 @@ krbhst_get_default_proto(struct krb5_krbhst_data *kd)
return KRB5_KRBHST_UDP;
}
static int
krbhst_get_default_port(struct krb5_krbhst_data *kd)
{
return kd->def_port;
}
/*
*
*/
@@ -218,6 +228,7 @@ parse_hostspec(krb5_context context, struct krb5_krbhst_data *kd,
hi->proto = KRB5_KRBHST_TCP;
p += 4;
} else if(strncmp(p, "udp/", 4) == 0) {
hi->proto = KRB5_KRBHST_UDP;
p += 4;
}
@@ -438,6 +449,9 @@ srv_get_hosts(krb5_context context, struct krb5_krbhst_data *kd,
krb5_krbhst_info **res;
int count, i;
if (krb5_realm_is_lkdc(kd->realm))
return;
ret = srv_find_realm(context, &res, &count, kd->realm, "SRV", proto, service,
kd->port);
_krb5_debug(context, 2, "searching DNS for realm %s %s.%s -> %d",
@@ -492,14 +506,23 @@ fallback_get_hosts(krb5_context context, struct krb5_krbhst_data *kd,
struct addrinfo hints;
char portstr[NI_MAXSERV];
ret = krb5_config_get_bool_default(context, NULL, KRB5_FALLBACK_DEFAULT,
"libdefaults", "use_fallback", NULL);
if (!ret) {
kd->flags |= KD_FALLBACK;
return 0;
}
_krb5_debug(context, 2, "fallback lookup %d for realm %s (service %s)",
kd->fallback_count, kd->realm, serv_string);
/*
* Don't try forever in case the DNS server keep returning us
* entries (like wildcard entries or the .nu TLD)
*
* Also don't try LKDC realms since fallback wont work on them at all.
*/
if(kd->fallback_count >= 5) {
if(kd->fallback_count >= 5 || krb5_realm_is_lkdc(kd->realm)) {
kd->flags |= KD_FALLBACK;
return 0;
}
@@ -547,24 +570,18 @@ fallback_get_hosts(krb5_context context, struct krb5_krbhst_data *kd,
*/
static krb5_error_code
add_locate(void *ctx, int type, struct sockaddr *addr)
add_plugin_host(struct krb5_krbhst_data *kd,
const char *host,
const char *port,
int portnum,
int proto)
{
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;
make_hints(&hints, krbhst_get_default_proto(kd));
make_hints(&hints, proto);
ret = getaddrinfo(host, port, &hints, &ai);
if (ret)
return 0;
@@ -575,8 +592,8 @@ add_locate(void *ctx, int type, struct sockaddr *addr)
if(hi == NULL)
return ENOMEM;
hi->proto = krbhst_get_default_proto(kd);
hi->port = hi->def_port = socket_get_port(addr);
hi->proto = proto;
hi->port = hi->def_port = portnum;
hi->ai = ai;
memmove(hi->hostname, host, hostlen);
hi->hostname[hostlen] = '\0';
@@ -585,29 +602,71 @@ add_locate(void *ctx, int type, struct sockaddr *addr)
return 0;
}
struct ghcontext {
struct krb5_krbhst_data *kd;
static krb5_error_code
add_locate(void *ctx, int type, struct sockaddr *addr)
{
struct krb5_krbhst_data *kd = ctx;
char host[NI_MAXHOST], port[NI_MAXSERV];
socklen_t socklen;
krb5_error_code ret;
int proto, portnum;
socklen = socket_sockaddr_size(addr);
portnum = socket_get_port(addr);
ret = getnameinfo(addr, socklen, host, sizeof(host), port, sizeof(port),
NI_NUMERICHOST|NI_NUMERICSERV);
if (ret != 0)
return 0;
if (kd->port)
snprintf(port, sizeof(port), "%d", kd->port);
else if (atoi(port) == 0)
snprintf(port, sizeof(port), "%d", krbhst_get_default_port(kd));
proto = krbhst_get_default_proto(kd);
ret = add_plugin_host(kd, host, port, portnum, proto);
if (ret)
return ret;
/*
* This is really kind of broken and should be solved a different
* way, some sites block UDP, and we don't, in the general case,
* fall back to TCP, that should also be done. But since that
* should require us to invert the whole "find kdc" stack, let put
* this in for now.
*/
if (proto == KRB5_KRBHST_UDP) {
ret = add_plugin_host(kd, host, port, portnum, KRB5_KRBHST_TCP);
if (ret)
return ret;
}
return 0;
}
struct plctx {
enum locate_service_type type;
struct krb5_krbhst_data *kd;
unsigned long flags;
};
static krb5_error_code KRB5_LIB_CALL
ghcallback(krb5_context context, const void *plug, void *plugctx, void *userctx)
static krb5_error_code
plcallback(krb5_context context,
const void *plug, void *plugctx, void *userctx)
{
krb5plugin_service_locate_ftable *service;
struct ghcontext *uc = userctx;
krb5_error_code ret;
service = (krb5plugin_service_locate_ftable *)plug;
const krb5plugin_service_locate_ftable *locate = plug;
struct plctx *plctx = userctx;
ret = service->lookup(plugctx, uc->type, uc->kd->realm, 0, 0,
add_locate, uc->kd);
if (ret && ret != KRB5_PLUGIN_NO_HANDLE) {
} else if (ret) {
_krb5_debug(context, 2, "plugin found result for realm %s", uc->kd->realm);
uc->kd->flags |= KD_CONFIG_EXISTS;
}
return ret;
if (locate->minor_version >= KRB5_PLUGIN_LOCATE_VERSION_2)
return locate->lookup(plugctx, plctx->flags, plctx->type, plctx->kd->realm, 0, 0, add_locate, plctx->kd);
if (plctx->flags & KRB5_PLF_ALLOW_HOMEDIR)
return locate->old_lookup(plugctx, plctx->type, plctx->kd->realm, 0, 0, add_locate, plctx->kd);
return KRB5_PLUGIN_NO_HANDLE;
}
static void
@@ -615,15 +674,31 @@ plugin_get_hosts(krb5_context context,
struct krb5_krbhst_data *kd,
enum locate_service_type type)
{
struct ghcontext userctx;
struct plctx ctx = { type, kd, 0 };
userctx.kd = kd;
userctx.type = type;
if (_krb5_homedir_access(context))
ctx.flags |= KRB5_PLF_ALLOW_HOMEDIR;
(void)_krb5_plugin_run_f(context, "krb5", KRB5_PLUGIN_LOCATE,
0, 0, &userctx, ghcallback);
_krb5_plugin_run_f(context, "krb5", KRB5_PLUGIN_LOCATE,
KRB5_PLUGIN_LOCATE_VERSION_0,
0, &ctx, plcallback);
}
/*
*
*/
static void
hostnames_get_hosts(krb5_context context,
struct krb5_krbhst_data *kd,
const char *type)
{
kd->flags |= KD_HOSTNAMES;
if (kd->hostname)
append_host_string(context, kd, kd->hostname, kd->def_port, kd->port);
}
/*
*
*/
@@ -635,6 +710,12 @@ kdc_get_next(krb5_context context,
{
krb5_error_code ret;
if ((kd->flags & KD_HOSTNAMES) == 0) {
hostnames_get_hosts(context, kd, "kdc");
if(get_next(kd, host))
return 0;
}
if ((kd->flags & KD_PLUGIN) == 0) {
plugin_get_hosts(context, kd, locate_service_kdc);
kd->flags |= KD_PLUGIN;
@@ -807,60 +888,20 @@ kpasswd_get_next(krb5_context context,
return KRB5_KDC_UNREACH;
}
static krb5_error_code
krb524_get_next(krb5_context context,
struct krb5_krbhst_data *kd,
krb5_krbhst_info **host)
static void
krbhost_dealloc(void *ptr)
{
if ((kd->flags & KD_PLUGIN) == 0) {
plugin_get_hosts(context, kd, locate_service_krb524);
kd->flags |= KD_PLUGIN;
if(get_next(kd, host))
return 0;
struct krb5_krbhst_data *handle = (struct krb5_krbhst_data *)ptr;
krb5_krbhst_info *h, *next;
for (h = handle->hosts; h != NULL; h = next) {
next = h->next;
_krb5_free_krbhst_info(h);
}
if (handle->hostname)
free(handle->hostname);
if((kd->flags & KD_CONFIG) == 0) {
config_get_hosts(context, kd, "krb524_server");
if(get_next(kd, host))
return 0;
kd->flags |= KD_CONFIG;
}
if (kd->flags & KD_CONFIG_EXISTS) {
_krb5_debug(context, 1,
"Configuration exists for realm %s, wont go to DNS",
kd->realm);
return KRB5_KDC_UNREACH;
}
if(context->srv_lookup) {
if((kd->flags & KD_SRV_UDP) == 0) {
srv_get_hosts(context, kd, "udp", "krb524");
kd->flags |= KD_SRV_UDP;
if(get_next(kd, host))
return 0;
}
if((kd->flags & KD_SRV_TCP) == 0) {
srv_get_hosts(context, kd, "tcp", "krb524");
kd->flags |= KD_SRV_TCP;
if(get_next(kd, host))
return 0;
}
}
/* no matches -> try kdc */
if (krbhst_empty(kd)) {
kd->flags = 0;
kd->port = kd->def_port;
kd->get_next = kdc_get_next;
return (*kd->get_next)(context, kd, host);
}
_krb5_debug(context, 0, "No kpasswd entries found for realm %s", kd->realm);
return KRB5_KDC_UNREACH;
free(handle->realm);
}
static struct krb5_krbhst_data*
@@ -871,11 +912,11 @@ common_init(krb5_context context,
{
struct krb5_krbhst_data *kd;
if((kd = calloc(1, sizeof(*kd))) == NULL)
if ((kd = heim_alloc(sizeof(*kd), "krbhst-context", krbhost_dealloc)) == NULL)
return NULL;
if((kd->realm = strdup(realm)) == NULL) {
free(kd);
heim_release(kd);
return NULL;
}
@@ -918,6 +959,8 @@ krb5_krbhst_init_flags(krb5_context context,
int def_port;
const char *service;
*handle = NULL;
switch(type) {
case KRB5_KRBHST_KDC:
next = kdc_get_next;
@@ -936,11 +979,6 @@ krb5_krbhst_init_flags(krb5_context context,
KPASSWD_PORT));
service = "change_password";
break;
case KRB5_KRBHST_KRB524:
next = krb524_get_next;
def_port = ntohs(krb5_getportbyname (context, "krb524", "udp", 4444));
service = "524";
break;
default:
krb5_set_error_message(context, ENOTTY,
N_("unknown krbhst type (%u)", ""), type);
@@ -988,6 +1026,22 @@ krb5_krbhst_next_as_string(krb5_context context,
return krb5_krbhst_format_string(context, host, hostname, hostlen);
}
/*
*
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_krbhst_set_hostname(krb5_context context,
krb5_krbhst_handle handle,
const char *hostname)
{
if (handle->hostname)
free(handle->hostname);
handle->hostname = strdup(hostname);
if (handle->hostname == NULL)
return ENOMEM;
return 0;
}
KRB5_LIB_FUNCTION void KRB5_LIB_CALL
krb5_krbhst_reset(krb5_context context, krb5_krbhst_handle handle)
@@ -998,20 +1052,11 @@ krb5_krbhst_reset(krb5_context context, krb5_krbhst_handle handle)
KRB5_LIB_FUNCTION void KRB5_LIB_CALL
krb5_krbhst_free(krb5_context context, krb5_krbhst_handle handle)
{
krb5_krbhst_info *h, *next;
if (handle == NULL)
return;
for (h = handle->hosts; h != NULL; h = next) {
next = h->next;
_krb5_free_krbhst_info(h);
}
free(handle->realm);
free(handle);
heim_release(handle);
}
#ifndef HEIMDAL_SMALLER
/* backwards compatibility ahead */
static krb5_error_code
@@ -1092,7 +1137,6 @@ krb5_get_krb524hst (krb5_context context,
return gethostlist(context, *realm, KRB5_KRBHST_KRB524, hostlist);
}
/*
* return an malloced list of KDC's for `realm' in `hostlist'
*/
@@ -1120,3 +1164,5 @@ krb5_free_krbhst (krb5_context context,
free (hostlist);
return 0;
}
#endif /* HEIMDAL_SMALLER */

View File

@@ -3,6 +3,8 @@
* (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:
@@ -37,6 +39,10 @@
#define HEIMDAL_KRB5_LOCATE_PLUGIN_H 1
#define KRB5_PLUGIN_LOCATE "service_locator"
#define KRB5_PLUGIN_LOCATE_VERSION 1
#define KRB5_PLUGIN_LOCATE_VERSION_0 0
#define KRB5_PLUGIN_LOCATE_VERSION_1 1
#define KRB5_PLUGIN_LOCATE_VERSION_2 2
enum locate_service_type {
locate_service_kdc = 1,
@@ -47,7 +53,15 @@ enum locate_service_type {
};
typedef krb5_error_code
(*krb5plugin_service_locate_lookup) (void *, enum locate_service_type,
(*krb5plugin_service_locate_lookup) (void *, unsigned long, enum locate_service_type,
const char *, int, int,
int (*)(void *,int,struct sockaddr *),
void *);
#define KRB5_PLF_ALLOW_HOMEDIR 1
typedef krb5_error_code
(*krb5plugin_service_locate_lookup_old) (void *, enum locate_service_type,
const char *, int, int,
int (*)(void *,int,struct sockaddr *),
void *);
@@ -57,7 +71,8 @@ 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_lookup_old old_lookup;
krb5plugin_service_locate_lookup lookup; /* version 2 */
} krb5plugin_service_locate_ftable;
#endif /* HEIMDAL_KRB5_LOCATE_PLUGIN_H */

View File

@@ -589,7 +589,7 @@ search_modules(heim_object_t key, heim_object_t value, void *ctx)
}
static void
eval_results(heim_object_t value, void *ctx)
eval_results(heim_object_t value, void *ctx, int *stop)
{
struct plug *pl = value;
struct iter_ctx *s = ctx;

View File

@@ -1126,6 +1126,64 @@ krb5_parse_nametype(krb5_context context, const char *str, int32_t *nametype)
return KRB5_PARSE_MALFORMED;
}
/**
* Returns true if name is Kerberos NULL name
*
* @ingroup krb5_principal
*/
krb5_boolean KRB5_LIB_FUNCTION
krb5_principal_is_null(krb5_context context, krb5_const_principal principal)
{
if (principal->name.name_type == KRB5_NT_WELLKNOWN &&
principal->name.name_string.len == 2 &&
strcmp(principal->name.name_string.val[0], "WELLKNOWN") == 0 &&
strcmp(principal->name.name_string.val[1], "NULL") == 0)
return TRUE;
return FALSE;
}
const char _krb5_wellknown_lkdc[] = "WELLKNOWN:COM.APPLE.LKDC";
static const char lkdc_prefix[] = "LKDC:";
/**
* Returns true if name is Kerberos an LKDC realm
*
* @ingroup krb5_principal
*/
krb5_boolean KRB5_LIB_FUNCTION
krb5_realm_is_lkdc(const char *realm)
{
return strncmp(realm, lkdc_prefix, sizeof(lkdc_prefix)-1) == 0 ||
strncmp(realm, _krb5_wellknown_lkdc, sizeof(_krb5_wellknown_lkdc) - 1) == 0;
}
/**
* Returns true if name is Kerberos an LKDC realm
*
* @ingroup krb5_principal
*/
krb5_boolean KRB5_LIB_FUNCTION
krb5_principal_is_lkdc(krb5_context context, krb5_const_principal principal)
{
return krb5_realm_is_lkdc(principal->realm);
}
/**
* Returns true if name is Kerberos an LKDC realm
*
* @ingroup krb5_principal
*/
krb5_boolean KRB5_LIB_FUNCTION
krb5_principal_is_pku2u(krb5_context context, krb5_const_principal principal)
{
return strcmp(principal->realm, KRB5_PKU2U_REALM_NAME) == 0;
}
/**
* Check if the cname part of the principal is a krbtgt principal
*

File diff suppressed because it is too large Load Diff

View File

@@ -40,6 +40,10 @@
#define KRB5_PLUGIN_SEND_TO_KDC "send_to_kdc"
#define KRB5_PLUGIN_SEND_TO_KDC_VERSION_0 0
#define KRB5_PLUGIN_SEND_TO_KDC_VERSION_2 2
#define KRB5_PLUGIN_SEND_TO_KDC_VERSION KRB5_PLUGIN_SEND_TO_KDC_VERSION_2
typedef krb5_error_code
(*krb5plugin_send_to_kdc_func)(krb5_context,
void *,
@@ -47,12 +51,21 @@ typedef krb5_error_code
time_t timeout,
const krb5_data *,
krb5_data *);
typedef krb5_error_code
(*krb5plugin_send_to_realm_func)(krb5_context,
void *,
krb5_const_realm,
time_t timeout,
const krb5_data *,
krb5_data *);
typedef struct krb5plugin_send_to_kdc_ftable {
int minor_version;
krb5_error_code (*init)(krb5_context, void **);
void (*fini)(void *);
krb5plugin_send_to_kdc_func send_to_kdc;
krb5plugin_send_to_realm_func send_to_realm; /* added in version 2 */
} krb5plugin_send_to_kdc_ftable;
#endif /* HEIMDAL_KRB5_SEND_TO_KDC_PLUGIN_H */