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 3 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, see <http://www.gnu.org/licenses/>.
22 #if defined(HAVE_KRB5) && defined(HAVE_KRB5_LOCATE_PLUGIN_H)
24 #include <krb5/locate_plugin.h>
26 static const char *get_service_from_locate_service_type(enum locate_service_type svc
)
29 case locate_service_kdc
:
30 case locate_service_master_kdc
:
32 case locate_service_kadmin
:
33 case locate_service_krb524
:
36 case locate_service_kpasswd
:
45 static const char *locate_service_type_name(enum locate_service_type svc
)
48 case locate_service_kdc
:
49 return "locate_service_kdc";
50 case locate_service_master_kdc
:
51 return "locate_service_master_kdc";
52 case locate_service_kadmin
:
53 return "locate_service_kadmin";
54 case locate_service_krb524
:
55 return "locate_service_krb524";
56 case locate_service_kpasswd
:
57 return "locate_service_kpasswd";
64 static const char *socktype_name(int socktype
)
77 static const char *family_name(int family
)
93 * Check input parameters, return KRB5_PLUGIN_NO_HANDLE for unsupported ones
97 * @param socktype integer
98 * @param family integer
103 static int smb_krb5_locator_lookup_sanity_check(enum locate_service_type svc
,
108 if (!realm
|| strlen(realm
) == 0) {
113 case locate_service_kdc
:
114 case locate_service_master_kdc
:
115 case locate_service_kpasswd
:
117 case locate_service_kadmin
:
118 case locate_service_krb524
:
119 #ifdef KRB5_PLUGIN_NO_HANDLE
120 return KRB5_PLUGIN_NO_HANDLE
;
122 return KRB5_KDC_UNREACH
; /* Heimdal */
132 case AF_INET6
: /* not yet */
133 #ifdef KRB5_PLUGIN_NO_HANDLE
134 return KRB5_PLUGIN_NO_HANDLE
;
136 return KRB5_KDC_UNREACH
; /* Heimdal */
145 case 0: /* Heimdal uses that */
155 * Try to get addrinfo for a given host and call the krb5 callback
158 * @param service string
159 * @param in struct addrinfo hint
160 * @param cbfunc krb5 callback function
161 * @param cbdata void pointer cbdata
163 * @return krb5_error_code.
166 static krb5_error_code
smb_krb5_locator_call_cbfunc(const char *name
,
169 int (*cbfunc
)(void *, int, struct sockaddr
*),
172 struct addrinfo
*out
;
178 ret
= getaddrinfo(name
, service
, in
, &out
);
183 if (ret
== EAI_AGAIN
) {
188 DEBUG(10,("smb_krb5_locator_lookup: got ret: %s (%d)\n",
189 gai_strerror(ret
), ret
));
190 #ifdef KRB5_PLUGIN_NO_HANDLE
191 return KRB5_PLUGIN_NO_HANDLE
;
193 return KRB5_KDC_UNREACH
; /* Heimdal */
197 ret
= cbfunc(cbdata
, out
->ai_socktype
, out
->ai_addr
);
199 DEBUG(10,("smb_krb5_locator_lookup: failed to call callback: %s (%d)\n",
200 error_message(ret
), ret
));
209 * PUBLIC INTERFACE: locate init
211 * @param context krb5_context
212 * @param privata_data pointer to private data pointer
214 * @return krb5_error_code.
217 krb5_error_code
smb_krb5_locator_init(krb5_context context
,
220 setup_logging("smb_krb5_locator", True
);
222 lp_load(dyn_CONFIGFILE
,True
,False
,False
,True
);
224 DEBUG(10,("smb_krb5_locator_init: called\n"));
230 * PUBLIC INTERFACE: close locate
232 * @param private_data pointer to private data
237 void smb_krb5_locator_close(void *private_data
)
239 DEBUG(10,("smb_krb5_locator_close: called\n"));
245 * PUBLIC INTERFACE: locate lookup
247 * @param private_data pointer to private data
248 * @param svc enum locate_service_type.
249 * @param realm string
250 * @param socktype integer
251 * @param family integer
252 * @param cbfunc callback function to send back entries
253 * @param cbdata void pointer to cbdata
255 * @return krb5_error_code.
258 krb5_error_code
smb_krb5_locator_lookup(void *private_data
,
259 enum locate_service_type svc
,
263 int (*cbfunc
)(void *, int, struct sockaddr
*),
268 char *sitename
= NULL
;
269 struct ip_service
*ip_list
;
271 struct addrinfo aihints
;
272 char *saf_name
= NULL
;
275 DEBUG(10,("smb_krb5_locator_lookup: called for\n"));
276 DEBUGADD(10,("\tsvc: %s (%d), realm: %s\n",
277 locate_service_type_name(svc
), svc
, realm
));
278 DEBUGADD(10,("\tsocktype: %s (%d), family: %s (%d)\n",
279 socktype_name(socktype
), socktype
,
280 family_name(family
), family
));
282 ret
= smb_krb5_locator_lookup_sanity_check(svc
, realm
, socktype
, family
);
284 DEBUG(10,("smb_krb5_locator_lookup: returning ret: %s (%d)\n",
285 error_message(ret
), ret
));
289 /* first try to fetch from SAF cache */
291 saf_name
= saf_fetch(realm
);
292 if (!saf_name
|| strlen(saf_name
) == 0) {
293 DEBUG(10,("smb_krb5_locator_lookup: no SAF name stored for %s\n",
298 DEBUG(10,("smb_krb5_locator_lookup: got %s for %s from SAF cache\n",
301 ZERO_STRUCT(aihints
);
303 aihints
.ai_family
= family
;
304 aihints
.ai_socktype
= socktype
;
306 ret
= smb_krb5_locator_call_cbfunc(saf_name
,
307 get_service_from_locate_service_type(svc
),
318 /* now try to find via site-aware DNS SRV query */
320 sitename
= sitename_fetch(realm
);
321 status
= get_kdc_list(realm
, sitename
, &ip_list
, &count
);
323 /* if we didn't found any KDCs on our site go to the main list */
325 if (NT_STATUS_IS_OK(status
) && sitename
&& (count
== 0)) {
328 status
= get_kdc_list(realm
, NULL
, &ip_list
, &count
);
333 if (!NT_STATUS_IS_OK(status
)) {
334 DEBUG(10,("smb_krb5_locator_lookup: got %s (%s)\n",
336 error_message(nt_status_to_krb5(status
))));
337 #ifdef KRB5_PLUGIN_NO_HANDLE
338 return KRB5_PLUGIN_NO_HANDLE
;
340 return KRB5_KDC_UNREACH
; /* Heimdal */
344 for (i
=0; i
<count
; i
++) {
346 const char *host
= NULL
;
347 const char *port
= NULL
;
349 ZERO_STRUCT(aihints
);
351 aihints
.ai_family
= family
;
352 aihints
.ai_socktype
= socktype
;
354 host
= inet_ntoa(ip_list
[i
].ip
);
355 port
= get_service_from_locate_service_type(svc
);
357 ret
= smb_krb5_locator_call_cbfunc(host
,
372 #ifdef HEIMDAL_KRB5_LOCATE_PLUGIN_H
373 #define SMB_KRB5_LOCATOR_SYMBOL_NAME resolve /* Heimdal */
375 #define SMB_KRB5_LOCATOR_SYMBOL_NAME service_locator /* MIT */
378 const krb5plugin_service_locate_ftable SMB_KRB5_LOCATOR_SYMBOL_NAME
= {
380 smb_krb5_locator_init
,
381 smb_krb5_locator_close
,
382 smb_krb5_locator_lookup
,