summaryrefslogtreecommitdiffstats
path: root/src/lib
diff options
context:
space:
mode:
authorKen Raeburn <raeburn@mit.edu>2006-03-07 20:45:24 +0000
committerKen Raeburn <raeburn@mit.edu>2006-03-07 20:45:24 +0000
commit8f09bfe9fa0e51c2bd1e2f533eb25655e88ca43b (patch)
tree68c4097fc6650d9d2952fdc0b242263b60ae7f95 /src/lib
parentca39d95f3cb9681664d3761f4c0c2ec23d36dfd3 (diff)
downloadkrb5-8f09bfe9fa0e51c2bd1e2f533eb25655e88ca43b.tar.gz
krb5-8f09bfe9fa0e51c2bd1e2f533eb25655e88ca43b.tar.xz
krb5-8f09bfe9fa0e51c2bd1e2f533eb25655e88ca43b.zip
Merge from plugin branch
Add plugin support: - plugin routines in support library (may break windows build!) - plugin support in KDC location code - sample Python-based plugin for KDC location, not built without tweaking sources - changed service location interface to use an enum instead of passing profile string and DNS strings and port numbers - changed pathnames for plugin locations, including kdb back end - remove locate_service from accessor API Also, do build shared libraries for Darwin just like any other UNIX box. Not present yet: - use new plugin interface for kdb back end - Windows support - Mac bundle support (but dlopen support works) - search path for libkrb5 plugins (only one hard-coded directory for now) - sorting of plugin collections for predictable ordering See the various ChangeLogs for specifics. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@17706 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/krb5/error_tables/ChangeLog4
-rw-r--r--src/lib/krb5/error_tables/krb5_err.et2
-rw-r--r--src/lib/krb5/os/ChangeLog49
-rw-r--r--src/lib/krb5/os/Makefile.in21
-rw-r--r--src/lib/krb5/os/accessor.c1
-rw-r--r--src/lib/krb5/os/changepw.c19
-rw-r--r--src/lib/krb5/os/init_os_ctx.c5
-rw-r--r--src/lib/krb5/os/locate_kdc.c397
-rw-r--r--src/lib/krb5/os/send524.c12
-rw-r--r--src/lib/krb5/os/sendto_kdc.c99
-rw-r--r--src/lib/krb5/os/t_locate_kdc.c8
-rw-r--r--src/lib/krb5/os/t_std_conf.c2
12 files changed, 442 insertions, 177 deletions
diff --git a/src/lib/krb5/error_tables/ChangeLog b/src/lib/krb5/error_tables/ChangeLog
index bb59895bfc..e84f292d35 100644
--- a/src/lib/krb5/error_tables/ChangeLog
+++ b/src/lib/krb5/error_tables/ChangeLog
@@ -1,3 +1,7 @@
+2006-03-06 Ken Raeburn <raeburn@mit.edu>
+
+ * krb5_err.et (KRB5_PLUGIN_NO_HANDLE): New error code.
+
2006-01-27 Sam Hartman <hartmans@mit.edu>
* kdb5_err.et: New error codes for plugin errors
diff --git a/src/lib/krb5/error_tables/krb5_err.et b/src/lib/krb5/error_tables/krb5_err.et
index 1f2bfca53c..865c838a62 100644
--- a/src/lib/krb5/error_tables/krb5_err.et
+++ b/src/lib/krb5/error_tables/krb5_err.et
@@ -342,4 +342,6 @@ error_code KRB5_CC_READONLY, "Ccache function not supported: read-only ccache
error_code KRB5_CC_NOSUPP, "Ccache function not supported: not implemented"
error_code KRB5_DELTAT_BADFORMAT, "Invalid format of Kerberos lifetime or clock skew string"
+
+error_code KRB5_PLUGIN_NO_HANDLE, "Supplied data not handled by this plugin"
end
diff --git a/src/lib/krb5/os/ChangeLog b/src/lib/krb5/os/ChangeLog
index d9bda00a64..889a8f314b 100644
--- a/src/lib/krb5/os/ChangeLog
+++ b/src/lib/krb5/os/ChangeLog
@@ -1,3 +1,52 @@
+2006-03-06 Ken Raeburn <raeburn@mit.edu>
+
+ * Makefile.in (DEFINES): New variable.
+ (t_locate_kdc.o): Depend on dnssrv.c and dnsglue.c too.
+
+ * init_os_ctx.c (krb5_os_init_context): Initialize new fields.
+ (krb5_os_free_context): Close opened plugin files.
+
+ * locate_kdc.c: Include k5-plugin.h.
+ (get_port): Deleted.
+ (grow_addrlist): Update for new fields in structure.
+ (krb5int_free_addrlist): Call the free function in the structure,
+ if the function pointer is non-null.
+ (add_addrinfo_to_list): Update for new fields. Shorten up debug
+ output.
+ (call_freeaddrinfo): New function.
+ (krb5int_add_host_to_list): Update for new fields.
+ (prof_locate_server, dns_locate_server): New functions, broken out
+ from krb5int_locate_server; use the new enum type for service
+ choice.
+ (objdir): New variable.
+ (struct module_callback_data): New struct.
+ (module_callback, module_locate_server): New functions.
+ (krb5int_locate_server): Use the above method-specific locator
+ functions. Change argument list to take enum and not multiple
+ strings and numbers.
+ (krb5_locate_kdc): Updated for new interface.
+
+ * send524.c (krb5int_524_sendto_kdc): Update for new locate_server
+ interface.
+ * changepw.c (krb5_locate_kpasswd): Likewise.
+ (krb5_change_set_password): Update for new fields.
+
+ * accessor.c (krb5int_accessor): Don't fill in locate_server
+ field.
+
+ * t_locate_kdc.c: Include dnsglue.c and dnssrv.c.
+ (print_addrs): Update for new fields.
+ * t_std_conf.c (test_locate_kdc): Update for new fields.
+
+ * sendto_kdc.c (krb5int_debug_fprint): No longer static. Print
+ more info.
+ (krb5int_print_addrlist): New function.
+ (merge_addrlists): Update for new fields.
+ (in_addrlist): New function.
+ (krb5_sendto_kdc): Use it. Update for new fields.
+ (krb5int_sendto): Update for new fields. Print more info when
+ debugging.
+
2006-02-24 Jeffrey Altman <jaltman@mit.edu>
* gmt_mktime.c, read_pwd.c: changes to support 64-bit builds
diff --git a/src/lib/krb5/os/Makefile.in b/src/lib/krb5/os/Makefile.in
index 49690e41fb..b58d40c1f9 100644
--- a/src/lib/krb5/os/Makefile.in
+++ b/src/lib/krb5/os/Makefile.in
@@ -6,6 +6,8 @@ KRB5_RUN_ENV = @KRB5_RUN_ENV@
PROG_LIBPATH=-L$(TOPLIBD)
PROG_RPATH=$(KRB5_LIBDIR)
+DEFINES=-DLIBDIR=\"$(KRB5_LIBDIR)\"
+
##DOS##BUILDTOP = ..\..\..
##DOS##PREFIXDIR=os
##DOS##OBJFILE=..\$(OUTPRE)$(PREFIXDIR).lst
@@ -163,7 +165,7 @@ shared:
TEST_PROGS= t_std_conf t_an_to_ln t_locate_kdc
T_STD_CONF_OBJS= t_std_conf.o def_realm.o get_krbhst.o realm_dom.o \
- hst_realm.o init_os_ctx.o locate_kdc.o dnsglue.o
+ hst_realm.o init_os_ctx.o locate_kdc.o dnsglue.o
T_AN_TO_LN_OBJS = t_an_to_ln.o an_to_ln.o
@@ -187,9 +189,8 @@ t_localaddr: localaddr.c
t_locate_kdc: t_locate_kdc.o
$(CC_LINK) $(ALL_CFLAGS) -o t_locate_kdc t_locate_kdc.o \
$(KRB5_BASE_LIBS)
-t_locate_kdc.o: t_locate_kdc.c locate_kdc.c
+t_locate_kdc.o: t_locate_kdc.c locate_kdc.c dnssrv.c dnsglue.c
$(OUTPRE)t_locate_kdc.exe: $(OUTPRE)t_locate_kdc.obj \
- $(OUTPRE)dnssrv.obj $(OUTPRE)dnsglue.obj \
$(KLIB) $(PLIB) $(CLIB) $(SLIB)
link $(EXE_LINKOPTS) -out:$@ $** ws2_32.lib $(DNSLIBS)
@@ -415,7 +416,7 @@ locate_kdc.so locate_kdc.po $(OUTPRE)locate_kdc.$(OBJEXT): \
$(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
$(SRCTOP)/include/k5-int.h $(BUILDTOP)/include/krb5/osconf.h \
$(BUILDTOP)/include/krb5.h $(COM_ERR_DEPS) $(BUILDTOP)/include/profile.h \
- $(SRCTOP)/include/krb5/kdb.h os-proto.h
+ $(SRCTOP)/include/krb5/kdb.h os-proto.h $(SRCTOP)/include/k5-plugin.h
lock_file.so lock_file.po $(OUTPRE)lock_file.$(OBJEXT): \
lock_file.c $(SRCTOP)/include/k5-int.h $(BUILDTOP)/include/krb5/osconf.h \
$(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/k5-platform.h \
@@ -540,12 +541,12 @@ t_gifconf.so t_gifconf.po $(OUTPRE)t_gifconf.$(OBJEXT): \
t_gifconf.c
t_locate_kdc.so t_locate_kdc.po $(OUTPRE)t_locate_kdc.$(OBJEXT): \
t_locate_kdc.c $(SRCTOP)/include/port-sockets.h $(BUILDTOP)/include/krb5/autoconf.h \
- $(COM_ERR_DEPS) locate_kdc.c $(SRCTOP)/include/fake-addrinfo.h \
- $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/k5-platform.h \
- $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/k5-int.h \
- $(BUILDTOP)/include/krb5/osconf.h $(BUILDTOP)/include/krb5.h \
- $(BUILDTOP)/include/profile.h $(SRCTOP)/include/krb5/kdb.h \
- os-proto.h
+ $(COM_ERR_DEPS) dnsglue.c dnsglue.h $(SRCTOP)/include/k5-int.h \
+ $(BUILDTOP)/include/krb5/osconf.h $(SRCTOP)/include/k5-platform.h \
+ $(SRCTOP)/include/k5-thread.h $(BUILDTOP)/include/krb5.h \
+ $(BUILDTOP)/include/profile.h $(SRCTOP)/include/socket-utils.h \
+ $(SRCTOP)/include/krb5/kdb.h os-proto.h dnssrv.c locate_kdc.c \
+ $(SRCTOP)/include/fake-addrinfo.h $(SRCTOP)/include/k5-plugin.h
t_realm_iter.so t_realm_iter.po $(OUTPRE)t_realm_iter.$(OBJEXT): \
t_realm_iter.c $(BUILDTOP)/include/krb5.h $(COM_ERR_DEPS)
t_std_conf.so t_std_conf.po $(OUTPRE)t_std_conf.$(OBJEXT): \
diff --git a/src/lib/krb5/os/accessor.c b/src/lib/krb5/os/accessor.c
index f16a6e3e60..0a2f8e8db4 100644
--- a/src/lib/krb5/os/accessor.c
+++ b/src/lib/krb5/os/accessor.c
@@ -38,7 +38,6 @@ krb5int_accessor(krb5int_access *internals, krb5_int32 version)
internals_temp.krb5_hmac = krb5_hmac;
internals_temp.md5_hash_provider = &krb5int_hash_md5;
internals_temp.arcfour_enc_provider = &krb5int_enc_arcfour;
- internals_temp.locate_server = &krb5int_locate_server;
internals_temp.sendto_udp = &krb5int_sendto;
internals_temp.add_host_to_list = krb5int_add_host_to_list;
#ifdef KRB5_DNS_LOOKUP
diff --git a/src/lib/krb5/os/changepw.c b/src/lib/krb5/os/changepw.c
index 1d4e1d3ada..5f900b6216 100644
--- a/src/lib/krb5/os/changepw.c
+++ b/src/lib/krb5/os/changepw.c
@@ -50,19 +50,17 @@ krb5_locate_kpasswd(krb5_context context, const krb5_data *realm,
{
krb5_error_code code;
- code = krb5int_locate_server (context, realm, addrlist, 0,
- "kpasswd_server", "_kpasswd", 0,
- htons(DEFAULT_KPASSWD_PORT), 0, 0);
+ code = krb5int_locate_server (context, realm, addrlist,
+ locate_service_kpasswd, 0, 0);
if (code == KRB5_REALM_CANT_RESOLVE || code == KRB5_REALM_UNKNOWN) {
- code = krb5int_locate_server (context, realm, addrlist, 0,
- "admin_server", "_kerberos-adm", 1,
- DEFAULT_KPASSWD_PORT, 0, 0);
+ code = krb5int_locate_server (context, realm, addrlist,
+ locate_service_kadmin, 1, 0);
if (!code) {
/* Success with admin_server but now we need to change the
port number to use DEFAULT_KPASSWD_PORT. */
int i;
for ( i=0;i<addrlist->naddrs;i++ ) {
- struct addrinfo *a = addrlist->addrs[i];
+ struct addrinfo *a = addrlist->addrs[i].ai;
if (a->ai_family == AF_INET)
sa2sin (a->ai_addr)->sin_port = htons(DEFAULT_KPASSWD_PORT);
}
@@ -157,11 +155,11 @@ krb5_change_set_password(
struct timeval timeout;
/* XXX Now the locate_ functions can return IPv6 addresses. */
- if (al.addrs[i]->ai_family != AF_INET)
+ if (al.addrs[i].ai->ai_family != AF_INET)
continue;
tried_one = 1;
- if (connect(s2, al.addrs[i]->ai_addr, al.addrs[i]->ai_addrlen) == SOCKET_ERROR) {
+ if (connect(s2, al.addrs[i].ai->ai_addr, al.addrs[i].ai->ai_addrlen) == SOCKET_ERROR) {
if (SOCKET_ERRNO == ECONNREFUSED || SOCKET_ERRNO == EHOSTUNREACH)
continue; /* try the next addr */
@@ -243,7 +241,8 @@ krb5_change_set_password(
if ((cc = sendto(s1, chpw_req.data,
(GETSOCKNAME_ARG3_TYPE) chpw_req.length, 0,
- al.addrs[i]->ai_addr, al.addrs[i]->ai_addrlen)) != chpw_req.length)
+ al.addrs[i].ai->ai_addr, al.addrs[i].ai->ai_addrlen))
+ != chpw_req.length)
{
if ((cc < 0) && ((SOCKET_ERRNO == ECONNREFUSED) ||
(SOCKET_ERRNO == EHOSTUNREACH)))
diff --git a/src/lib/krb5/os/init_os_ctx.c b/src/lib/krb5/os/init_os_ctx.c
index f4f9b690a0..e91a05ff1c 100644
--- a/src/lib/krb5/os/init_os_ctx.c
+++ b/src/lib/krb5/os/init_os_ctx.c
@@ -355,6 +355,9 @@ krb5_os_init_context(krb5_context ctx)
os_ctx->os_flags = 0;
os_ctx->default_ccname = 0;
+ ctx->vtbl = 0;
+ PLUGIN_DIR_INIT(&ctx->libkrb5_plugins);
+
retval = os_init_paths(ctx);
/*
* If there's an error in the profile, return an error. Just
@@ -478,6 +481,8 @@ krb5_os_free_context(krb5_context ctx)
ctx->profile = 0;
}
+ krb5int_close_plugin_dir (&ctx->libkrb5_plugins);
+
#ifdef _WIN32
WSACleanup();
#endif /* _WIN32 */
diff --git a/src/lib/krb5/os/locate_kdc.c b/src/lib/krb5/os/locate_kdc.c
index 50c889dd8f..e751ca24d0 100644
--- a/src/lib/krb5/os/locate_kdc.c
+++ b/src/lib/krb5/os/locate_kdc.c
@@ -1,7 +1,7 @@
/*
* lib/krb5/os/locate_kdc.c
*
- * Copyright 1990,2000,2001,2002,2003,2004 Massachusetts Institute of Technology.
+ * Copyright 1990,2000,2001,2002,2003,2004,2006 Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
@@ -100,52 +100,23 @@ _krb5_use_dns_realm(krb5_context context)
#endif /* KRB5_DNS_LOOKUP */
-static int get_port (const char *service, int stream, int defalt)
-{
-#if 0 /* Only used for "kerberos" and "kerberos-sec", and we want the
- right port numbers even on the OSes that botch the entries in
- /etc/services. So don't bother with the lookup, except maybe
- to produce a warning. */
- struct addrinfo hints = { 0 };
- struct addrinfo *ai;
- int err;
-
- hints.ai_family = PF_INET;
- hints.ai_socktype = stream ? SOCK_STREAM : SOCK_DGRAM;
- err = getaddrinfo (NULL, service, &hints, &ai);
- if (err == 0 && ai != 0) {
- if (ai->ai_addr->sa_family == AF_INET) {
- int port = ((struct sockaddr_in *)ai->ai_addr)->sin_port;
- freeaddrinfo (ai);
- return port;
- }
- freeaddrinfo (ai);
- }
-#endif
- /* Any error - don't complain, just use default. */
- return htons (defalt);
-}
-
int
krb5int_grow_addrlist (struct addrlist *lp, int nmore)
{
int i;
int newspace = lp->space + nmore;
- size_t newsize = newspace * sizeof (struct addrlist);
- struct addrinfo **newaddrs;
-
- /* NULL check a concession to SunOS4 compatibility for now; not
- required for pure ANSI support. */
- if (lp->addrs)
- newaddrs = realloc (lp->addrs, newsize);
- else
- newaddrs = malloc (newsize);
+ size_t newsize = newspace * sizeof (*lp->addrs);
+ void *newaddrs;
+ newaddrs = realloc (lp->addrs, newsize);
if (newaddrs == NULL)
return errno;
- for (i = lp->space; i < newspace; i++)
- newaddrs[i] = NULL;
lp->addrs = newaddrs;
+ for (i = lp->space; i < newspace; i++) {
+ lp->addrs[i].ai = NULL;
+ lp->addrs[i].freefn = NULL;
+ lp->addrs[i].data = NULL;
+ }
lp->space = newspace;
return 0;
}
@@ -158,7 +129,8 @@ krb5int_free_addrlist (struct addrlist *lp)
{
int i;
for (i = 0; i < lp->naddrs; i++)
- freeaddrinfo (lp->addrs[i]);
+ if (lp->addrs[i].freefn)
+ (lp->addrs[i].freefn)(lp->addrs[i].data);
free (lp->addrs);
lp->addrs = NULL;
lp->naddrs = lp->space = 0;
@@ -214,26 +186,23 @@ static inline void Tprintf(const char *fmt, ...)
#endif
}
-static int add_addrinfo_to_list (struct addrlist *lp, struct addrinfo *a)
+#if 0
+extern void krb5int_debug_fprint(const char *, ...);
+#define dprint krb5int_debug_fprint
+#define print_addrlist krb5int_print_addrlist
+extern void print_addrlist (const struct addrlist *a);
+#else
+static inline void dprint(const char *fmt, ...) { }
+static inline void print_addrlist(const struct addrlist *a) { }
+#endif
+
+static int add_addrinfo_to_list (struct addrlist *lp, struct addrinfo *a,
+ void (*freefn)(void *), void *data)
{
int err;
- switch (a->ai_socktype) {
- case SOCK_DGRAM:
- Tprintf("\tdgram\n");
- break;
- case SOCK_STREAM:
- Tprintf("\tstream\n");
- break;
- case SOCK_RAW:
- Tprintf("\traw\n");
- break;
- case 0:
- break;
- default:
- Tprintf("\tsocket type %d\n", a->ai_socktype);
- break;
- }
+ dprint("\tadding %p=%A to %p (naddrs=%d space=%d)\n", a, a, lp,
+ lp->naddrs, lp->space);
if (lp->naddrs == lp->space) {
err = grow_list (lp, 1);
@@ -242,14 +211,27 @@ static int add_addrinfo_to_list (struct addrlist *lp, struct addrinfo *a)
return err;
}
}
- lp->addrs[lp->naddrs++] = a;
- a->ai_next = 0;
- Tprintf ("count is now %d\n", lp->naddrs);
+ Tprintf("setting element %d\n", lp->naddrs);
+ lp->addrs[lp->naddrs].ai = a;
+ lp->addrs[lp->naddrs].freefn = freefn;
+ lp->addrs[lp->naddrs].data = data;
+ lp->naddrs++;
+ Tprintf ("\tcount is now %d: ", lp->naddrs);
+ print_addrlist(lp);
+ Tprintf("\n");
return 0;
}
#define add_host_to_list krb5int_add_host_to_list
+static void call_freeaddrinfo(void *data)
+{
+ /* Strict interpretation of the C standard says we can't assume
+ that the ABI for f(void*) and f(struct foo *) will be
+ compatible. Use this stub just to be paranoid. */
+ freeaddrinfo(data);
+}
+
int
krb5int_add_host_to_list (struct addrlist *lp, const char *hostname,
int port, int secport,
@@ -258,6 +240,7 @@ krb5int_add_host_to_list (struct addrlist *lp, const char *hostname,
struct addrinfo *addrs, *a, *anext, hint;
int err;
char portbuf[10], secportbuf[10];
+ void (*freefn)(void *);
Tprintf ("adding hostname %s, ports %d,%d, family %d, socktype %d\n",
hostname, ntohs (port), ntohs (secport),
@@ -277,10 +260,11 @@ krb5int_add_host_to_list (struct addrlist *lp, const char *hostname,
hostname, portbuf, err, gai_strerror (err));
return translate_ai_error (err);
}
+ freefn = call_freeaddrinfo;
anext = 0;
- for (a = addrs; a != 0 && err == 0; a = anext) {
+ for (a = addrs; a != 0 && err == 0; a = anext, freefn = 0) {
anext = a->ai_next;
- err = add_addrinfo_to_list (lp, a);
+ err = add_addrinfo_to_list (lp, a, freefn, a);
}
if (err || secport == 0)
goto egress;
@@ -294,13 +278,13 @@ krb5int_add_host_to_list (struct addrlist *lp, const char *hostname,
err = translate_ai_error (err);
goto egress;
}
- for (a = addrs; a != 0 && err == 0; a = anext) {
+ freefn = call_freeaddrinfo;
+ for (a = addrs; a != 0 && err == 0; a = anext, freefn = 0) {
anext = a->ai_next;
- err = add_addrinfo_to_list (lp, a);
+ err = add_addrinfo_to_list (lp, a, freefn, a);
}
egress:
- if (anext)
- freeaddrinfo (anext);
+ /* XXX Memory leaks possible here if add_addrinfo_to_list fails. */
return err;
}
@@ -559,58 +543,260 @@ krb5_locate_srv_dns_1 (const krb5_data *realm,
}
#endif
+#include "k5-plugin.h"
+
+static const char objdir[] = LIBDIR "/krb5/plugins/libkrb5";
+
+struct module_callback_data {
+ int out_of_mem;
+ struct addrlist *lp;
+};
+
+static int
+module_callback (void *cbdata, int socktype, struct sockaddr *sa)
+{
+ struct module_callback_data *d = cbdata;
+ struct {
+ struct addrinfo ai;
+ union {
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ } u;
+ } *x;
+
+ if (socktype != SOCK_STREAM && socktype != SOCK_DGRAM)
+ return 0;
+ if (sa->sa_family != AF_INET && sa->sa_family != AF_INET6)
+ return 0;
+ x = malloc (sizeof (*x));
+ if (x == 0) {
+ d->out_of_mem = 1;
+ return 1;
+ }
+ memset(x, 0, sizeof (*x));
+ x->ai.ai_addr = (struct sockaddr *) &x->u;
+ x->ai.ai_socktype = socktype;
+ x->ai.ai_family = sa->sa_family;
+ if (sa->sa_family == AF_INET) {
+ x->u.sin = *(struct sockaddr_in *)sa;
+ x->ai.ai_addrlen = sizeof(struct sockaddr_in);
+ }
+ if (sa->sa_family == AF_INET6) {
+ x->u.sin6 = *(struct sockaddr_in6 *)sa;
+ x->ai.ai_addrlen = sizeof(struct sockaddr_in6);
+ }
+ if (add_addrinfo_to_list (d->lp, &x->ai, free, x) != 0) {
+ /* Assumes only error is ENOMEM. */
+ d->out_of_mem = 1;
+ return 1;
+ }
+ return 0;
+}
+
+static krb5_error_code
+module_locate_server (krb5_context ctx, const krb5_data *realm,
+ struct addrlist *addrlist,
+ enum locate_service_type svc, int socktype, int family)
+{
+ struct krb5plugin_service_locate_result *res = NULL;
+ krb5_error_code code;
+ struct krb5plugin_service_locate_ftable *vtbl = NULL;
+ void **ptrs;
+ int i;
+ struct module_callback_data cbdata = { 0, addrlist };
+
+ Tprintf("in module_locate_server\n");
+ if (!PLUGIN_DIR_OPEN (&ctx->libkrb5_plugins)) {
+ code = krb5int_open_plugin_dir (objdir, &ctx->libkrb5_plugins);
+ if (code)
+ return KRB5_PLUGIN_NO_HANDLE;
+ }
+
+ code = krb5int_get_plugin_dir_data (&ctx->libkrb5_plugins, "service_locator", &ptrs);
+ if (code) {
+ Tprintf("error looking up plugin symbols: %s\n", error_message(code));
+ return KRB5_PLUGIN_NO_HANDLE;
+ }
+
+ for (i = 0; ptrs[i]; i++) {
+ void *blob;
+
+ vtbl = ptrs[i];
+ Tprintf("element %d is %p\n", i, ptrs[i]);
+
+ /* For now, don't keep the plugin data alive. For long-lived
+ contexts, it may be desirable to change that later. */
+ code = vtbl->init(ctx, &blob);
+ if (code)
+ continue;
+
+ code = vtbl->lookup(blob, svc, realm->data, socktype, family,
+ module_callback, &cbdata);
+ vtbl->fini(blob);
+ if (code == KRB5_PLUGIN_NO_HANDLE) {
+ /* Module passes, keep going. */
+ /* XXX */
+ Tprintf("plugin doesn't handle this realm (KRB5_PLUGIN_NO_HANDLE)\n");
+ continue;
+ }
+ if (code != 0) {
+ /* Module encountered an actual error. */
+ Tprintf("plugin lookup routine returned error %d: %s\n",
+ code, error_message(code));
+ krb5int_free_plugin_dir_data (ptrs);
+ return code;
+ }
+ break;
+ }
+ if (ptrs[i] == NULL) {
+ Tprintf("ran off end of plugin list\n");
+ krb5int_free_plugin_dir_data (ptrs);
+ return KRB5_PLUGIN_NO_HANDLE;
+ }
+ Tprintf("stopped with plugin #%d, res=%p\n", i, res);
+
+ /* Got something back, yippee. */
+ Tprintf("now have %d addrs in list %p\n", addrlist->naddrs, addrlist);
+ print_addrlist(addrlist);
+ krb5int_free_plugin_dir_data (ptrs);
+ return 0;
+}
+
+static krb5_error_code
+prof_locate_server (krb5_context context, const krb5_data *realm,
+ struct addrlist *addrlist,
+ enum locate_service_type svc, int socktype, int family)
+{
+ const char *profname;
+ int dflport1, dflport2 = 0;
+ struct servent *serv;
+
+ switch (svc) {
+ case locate_service_kdc:
+ profname = "kdc";
+ /* We used to use /etc/services for these, but enough systems
+ have old, crufty, wrong settings that this is probably
+ better. */
+ kdc_ports:
+ dflport1 = htons(KRB5_DEFAULT_PORT);
+ dflport2 = htons(KRB5_DEFAULT_SEC_PORT);
+ break;
+ case locate_service_master_kdc:
+ profname = "master_kdc";
+ goto kdc_ports;
+ case locate_service_kadmin:
+ profname = "admin_server";
+ dflport1 = htons(DEFAULT_KADM5_PORT);
+ break;
+ case locate_service_krb524:
+ profname = "krb524_server";
+ serv = getservbyname(KRB524_SERVICE, "udp");
+ dflport1 = serv ? serv->s_port : htons (KRB524_PORT);
+ break;
+ case locate_service_kpasswd:
+ profname = "kpasswd_server";
+ dflport1 = htons(DEFAULT_KPASSWD_PORT);
+ break;
+ default:
+ return EBUSY; /* XXX */
+ }
+
+ return krb5_locate_srv_conf_1 (context, realm, profname, addrlist,
+ 0, socktype,
+ dflport1, dflport2, family);
+}
+
+static krb5_error_code
+dns_locate_server (krb5_context context, const krb5_data *realm,
+ struct addrlist *addrlist,
+ enum locate_service_type svc, int socktype, int family)
+{
+ const char *dnsname;
+ int use_dns = _krb5_use_dns_kdc(context);
+ krb5_error_code code;
+
+ if (!use_dns)
+ return KRB5_PLUGIN_NO_HANDLE;
+
+ switch (svc) {
+ case locate_service_kdc:
+ dnsname = "_kerberos";
+ break;
+ case locate_service_master_kdc:
+ dnsname = "_kerberos-master";
+ break;
+ case locate_service_kadmin:
+ dnsname = "_kerberos-adm";
+ break;
+ case locate_service_krb524:
+ dnsname = "_krb524";
+ break;
+ case locate_service_kpasswd:
+ dnsname = "_kpasswd";
+ break;
+ default:
+ return KRB5_PLUGIN_NO_HANDLE;
+ }
+
+ code = 0;
+ if (socktype == SOCK_DGRAM || socktype == 0) {
+ code = krb5_locate_srv_dns_1(realm, dnsname, "_udp", addrlist, family);
+ if (code)
+ Tprintf("dns udp lookup returned error %d\n", code);
+ }
+ if ((socktype == SOCK_STREAM || socktype == 0) && code == 0) {
+ code = krb5_locate_srv_dns_1(realm, dnsname, "_tcp", addrlist, family);
+ if (code)
+ Tprintf("dns tcp lookup returned error %d\n", code);
+ }
+ return code;
+}
+
/*
- * Wrapper function for the two backends
+ * Wrapper function for the various backends
*/
krb5_error_code
krb5int_locate_server (krb5_context context, const krb5_data *realm,
struct addrlist *addrlist,
- int get_masters,
- const char *profname, const char *dnsname,
- int socktype,
- /* network order port numbers! */
- int dflport1, int dflport2,
- int family)
+ enum locate_service_type svc,
+ int socktype, int family)
{
krb5_error_code code;
struct addrlist al = ADDRLIST_INIT;
*addrlist = al;
+ code = module_locate_server(context, realm, &al, svc, socktype, family);
+ Tprintf("module_locate_server returns %d\n", code);
+ if (code != KRB5_PLUGIN_NO_HANDLE) {
+ *addrlist = al;
+ return code;
+ }
+
/*
- * We always try the local file first
+ * We always try the local file before DNS
*/
- code = krb5_locate_srv_conf_1(context, realm, profname, &al, get_masters,
- socktype, dflport1, dflport2, family);
+ code = prof_locate_server(context, realm, &al, svc, socktype, family);
+
+ /* We could put more heuristics here, like looking up a hostname
+ of "kerberos."+REALM, etc. */
#ifdef KRB5_DNS_LOOKUP
- if (code && dnsname != 0) {
- int use_dns = _krb5_use_dns_kdc(context);
- if (use_dns) {
- code = 0;
- if (socktype == SOCK_DGRAM || socktype == 0) {
- code = krb5_locate_srv_dns_1(realm, dnsname, "_udp",
- &al, family);
- if (code)
- Tprintf("dns udp lookup returned error %d\n", code);
- }
- if ((socktype == SOCK_STREAM || socktype == 0) && code == 0) {
- code = krb5_locate_srv_dns_1(realm, dnsname, "_tcp",
- &al, family);
- if (code)
- Tprintf("dns tcp lookup returned error %d\n", code);
- }
- }
+ if (code) {
+ krb5_error_code code2;
+ code2 = dns_locate_server(context, realm, &al, svc, socktype, family);
+ if (code2 != KRB5_PLUGIN_NO_HANDLE)
+ code = code2;
}
#endif /* KRB5_DNS_LOOKUP */
if (code == 0)
Tprintf ("krb5int_locate_server found %d addresses\n",
al.naddrs);
else
- Tprintf ("krb5int_locate_server returning error code %d\n",
- code);
+ Tprintf ("krb5int_locate_server returning error code %d/%s\n",
+ code, error_message(code));
if (code != 0) {
if (al.space)
free_list (&al);
@@ -630,24 +816,9 @@ krb5_locate_kdc(krb5_context context, const krb5_data *realm,
struct addrlist *addrlist,
int get_masters, int socktype, int family)
{
- int udpport, sec_udpport;
-
- udpport = get_port (KDC_PORTNAME, 0, KRB5_DEFAULT_PORT);
- if (socktype == SOCK_STREAM)
- sec_udpport = 0;
- else {
- sec_udpport = get_port (KDC_SECONDARY_PORTNAME, 0,
- (udpport == htons (KRB5_DEFAULT_PORT)
- ? KRB5_DEFAULT_SEC_PORT
- : KRB5_DEFAULT_PORT));
- if (sec_udpport == udpport)
- sec_udpport = 0;
- }
-
- return krb5int_locate_server(context, realm, addrlist, 0,
- get_masters ? "master_kdc" : "kdc",
+ return krb5int_locate_server(context, realm, addrlist,
(get_masters
- ? "_kerberos-master"
- : "_kerberos"),
- socktype, udpport, sec_udpport, family);
+ ? locate_service_master_kdc
+ : locate_service_kdc),
+ socktype, family);
}
diff --git a/src/lib/krb5/os/send524.c b/src/lib/krb5/os/send524.c
index 004d803486..09c9c90228 100644
--- a/src/lib/krb5/os/send524.c
+++ b/src/lib/krb5/os/send524.c
@@ -77,10 +77,8 @@ krb5int_524_sendto_kdc (context, message, realm, reply, addr, addrlen)
serv = getservbyname(KRB524_SERVICE, "udp");
port = serv ? serv->s_port : htons (KRB524_PORT);
- retval = krb5int_locate_server(context, realm, &al, 0,
- "krb524_server", "_krb524",
- SOCK_DGRAM, port,
- 0, PF_INET);
+ retval = krb5int_locate_server(context, realm, &al, locate_service_krb524,
+ SOCK_DGRAM, PF_INET);
if (retval == KRB5_REALM_CANT_RESOLVE || retval == KRB5_REALM_UNKNOWN) {
/* Fallback heuristic: Assume krb524 port on every KDC might
work. */
@@ -90,9 +88,9 @@ krb5int_524_sendto_kdc (context, message, realm, reply, addr, addrlen)
*/
if (retval == 0)
for (i = 0; i < al.naddrs; i++) {
- al.addrs[i]->ai_socktype = SOCK_DGRAM;
- if (al.addrs[i]->ai_family == AF_INET)
- sa2sin (al.addrs[i]->ai_addr)->sin_port = port;
+ al.addrs[i].ai->ai_socktype = SOCK_DGRAM;
+ if (al.addrs[i].ai->ai_family == AF_INET)
+ sa2sin (al.addrs[i].ai->ai_addr)->sin_port = port;
}
}
if (retval)
diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c
index e35c337d36..23e99d51c9 100644
--- a/src/lib/krb5/os/sendto_kdc.c
+++ b/src/lib/krb5/os/sendto_kdc.c
@@ -93,7 +93,7 @@ void (*krb5int_sendtokdc_debug_handler) (const void *, size_t) = 0;
#endif
#define dprint krb5int_debug_fprint
-static void
+ void
krb5int_debug_fprint (const char *fmt, ...)
{
#ifdef DEBUG
@@ -198,18 +198,22 @@ krb5int_debug_fprint (const char *fmt, ...)
case 'A':
/* %A => addrinfo */
ai = va_arg(args, struct addrinfo *);
+ if (ai->ai_socktype == SOCK_DGRAM)
+ strcpy(tmpbuf, "dgram");
+ else if (ai->ai_socktype == SOCK_STREAM)
+ strcpy(tmpbuf, "stream");
+ else
+ sprintf(tmpbuf, "socktype%d", ai->ai_socktype);
if (0 != getnameinfo (ai->ai_addr, ai->ai_addrlen,
addrbuf, sizeof (addrbuf),
portbuf, sizeof (portbuf),
- NI_NUMERICHOST | NI_NUMERICSERV))
- strcpy (addrbuf, "??"), strcpy (portbuf, "??");
- sprintf(tmpbuf, "%s %s.%s",
- (ai->ai_socktype == SOCK_DGRAM
- ? "udp"
- : ai->ai_socktype == SOCK_STREAM
- ? "tcp"
- : "???"),
- addrbuf, portbuf);
+ NI_NUMERICHOST | NI_NUMERICSERV)) {
+ if (ai->ai_addr->sa_family == AF_UNSPEC)
+ strcpy(tmpbuf + strlen(tmpbuf), " AF_UNSPEC");
+ else
+ sprintf(tmpbuf + strlen(tmpbuf), " af%d", ai->ai_addr->sa_family);
+ } else
+ sprintf(tmpbuf + strlen(tmpbuf), " %s.%s", addrbuf, portbuf);
putstr(tmpbuf);
break;
case 'D':
@@ -224,17 +228,30 @@ krb5int_debug_fprint (const char *fmt, ...)
#endif
}
+#define print_addrlist krb5int_print_addrlist
+static void
+print_addrlist (const struct addrlist *a)
+{
+ int i;
+ dprint("%d{", a->naddrs);
+ for (i = 0; i < a->naddrs; i++)
+ dprint("%s%p=%A", i ? "," : "", (void*)a->addrs[i].ai, a->addrs[i].ai);
+ dprint("}");
+}
+
static int
merge_addrlists (struct addrlist *dest, struct addrlist *src)
{
+ /* Wouldn't it be nice if we could filter out duplicates? The
+ alloc/free handling makes that pretty difficult though. */
int err, i;
dprint("merging addrlists:\n\tlist1: ");
for (i = 0; i < dest->naddrs; i++)
- dprint(" %A", dest->addrs[i]);
+ dprint(" %A", dest->addrs[i].ai);
dprint("\n\tlist2: ");
for (i = 0; i < src->naddrs; i++)
- dprint(" %A", src->addrs[i]);
+ dprint(" %A", src->addrs[i].ai);
dprint("\n");
err = krb5int_grow_addrlist (dest, src->naddrs);
@@ -242,19 +259,33 @@ merge_addrlists (struct addrlist *dest, struct addrlist *src)
return err;
for (i = 0; i < src->naddrs; i++) {
dest->addrs[dest->naddrs + i] = src->addrs[i];
- src->addrs[i] = 0;
+ src->addrs[i].ai = 0;
+ src->addrs[i].freefn = 0;
}
dest->naddrs += i;
src->naddrs = 0;
dprint("\tout: ");
for (i = 0; i < dest->naddrs; i++)
- dprint(" %A", dest->addrs[i]);
+ dprint(" %A", dest->addrs[i].ai);
dprint("\n");
return 0;
}
+static int
+in_addrlist (struct addrinfo *thisaddr, struct addrlist *list)
+{
+ int i;
+ for (i = 0; i < list->naddrs; i++) {
+ if (thisaddr->ai_addrlen == list->addrs[i].ai->ai_addrlen
+ && !memcmp(thisaddr->ai_addr, list->addrs[i].ai->ai_addr,
+ thisaddr->ai_addrlen))
+ return 1;
+ }
+ return 0;
+}
+
/*
* send the formatted request 'message' to a KDC for realm 'realm' and
* return the response (if any) in 'reply'.
@@ -271,7 +302,7 @@ krb5_sendto_kdc (krb5_context context, const krb5_data *message,
const krb5_data *realm, krb5_data *reply,
int *use_master, int tcp_only)
{
- krb5_error_code retval;
+ krb5_error_code retval, retval2;
struct addrlist addrs;
int socktype1 = 0, socktype2 = 0, addr_used;
@@ -321,12 +352,23 @@ krb5_sendto_kdc (krb5_context context, const krb5_data *message,
if (socktype2) {
struct addrlist addrs2;
- retval = krb5_locate_kdc(context, realm, &addrs2, *use_master,
- socktype2, 0);
+ retval2 = krb5_locate_kdc(context, realm, &addrs2, *use_master,
+ socktype2, 0);
+#if 0
+ if (retval2 == 0) {
+ (void) merge_addrlists(&addrs, &addrs2);
+ krb5int_free_addrlist(&addrs2);
+ retval = 0;
+ } else if (retval == KRB5_REALM_CANT_RESOLVE) {
+ retval = retval2;
+ }
+#else
+ retval = retval2;
if (retval == 0) {
(void) merge_addrlists(&addrs, &addrs2);
krb5int_free_addrlist(&addrs2);
}
+#endif
}
if (addrs.naddrs > 0) {
@@ -340,20 +382,11 @@ krb5_sendto_kdc (krb5_context context, const krb5_data *message,
if (*use_master == 0) {
struct addrlist addrs3;
retval = krb5_locate_kdc(context, realm, &addrs3, 1,
- addrs.addrs[addr_used]->ai_socktype,
- addrs.addrs[addr_used]->ai_family);
+ addrs.addrs[addr_used].ai->ai_socktype,
+ addrs.addrs[addr_used].ai->ai_family);
if (retval == 0) {
- int i;
- for (i = 0; i < addrs3.naddrs; i++) {
- if (addrs.addrs[addr_used]->ai_addrlen ==
- addrs3.addrs[i]->ai_addrlen &&
- memcmp(addrs.addrs[addr_used]->ai_addr,
- addrs3.addrs[i]->ai_addr,
- addrs.addrs[addr_used]->ai_addrlen) == 0) {
- *use_master = 1;
- break;
- }
- }
+ if (in_addrlist(addrs.addrs[addr_used].ai, &addrs3))
+ *use_master = 1;
krb5int_free_addrlist (&addrs3);
}
}
@@ -1039,7 +1072,9 @@ krb5int_sendto (krb5_context context, const krb5_data *message,
unsigned char message_len_buf[4];
char *udpbuf = 0;
- dprint("krb5int_sendto(message=%d@%p)\n", message->length, message->data);
+ dprint("krb5int_sendto(message=%d@%p, addrlist=", message->length, message->data);
+ print_addrlist(addrs);
+ dprint(")\n");
reply->data = 0;
reply->length = 0;
@@ -1075,7 +1110,7 @@ krb5int_sendto (krb5_context context, const krb5_data *message,
/* Set up connections. */
for (host = 0; host < n_conns; host++) {
- retval = setup_connection (&conns[host], addrs->addrs[host],
+ retval = setup_connection (&conns[host], addrs->addrs[host].ai,
message, message_len_buf, &udpbuf);
if (retval)
continue;
diff --git a/src/lib/krb5/os/t_locate_kdc.c b/src/lib/krb5/os/t_locate_kdc.c
index 7d5d554fab..165366f5be 100644
--- a/src/lib/krb5/os/t_locate_kdc.c
+++ b/src/lib/krb5/os/t_locate_kdc.c
@@ -5,6 +5,8 @@
#include <com_err.h>
#define TEST
+#include "dnsglue.c"
+#include "dnssrv.c"
#include "locate_kdc.c"
enum {
@@ -43,14 +45,14 @@ void print_addrs (void)
{
int i;
- struct addrinfo **addrs = al.addrs;
int naddrs = al.naddrs;
printf ("%d addresses:\n", naddrs);
for (i = 0; i < naddrs; i++) {
int err;
+ struct addrinfo *ai = al.addrs[i].ai;
char hostbuf[NI_MAXHOST], srvbuf[NI_MAXSERV];
- err = getnameinfo (addrs[i]->ai_addr, addrs[i]->ai_addrlen,
+ err = getnameinfo (ai->ai_addr, ai->ai_addrlen,
hostbuf, sizeof (hostbuf),
srvbuf, sizeof (srvbuf),
NI_NUMERICHOST | NI_NUMERICSERV);
@@ -59,7 +61,7 @@ void print_addrs (void)
i, err, gai_strerror (err));
else
printf ("%2d: address %s\t%s\tport %s\n", i, hostbuf,
- stypename (addrs[i]->ai_socktype), srvbuf);
+ stypename (ai->ai_socktype), srvbuf);
}
}
diff --git a/src/lib/krb5/os/t_std_conf.c b/src/lib/krb5/os/t_std_conf.c
index adaf6893db..04b75d7b80 100644
--- a/src/lib/krb5/os/t_std_conf.c
+++ b/src/lib/krb5/os/t_std_conf.c
@@ -113,7 +113,7 @@ static void test_locate_kdc(krb5_context ctx, char *realm)
}
printf("krb_locate_kdc(%s) returned:", realm);
for (i=0; i < addrs.naddrs; i++) {
- struct addrinfo *ai = addrs.addrs[i];
+ struct addrinfo *ai = addrs.addrs[i].ai;
switch (ai->ai_family) {
case AF_INET:
{