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)
27 BOOL winbind_env_set(void);
29 #include <krb5/locate_plugin.h>
31 #ifndef KRB5_PLUGIN_NO_HANDLE
32 #define KRB5_PLUGIN_NO_HANDLE KRB5_KDC_UNREACH /* Heimdal */
35 static const char *get_service_from_locate_service_type(enum locate_service_type svc)
38 case locate_service_kdc:
39 case locate_service_master_kdc:
41 case locate_service_kadmin:
42 case locate_service_krb524:
45 case locate_service_kpasswd:
55 static const char *locate_service_type_name(enum locate_service_type svc)
58 case locate_service_kdc:
59 return "locate_service_kdc";
60 case locate_service_master_kdc:
61 return "locate_service_master_kdc";
62 case locate_service_kadmin:
63 return "locate_service_kadmin";
64 case locate_service_krb524:
65 return "locate_service_krb524";
66 case locate_service_kpasswd:
67 return "locate_service_kpasswd";
74 static const char *socktype_name(int socktype)
87 static const char *family_name(int family)
104 * Check input parameters, return KRB5_PLUGIN_NO_HANDLE for unsupported ones
107 * @param realm string
108 * @param socktype integer
109 * @param family integer
114 static int smb_krb5_locator_lookup_sanity_check(enum locate_service_type svc,
119 if (!realm || strlen(realm) == 0) {
124 case locate_service_kdc:
125 case locate_service_master_kdc:
126 case locate_service_kpasswd:
128 case locate_service_kadmin:
129 case locate_service_krb524:
130 return KRB5_PLUGIN_NO_HANDLE;
139 case AF_INET6: /* not yet */
140 return KRB5_PLUGIN_NO_HANDLE;
148 case 0: /* Heimdal uses that */
158 * Try to get addrinfo for a given host and call the krb5 callback
161 * @param service string
162 * @param in struct addrinfo hint
163 * @param cbfunc krb5 callback function
164 * @param cbdata void pointer cbdata
166 * @return krb5_error_code.
169 static krb5_error_code smb_krb5_locator_call_cbfunc(const char *name,
172 int (*cbfunc)(void *, int, struct sockaddr *),
175 struct addrinfo *out;
181 ret = getaddrinfo(name, service, in, &out);
186 if (ret == EAI_AGAIN) {
192 fprintf(stderr, "[%5u]: smb_krb5_locator_lookup: "
193 "getaddrinfo failed: %s (%d)\n",
194 (unsigned int)getpid(), gai_strerror(ret), ret);
197 return KRB5_PLUGIN_NO_HANDLE;
200 ret = cbfunc(cbdata, out->ai_socktype, out->ai_addr);
203 fprintf(stderr, "[%5u]: smb_krb5_locator_lookup: "
204 "failed to call callback: %s (%d)\n",
205 (unsigned int)getpid(), error_message(ret), ret);
215 * PUBLIC INTERFACE: locate init
217 * @param context krb5_context
218 * @param privata_data pointer to private data pointer
220 * @return krb5_error_code.
223 krb5_error_code smb_krb5_locator_init(krb5_context context,
230 * PUBLIC INTERFACE: close locate
232 * @param private_data pointer to private data
237 void smb_krb5_locator_close(void *private_data)
243 static int ask_winbind(const char *realm, char **dcname)
246 struct winbindd_request request;
247 struct winbindd_response response;
249 ZERO_STRUCT(request);
250 ZERO_STRUCT(response);
252 request.flags = 0x40020600;
258 strncpy(request.domain_name, realm,
259 sizeof(request.domain_name)-1);
261 status = winbindd_request_response(WINBINDD_DSGETDCNAME,
262 &request, &response);
263 if (status != NSS_STATUS_SUCCESS) {
265 fprintf(stderr,"[%5u]: smb_krb5_locator_lookup: failed with: %s\n",
266 (unsigned int)getpid(), nss_err_str(status));
271 *dcname = strdup(response.data.dc_name);
280 * PUBLIC INTERFACE: locate lookup
282 * @param private_data pointer to private data
283 * @param svc enum locate_service_type.
284 * @param realm string
285 * @param socktype integer
286 * @param family integer
287 * @param cbfunc callback function to send back entries
288 * @param cbdata void pointer to cbdata
290 * @return krb5_error_code.
293 krb5_error_code smb_krb5_locator_lookup(void *private_data,
294 enum locate_service_type svc,
298 int (*cbfunc)(void *, int, struct sockaddr *),
302 struct addrinfo aihints;
303 char *kdc_name = NULL;
304 const char *service = get_service_from_locate_service_type(svc);
306 ZERO_STRUCT(aihints);
309 fprintf(stderr,"[%5u]: smb_krb5_locator_lookup: called for '%s' "
311 "socktype: '%s' (%d), family: '%s' (%d)\n",
312 (unsigned int)getpid(), realm,
313 locate_service_type_name(svc), svc,
314 socktype_name(socktype), socktype,
315 family_name(family), family);
317 ret = smb_krb5_locator_lookup_sanity_check(svc, realm, socktype,
321 fprintf(stderr, "[%5u]: smb_krb5_locator_lookup: "
322 "returning ret: %s (%d)\n",
323 (unsigned int)getpid(), error_message(ret), ret);
328 if (!winbind_env_set()) {
329 if (!ask_winbind(realm, &kdc_name)) {
331 fprintf(stderr, "[%5u]: smb_krb5_locator_lookup: "
332 "failed to query winbindd\n",
333 (unsigned int)getpid());
338 const char *env = NULL;
340 if (asprintf(&var, "%s_%s",
341 WINBINDD_LOCATOR_KDC_ADDRESS, realm) == -1) {
347 fprintf(stderr, "[%5u]: smb_krb5_locator_lookup: "
348 "failed to get kdc from env %s\n",
349 (unsigned int)getpid(), var);
356 kdc_name = strdup(env);
362 fprintf(stderr, "[%5u]: smb_krb5_locator_lookup: "
363 "got '%s' for '%s' from winbindd\n", (unsigned int)getpid(),
367 aihints.ai_family = family;
368 aihints.ai_socktype = socktype;
370 ret = smb_krb5_locator_call_cbfunc(kdc_name,
379 return KRB5_PLUGIN_NO_HANDLE;
382 #ifdef HEIMDAL_KRB5_LOCATE_PLUGIN_H
383 #define SMB_KRB5_LOCATOR_SYMBOL_NAME resolve /* Heimdal */
385 #define SMB_KRB5_LOCATOR_SYMBOL_NAME service_locator /* MIT */
388 const krb5plugin_service_locate_ftable SMB_KRB5_LOCATOR_SYMBOL_NAME = {
390 smb_krb5_locator_init,
391 smb_krb5_locator_close,
392 smb_krb5_locator_lookup,