ctdb-scripts: Improve update and listing code
[samba4-gss.git] / nsswitch / libwbclient / wbc_util.c
blob5618039a89d68ca1eb5d0836db09d646f4153fd8
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 free(i->trust_routing);
553 i += 1;
557 /* Enumerate the domain trusts known by Winbind */
558 _PUBLIC_
559 wbcErr wbcCtxListTrusts(struct wbcContext *ctx,
560 struct wbcDomainInfo **domains, size_t *num_domains)
562 struct winbindd_response response;
563 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
564 char *p = NULL;
565 char *extra_data = NULL;
566 struct wbcDomainInfo *d_list = NULL;
567 int i = 0;
569 *domains = NULL;
570 *num_domains = 0;
572 ZERO_STRUCT(response);
574 /* Send request */
576 wbc_status = wbcRequestResponse(ctx, WINBINDD_LIST_TRUSTDOM,
577 NULL,
578 &response);
579 BAIL_ON_WBC_ERROR(wbc_status);
581 /* Decode the response */
583 p = (char *)response.extra_data.data;
585 if ((p == NULL) || (strlen(p) == 0)) {
586 /* We should always at least get back our
587 own SAM domain */
589 wbc_status = WBC_ERR_DOMAIN_NOT_FOUND;
590 BAIL_ON_WBC_ERROR(wbc_status);
593 d_list = (struct wbcDomainInfo *)wbcAllocateMemory(
594 response.data.num_entries + 1,sizeof(struct wbcDomainInfo),
595 wbcDomainInfoListDestructor);
596 BAIL_ON_PTR_ERROR(d_list, wbc_status);
598 extra_data = strdup((char*)response.extra_data.data);
599 BAIL_ON_PTR_ERROR(extra_data, wbc_status);
601 p = extra_data;
603 /* Outer loop processes the list of domain information */
605 for (i=0; i<response.data.num_entries && p; i++) {
606 char *next = strchr(p, '\n');
608 if (next) {
609 *next = '\0';
610 next++;
613 wbc_status = process_domain_info_string(&d_list[i], p);
614 BAIL_ON_WBC_ERROR(wbc_status);
616 p = next;
619 *domains = d_list;
620 d_list = NULL;
621 *num_domains = i;
623 done:
624 winbindd_free_response(&response);
625 wbcFreeMemory(d_list);
626 free(extra_data);
627 return wbc_status;
630 _PUBLIC_
631 wbcErr wbcListTrusts(struct wbcDomainInfo **domains, size_t *num_domains)
633 return wbcCtxListTrusts(NULL, domains, num_domains);
636 static void wbcDomainControllerInfoDestructor(void *ptr)
638 struct wbcDomainControllerInfo *i =
639 (struct wbcDomainControllerInfo *)ptr;
640 free(i->dc_name);
643 /* Enumerate the domain trusts known by Winbind */
644 _PUBLIC_
645 wbcErr wbcCtxLookupDomainController(struct wbcContext *ctx,
646 const char *domain, uint32_t flags,
647 struct wbcDomainControllerInfo **dc_info)
649 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
650 struct winbindd_request request;
651 struct winbindd_response response;
652 struct wbcDomainControllerInfo *dc = NULL;
654 /* validate input params */
656 if (!domain || !dc_info) {
657 wbc_status = WBC_ERR_INVALID_PARAM;
658 BAIL_ON_WBC_ERROR(wbc_status);
661 ZERO_STRUCT(request);
662 ZERO_STRUCT(response);
664 strncpy(request.data.dsgetdcname.domain_name, domain,
665 sizeof(request.data.dsgetdcname.domain_name)-1);
667 request.flags = flags;
669 dc = (struct wbcDomainControllerInfo *)wbcAllocateMemory(
670 1, sizeof(struct wbcDomainControllerInfo),
671 wbcDomainControllerInfoDestructor);
672 BAIL_ON_PTR_ERROR(dc, wbc_status);
674 /* Send request */
676 wbc_status = wbcRequestResponse(ctx, WINBINDD_DSGETDCNAME,
677 &request,
678 &response);
679 BAIL_ON_WBC_ERROR(wbc_status);
681 dc->dc_name = strdup(response.data.dsgetdcname.dc_unc);
682 BAIL_ON_PTR_ERROR(dc->dc_name, wbc_status);
684 *dc_info = dc;
685 dc = NULL;
687 done:
688 wbcFreeMemory(dc);
689 return wbc_status;
692 _PUBLIC_
693 wbcErr wbcLookupDomainController(const char *domain, uint32_t flags,
694 struct wbcDomainControllerInfo **dc_info)
696 return wbcCtxLookupDomainController(NULL, domain, flags, dc_info);
699 static void wbcDomainControllerInfoExDestructor(void *ptr)
701 struct wbcDomainControllerInfoEx *i =
702 (struct wbcDomainControllerInfoEx *)ptr;
703 free(discard_const_p(char, i->dc_unc));
704 free(discard_const_p(char, i->dc_address));
705 free(discard_const_p(char, i->domain_guid));
706 free(discard_const_p(char, i->domain_name));
707 free(discard_const_p(char, i->forest_name));
708 free(discard_const_p(char, i->dc_site_name));
709 free(discard_const_p(char, i->client_site_name));
712 static wbcErr wbc_create_domain_controller_info_ex(const struct winbindd_response *resp,
713 struct wbcDomainControllerInfoEx **_i)
715 wbcErr wbc_status = WBC_ERR_SUCCESS;
716 struct wbcDomainControllerInfoEx *i;
717 struct wbcGuid guid;
719 i = (struct wbcDomainControllerInfoEx *)wbcAllocateMemory(
720 1, sizeof(struct wbcDomainControllerInfoEx),
721 wbcDomainControllerInfoExDestructor);
722 BAIL_ON_PTR_ERROR(i, wbc_status);
724 i->dc_unc = strdup(resp->data.dsgetdcname.dc_unc);
725 BAIL_ON_PTR_ERROR(i->dc_unc, wbc_status);
727 i->dc_address = strdup(resp->data.dsgetdcname.dc_address);
728 BAIL_ON_PTR_ERROR(i->dc_address, wbc_status);
730 i->dc_address_type = resp->data.dsgetdcname.dc_address_type;
732 wbc_status = wbcStringToGuid(resp->data.dsgetdcname.domain_guid, &guid);
733 if (WBC_ERROR_IS_OK(wbc_status)) {
734 i->domain_guid = (struct wbcGuid *)malloc(
735 sizeof(struct wbcGuid));
736 BAIL_ON_PTR_ERROR(i->domain_guid, wbc_status);
738 *i->domain_guid = guid;
741 i->domain_name = strdup(resp->data.dsgetdcname.domain_name);
742 BAIL_ON_PTR_ERROR(i->domain_name, wbc_status);
744 if (resp->data.dsgetdcname.forest_name[0] != '\0') {
745 i->forest_name = strdup(resp->data.dsgetdcname.forest_name);
746 BAIL_ON_PTR_ERROR(i->forest_name, wbc_status);
749 i->dc_flags = resp->data.dsgetdcname.dc_flags;
751 if (resp->data.dsgetdcname.dc_site_name[0] != '\0') {
752 i->dc_site_name = strdup(resp->data.dsgetdcname.dc_site_name);
753 BAIL_ON_PTR_ERROR(i->dc_site_name, wbc_status);
756 if (resp->data.dsgetdcname.client_site_name[0] != '\0') {
757 i->client_site_name = strdup(
758 resp->data.dsgetdcname.client_site_name);
759 BAIL_ON_PTR_ERROR(i->client_site_name, wbc_status);
762 *_i = i;
763 i = NULL;
765 done:
766 if (i != NULL) {
767 wbcFreeMemory(i);
769 return wbc_status;
772 /* Get extended domain controller information */
773 _PUBLIC_
774 wbcErr wbcCtxLookupDomainControllerEx(struct wbcContext *ctx,
775 const char *domain,
776 struct wbcGuid *guid,
777 const char *site,
778 uint32_t flags,
779 struct wbcDomainControllerInfoEx **dc_info)
781 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
782 struct winbindd_request request;
783 struct winbindd_response response;
785 /* validate input params */
787 if (!domain || !dc_info) {
788 wbc_status = WBC_ERR_INVALID_PARAM;
789 BAIL_ON_WBC_ERROR(wbc_status);
792 ZERO_STRUCT(request);
793 ZERO_STRUCT(response);
795 request.data.dsgetdcname.flags = flags;
797 strncpy(request.data.dsgetdcname.domain_name, domain,
798 sizeof(request.data.dsgetdcname.domain_name)-1);
800 if (site) {
801 strncpy(request.data.dsgetdcname.site_name, site,
802 sizeof(request.data.dsgetdcname.site_name)-1);
805 if (guid) {
806 char *str = NULL;
808 wbc_status = wbcGuidToString(guid, &str);
809 BAIL_ON_WBC_ERROR(wbc_status);
811 strncpy(request.data.dsgetdcname.domain_guid, str,
812 sizeof(request.data.dsgetdcname.domain_guid)-1);
814 wbcFreeMemory(str);
817 /* Send request */
819 wbc_status = wbcRequestResponse(ctx, WINBINDD_DSGETDCNAME,
820 &request,
821 &response);
822 BAIL_ON_WBC_ERROR(wbc_status);
824 if (dc_info) {
825 wbc_status = wbc_create_domain_controller_info_ex(&response,
826 dc_info);
827 BAIL_ON_WBC_ERROR(wbc_status);
830 wbc_status = WBC_ERR_SUCCESS;
831 done:
832 return wbc_status;
835 _PUBLIC_
836 wbcErr wbcLookupDomainControllerEx(const char *domain,
837 struct wbcGuid *guid,
838 const char *site,
839 uint32_t flags,
840 struct wbcDomainControllerInfoEx **dc_info)
842 return wbcCtxLookupDomainControllerEx(NULL, domain, guid, site,
843 flags, dc_info);
846 static void wbcNamedBlobDestructor(void *ptr)
848 struct wbcNamedBlob *b = (struct wbcNamedBlob *)ptr;
850 while (b->name != NULL) {
851 free(discard_const_p(char, b->name));
852 free(b->blob.data);
853 b += 1;
857 /* Initialize a named blob and add to list of blobs */
858 _PUBLIC_
859 wbcErr wbcAddNamedBlob(size_t *num_blobs,
860 struct wbcNamedBlob **pblobs,
861 const char *name,
862 uint32_t flags,
863 uint8_t *data,
864 size_t length)
866 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
867 struct wbcNamedBlob *blobs, *blob;
869 if (name == NULL) {
870 return WBC_ERR_INVALID_PARAM;
874 * Overallocate the b->name==NULL terminator for
875 * wbcNamedBlobDestructor
877 blobs = (struct wbcNamedBlob *)wbcAllocateMemory(
878 *num_blobs + 2, sizeof(struct wbcNamedBlob),
879 wbcNamedBlobDestructor);
881 if (blobs == NULL) {
882 return WBC_ERR_NO_MEMORY;
885 if (*pblobs != NULL) {
886 struct wbcNamedBlob *old = *pblobs;
887 memcpy(blobs, old, sizeof(struct wbcNamedBlob) * (*num_blobs));
888 if (*num_blobs != 0) {
889 /* end indicator for wbcNamedBlobDestructor */
890 old[0].name = NULL;
892 wbcFreeMemory(old);
894 *pblobs = blobs;
896 blob = &blobs[*num_blobs];
898 blob->name = strdup(name);
899 BAIL_ON_PTR_ERROR(blob->name, wbc_status);
900 blob->flags = flags;
902 blob->blob.length = length;
903 blob->blob.data = (uint8_t *)malloc(length);
904 BAIL_ON_PTR_ERROR(blob->blob.data, wbc_status);
905 memcpy(blob->blob.data, data, length);
907 *num_blobs += 1;
908 *pblobs = blobs;
909 blobs = NULL;
911 wbc_status = WBC_ERR_SUCCESS;
912 done:
913 wbcFreeMemory(blobs);
914 return wbc_status;
917 _PUBLIC_
918 void wbcSetClientProcessName(const char *name)
920 winbind_set_client_name(name);