lib:ldb: Document environment variables in ldb manpage
[Samba.git] / nsswitch / libwbclient / wbc_util.c
blob9e54baf54d74771e6ac7e1ed92f5c3c599076ce6
1 /*
2 Unix SMB/CIFS implementation.
4 Winbind client asynchronous API, utility functions
6 Copyright (C) Gerald (Jerry) Carter 2007-2008
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.
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.
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/>.
23 /* Required Headers */
25 #include "replace.h"
26 #include "libwbclient.h"
27 #include "../winbind_client.h"
29 /** @brief Ping winbindd to see if the daemon is running
31 * @param *ctx wbclient Context
33 * @return #wbcErr
34 **/
35 _PUBLIC_
36 wbcErr wbcCtxPing(struct wbcContext *ctx)
38 struct winbindd_request request;
39 struct winbindd_response response;
41 /* Initialize request */
43 ZERO_STRUCT(request);
44 ZERO_STRUCT(response);
46 return wbcRequestResponse(ctx, WINBINDD_PING, &request, &response);
49 _PUBLIC_
50 wbcErr wbcPing(void)
52 return wbcCtxPing(NULL);
55 static void wbcInterfaceDetailsDestructor(void *ptr)
57 struct wbcInterfaceDetails *i = (struct wbcInterfaceDetails *)ptr;
58 free(i->winbind_version);
59 free(i->netbios_name);
60 free(i->netbios_domain);
61 free(i->dns_domain);
64 /**
65 * @brief Query useful information about the winbind service
67 * @param *_details pointer to hold the struct wbcInterfaceDetails
69 * @return #wbcErr
72 _PUBLIC_
73 wbcErr wbcCtxInterfaceDetails(struct wbcContext *ctx,
74 struct wbcInterfaceDetails **_details)
76 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
77 struct wbcInterfaceDetails *info;
78 struct wbcDomainInfo *domain = NULL;
79 struct winbindd_request request;
80 struct winbindd_response response;
82 /* Initialize request */
84 ZERO_STRUCT(request);
85 ZERO_STRUCT(response);
87 info = (struct wbcInterfaceDetails *)wbcAllocateMemory(
88 1, sizeof(struct wbcInterfaceDetails),
89 wbcInterfaceDetailsDestructor);
90 BAIL_ON_PTR_ERROR(info, wbc_status);
92 /* first the interface version */
93 wbc_status = wbcRequestResponse(ctx, WINBINDD_INTERFACE_VERSION,
94 NULL, &response);
95 BAIL_ON_WBC_ERROR(wbc_status);
96 info->interface_version = response.data.interface_version;
98 /* then the samba version and the winbind separator */
99 wbc_status = wbcRequestResponse(ctx, WINBINDD_INFO, NULL, &response);
100 BAIL_ON_WBC_ERROR(wbc_status);
102 info->winbind_version = strdup(response.data.info.samba_version);
103 BAIL_ON_PTR_ERROR(info->winbind_version, wbc_status);
104 info->winbind_separator = response.data.info.winbind_separator;
106 /* then the local netbios name */
107 wbc_status = wbcRequestResponse(ctx, WINBINDD_NETBIOS_NAME,
108 NULL, &response);
109 BAIL_ON_WBC_ERROR(wbc_status);
111 info->netbios_name = strdup(response.data.netbios_name);
112 BAIL_ON_PTR_ERROR(info->netbios_name, wbc_status);
114 /* then the local workgroup name */
115 wbc_status = wbcRequestResponse(ctx, WINBINDD_DOMAIN_NAME,
116 NULL, &response);
117 BAIL_ON_WBC_ERROR(wbc_status);
119 info->netbios_domain = strdup(response.data.domain_name);
120 BAIL_ON_PTR_ERROR(info->netbios_domain, wbc_status);
122 wbc_status = wbcCtxDomainInfo(ctx, info->netbios_domain, &domain);
123 if (wbc_status == WBC_ERR_DOMAIN_NOT_FOUND) {
124 /* maybe it's a standalone server */
125 domain = NULL;
126 } else {
127 BAIL_ON_WBC_ERROR(wbc_status);
130 if (domain) {
131 info->dns_domain = strdup(domain->dns_name);
132 wbcFreeMemory(domain);
133 BAIL_ON_PTR_ERROR(info->dns_domain, wbc_status);
134 } else {
135 info->dns_domain = NULL;
138 *_details = info;
139 info = NULL;
141 wbc_status = WBC_ERR_SUCCESS;
143 done:
144 wbcFreeMemory(info);
145 return wbc_status;
148 _PUBLIC_
149 wbcErr wbcInterfaceDetails(struct wbcInterfaceDetails **_details)
151 return wbcCtxInterfaceDetails(NULL, _details);
154 static void wbcDomainInfoDestructor(void *ptr)
156 struct wbcDomainInfo *i = (struct wbcDomainInfo *)ptr;
157 free(i->short_name);
158 free(i->dns_name);
161 /** @brief Lookup the current status of a trusted domain, sync wrapper
163 * @param domain Domain to query
164 * @param *dinfo Pointer to returned struct wbcDomainInfo
166 * @return #wbcErr
169 _PUBLIC_
170 wbcErr wbcCtxDomainInfo(struct wbcContext *ctx,
171 const char *domain,
172 struct wbcDomainInfo **dinfo)
174 struct winbindd_request request;
175 struct winbindd_response response;
176 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
177 struct wbcDomainInfo *info = NULL;
179 if (!domain || !dinfo) {
180 wbc_status = WBC_ERR_INVALID_PARAM;
181 BAIL_ON_WBC_ERROR(wbc_status);
184 /* Initialize request */
186 ZERO_STRUCT(request);
187 ZERO_STRUCT(response);
189 strncpy(request.domain_name, domain,
190 sizeof(request.domain_name)-1);
192 wbc_status = wbcRequestResponse(ctx, WINBINDD_DOMAIN_INFO,
193 &request,
194 &response);
195 BAIL_ON_WBC_ERROR(wbc_status);
197 info = (struct wbcDomainInfo *)wbcAllocateMemory(
198 1, sizeof(struct wbcDomainInfo), wbcDomainInfoDestructor);
199 BAIL_ON_PTR_ERROR(info, wbc_status);
201 info->short_name = strdup(response.data.domain_info.name);
202 BAIL_ON_PTR_ERROR(info->short_name, wbc_status);
204 info->dns_name = strdup(response.data.domain_info.alt_name);
205 BAIL_ON_PTR_ERROR(info->dns_name, wbc_status);
207 wbc_status = wbcStringToSid(response.data.domain_info.sid,
208 &info->sid);
209 BAIL_ON_WBC_ERROR(wbc_status);
211 if (response.data.domain_info.native_mode)
212 info->domain_flags |= WBC_DOMINFO_DOMAIN_NATIVE;
213 if (response.data.domain_info.active_directory)
214 info->domain_flags |= WBC_DOMINFO_DOMAIN_AD;
215 if (response.data.domain_info.primary)
216 info->domain_flags |= WBC_DOMINFO_DOMAIN_PRIMARY;
218 *dinfo = info;
219 info = NULL;
221 wbc_status = WBC_ERR_SUCCESS;
223 done:
224 wbcFreeMemory(info);
225 return wbc_status;
228 _PUBLIC_
229 wbcErr wbcDomainInfo(const char *domain, struct wbcDomainInfo **dinfo)
231 return wbcCtxDomainInfo(NULL, domain, dinfo);
234 /* Get the list of current DCs */
235 _PUBLIC_
236 wbcErr wbcCtxDcInfo(struct wbcContext *ctx,
237 const char *domain, size_t *num_dcs,
238 const char ***dc_names, const char ***dc_ips)
240 struct winbindd_request request;
241 struct winbindd_response response;
242 const char **names = NULL;
243 const char **ips = NULL;
244 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
245 size_t extra_len;
246 int i;
247 char *p;
249 /* Initialise request */
251 ZERO_STRUCT(request);
252 ZERO_STRUCT(response);
254 if (domain != NULL) {
255 strncpy(request.domain_name, domain,
256 sizeof(request.domain_name) - 1);
259 wbc_status = wbcRequestResponse(ctx, WINBINDD_DC_INFO,
260 &request, &response);
261 BAIL_ON_WBC_ERROR(wbc_status);
263 names = wbcAllocateStringArray(response.data.num_entries);
264 BAIL_ON_PTR_ERROR(names, wbc_status);
266 ips = wbcAllocateStringArray(response.data.num_entries);
267 BAIL_ON_PTR_ERROR(ips, wbc_status);
269 wbc_status = WBC_ERR_INVALID_RESPONSE;
271 p = (char *)response.extra_data.data;
273 if (response.length < (sizeof(struct winbindd_response)+1)) {
274 goto done;
277 extra_len = response.length - sizeof(struct winbindd_response);
279 if (p[extra_len-1] != '\0') {
280 goto done;
283 for (i=0; i<response.data.num_entries; i++) {
284 char *q;
286 q = strchr(p, '\n');
287 if (q == NULL) {
288 goto done;
290 names[i] = strndup(p, q-p);
291 BAIL_ON_PTR_ERROR(names[i], wbc_status);
292 p = q+1;
294 q = strchr(p, '\n');
295 if (q == NULL) {
296 goto done;
298 ips[i] = strndup(p, q-p);
299 BAIL_ON_PTR_ERROR(ips[i], wbc_status);
300 p = q+1;
302 if (p[0] != '\0') {
303 goto done;
306 wbc_status = WBC_ERR_SUCCESS;
307 done:
308 if (response.extra_data.data)
309 free(response.extra_data.data);
311 if (WBC_ERROR_IS_OK(wbc_status)) {
312 *num_dcs = response.data.num_entries;
313 *dc_names = names;
314 names = NULL;
315 *dc_ips = ips;
316 ips = NULL;
318 wbcFreeMemory(names);
319 wbcFreeMemory(ips);
320 return wbc_status;
323 _PUBLIC_
324 wbcErr wbcDcInfo(const char *domain, size_t *num_dcs,
325 const char ***dc_names, const char ***dc_ips)
327 return wbcCtxDcInfo(NULL, domain, num_dcs, dc_names, dc_ips);
330 /* Resolve a NetbiosName via WINS */
331 _PUBLIC_
332 wbcErr wbcCtxResolveWinsByName(struct wbcContext *ctx,
333 const char *name, char **ip)
335 struct winbindd_request request;
336 struct winbindd_response response;
337 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
338 char *ipaddr;
340 ZERO_STRUCT(request);
341 ZERO_STRUCT(response);
343 /* Send request */
345 strncpy(request.data.winsreq, name,
346 sizeof(request.data.winsreq)-1);
348 wbc_status = wbcRequestResponse(ctx, WINBINDD_WINS_BYNAME,
349 &request,
350 &response);
351 BAIL_ON_WBC_ERROR(wbc_status);
353 /* Display response */
355 ipaddr = wbcStrDup(response.data.winsresp);
356 BAIL_ON_PTR_ERROR(ipaddr, wbc_status);
358 *ip = ipaddr;
359 wbc_status = WBC_ERR_SUCCESS;
361 done:
362 return wbc_status;
365 _PUBLIC_
366 wbcErr wbcResolveWinsByName(const char *name, char **ip)
368 return wbcCtxResolveWinsByName(NULL, name, ip);
371 /* Resolve an IP address via WINS into a NetbiosName */
372 _PUBLIC_
373 wbcErr wbcCtxResolveWinsByIP(struct wbcContext *ctx,
374 const char *ip, char **name)
376 struct winbindd_request request;
377 struct winbindd_response response;
378 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
379 char *name_str;
381 ZERO_STRUCT(request);
382 ZERO_STRUCT(response);
384 /* Send request */
386 strncpy(request.data.winsreq, ip,
387 sizeof(request.data.winsreq)-1);
389 wbc_status = wbcRequestResponse(ctx, WINBINDD_WINS_BYIP,
390 &request,
391 &response);
392 BAIL_ON_WBC_ERROR(wbc_status);
394 /* Display response */
396 name_str = wbcStrDup(response.data.winsresp);
397 BAIL_ON_PTR_ERROR(name_str, wbc_status);
399 *name = name_str;
400 wbc_status = WBC_ERR_SUCCESS;
402 done:
403 return wbc_status;
406 _PUBLIC_
407 wbcErr wbcResolveWinsByIP(const char *ip, char **name)
409 return wbcCtxResolveWinsByIP(NULL, ip, name);
415 static wbcErr process_domain_info_string(struct wbcDomainInfo *info,
416 char *info_string)
418 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
419 char *r = NULL;
420 char *s = NULL;
422 r = info_string;
424 /* Short Name */
425 if ((s = strchr(r, '\\')) == NULL) {
426 wbc_status = WBC_ERR_INVALID_RESPONSE;
427 BAIL_ON_WBC_ERROR(wbc_status);
429 *s = '\0';
430 s++;
432 info->short_name = strdup(r);
433 BAIL_ON_PTR_ERROR(info->short_name, wbc_status);
436 /* DNS Name */
437 r = s;
438 if ((s = strchr(r, '\\')) == NULL) {
439 wbc_status = WBC_ERR_INVALID_RESPONSE;
440 BAIL_ON_WBC_ERROR(wbc_status);
442 *s = '\0';
443 s++;
445 info->dns_name = strdup(r);
446 BAIL_ON_PTR_ERROR(info->dns_name, wbc_status);
448 /* SID */
449 r = s;
450 if ((s = strchr(r, '\\')) == NULL) {
451 wbc_status = WBC_ERR_INVALID_RESPONSE;
452 BAIL_ON_WBC_ERROR(wbc_status);
454 *s = '\0';
455 s++;
457 wbc_status = wbcStringToSid(r, &info->sid);
458 BAIL_ON_WBC_ERROR(wbc_status);
460 /* Trust type */
461 r = s;
462 if ((s = strchr(r, '\\')) == NULL) {
463 wbc_status = WBC_ERR_INVALID_RESPONSE;
464 BAIL_ON_WBC_ERROR(wbc_status);
466 *s = '\0';
467 s++;
469 if (strncmp(r, "Routed", strlen("Routed")) == 0) {
470 info->trust_type = WBC_DOMINFO_TRUSTTYPE_NONE;
471 info->trust_routing = strdup(r);
472 BAIL_ON_PTR_ERROR(info->trust_routing, wbc_status);
473 } else if (strcmp(r, "Local") == 0) {
474 info->trust_type = WBC_DOMINFO_TRUSTTYPE_LOCAL;
475 } else if (strcmp(r, "Workstation") == 0) {
476 info->trust_type = WBC_DOMINFO_TRUSTTYPE_WKSTA;
477 } else if (strcmp(r, "RWDC") == 0) {
478 info->trust_type = WBC_DOMINFO_TRUSTTYPE_RWDC;
479 } else if (strcmp(r, "RODC") == 0) {
480 info->trust_type = WBC_DOMINFO_TRUSTTYPE_RODC;
481 } else if (strcmp(r, "PDC") == 0) {
482 info->trust_type = WBC_DOMINFO_TRUSTTYPE_PDC;
483 } else if (strcmp(r, "External") == 0) {
484 info->trust_type = WBC_DOMINFO_TRUSTTYPE_EXTERNAL;
485 } else if (strcmp(r, "Forest") == 0) {
486 info->trust_type = WBC_DOMINFO_TRUSTTYPE_FOREST;
487 } else if (strcmp(r, "In Forest") == 0) {
488 info->trust_type = WBC_DOMINFO_TRUSTTYPE_IN_FOREST;
489 } else {
490 wbc_status = WBC_ERR_INVALID_RESPONSE;
491 BAIL_ON_WBC_ERROR(wbc_status);
494 /* Transitive */
495 r = s;
496 if ((s = strchr(r, '\\')) == NULL) {
497 wbc_status = WBC_ERR_INVALID_RESPONSE;
498 BAIL_ON_WBC_ERROR(wbc_status);
500 *s = '\0';
501 s++;
503 if (strcmp(r, "Yes") == 0) {
504 info->trust_flags |= WBC_DOMINFO_TRUST_TRANSITIVE;
507 /* Incoming */
508 r = s;
509 if ((s = strchr(r, '\\')) == NULL) {
510 wbc_status = WBC_ERR_INVALID_RESPONSE;
511 BAIL_ON_WBC_ERROR(wbc_status);
513 *s = '\0';
514 s++;
516 if (strcmp(r, "Yes") == 0) {
517 info->trust_flags |= WBC_DOMINFO_TRUST_INCOMING;
520 /* Outgoing */
521 r = s;
522 if ((s = strchr(r, '\\')) == NULL) {
523 wbc_status = WBC_ERR_INVALID_RESPONSE;
524 BAIL_ON_WBC_ERROR(wbc_status);
526 *s = '\0';
527 s++;
529 if (strcmp(r, "Yes") == 0) {
530 info->trust_flags |= WBC_DOMINFO_TRUST_OUTGOING;
533 /* Online/Offline status */
534 r = s;
535 if ( strcmp(r, "Offline") == 0) {
536 info->domain_flags |= WBC_DOMINFO_DOMAIN_OFFLINE;
539 wbc_status = WBC_ERR_SUCCESS;
541 done:
542 return wbc_status;
545 static void wbcDomainInfoListDestructor(void *ptr)
547 struct wbcDomainInfo *i = (struct wbcDomainInfo *)ptr;
549 while (i->short_name != NULL) {
550 free(i->short_name);
551 free(i->dns_name);
552 i += 1;
556 /* Enumerate the domain trusts known by Winbind */
557 _PUBLIC_
558 wbcErr wbcCtxListTrusts(struct wbcContext *ctx,
559 struct wbcDomainInfo **domains, size_t *num_domains)
561 struct winbindd_response response;
562 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
563 char *p = NULL;
564 char *extra_data = NULL;
565 struct wbcDomainInfo *d_list = NULL;
566 int i = 0;
568 *domains = NULL;
569 *num_domains = 0;
571 ZERO_STRUCT(response);
573 /* Send request */
575 wbc_status = wbcRequestResponse(ctx, WINBINDD_LIST_TRUSTDOM,
576 NULL,
577 &response);
578 BAIL_ON_WBC_ERROR(wbc_status);
580 /* Decode the response */
582 p = (char *)response.extra_data.data;
584 if ((p == NULL) || (strlen(p) == 0)) {
585 /* We should always at least get back our
586 own SAM domain */
588 wbc_status = WBC_ERR_DOMAIN_NOT_FOUND;
589 BAIL_ON_WBC_ERROR(wbc_status);
592 d_list = (struct wbcDomainInfo *)wbcAllocateMemory(
593 response.data.num_entries + 1,sizeof(struct wbcDomainInfo),
594 wbcDomainInfoListDestructor);
595 BAIL_ON_PTR_ERROR(d_list, wbc_status);
597 extra_data = strdup((char*)response.extra_data.data);
598 BAIL_ON_PTR_ERROR(extra_data, wbc_status);
600 p = extra_data;
602 /* Outer loop processes the list of domain information */
604 for (i=0; i<response.data.num_entries && p; i++) {
605 char *next = strchr(p, '\n');
607 if (next) {
608 *next = '\0';
609 next++;
612 wbc_status = process_domain_info_string(&d_list[i], p);
613 BAIL_ON_WBC_ERROR(wbc_status);
615 p = next;
618 *domains = d_list;
619 d_list = NULL;
620 *num_domains = i;
622 done:
623 winbindd_free_response(&response);
624 wbcFreeMemory(d_list);
625 free(extra_data);
626 return wbc_status;
629 _PUBLIC_
630 wbcErr wbcListTrusts(struct wbcDomainInfo **domains, size_t *num_domains)
632 return wbcCtxListTrusts(NULL, domains, num_domains);
635 static void wbcDomainControllerInfoDestructor(void *ptr)
637 struct wbcDomainControllerInfo *i =
638 (struct wbcDomainControllerInfo *)ptr;
639 free(i->dc_name);
642 /* Enumerate the domain trusts known by Winbind */
643 _PUBLIC_
644 wbcErr wbcCtxLookupDomainController(struct wbcContext *ctx,
645 const char *domain, uint32_t flags,
646 struct wbcDomainControllerInfo **dc_info)
648 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
649 struct winbindd_request request;
650 struct winbindd_response response;
651 struct wbcDomainControllerInfo *dc = NULL;
653 /* validate input params */
655 if (!domain || !dc_info) {
656 wbc_status = WBC_ERR_INVALID_PARAM;
657 BAIL_ON_WBC_ERROR(wbc_status);
660 ZERO_STRUCT(request);
661 ZERO_STRUCT(response);
663 strncpy(request.data.dsgetdcname.domain_name, domain,
664 sizeof(request.data.dsgetdcname.domain_name)-1);
666 request.flags = flags;
668 dc = (struct wbcDomainControllerInfo *)wbcAllocateMemory(
669 1, sizeof(struct wbcDomainControllerInfo),
670 wbcDomainControllerInfoDestructor);
671 BAIL_ON_PTR_ERROR(dc, wbc_status);
673 /* Send request */
675 wbc_status = wbcRequestResponse(ctx, WINBINDD_DSGETDCNAME,
676 &request,
677 &response);
678 BAIL_ON_WBC_ERROR(wbc_status);
680 dc->dc_name = strdup(response.data.dsgetdcname.dc_unc);
681 BAIL_ON_PTR_ERROR(dc->dc_name, wbc_status);
683 *dc_info = dc;
684 dc = NULL;
686 done:
687 wbcFreeMemory(dc);
688 return wbc_status;
691 _PUBLIC_
692 wbcErr wbcLookupDomainController(const char *domain, uint32_t flags,
693 struct wbcDomainControllerInfo **dc_info)
695 return wbcCtxLookupDomainController(NULL, domain, flags, dc_info);
698 static void wbcDomainControllerInfoExDestructor(void *ptr)
700 struct wbcDomainControllerInfoEx *i =
701 (struct wbcDomainControllerInfoEx *)ptr;
702 free(discard_const_p(char, i->dc_unc));
703 free(discard_const_p(char, i->dc_address));
704 free(discard_const_p(char, i->domain_guid));
705 free(discard_const_p(char, i->domain_name));
706 free(discard_const_p(char, i->forest_name));
707 free(discard_const_p(char, i->dc_site_name));
708 free(discard_const_p(char, i->client_site_name));
711 static wbcErr wbc_create_domain_controller_info_ex(const struct winbindd_response *resp,
712 struct wbcDomainControllerInfoEx **_i)
714 wbcErr wbc_status = WBC_ERR_SUCCESS;
715 struct wbcDomainControllerInfoEx *i;
716 struct wbcGuid guid;
718 i = (struct wbcDomainControllerInfoEx *)wbcAllocateMemory(
719 1, sizeof(struct wbcDomainControllerInfoEx),
720 wbcDomainControllerInfoExDestructor);
721 BAIL_ON_PTR_ERROR(i, wbc_status);
723 i->dc_unc = strdup(resp->data.dsgetdcname.dc_unc);
724 BAIL_ON_PTR_ERROR(i->dc_unc, wbc_status);
726 i->dc_address = strdup(resp->data.dsgetdcname.dc_address);
727 BAIL_ON_PTR_ERROR(i->dc_address, wbc_status);
729 i->dc_address_type = resp->data.dsgetdcname.dc_address_type;
731 wbc_status = wbcStringToGuid(resp->data.dsgetdcname.domain_guid, &guid);
732 if (WBC_ERROR_IS_OK(wbc_status)) {
733 i->domain_guid = (struct wbcGuid *)malloc(
734 sizeof(struct wbcGuid));
735 BAIL_ON_PTR_ERROR(i->domain_guid, wbc_status);
737 *i->domain_guid = guid;
740 i->domain_name = strdup(resp->data.dsgetdcname.domain_name);
741 BAIL_ON_PTR_ERROR(i->domain_name, wbc_status);
743 if (resp->data.dsgetdcname.forest_name[0] != '\0') {
744 i->forest_name = strdup(resp->data.dsgetdcname.forest_name);
745 BAIL_ON_PTR_ERROR(i->forest_name, wbc_status);
748 i->dc_flags = resp->data.dsgetdcname.dc_flags;
750 if (resp->data.dsgetdcname.dc_site_name[0] != '\0') {
751 i->dc_site_name = strdup(resp->data.dsgetdcname.dc_site_name);
752 BAIL_ON_PTR_ERROR(i->dc_site_name, wbc_status);
755 if (resp->data.dsgetdcname.client_site_name[0] != '\0') {
756 i->client_site_name = strdup(
757 resp->data.dsgetdcname.client_site_name);
758 BAIL_ON_PTR_ERROR(i->client_site_name, wbc_status);
761 *_i = i;
762 i = NULL;
764 done:
765 if (i != NULL) {
766 wbcFreeMemory(i);
768 return wbc_status;
771 /* Get extended domain controller information */
772 _PUBLIC_
773 wbcErr wbcCtxLookupDomainControllerEx(struct wbcContext *ctx,
774 const char *domain,
775 struct wbcGuid *guid,
776 const char *site,
777 uint32_t flags,
778 struct wbcDomainControllerInfoEx **dc_info)
780 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
781 struct winbindd_request request;
782 struct winbindd_response response;
784 /* validate input params */
786 if (!domain || !dc_info) {
787 wbc_status = WBC_ERR_INVALID_PARAM;
788 BAIL_ON_WBC_ERROR(wbc_status);
791 ZERO_STRUCT(request);
792 ZERO_STRUCT(response);
794 request.data.dsgetdcname.flags = flags;
796 strncpy(request.data.dsgetdcname.domain_name, domain,
797 sizeof(request.data.dsgetdcname.domain_name)-1);
799 if (site) {
800 strncpy(request.data.dsgetdcname.site_name, site,
801 sizeof(request.data.dsgetdcname.site_name)-1);
804 if (guid) {
805 char *str = NULL;
807 wbc_status = wbcGuidToString(guid, &str);
808 BAIL_ON_WBC_ERROR(wbc_status);
810 strncpy(request.data.dsgetdcname.domain_guid, str,
811 sizeof(request.data.dsgetdcname.domain_guid)-1);
813 wbcFreeMemory(str);
816 /* Send request */
818 wbc_status = wbcRequestResponse(ctx, WINBINDD_DSGETDCNAME,
819 &request,
820 &response);
821 BAIL_ON_WBC_ERROR(wbc_status);
823 if (dc_info) {
824 wbc_status = wbc_create_domain_controller_info_ex(&response,
825 dc_info);
826 BAIL_ON_WBC_ERROR(wbc_status);
829 wbc_status = WBC_ERR_SUCCESS;
830 done:
831 return wbc_status;
834 _PUBLIC_
835 wbcErr wbcLookupDomainControllerEx(const char *domain,
836 struct wbcGuid *guid,
837 const char *site,
838 uint32_t flags,
839 struct wbcDomainControllerInfoEx **dc_info)
841 return wbcCtxLookupDomainControllerEx(NULL, domain, guid, site,
842 flags, dc_info);
845 static void wbcNamedBlobDestructor(void *ptr)
847 struct wbcNamedBlob *b = (struct wbcNamedBlob *)ptr;
849 while (b->name != NULL) {
850 free(discard_const_p(char, b->name));
851 free(b->blob.data);
852 b += 1;
856 /* Initialize a named blob and add to list of blobs */
857 _PUBLIC_
858 wbcErr wbcAddNamedBlob(size_t *num_blobs,
859 struct wbcNamedBlob **pblobs,
860 const char *name,
861 uint32_t flags,
862 uint8_t *data,
863 size_t length)
865 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
866 struct wbcNamedBlob *blobs, *blob;
868 if (name == NULL) {
869 return WBC_ERR_INVALID_PARAM;
873 * Overallocate the b->name==NULL terminator for
874 * wbcNamedBlobDestructor
876 blobs = (struct wbcNamedBlob *)wbcAllocateMemory(
877 *num_blobs + 2, sizeof(struct wbcNamedBlob),
878 wbcNamedBlobDestructor);
880 if (blobs == NULL) {
881 return WBC_ERR_NO_MEMORY;
884 if (*pblobs != NULL) {
885 struct wbcNamedBlob *old = *pblobs;
886 memcpy(blobs, old, sizeof(struct wbcNamedBlob) * (*num_blobs));
887 if (*num_blobs != 0) {
888 /* end indicator for wbcNamedBlobDestructor */
889 old[0].name = NULL;
891 wbcFreeMemory(old);
893 *pblobs = blobs;
895 blob = &blobs[*num_blobs];
897 blob->name = strdup(name);
898 BAIL_ON_PTR_ERROR(blob->name, wbc_status);
899 blob->flags = flags;
901 blob->blob.length = length;
902 blob->blob.data = (uint8_t *)malloc(length);
903 BAIL_ON_PTR_ERROR(blob->blob.data, wbc_status);
904 memcpy(blob->blob.data, data, length);
906 *num_blobs += 1;
907 *pblobs = blobs;
908 blobs = NULL;
910 wbc_status = WBC_ERR_SUCCESS;
911 done:
912 wbcFreeMemory(blobs);
913 return wbc_status;
916 _PUBLIC_
917 void wbcSetClientProcessName(const char *name)
919 winbind_set_client_name(name);