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
,