source: branches/samba-3.5.x/nsswitch/libwbclient/wbc_util.c

Last change on this file was 414, checked in by Herwig Bauernfeind, 15 years ago

Samba 3.5.0: Initial import

File size: 15.4 KB
Line 
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}
Note: See TracBrowser for help on using the repository browser.