• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/samba-3.5.8/nsswitch/libwbclient/
1/*
2   Unix SMB/CIFS implementation.
3
4   Winbind client API
5
6   Copyright (C) Gerald (Jerry) Carter 2007-2008
7
8
9   This library is free software; you can redistribute it and/or
10   modify it under the terms of the GNU Lesser General Public
11   License as published by the Free Software Foundation; either
12   version 3 of the License, or (at your option) any later version.
13
14   This library is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17   Library General Public License for more details.
18
19   You should have received a copy of the GNU Lesser General Public License
20   along with this program.  If not, see <http://www.gnu.org/licenses/>.
21*/
22
23/* Required Headers */
24
25#include "replace.h"
26#include "libwbclient.h"
27
28
29
30/** @brief Ping winbindd to see if the daemon is running
31 *
32 * @return #wbcErr
33 **/
34
35wbcErr wbcPing(void)
36{
37	struct winbindd_request request;
38	struct winbindd_response response;
39
40	/* Initialize request */
41
42	ZERO_STRUCT(request);
43	ZERO_STRUCT(response);
44
45	return wbcRequestResponse(WINBINDD_PING, &request, &response);
46}
47
48wbcErr wbcInterfaceDetails(struct wbcInterfaceDetails **_details)
49{
50	wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
51	struct wbcInterfaceDetails *info;
52	struct wbcDomainInfo *domain = NULL;
53	struct winbindd_request request;
54	struct winbindd_response response;
55
56	/* Initialize request */
57
58	ZERO_STRUCT(request);
59	ZERO_STRUCT(response);
60
61	info = talloc(NULL, struct wbcInterfaceDetails);
62	BAIL_ON_PTR_ERROR(info, wbc_status);
63
64	/* first the interface version */
65	wbc_status = wbcRequestResponse(WINBINDD_INTERFACE_VERSION, NULL, &response);
66	BAIL_ON_WBC_ERROR(wbc_status);
67	info->interface_version = response.data.interface_version;
68
69	/* then the samba version and the winbind separator */
70	wbc_status = wbcRequestResponse(WINBINDD_INFO, NULL, &response);
71	BAIL_ON_WBC_ERROR(wbc_status);
72
73	info->winbind_version = talloc_strdup(info,
74					      response.data.info.samba_version);
75	BAIL_ON_PTR_ERROR(info->winbind_version, wbc_status);
76	info->winbind_separator = response.data.info.winbind_separator;
77
78	/* then the local netbios name */
79	wbc_status = wbcRequestResponse(WINBINDD_NETBIOS_NAME, NULL, &response);
80	BAIL_ON_WBC_ERROR(wbc_status);
81
82	info->netbios_name = talloc_strdup(info,
83					   response.data.netbios_name);
84	BAIL_ON_PTR_ERROR(info->netbios_name, wbc_status);
85
86	/* then the local workgroup name */
87	wbc_status = wbcRequestResponse(WINBINDD_DOMAIN_NAME, NULL, &response);
88	BAIL_ON_WBC_ERROR(wbc_status);
89
90	info->netbios_domain = talloc_strdup(info,
91					response.data.domain_name);
92	BAIL_ON_PTR_ERROR(info->netbios_domain, wbc_status);
93
94	wbc_status = wbcDomainInfo(info->netbios_domain, &domain);
95	if (wbc_status == WBC_ERR_DOMAIN_NOT_FOUND) {
96		/* maybe it's a standalone server */
97		domain = NULL;
98		wbc_status = WBC_ERR_SUCCESS;
99	} else {
100		BAIL_ON_WBC_ERROR(wbc_status);
101	}
102
103	if (domain) {
104		info->dns_domain = talloc_strdup(info,
105						 domain->dns_name);
106		wbcFreeMemory(domain);
107		BAIL_ON_PTR_ERROR(info->dns_domain, wbc_status);
108	} else {
109		info->dns_domain = NULL;
110	}
111
112	*_details = info;
113	info = NULL;
114
115	wbc_status = WBC_ERR_SUCCESS;
116
117done:
118	talloc_free(info);
119	return wbc_status;
120}
121
122
123/* Lookup the current status of a trusted domain */
124wbcErr wbcDomainInfo(const char *domain, struct wbcDomainInfo **dinfo)
125{
126	struct winbindd_request request;
127	struct winbindd_response response;
128	wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
129	struct wbcDomainInfo *info = NULL;
130
131	if (!domain || !dinfo) {
132		wbc_status = WBC_ERR_INVALID_PARAM;
133		BAIL_ON_WBC_ERROR(wbc_status);
134	}
135
136	/* Initialize request */
137
138	ZERO_STRUCT(request);
139	ZERO_STRUCT(response);
140
141	strncpy(request.domain_name, domain,
142		sizeof(request.domain_name)-1);
143
144	wbc_status = wbcRequestResponse(WINBINDD_DOMAIN_INFO,
145					&request,
146					&response);
147	BAIL_ON_WBC_ERROR(wbc_status);
148
149	info = talloc(NULL, struct wbcDomainInfo);
150	BAIL_ON_PTR_ERROR(info, wbc_status);
151
152	info->short_name = talloc_strdup(info,
153					 response.data.domain_info.name);
154	BAIL_ON_PTR_ERROR(info->short_name, wbc_status);
155
156	info->dns_name = talloc_strdup(info,
157				       response.data.domain_info.alt_name);
158	BAIL_ON_PTR_ERROR(info->dns_name, wbc_status);
159
160	wbc_status = wbcStringToSid(response.data.domain_info.sid,
161				    &info->sid);
162	BAIL_ON_WBC_ERROR(wbc_status);
163
164	if (response.data.domain_info.native_mode)
165		info->domain_flags |= WBC_DOMINFO_DOMAIN_NATIVE;
166	if (response.data.domain_info.active_directory)
167		info->domain_flags |= WBC_DOMINFO_DOMAIN_AD;
168	if (response.data.domain_info.primary)
169		info->domain_flags |= WBC_DOMINFO_DOMAIN_PRIMARY;
170
171	*dinfo = info;
172
173	wbc_status = WBC_ERR_SUCCESS;
174
175 done:
176	if (!WBC_ERROR_IS_OK(wbc_status)) {
177		talloc_free(info);
178	}
179
180	return wbc_status;
181}
182
183
184/* Resolve a NetbiosName via WINS */
185wbcErr wbcResolveWinsByName(const char *name, char **ip)
186{
187	struct winbindd_request request;
188	struct winbindd_response response;
189	wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
190	char *ipaddr;
191
192	ZERO_STRUCT(request);
193	ZERO_STRUCT(response);
194
195	/* Send request */
196
197	strncpy(request.data.winsreq, name,
198		sizeof(request.data.winsreq)-1);
199
200	wbc_status = wbcRequestResponse(WINBINDD_WINS_BYNAME,
201					&request,
202					&response);
203	BAIL_ON_WBC_ERROR(wbc_status);
204
205	/* Display response */
206
207	ipaddr = talloc_strdup(NULL, response.data.winsresp);
208	BAIL_ON_PTR_ERROR(ipaddr, wbc_status);
209
210	*ip = ipaddr;
211	wbc_status = WBC_ERR_SUCCESS;
212
213 done:
214	return wbc_status;
215}
216
217/* Resolve an IP address via WINS into a NetbiosName */
218wbcErr wbcResolveWinsByIP(const char *ip, char **name)
219{
220	struct winbindd_request request;
221	struct winbindd_response response;
222	wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
223	char *name_str;
224
225	ZERO_STRUCT(request);
226	ZERO_STRUCT(response);
227
228	/* Send request */
229
230	strncpy(request.data.winsreq, ip,
231		sizeof(request.data.winsreq)-1);
232
233	wbc_status = wbcRequestResponse(WINBINDD_WINS_BYIP,
234					&request,
235					&response);
236	BAIL_ON_WBC_ERROR(wbc_status);
237
238	/* Display response */
239
240	name_str = talloc_strdup(NULL, response.data.winsresp);
241	BAIL_ON_PTR_ERROR(name_str, wbc_status);
242
243	*name = name_str;
244	wbc_status = WBC_ERR_SUCCESS;
245
246 done:
247	return wbc_status;
248}
249
250/**
251 */
252
253static wbcErr process_domain_info_string(TALLOC_CTX *ctx,
254					 struct wbcDomainInfo *info,
255					 char *info_string)
256{
257	wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
258	char *r = NULL;
259	char *s = NULL;
260
261	if (!info || !info_string) {
262		wbc_status = WBC_ERR_INVALID_PARAM;
263		BAIL_ON_WBC_ERROR(wbc_status);
264	}
265
266	ZERO_STRUCTP(info);
267
268	r = info_string;
269
270	/* Short Name */
271	if ((s = strchr(r, '\\')) == NULL) {
272		wbc_status = WBC_ERR_INVALID_RESPONSE;
273		BAIL_ON_WBC_ERROR(wbc_status);
274	}
275	*s = '\0';
276	s++;
277
278	info->short_name = talloc_strdup(ctx, r);
279	BAIL_ON_PTR_ERROR(info->short_name, wbc_status);
280
281
282	/* DNS Name */
283	r = s;
284	if ((s = strchr(r, '\\')) == NULL) {
285		wbc_status = WBC_ERR_INVALID_RESPONSE;
286		BAIL_ON_WBC_ERROR(wbc_status);
287	}
288	*s = '\0';
289	s++;
290
291	info->dns_name = talloc_strdup(ctx, r);
292	BAIL_ON_PTR_ERROR(info->dns_name, wbc_status);
293
294	/* SID */
295	r = s;
296	if ((s = strchr(r, '\\')) == NULL) {
297		wbc_status = WBC_ERR_INVALID_RESPONSE;
298		BAIL_ON_WBC_ERROR(wbc_status);
299	}
300	*s = '\0';
301	s++;
302
303	wbc_status = wbcStringToSid(r, &info->sid);
304	BAIL_ON_WBC_ERROR(wbc_status);
305
306	/* Trust type */
307	r = s;
308	if ((s = strchr(r, '\\')) == NULL) {
309		wbc_status = WBC_ERR_INVALID_RESPONSE;
310		BAIL_ON_WBC_ERROR(wbc_status);
311	}
312	*s = '\0';
313	s++;
314
315	if (strcmp(r, "None") == 0) {
316		info->trust_type = WBC_DOMINFO_TRUSTTYPE_NONE;
317	} else if (strcmp(r, "External") == 0) {
318		info->trust_type = WBC_DOMINFO_TRUSTTYPE_EXTERNAL;
319	} else if (strcmp(r, "Forest") == 0) {
320		info->trust_type = WBC_DOMINFO_TRUSTTYPE_FOREST;
321	} else if (strcmp(r, "In Forest") == 0) {
322		info->trust_type = WBC_DOMINFO_TRUSTTYPE_IN_FOREST;
323	} else {
324		wbc_status = WBC_ERR_INVALID_RESPONSE;
325		BAIL_ON_WBC_ERROR(wbc_status);
326	}
327
328	/* Transitive */
329	r = s;
330	if ((s = strchr(r, '\\')) == NULL) {
331		wbc_status = WBC_ERR_INVALID_RESPONSE;
332		BAIL_ON_WBC_ERROR(wbc_status);
333	}
334	*s = '\0';
335	s++;
336
337	if (strcmp(r, "Yes") == 0) {
338		info->trust_flags |= WBC_DOMINFO_TRUST_TRANSITIVE;
339	}
340
341	/* Incoming */
342	r = s;
343	if ((s = strchr(r, '\\')) == NULL) {
344		wbc_status = WBC_ERR_INVALID_RESPONSE;
345		BAIL_ON_WBC_ERROR(wbc_status);
346	}
347	*s = '\0';
348	s++;
349
350	if (strcmp(r, "Yes") == 0) {
351		info->trust_flags |= WBC_DOMINFO_TRUST_INCOMING;
352	}
353
354	/* Outgoing */
355	r = s;
356	if ((s = strchr(r, '\\')) == NULL) {
357		wbc_status = WBC_ERR_INVALID_RESPONSE;
358		BAIL_ON_WBC_ERROR(wbc_status);
359	}
360	*s = '\0';
361	s++;
362
363	if (strcmp(r, "Yes") == 0) {
364		info->trust_flags |= WBC_DOMINFO_TRUST_OUTGOING;
365	}
366
367	/* Online/Offline status */
368
369	r = s;
370	if (r == NULL) {
371		wbc_status = WBC_ERR_INVALID_RESPONSE;
372		BAIL_ON_WBC_ERROR(wbc_status);
373	}
374	if ( strcmp(r, "Offline") == 0) {
375		info->domain_flags |= WBC_DOMINFO_DOMAIN_OFFLINE;
376	}
377
378	wbc_status = WBC_ERR_SUCCESS;
379
380 done:
381	return wbc_status;
382}
383
384/* Enumerate the domain trusts known by Winbind */
385wbcErr wbcListTrusts(struct wbcDomainInfo **domains, size_t *num_domains)
386{
387	struct winbindd_response response;
388	wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
389	char *p = NULL;
390	char *q = NULL;
391	char *extra_data = NULL;
392	int count = 0;
393	struct wbcDomainInfo *d_list = NULL;
394	int i = 0;
395
396	*domains = NULL;
397	*num_domains = 0;
398
399	ZERO_STRUCT(response);
400
401	/* Send request */
402
403	wbc_status = wbcRequestResponse(WINBINDD_LIST_TRUSTDOM,
404					NULL,
405					&response);
406	BAIL_ON_WBC_ERROR(wbc_status);
407
408	/* Decode the response */
409
410	p = (char *)response.extra_data.data;
411
412	if ((p == NULL) || (strlen(p) == 0)) {
413		/* We should always at least get back our
414		   own SAM domain */
415
416		wbc_status = WBC_ERR_DOMAIN_NOT_FOUND;
417		BAIL_ON_WBC_ERROR(wbc_status);
418	}
419
420	/* Count number of domains */
421
422	count = 0;
423	while (p) {
424		count++;
425
426		if ((q = strchr(p, '\n')) != NULL)
427			q++;
428		p = q;
429	}
430
431	d_list = talloc_array(NULL, struct wbcDomainInfo, count);
432	BAIL_ON_PTR_ERROR(d_list, wbc_status);
433
434	extra_data = strdup((char*)response.extra_data.data);
435	BAIL_ON_PTR_ERROR(extra_data, wbc_status);
436
437	p = extra_data;
438
439	/* Outer loop processes the list of domain information */
440
441	for (i=0; i<count && p; i++) {
442		char *next = strchr(p, '\n');
443
444		if (next) {
445			*next = '\0';
446			next++;
447		}
448
449		wbc_status = process_domain_info_string(d_list, &d_list[i], p);
450		BAIL_ON_WBC_ERROR(wbc_status);
451
452		p = next;
453	}
454
455	*domains = d_list;
456	*num_domains = i;
457
458 done:
459	if (!WBC_ERROR_IS_OK(wbc_status)) {
460		if (d_list)
461			talloc_free(d_list);
462		if (extra_data)
463			free(extra_data);
464	}
465
466	return wbc_status;
467}
468
469/* Enumerate the domain trusts known by Winbind */
470wbcErr wbcLookupDomainController(const char *domain,
471				 uint32_t flags,
472				struct wbcDomainControllerInfo **dc_info)
473{
474	wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
475	struct winbindd_request request;
476	struct winbindd_response response;
477	struct wbcDomainControllerInfo *dc = NULL;
478
479	/* validate input params */
480
481	if (!domain || !dc_info) {
482		wbc_status = WBC_ERR_INVALID_PARAM;
483		BAIL_ON_WBC_ERROR(wbc_status);
484	}
485
486	ZERO_STRUCT(request);
487	ZERO_STRUCT(response);
488
489	strncpy(request.data.dsgetdcname.domain_name, domain,
490		sizeof(request.data.dsgetdcname.domain_name)-1);
491
492	request.flags = flags;
493
494	dc = talloc(NULL, struct wbcDomainControllerInfo);
495	BAIL_ON_PTR_ERROR(dc, wbc_status);
496
497	/* Send request */
498
499	wbc_status = wbcRequestResponse(WINBINDD_DSGETDCNAME,
500					&request,
501					&response);
502	BAIL_ON_WBC_ERROR(wbc_status);
503
504	dc->dc_name = talloc_strdup(dc, response.data.dsgetdcname.dc_unc);
505	BAIL_ON_PTR_ERROR(dc->dc_name, wbc_status);
506
507	*dc_info = dc;
508
509done:
510	if (!WBC_ERROR_IS_OK(wbc_status)) {
511		talloc_free(dc);
512	}
513
514	return wbc_status;
515}
516
517static wbcErr wbc_create_domain_controller_info_ex(TALLOC_CTX *mem_ctx,
518						   const struct winbindd_response *resp,
519						   struct wbcDomainControllerInfoEx **_i)
520{
521	wbcErr wbc_status = WBC_ERR_SUCCESS;
522	struct wbcDomainControllerInfoEx *i;
523	struct wbcGuid guid;
524
525	i = talloc(mem_ctx, struct wbcDomainControllerInfoEx);
526	BAIL_ON_PTR_ERROR(i, wbc_status);
527
528	i->dc_unc = talloc_strdup(i, resp->data.dsgetdcname.dc_unc);
529	BAIL_ON_PTR_ERROR(i->dc_unc, wbc_status);
530
531	i->dc_address = talloc_strdup(i, resp->data.dsgetdcname.dc_address);
532	BAIL_ON_PTR_ERROR(i->dc_address, wbc_status);
533
534	i->dc_address_type = resp->data.dsgetdcname.dc_address_type;
535
536	wbc_status = wbcStringToGuid(resp->data.dsgetdcname.domain_guid, &guid);
537	if (WBC_ERROR_IS_OK(wbc_status)) {
538		i->domain_guid = talloc(i, struct wbcGuid);
539		BAIL_ON_PTR_ERROR(i->domain_guid, wbc_status);
540
541		*i->domain_guid = guid;
542	} else {
543		i->domain_guid = NULL;
544	}
545
546	i->domain_name = talloc_strdup(i, resp->data.dsgetdcname.domain_name);
547	BAIL_ON_PTR_ERROR(i->domain_name, wbc_status);
548
549	if (resp->data.dsgetdcname.forest_name[0] != '\0') {
550		i->forest_name = talloc_strdup(i,
551			resp->data.dsgetdcname.forest_name);
552		BAIL_ON_PTR_ERROR(i->forest_name, wbc_status);
553	} else {
554		i->forest_name = NULL;
555	}
556
557	i->dc_flags = resp->data.dsgetdcname.dc_flags;
558
559	if (resp->data.dsgetdcname.dc_site_name[0] != '\0') {
560		i->dc_site_name = talloc_strdup(i,
561			resp->data.dsgetdcname.dc_site_name);
562		BAIL_ON_PTR_ERROR(i->dc_site_name, wbc_status);
563	} else {
564		i->dc_site_name = NULL;
565	}
566
567	if (resp->data.dsgetdcname.client_site_name[0] != '\0') {
568		i->client_site_name = talloc_strdup(i,
569			resp->data.dsgetdcname.client_site_name);
570		BAIL_ON_PTR_ERROR(i->client_site_name, wbc_status);
571	} else {
572		i->client_site_name = NULL;
573	}
574
575	*_i = i;
576	i = NULL;
577
578done:
579	talloc_free(i);
580	return wbc_status;
581}
582
583/* Get extended domain controller information */
584wbcErr wbcLookupDomainControllerEx(const char *domain,
585				   struct wbcGuid *guid,
586				   const char *site,
587				   uint32_t flags,
588				   struct wbcDomainControllerInfoEx **dc_info)
589{
590	wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
591	struct winbindd_request request;
592	struct winbindd_response response;
593
594	/* validate input params */
595
596	if (!domain || !dc_info) {
597		wbc_status = WBC_ERR_INVALID_PARAM;
598		BAIL_ON_WBC_ERROR(wbc_status);
599	}
600
601	ZERO_STRUCT(request);
602	ZERO_STRUCT(response);
603
604	request.data.dsgetdcname.flags = flags;
605
606	strncpy(request.data.dsgetdcname.domain_name, domain,
607		sizeof(request.data.dsgetdcname.domain_name)-1);
608
609	if (site) {
610		strncpy(request.data.dsgetdcname.site_name, site,
611			sizeof(request.data.dsgetdcname.site_name)-1);
612	}
613
614	if (guid) {
615		char *str = NULL;
616
617		wbc_status = wbcGuidToString(guid, &str);
618		BAIL_ON_WBC_ERROR(wbc_status);
619
620		strncpy(request.data.dsgetdcname.domain_guid, str,
621			sizeof(request.data.dsgetdcname.domain_guid)-1);
622
623		wbcFreeMemory(str);
624	}
625
626	/* Send request */
627
628	wbc_status = wbcRequestResponse(WINBINDD_DSGETDCNAME,
629					&request,
630					&response);
631	BAIL_ON_WBC_ERROR(wbc_status);
632
633	if (dc_info) {
634		wbc_status = wbc_create_domain_controller_info_ex(NULL,
635								  &response,
636								  dc_info);
637		BAIL_ON_WBC_ERROR(wbc_status);
638	}
639
640	wbc_status = WBC_ERR_SUCCESS;
641done:
642	return wbc_status;
643}
644
645/* Initialize a named blob and add to list of blobs */
646wbcErr wbcAddNamedBlob(size_t *num_blobs,
647		       struct wbcNamedBlob **blobs,
648		       const char *name,
649		       uint32_t flags,
650		       uint8_t *data,
651		       size_t length)
652{
653	wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
654	struct wbcNamedBlob blob;
655
656	*blobs = talloc_realloc(NULL, *blobs, struct wbcNamedBlob,
657				*(num_blobs)+1);
658	BAIL_ON_PTR_ERROR(*blobs, wbc_status);
659
660	blob.name		= talloc_strdup(*blobs, name);
661	BAIL_ON_PTR_ERROR(blob.name, wbc_status);
662	blob.flags		= flags;
663	blob.blob.length	= length;
664	blob.blob.data		= (uint8_t *)talloc_memdup(*blobs, data, length);
665	BAIL_ON_PTR_ERROR(blob.blob.data, wbc_status);
666
667	(*(blobs))[*num_blobs] = blob;
668	*(num_blobs) += 1;
669
670	wbc_status = WBC_ERR_SUCCESS;
671done:
672	if (!WBC_ERROR_IS_OK(wbc_status) && blobs) {
673		wbcFreeMemory(*blobs);
674	}
675	return wbc_status;
676}
677