rewrite send to kdc to be more agressive, try kdcs in paralell and easier to configure behavior
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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;
|
||||
|
||||
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;
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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 */
|
||||
|
@@ -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
|
||||
|
@@ -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 *,
|
||||
|
@@ -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 {
|
||||
|
@@ -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;
|
||||
const krb5plugin_service_locate_ftable *locate = plug;
|
||||
struct plctx *plctx = userctx;
|
||||
|
||||
service = (krb5plugin_service_locate_ftable *)plug;
|
||||
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);
|
||||
|
||||
ret = service->lookup(plugctx, uc->type, uc->kd->realm, 0, 0,
|
||||
add_locate, uc->kd);
|
||||
if (ret && ret != KRB5_PLUGIN_NO_HANDLE) {
|
||||
if (plctx->flags & KRB5_PLF_ALLOW_HOMEDIR)
|
||||
return locate->old_lookup(plugctx, plctx->type, plctx->kd->realm, 0, 0, add_locate, plctx->kd);
|
||||
|
||||
} else if (ret) {
|
||||
_krb5_debug(context, 2, "plugin found result for realm %s", uc->kd->realm);
|
||||
uc->kd->flags |= KD_CONFIG_EXISTS;
|
||||
}
|
||||
return ret;
|
||||
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 */
|
||||
|
@@ -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 */
|
||||
|
@@ -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;
|
||||
|
@@ -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
@@ -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 */
|
||||
|
Reference in New Issue
Block a user