2 Unix SMB/CIFS implementation.
3 kerberos locator plugin
4 Copyright (C) Guenther Deschner 2007-2008
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/>.
20 #include "nsswitch/winbind_client.h"
21 #include "libwbclient/wbclient.h"
27 #if defined(HAVE_KRB5) && defined(HAVE_KRB5_LOCATE_PLUGIN_H)
34 #include <krb5/locate_plugin.h>
36 #ifndef KRB5_PLUGIN_NO_HANDLE
37 #define KRB5_PLUGIN_NO_HANDLE KRB5_KDC_UNREACH /* Heimdal */
40 static const char *get_service_from_locate_service_type(enum locate_service_type svc
)
43 case locate_service_kdc
:
44 case locate_service_master_kdc
:
46 case locate_service_kadmin
:
47 case locate_service_krb524
:
50 case locate_service_kpasswd
:
60 static const char *locate_service_type_name(enum locate_service_type svc
)
63 case locate_service_kdc
:
64 return "locate_service_kdc";
65 case locate_service_master_kdc
:
66 return "locate_service_master_kdc";
67 case locate_service_kadmin
:
68 return "locate_service_kadmin";
69 case locate_service_krb524
:
70 return "locate_service_krb524";
71 case locate_service_kpasswd
:
72 return "locate_service_kpasswd";
79 static const char *socktype_name(int socktype
)
92 static const char *family_name(int family
)
99 #if defined(HAVE_IPV6)
111 * Check input parameters, return KRB5_PLUGIN_NO_HANDLE for unsupported ones
114 * @param realm string
115 * @param socktype integer
116 * @param family integer
121 static int smb_krb5_locator_lookup_sanity_check(enum locate_service_type svc
,
126 if (!realm
|| strlen(realm
) == 0) {
131 case locate_service_kdc
:
132 case locate_service_master_kdc
:
133 case locate_service_kpasswd
:
135 case locate_service_kadmin
:
136 case locate_service_krb524
:
137 return KRB5_PLUGIN_NO_HANDLE
;
145 #if defined(HAVE_IPV6)
156 case 0: /* Heimdal uses that */
166 * Try to get addrinfo for a given host and call the krb5 callback
169 * @param service string
170 * @param in struct addrinfo hint
171 * @param cbfunc krb5 callback function
172 * @param cbdata void pointer cbdata
174 * @return krb5_error_code.
177 static krb5_error_code
smb_krb5_locator_call_cbfunc(const char *name
,
180 int (*cbfunc
)(void *, int, struct sockaddr
*),
183 struct addrinfo
*out
= NULL
;
185 struct addrinfo
*res
= NULL
;
190 ret
= getaddrinfo(name
, service
, in
, &out
);
195 if ((ret
== EAI_AGAIN
) && (count
> 1)) {
201 fprintf(stderr
, "[%5u]: smb_krb5_locator_lookup: "
202 "getaddrinfo failed: %s (%d)\n",
203 (unsigned int)getpid(), gai_strerror(ret
), ret
);
206 return KRB5_PLUGIN_NO_HANDLE
;
209 for (res
= out
; res
; res
= res
->ai_next
) {
210 if (!res
->ai_addr
|| res
->ai_addrlen
== 0) {
214 ret
= cbfunc(cbdata
, res
->ai_socktype
, res
->ai_addr
);
217 fprintf(stderr
, "[%5u]: smb_krb5_locator_lookup: "
218 "failed to call callback: %s (%d)\n",
219 (unsigned int)getpid(), error_message(ret
), ret
);
232 * PUBLIC INTERFACE: locate init
234 * @param context krb5_context
235 * @param privata_data pointer to private data pointer
237 * @return krb5_error_code.
240 static krb5_error_code
smb_krb5_locator_init(krb5_context context
,
247 * PUBLIC INTERFACE: close locate
249 * @param private_data pointer to private data
254 static void smb_krb5_locator_close(void *private_data
)
260 static bool ask_winbind(const char *realm
, char **dcname
)
263 const char *dc
= NULL
;
264 struct wbcDomainControllerInfoEx
*dc_info
= NULL
;
267 flags
= WBC_LOOKUP_DC_KDC_REQUIRED
|
268 WBC_LOOKUP_DC_IS_DNS_NAME
|
269 WBC_LOOKUP_DC_RETURN_DNS_NAME
;
271 wbc_status
= wbcLookupDomainControllerEx(realm
, NULL
, NULL
, flags
, &dc_info
);
273 if (!WBC_ERROR_IS_OK(wbc_status
)) {
275 fprintf(stderr
,"[%5u]: smb_krb5_locator_lookup: failed with: %s\n",
276 (unsigned int)getpid(), wbcErrorString(wbc_status
));
281 if (!dc
&& dc_info
->dc_unc
) {
282 dc
= dc_info
->dc_unc
;
283 if (dc
[0] == '\\') dc
++;
284 if (dc
[0] == '\\') dc
++;
288 wbcFreeMemory(dc_info
);
292 *dcname
= strdup(dc
);
294 wbcFreeMemory(dc_info
);
298 wbcFreeMemory(dc_info
);
303 * PUBLIC INTERFACE: locate lookup
305 * @param private_data pointer to private data
306 * @param svc enum locate_service_type.
307 * @param realm string
308 * @param socktype integer
309 * @param family integer
310 * @param cbfunc callback function to send back entries
311 * @param cbdata void pointer to cbdata
313 * @return krb5_error_code.
316 static krb5_error_code
smb_krb5_locator_lookup(void *private_data
,
317 enum locate_service_type svc
,
321 int (*cbfunc
)(void *, int, struct sockaddr
*),
325 struct addrinfo aihints
;
326 char *kdc_name
= NULL
;
327 const char *service
= get_service_from_locate_service_type(svc
);
329 ZERO_STRUCT(aihints
);
332 fprintf(stderr
,"[%5u]: smb_krb5_locator_lookup: called for '%s' "
334 "socktype: '%s' (%d), family: '%s' (%d)\n",
335 (unsigned int)getpid(), realm
,
336 locate_service_type_name(svc
), svc
,
337 socktype_name(socktype
), socktype
,
338 family_name(family
), family
);
340 ret
= smb_krb5_locator_lookup_sanity_check(svc
, realm
, socktype
,
344 fprintf(stderr
, "[%5u]: smb_krb5_locator_lookup: "
345 "returning ret: %s (%d)\n",
346 (unsigned int)getpid(), error_message(ret
), ret
);
351 if (!winbind_env_set()) {
352 if (!ask_winbind(realm
, &kdc_name
)) {
354 fprintf(stderr
, "[%5u]: smb_krb5_locator_lookup: "
355 "failed to query winbindd\n",
356 (unsigned int)getpid());
361 const char *env
= NULL
;
363 if (asprintf(&var
, "%s_%s",
364 WINBINDD_LOCATOR_KDC_ADDRESS
, realm
) == -1) {
370 fprintf(stderr
, "[%5u]: smb_krb5_locator_lookup: "
371 "failed to get kdc from env %s\n",
372 (unsigned int)getpid(), var
);
379 kdc_name
= strdup(env
);
385 fprintf(stderr
, "[%5u]: smb_krb5_locator_lookup: "
386 "got '%s' for '%s' from winbindd\n", (unsigned int)getpid(),
390 aihints
.ai_family
= family
;
391 aihints
.ai_socktype
= socktype
;
393 ret
= smb_krb5_locator_call_cbfunc(kdc_name
,
402 return KRB5_PLUGIN_NO_HANDLE
;
405 #ifdef HEIMDAL_KRB5_LOCATE_PLUGIN_H
406 #define SMB_KRB5_LOCATOR_SYMBOL_NAME resolve /* Heimdal */
408 #define SMB_KRB5_LOCATOR_SYMBOL_NAME service_locator /* MIT */
411 _PUBLIC_
const krb5plugin_service_locate_ftable SMB_KRB5_LOCATOR_SYMBOL_NAME
= {
413 .init
= smb_krb5_locator_init
,
414 .fini
= smb_krb5_locator_close
,
415 #ifdef KRB5_PLUGIN_LOCATE_VERSION_2
416 .old_lookup
= smb_krb5_locator_lookup
,
418 .lookup
= smb_krb5_locator_lookup
,