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/>.
20 #include "nsswitch/winbind_client.h"
26 #if defined(HAVE_KRB5) && defined(HAVE_KRB5_LOCATE_PLUGIN_H)
28 #include <krb5/locate_plugin.h>
30 #ifndef KRB5_PLUGIN_NO_HANDLE
31 #define KRB5_PLUGIN_NO_HANDLE KRB5_KDC_UNREACH /* Heimdal */
34 static const char *get_service_from_locate_service_type(enum locate_service_type svc
)
37 case locate_service_kdc
:
38 case locate_service_master_kdc
:
40 case locate_service_kadmin
:
41 case locate_service_krb524
:
44 case locate_service_kpasswd
:
54 static const char *locate_service_type_name(enum locate_service_type svc
)
57 case locate_service_kdc
:
58 return "locate_service_kdc";
59 case locate_service_master_kdc
:
60 return "locate_service_master_kdc";
61 case locate_service_kadmin
:
62 return "locate_service_kadmin";
63 case locate_service_krb524
:
64 return "locate_service_krb524";
65 case locate_service_kpasswd
:
66 return "locate_service_kpasswd";
73 static const char *socktype_name(int socktype
)
86 static const char *family_name(int family
)
103 * Check input parameters, return KRB5_PLUGIN_NO_HANDLE for unsupported ones
106 * @param realm string
107 * @param socktype integer
108 * @param family integer
113 static int smb_krb5_locator_lookup_sanity_check(enum locate_service_type svc
,
118 if (!realm
|| strlen(realm
) == 0) {
123 case locate_service_kdc
:
124 case locate_service_master_kdc
:
125 case locate_service_kpasswd
:
127 case locate_service_kadmin
:
128 case locate_service_krb524
:
129 return KRB5_PLUGIN_NO_HANDLE
;
138 case AF_INET6
: /* not yet */
139 return KRB5_PLUGIN_NO_HANDLE
;
147 case 0: /* Heimdal uses that */
157 * Try to get addrinfo for a given host and call the krb5 callback
160 * @param service string
161 * @param in struct addrinfo hint
162 * @param cbfunc krb5 callback function
163 * @param cbdata void pointer cbdata
165 * @return krb5_error_code.
168 static krb5_error_code
smb_krb5_locator_call_cbfunc(const char *name
,
171 int (*cbfunc
)(void *, int, struct sockaddr
*),
174 struct addrinfo
*out
;
180 ret
= getaddrinfo(name
, service
, in
, &out
);
185 if (ret
== EAI_AGAIN
) {
191 fprintf(stderr
, "[%5u]: smb_krb5_locator_lookup: "
192 "getaddrinfo failed: %s (%d)\n",
193 (unsigned int)getpid(), gai_strerror(ret
), ret
);
196 return KRB5_PLUGIN_NO_HANDLE
;
199 ret
= cbfunc(cbdata
, out
->ai_socktype
, out
->ai_addr
);
202 fprintf(stderr
, "[%5u]: smb_krb5_locator_lookup: "
203 "failed to call callback: %s (%d)\n",
204 (unsigned int)getpid(), error_message(ret
), ret
);
214 * PUBLIC INTERFACE: locate init
216 * @param context krb5_context
217 * @param privata_data pointer to private data pointer
219 * @return krb5_error_code.
222 krb5_error_code
smb_krb5_locator_init(krb5_context context
,
229 * PUBLIC INTERFACE: close locate
231 * @param private_data pointer to private data
236 void smb_krb5_locator_close(void *private_data
)
242 static bool ask_winbind(const char *realm
, char **dcname
)
245 struct winbindd_request request
;
246 struct winbindd_response response
;
248 ZERO_STRUCT(request
);
249 ZERO_STRUCT(response
);
251 request
.flags
= 0x40020600;
257 strncpy(request
.domain_name
, realm
,
258 sizeof(request
.domain_name
)-1);
260 status
= winbindd_request_response(WINBINDD_DSGETDCNAME
,
261 &request
, &response
);
262 if (status
!= NSS_STATUS_SUCCESS
) {
264 fprintf(stderr
,"[%5u]: smb_krb5_locator_lookup: failed with: %s\n",
265 (unsigned int)getpid(), nss_err_str(status
));
270 *dcname
= strdup(response
.data
.dc_name
);
279 * PUBLIC INTERFACE: locate lookup
281 * @param private_data pointer to private data
282 * @param svc enum locate_service_type.
283 * @param realm string
284 * @param socktype integer
285 * @param family integer
286 * @param cbfunc callback function to send back entries
287 * @param cbdata void pointer to cbdata
289 * @return krb5_error_code.
292 krb5_error_code
smb_krb5_locator_lookup(void *private_data
,
293 enum locate_service_type svc
,
297 int (*cbfunc
)(void *, int, struct sockaddr
*),
301 struct addrinfo aihints
;
302 char *kdc_name
= NULL
;
303 const char *service
= get_service_from_locate_service_type(svc
);
305 ZERO_STRUCT(aihints
);
308 fprintf(stderr
,"[%5u]: smb_krb5_locator_lookup: called for '%s' "
310 "socktype: '%s' (%d), family: '%s' (%d)\n",
311 (unsigned int)getpid(), realm
,
312 locate_service_type_name(svc
), svc
,
313 socktype_name(socktype
), socktype
,
314 family_name(family
), family
);
316 ret
= smb_krb5_locator_lookup_sanity_check(svc
, realm
, socktype
,
320 fprintf(stderr
, "[%5u]: smb_krb5_locator_lookup: "
321 "returning ret: %s (%d)\n",
322 (unsigned int)getpid(), error_message(ret
), ret
);
327 if (!winbind_env_set()) {
328 if (!ask_winbind(realm
, &kdc_name
)) {
330 fprintf(stderr
, "[%5u]: smb_krb5_locator_lookup: "
331 "failed to query winbindd\n",
332 (unsigned int)getpid());
337 const char *env
= NULL
;
339 if (asprintf(&var
, "%s_%s",
340 WINBINDD_LOCATOR_KDC_ADDRESS
, realm
) == -1) {
346 fprintf(stderr
, "[%5u]: smb_krb5_locator_lookup: "
347 "failed to get kdc from env %s\n",
348 (unsigned int)getpid(), var
);
355 kdc_name
= strdup(env
);
361 fprintf(stderr
, "[%5u]: smb_krb5_locator_lookup: "
362 "got '%s' for '%s' from winbindd\n", (unsigned int)getpid(),
366 aihints
.ai_family
= family
;
367 aihints
.ai_socktype
= socktype
;
369 ret
= smb_krb5_locator_call_cbfunc(kdc_name
,
378 return KRB5_PLUGIN_NO_HANDLE
;
381 #ifdef HEIMDAL_KRB5_LOCATE_PLUGIN_H
382 #define SMB_KRB5_LOCATOR_SYMBOL_NAME resolve /* Heimdal */
384 #define SMB_KRB5_LOCATOR_SYMBOL_NAME service_locator /* MIT */
387 const krb5plugin_service_locate_ftable SMB_KRB5_LOCATOR_SYMBOL_NAME
= {
389 smb_krb5_locator_init
,
390 smb_krb5_locator_close
,
391 smb_krb5_locator_lookup
,