2 Unix SMB/CIFS implementation.
3 kerberos locator plugin
4 Copyright (C) Guenther Deschner 2007
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #if defined(HAVE_KRB5) && defined(HAVE_KRB5_LOCATE_PLUGIN_H)
25 #include <krb5/locate_plugin.h>
27 static const char *get_service_from_locate_service_type(enum locate_service_type svc)
30 case locate_service_kdc:
31 case locate_service_master_kdc:
33 case locate_service_kadmin:
34 case locate_service_krb524:
37 case locate_service_kpasswd:
46 static const char *locate_service_type_name(enum locate_service_type svc)
49 case locate_service_kdc:
50 return "locate_service_kdc";
51 case locate_service_master_kdc:
52 return "locate_service_master_kdc";
53 case locate_service_kadmin:
54 return "locate_service_kadmin";
55 case locate_service_krb524:
56 return "locate_service_krb524";
57 case locate_service_kpasswd:
58 return "locate_service_kpasswd";
65 static const char *socktype_name(int socktype)
78 static const char *family_name(int family)
94 * Check input parameters, return KRB5_PLUGIN_NO_HANDLE for unsupported ones
98 * @param socktype integer
99 * @param family integer
104 static int smb_krb5_locator_lookup_sanity_check(enum locate_service_type svc,
109 if (!realm || strlen(realm) == 0) {
114 case locate_service_kdc:
115 case locate_service_master_kdc:
116 case locate_service_kpasswd:
118 case locate_service_kadmin:
119 case locate_service_krb524:
120 #ifdef KRB5_PLUGIN_NO_HANDLE
121 return KRB5_PLUGIN_NO_HANDLE;
123 return KRB5_KDC_UNREACH; /* Heimdal */
133 case AF_INET6: /* not yet */
134 #ifdef KRB5_PLUGIN_NO_HANDLE
135 return KRB5_PLUGIN_NO_HANDLE;
137 return KRB5_KDC_UNREACH; /* Heimdal */
146 case 0: /* Heimdal uses that */
156 * Try to get addrinfo for a given host and call the krb5 callback
159 * @param service string
160 * @param in struct addrinfo hint
161 * @param cbfunc krb5 callback function
162 * @param cbdata void pointer cbdata
164 * @return krb5_error_code.
167 static krb5_error_code smb_krb5_locator_call_cbfunc(const char *name,
170 int (*cbfunc)(void *, int, struct sockaddr *),
173 struct addrinfo *out;
179 ret = getaddrinfo(name, service, in, &out);
184 if (ret == EAI_AGAIN) {
189 DEBUG(10,("smb_krb5_locator_lookup: got ret: %s (%d)\n",
190 gai_strerror(ret), ret));
191 #ifdef KRB5_PLUGIN_NO_HANDLE
192 return KRB5_PLUGIN_NO_HANDLE;
194 return KRB5_KDC_UNREACH; /* Heimdal */
198 ret = cbfunc(cbdata, out->ai_socktype, out->ai_addr);
200 DEBUG(10,("smb_krb5_locator_lookup: failed to call callback: %s (%d)\n",
201 error_message(ret), ret));
210 * PUBLIC INTERFACE: locate init
212 * @param context krb5_context
213 * @param privata_data pointer to private data pointer
215 * @return krb5_error_code.
218 krb5_error_code smb_krb5_locator_init(krb5_context context,
221 setup_logging("smb_krb5_locator", True);
223 lp_load(dyn_CONFIGFILE,True,False,False,True);
225 DEBUG(10,("smb_krb5_locator_init: called\n"));
231 * PUBLIC INTERFACE: close locate
233 * @param private_data pointer to private data
238 void smb_krb5_locator_close(void *private_data)
240 DEBUG(10,("smb_krb5_locator_close: called\n"));
246 * PUBLIC INTERFACE: locate lookup
248 * @param private_data pointer to private data
249 * @param svc enum locate_service_type.
250 * @param realm string
251 * @param socktype integer
252 * @param family integer
253 * @param cbfunc callback function to send back entries
254 * @param cbdata void pointer to cbdata
256 * @return krb5_error_code.
259 krb5_error_code smb_krb5_locator_lookup(void *private_data,
260 enum locate_service_type svc,
264 int (*cbfunc)(void *, int, struct sockaddr *),
269 char *sitename = NULL;
270 struct ip_service *ip_list;
272 struct addrinfo aihints;
273 char *saf_name = NULL;
276 DEBUG(10,("smb_krb5_locator_lookup: called for\n"));
277 DEBUGADD(10,("\tsvc: %s (%d), realm: %s\n",
278 locate_service_type_name(svc), svc, realm));
279 DEBUGADD(10,("\tsocktype: %s (%d), family: %s (%d)\n",
280 socktype_name(socktype), socktype,
281 family_name(family), family));
283 ret = smb_krb5_locator_lookup_sanity_check(svc, realm, socktype, family);
285 DEBUG(10,("smb_krb5_locator_lookup: returning ret: %s (%d)\n",
286 error_message(ret), ret));
290 /* first try to fetch from SAF cache */
292 saf_name = saf_fetch(realm);
293 if (!saf_name || strlen(saf_name) == 0) {
294 DEBUG(10,("smb_krb5_locator_lookup: no SAF name stored for %s\n",
299 DEBUG(10,("smb_krb5_locator_lookup: got %s for %s from SAF cache\n",
302 ZERO_STRUCT(aihints);
304 aihints.ai_family = family;
305 aihints.ai_socktype = socktype;
307 ret = smb_krb5_locator_call_cbfunc(saf_name,
308 get_service_from_locate_service_type(svc),
319 /* now try to find via site-aware DNS SRV query */
321 sitename = sitename_fetch(realm);
322 status = get_kdc_list(realm, sitename, &ip_list, &count);
324 /* if we didn't found any KDCs on our site go to the main list */
326 if (NT_STATUS_IS_OK(status) && sitename && (count == 0)) {
329 status = get_kdc_list(realm, NULL, &ip_list, &count);
334 if (!NT_STATUS_IS_OK(status)) {
335 DEBUG(10,("smb_krb5_locator_lookup: got %s (%s)\n",
337 error_message(nt_status_to_krb5(status))));
338 #ifdef KRB5_PLUGIN_NO_HANDLE
339 return KRB5_PLUGIN_NO_HANDLE;
341 return KRB5_KDC_UNREACH; /* Heimdal */
345 for (i=0; i<count; i++) {
347 const char *host = NULL;
348 const char *port = NULL;
350 ZERO_STRUCT(aihints);
352 aihints.ai_family = family;
353 aihints.ai_socktype = socktype;
355 host = inet_ntoa(ip_list[i].ip);
356 port = get_service_from_locate_service_type(svc);
358 ret = smb_krb5_locator_call_cbfunc(host,
373 #ifdef HEIMDAL_KRB5_LOCATE_PLUGIN_H
374 #define SMB_KRB5_LOCATOR_SYMBOL_NAME resolve /* Heimdal */
376 #define SMB_KRB5_LOCATOR_SYMBOL_NAME service_locator /* MIT */
379 const krb5plugin_service_locate_ftable SMB_KRB5_LOCATOR_SYMBOL_NAME = {
381 smb_krb5_locator_init,
382 smb_krb5_locator_close,
383 smb_krb5_locator_lookup,