mirror of
https://github.com/samba-team/samba.git
synced 2024-12-24 21:34:56 +03:00
r21822: Adding experimental krb5 lib locator plugin.
This is a starting point and may get changed. Basically we need follow the exact same path to detect (K)DCs like other Samba tools/winbind do. In particular with regard to the server affinity cache and the site-awarness for DNS SRV lookups. To compile just call "make bin/smb_krb5_locator.so", copy to /usr/lib/plugin/krb5/ (Heimdal HEAD) or /usr/lib/krb5/plugins/libkrb5/ (MIT) and you should immediately be able to kinit to your AD domain without having your REALM with kdc or kpasswd directives defined in /etc/krb5.conf at all. Tested with todays Heimdal HEAD and MIT krb5 1.5. Guenther
This commit is contained in:
parent
4efc7b4598
commit
34ae610bd5
@ -844,6 +844,10 @@ LDBADD_OBJ = $(LDB_CMDLINE_OBJ) lib/ldb/tools/ldbadd.o
|
||||
LDBDEL_OBJ = $(LDB_CMDLINE_OBJ) lib/ldb/tools/ldbdel.o
|
||||
LDBMODIFY_OBJ = $(LDB_CMDLINE_OBJ) lib/ldb/tools/ldbmodify.o
|
||||
|
||||
SMB_KRB5_LOCATOR_OBJ1 = libads/smb_krb5_locator.o
|
||||
SMB_KRB5_LOCATOR_OBJ = $(SMB_KRB5_LOCATOR_OBJ1) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \
|
||||
$(LIBNMB_OBJ) $(RPC_PARSE_OBJ1) $(SECRETS_OBJ) $(LIBSAMBA_OBJ) $(DOSERR_OBJ)
|
||||
|
||||
POPT_OBJ=popt/findme.o popt/popt.o popt/poptconfig.o \
|
||||
popt/popthelp.o popt/poptparse.o
|
||||
|
||||
@ -1370,6 +1374,12 @@ bin/winbindd@EXEEXT@: proto_exists $(WINBINDD_OBJ) @BUILD_POPT@ bin/.dummy
|
||||
$(LDAP_LIBS) $(KRB5LIBS) $(LIBS) \
|
||||
@SONAMEFLAG@`basename $@`@NSSSONAMEVERSIONSUFFIX@
|
||||
|
||||
@SMB_KRB5_LOCATOR@: $(SMB_KRB5_LOCATOR_OBJ)
|
||||
@echo "Linking $@"
|
||||
@$(SHLD) $(LDSHFLAGS) -o $@ $(SMB_KRB5_LOCATOR_OBJ) \
|
||||
$(LDAP_LIBS) $(LIBS) -lcom_err \
|
||||
@SONAMEFLAG@`basename $@`
|
||||
|
||||
bin/pam_winbind.@SHLIBEXT@: $(PAM_WINBIND_OBJ) bin/.dummy
|
||||
@echo "Linking shared library $@"
|
||||
@$(SHLD) $(LDSHFLAGS) -o $@ $(PAM_WINBIND_OBJ) -lpam @INIPARSERLIBS@ $(GPLIBS) \
|
||||
|
@ -3446,6 +3446,7 @@ if test x"$with_ads_support" != x"no"; then
|
||||
CPPFLAGS=$ac_save_CPPFLAGS
|
||||
LDFLAGS=$ac_save_LDFLAGS
|
||||
fi
|
||||
AC_CHECK_HEADERS(krb5/locate_plugin.h)
|
||||
fi
|
||||
|
||||
# Now we have determined whether we really want ADS support
|
||||
@ -5624,6 +5625,8 @@ WINBIND_WINS_NSS="nsswitch/libnss_wins.$SHLIBEXT"
|
||||
WINBIND_NSS_LDSHFLAGS=$LDSHFLAGS
|
||||
NSSSONAMEVERSIONSUFFIX=""
|
||||
|
||||
SMB_KRB5_LOCATOR="bin/smb_krb5_locator.$SHLIBEXT"
|
||||
|
||||
case "$host_os" in
|
||||
*linux*)
|
||||
NSSSONAMEVERSIONSUFFIX=".2"
|
||||
@ -5693,6 +5696,8 @@ AC_SUBST(WINBIND_NSS_EXTRA_OBJS)
|
||||
AC_SUBST(WINBIND_NSS_EXTRA_LIBS)
|
||||
AC_SUBST(NSSSONAMEVERSIONSUFFIX)
|
||||
|
||||
AC_SUBST(SMB_KRB5_LOCATOR)
|
||||
|
||||
# Check the setting of --with-winbind
|
||||
|
||||
AC_ARG_WITH(winbind,
|
||||
|
384
source/libads/smb_krb5_locator.c
Normal file
384
source/libads/smb_krb5_locator.c
Normal file
@ -0,0 +1,384 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
kerberos locator plugin
|
||||
Copyright (C) Guenther Deschner 2007
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#if defined(HAVE_KRB5) && defined(HAVE_KRB5_LOCATE_PLUGIN_H)
|
||||
|
||||
#include <krb5/locate_plugin.h>
|
||||
|
||||
static const char *get_service_from_locate_service_type(enum locate_service_type svc)
|
||||
{
|
||||
switch (svc) {
|
||||
case locate_service_kdc:
|
||||
case locate_service_master_kdc:
|
||||
return "88";
|
||||
case locate_service_kadmin:
|
||||
case locate_service_krb524:
|
||||
/* not supported */
|
||||
return NULL;
|
||||
case locate_service_kpasswd:
|
||||
return "464";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
static const char *locate_service_type_name(enum locate_service_type svc)
|
||||
{
|
||||
switch (svc) {
|
||||
case locate_service_kdc:
|
||||
return "locate_service_kdc";
|
||||
case locate_service_master_kdc:
|
||||
return "locate_service_master_kdc";
|
||||
case locate_service_kadmin:
|
||||
return "locate_service_kadmin";
|
||||
case locate_service_krb524:
|
||||
return "locate_service_krb524";
|
||||
case locate_service_kpasswd:
|
||||
return "locate_service_kpasswd";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *socktype_name(int socktype)
|
||||
{
|
||||
switch (socktype) {
|
||||
case SOCK_STREAM:
|
||||
return "SOCK_STREAM";
|
||||
case SOCK_DGRAM:
|
||||
return "SOCK_DGRAM";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
static const char *family_name(int family)
|
||||
{
|
||||
switch (family) {
|
||||
case AF_UNSPEC:
|
||||
return "AF_UNSPEC";
|
||||
case AF_INET:
|
||||
return "AF_INET";
|
||||
case AF_INET6:
|
||||
return "AF_INET6";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
/**
|
||||
* Check input parameters, return KRB5_PLUGIN_NO_HANDLE for unsupported ones
|
||||
*
|
||||
* @param svc
|
||||
* @param realm string
|
||||
* @param socktype integer
|
||||
* @param family integer
|
||||
*
|
||||
* @return integer.
|
||||
*/
|
||||
|
||||
static int smb_krb5_locator_lookup_sanity_check(enum locate_service_type svc,
|
||||
const char *realm,
|
||||
int socktype,
|
||||
int family)
|
||||
{
|
||||
if (!realm || strlen(realm) == 0) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
switch (svc) {
|
||||
case locate_service_kdc:
|
||||
case locate_service_master_kdc:
|
||||
case locate_service_kpasswd:
|
||||
break;
|
||||
case locate_service_kadmin:
|
||||
case locate_service_krb524:
|
||||
#ifdef KRB5_PLUGIN_NO_HANDLE
|
||||
return KRB5_PLUGIN_NO_HANDLE;
|
||||
#else
|
||||
return KRB5_KDC_UNREACH; /* Heimdal */
|
||||
#endif
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
switch (family) {
|
||||
case AF_UNSPEC:
|
||||
case AF_INET:
|
||||
break;
|
||||
case AF_INET6: /* not yet */
|
||||
#ifdef KRB5_PLUGIN_NO_HANDLE
|
||||
return KRB5_PLUGIN_NO_HANDLE;
|
||||
#else
|
||||
return KRB5_KDC_UNREACH; /* Heimdal */
|
||||
#endif
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
switch (socktype) {
|
||||
case SOCK_STREAM:
|
||||
case SOCK_DGRAM:
|
||||
case 0: /* Heimdal uses that */
|
||||
break;
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to get addrinfo for a given host and call the krb5 callback
|
||||
*
|
||||
* @param name string
|
||||
* @param service string
|
||||
* @param in struct addrinfo hint
|
||||
* @param cbfunc krb5 callback function
|
||||
* @param cbdata void pointer cbdata
|
||||
*
|
||||
* @return krb5_error_code.
|
||||
*/
|
||||
|
||||
static krb5_error_code smb_krb5_locator_call_cbfunc(const char *name,
|
||||
const char *service,
|
||||
struct addrinfo *in,
|
||||
int (*cbfunc)(void *, int, struct sockaddr *),
|
||||
void *cbdata)
|
||||
{
|
||||
struct addrinfo *out;
|
||||
int ret;
|
||||
int count = 3;
|
||||
|
||||
while (count) {
|
||||
|
||||
ret = getaddrinfo(name, service, in, &out);
|
||||
if (ret == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret == EAI_AGAIN) {
|
||||
count--;
|
||||
continue;
|
||||
}
|
||||
|
||||
DEBUG(10,("smb_krb5_locator_lookup: got ret: %s (%d)\n",
|
||||
gai_strerror(ret), ret));
|
||||
#ifdef KRB5_PLUGIN_NO_HANDLE
|
||||
return KRB5_PLUGIN_NO_HANDLE;
|
||||
#else
|
||||
return KRB5_KDC_UNREACH; /* Heimdal */
|
||||
#endif
|
||||
}
|
||||
|
||||
ret = cbfunc(cbdata, out->ai_socktype, out->ai_addr);
|
||||
if (ret) {
|
||||
DEBUG(10,("smb_krb5_locator_lookup: failed to call callback: %s (%d)\n",
|
||||
error_message(ret), ret));
|
||||
}
|
||||
|
||||
freeaddrinfo(out);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* PUBLIC INTERFACE: locate init
|
||||
*
|
||||
* @param context krb5_context
|
||||
* @param privata_data pointer to private data pointer
|
||||
*
|
||||
* @return krb5_error_code.
|
||||
*/
|
||||
|
||||
krb5_error_code smb_krb5_locator_init(krb5_context context,
|
||||
void **private_data)
|
||||
{
|
||||
setup_logging("smb_krb5_locator", True);
|
||||
load_case_tables();
|
||||
lp_load(dyn_CONFIGFILE,True,False,False,True);
|
||||
|
||||
DEBUG(10,("smb_krb5_locator_init: called\n"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* PUBLIC INTERFACE: close locate
|
||||
*
|
||||
* @param private_data pointer to private data
|
||||
*
|
||||
* @return void.
|
||||
*/
|
||||
|
||||
void smb_krb5_locator_close(void *private_data)
|
||||
{
|
||||
DEBUG(10,("smb_krb5_locator_close: called\n"));
|
||||
|
||||
gfree_all();
|
||||
}
|
||||
|
||||
/**
|
||||
* PUBLIC INTERFACE: locate lookup
|
||||
*
|
||||
* @param private_data pointer to private data
|
||||
* @param svc enum locate_service_type.
|
||||
* @param realm string
|
||||
* @param socktype integer
|
||||
* @param family integer
|
||||
* @param cbfunc callback function to send back entries
|
||||
* @param cbdata void pointer to cbdata
|
||||
*
|
||||
* @return krb5_error_code.
|
||||
*/
|
||||
|
||||
krb5_error_code smb_krb5_locator_lookup(void *private_data,
|
||||
enum locate_service_type svc,
|
||||
const char *realm,
|
||||
int socktype,
|
||||
int family,
|
||||
int (*cbfunc)(void *, int, struct sockaddr *),
|
||||
void *cbdata)
|
||||
{
|
||||
NTSTATUS status;
|
||||
krb5_error_code ret;
|
||||
char *sitename = NULL;
|
||||
struct ip_service *ip_list;
|
||||
int count = 0;
|
||||
struct addrinfo aihints;
|
||||
char *saf_name = NULL;
|
||||
int i;
|
||||
|
||||
DEBUG(10,("smb_krb5_locator_lookup: called for\n"));
|
||||
DEBUGADD(10,("\tsvc: %s (%d), realm: %s\n",
|
||||
locate_service_type_name(svc), svc, realm));
|
||||
DEBUGADD(10,("\tsocktype: %s (%d), family: %s (%d)\n",
|
||||
socktype_name(socktype), socktype,
|
||||
family_name(family), family));
|
||||
|
||||
ret = smb_krb5_locator_lookup_sanity_check(svc, realm, socktype, family);
|
||||
if (ret) {
|
||||
DEBUG(10,("smb_krb5_locator_lookup: returning ret: %s (%d)\n",
|
||||
error_message(ret), ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* first try to fetch from SAF cache */
|
||||
|
||||
saf_name = saf_fetch(realm);
|
||||
if (!saf_name || strlen(saf_name) == 0) {
|
||||
DEBUG(10,("smb_krb5_locator_lookup: no SAF name stored for %s\n",
|
||||
realm));
|
||||
goto find_kdc;
|
||||
}
|
||||
|
||||
DEBUG(10,("smb_krb5_locator_lookup: got %s for %s from SAF cache\n",
|
||||
saf_name, realm));
|
||||
|
||||
ZERO_STRUCT(aihints);
|
||||
|
||||
aihints.ai_family = family;
|
||||
aihints.ai_socktype = socktype;
|
||||
|
||||
ret = smb_krb5_locator_call_cbfunc(saf_name,
|
||||
get_service_from_locate_service_type(svc),
|
||||
&aihints,
|
||||
cbfunc, cbdata);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
find_kdc:
|
||||
|
||||
/* now try to find via site-aware DNS SRV query */
|
||||
|
||||
sitename = sitename_fetch(realm);
|
||||
status = get_kdc_list(realm, sitename, &ip_list, &count);
|
||||
|
||||
/* if we didn't found any KDCs on our site go to the main list */
|
||||
|
||||
if (NT_STATUS_IS_OK(status) && sitename && (count == 0)) {
|
||||
ip_list = NULL;
|
||||
SAFE_FREE(sitename);
|
||||
status = get_kdc_list(realm, NULL, &ip_list, &count);
|
||||
}
|
||||
|
||||
SAFE_FREE(sitename);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(10,("smb_krb5_locator_lookup: got %s (%s)\n",
|
||||
nt_errstr(status),
|
||||
error_message(nt_status_to_krb5(status))));
|
||||
#ifdef KRB5_PLUGIN_NO_HANDLE
|
||||
return KRB5_PLUGIN_NO_HANDLE;
|
||||
#else
|
||||
return KRB5_KDC_UNREACH; /* Heimdal */
|
||||
#endif
|
||||
}
|
||||
|
||||
for (i=0; i<count; i++) {
|
||||
|
||||
const char *host = NULL;
|
||||
const char *port = NULL;
|
||||
|
||||
ZERO_STRUCT(aihints);
|
||||
|
||||
aihints.ai_family = family;
|
||||
aihints.ai_socktype = socktype;
|
||||
|
||||
host = inet_ntoa(ip_list[i].ip);
|
||||
port = get_service_from_locate_service_type(svc);
|
||||
|
||||
ret = smb_krb5_locator_call_cbfunc(host,
|
||||
port,
|
||||
&aihints,
|
||||
cbfunc, cbdata);
|
||||
if (ret) {
|
||||
/* got error */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef HEIMDAL_KRB5_LOCATE_PLUGIN_H
|
||||
#define SMB_KRB5_LOCATOR_SYMBOL_NAME resolve /* Heimdal */
|
||||
#else
|
||||
#define SMB_KRB5_LOCATOR_SYMBOL_NAME service_locator /* MIT */
|
||||
#endif
|
||||
|
||||
const krb5plugin_service_locate_ftable SMB_KRB5_LOCATOR_SYMBOL_NAME = {
|
||||
0, /* version */
|
||||
smb_krb5_locator_init,
|
||||
smb_krb5_locator_close,
|
||||
smb_krb5_locator_lookup,
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user