autobuild: Move defaulttasks to one-per-line
[Samba.git] / nsswitch / libwbclient / wbc_util.c
blobfc6a840cc716e2f8b9e3259cad2013682a72ae59
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 wbcErr wbcCtxPing(struct wbcContext *ctx)
37 struct winbindd_request request;
38 struct winbindd_response response;
40 /* Initialize request */
42 ZERO_STRUCT(request);
43 ZERO_STRUCT(response);
45 return wbcRequestResponse(ctx, WINBINDD_PING, &request, &response);
48 wbcErr wbcPing(void)
50 return wbcCtxPing(NULL);
53 static void wbcInterfaceDetailsDestructor(void *ptr)
55 struct wbcInterfaceDetails *i = (struct wbcInterfaceDetails *)ptr;
56 free(i->winbind_version);
57 free(i->netbios_name);
58 free(i->netbios_domain);
59 free(i->dns_domain);
62 /**
63 * @brief Query useful information about the winbind service
65 * @param *_details pointer to hold the struct wbcInterfaceDetails
67 * @return #wbcErr
70 wbcErr wbcCtxInterfaceDetails(struct wbcContext *ctx,
71 struct wbcInterfaceDetails **_details)
73 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
74 struct wbcInterfaceDetails *info;
75 struct wbcDomainInfo *domain = NULL;
76 struct winbindd_request request;
77 struct winbindd_response response;
79 /* Initialize request */
81 ZERO_STRUCT(request);
82 ZERO_STRUCT(response);
84 info = (struct wbcInterfaceDetails *)wbcAllocateMemory(
85 1, sizeof(struct wbcInterfaceDetails),
86 wbcInterfaceDetailsDestructor);
87 BAIL_ON_PTR_ERROR(info, wbc_status);
89 /* first the interface version */
90 wbc_status = wbcRequestResponse(ctx, WINBINDD_INTERFACE_VERSION,
91 NULL, &response);
92 BAIL_ON_WBC_ERROR(wbc_status);
93 info->interface_version = response.data.interface_version;
95 /* then the samba version and the winbind separator */
96 wbc_status = wbcRequestResponse(ctx, WINBINDD_INFO, NULL, &response);
97 BAIL_ON_WBC_ERROR(wbc_status);
99 info->winbind_version = strdup(response.data.info.samba_version);
100 BAIL_ON_PTR_ERROR(info->winbind_version, wbc_status);
101 info->winbind_separator = response.data.info.winbind_separator;
103 /* then the local netbios name */
104 wbc_status = wbcRequestResponse(ctx, WINBINDD_NETBIOS_NAME,
105 NULL, &response);
106 BAIL_ON_WBC_ERROR(wbc_status);
108 info->netbios_name = strdup(response.data.netbios_name);
109 BAIL_ON_PTR_ERROR(info->netbios_name, wbc_status);
111 /* then the local workgroup name */
112 wbc_status = wbcRequestResponse(ctx, WINBINDD_DOMAIN_NAME,
113 NULL, &response);
114 BAIL_ON_WBC_ERROR(wbc_status);
116 info->netbios_domain = strdup(response.data.domain_name);
117 BAIL_ON_PTR_ERROR(info->netbios_domain, wbc_status);
119 wbc_status = wbcCtxDomainInfo(ctx, info->netbios_domain, &domain);
120 if (wbc_status == WBC_ERR_DOMAIN_NOT_FOUND) {
121 /* maybe it's a standalone server */
122 domain = NULL;
123 wbc_status = WBC_ERR_SUCCESS;
124 } else {
125 BAIL_ON_WBC_ERROR(wbc_status);
128 if (domain) {
129 info->dns_domain = strdup(domain->dns_name);
130 wbcFreeMemory(domain);
131 BAIL_ON_PTR_ERROR(info->dns_domain, wbc_status);
132 } else {
133 info->dns_domain = NULL;
136 *_details = info;
137 info = NULL;
139 wbc_status = WBC_ERR_SUCCESS;
141 done:
142 wbcFreeMemory(info);
143 return wbc_status;
146 wbcErr wbcInterfaceDetails(struct wbcInterfaceDetails **_details)
148 return wbcCtxInterfaceDetails(NULL, _details);
151 static void wbcDomainInfoDestructor(void *ptr)
153 struct wbcDomainInfo *i = (struct wbcDomainInfo *)ptr;
154 free(i->short_name);
155 free(i->dns_name);
158 /** @brief Lookup the current status of a trusted domain, sync wrapper
160 * @param domain Domain to query
161 * @param *dinfo Pointer to returned struct wbcDomainInfo
163 * @return #wbcErr
166 wbcErr wbcCtxDomainInfo(struct wbcContext *ctx,
167 const char *domain,
168 struct wbcDomainInfo **dinfo)
170 struct winbindd_request request;
171 struct winbindd_response response;
172 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
173 struct wbcDomainInfo *info = NULL;
175 if (!domain || !dinfo) {
176 wbc_status = WBC_ERR_INVALID_PARAM;
177 BAIL_ON_WBC_ERROR(wbc_status);
180 /* Initialize request */
182 ZERO_STRUCT(request);
183 ZERO_STRUCT(response);
185 strncpy(request.domain_name, domain,
186 sizeof(request.domain_name)-1);
188 wbc_status = wbcRequestResponse(ctx, WINBINDD_DOMAIN_INFO,
189 &request,
190 &response);
191 BAIL_ON_WBC_ERROR(wbc_status);
193 info = (struct wbcDomainInfo *)wbcAllocateMemory(
194 1, sizeof(struct wbcDomainInfo), wbcDomainInfoDestructor);
195 BAIL_ON_PTR_ERROR(info, wbc_status);
197 info->short_name = strdup(response.data.domain_info.name);
198 BAIL_ON_PTR_ERROR(info->short_name, wbc_status);
200 info->dns_name = strdup(response.data.domain_info.alt_name);
201 BAIL_ON_PTR_ERROR(info->dns_name, wbc_status);
203 wbc_status = wbcStringToSid(response.data.domain_info.sid,
204 &info->sid);
205 BAIL_ON_WBC_ERROR(wbc_status);
207 if (response.data.domain_info.native_mode)
208 info->domain_flags |= WBC_DOMINFO_DOMAIN_NATIVE;
209 if (response.data.domain_info.active_directory)
210 info->domain_flags |= WBC_DOMINFO_DOMAIN_AD;
211 if (response.data.domain_info.primary)
212 info->domain_flags |= WBC_DOMINFO_DOMAIN_PRIMARY;
214 *dinfo = info;
215 info = NULL;
217 wbc_status = WBC_ERR_SUCCESS;
219 done:
220 wbcFreeMemory(info);
221 return wbc_status;
224 wbcErr wbcDomainInfo(const char *domain, struct wbcDomainInfo **dinfo)
226 return wbcCtxDomainInfo(NULL, domain, dinfo);
229 /* Get the list of current DCs */
230 wbcErr wbcCtxDcInfo(struct wbcContext *ctx,
231 const char *domain, size_t *num_dcs,
232 const char ***dc_names, const char ***dc_ips)
234 struct winbindd_request request;
235 struct winbindd_response response;
236 const char **names = NULL;
237 const char **ips = NULL;
238 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
239 size_t extra_len;
240 int i;
241 char *p;
243 /* Initialise request */
245 ZERO_STRUCT(request);
246 ZERO_STRUCT(response);
248 if (domain != NULL) {
249 strncpy(request.domain_name, domain,
250 sizeof(request.domain_name) - 1);
253 wbc_status = wbcRequestResponse(ctx, WINBINDD_DC_INFO,
254 &request, &response);
255 BAIL_ON_WBC_ERROR(wbc_status);
257 names = wbcAllocateStringArray(response.data.num_entries);
258 BAIL_ON_PTR_ERROR(names, wbc_status);
260 ips = wbcAllocateStringArray(response.data.num_entries);
261 BAIL_ON_PTR_ERROR(ips, wbc_status);
263 wbc_status = WBC_ERR_INVALID_RESPONSE;
265 p = (char *)response.extra_data.data;
267 if (response.length < (sizeof(struct winbindd_response)+1)) {
268 goto done;
271 extra_len = response.length - sizeof(struct winbindd_response);
273 if (p[extra_len-1] != '\0') {
274 goto done;
277 for (i=0; i<response.data.num_entries; i++) {
278 char *q;
280 q = strchr(p, '\n');
281 if (q == NULL) {
282 goto done;
284 names[i] = strndup(p, q-p);
285 BAIL_ON_PTR_ERROR(names[i], wbc_status);
286 p = q+1;
288 q = strchr(p, '\n');
289 if (q == NULL) {
290 goto done;
292 ips[i] = strndup(p, q-p);
293 BAIL_ON_PTR_ERROR(ips[i], wbc_status);
294 p = q+1;
296 if (p[0] != '\0') {
297 goto done;
300 wbc_status = WBC_ERR_SUCCESS;
301 done:
302 if (response.extra_data.data)
303 free(response.extra_data.data);
305 if (WBC_ERROR_IS_OK(wbc_status)) {
306 *num_dcs = response.data.num_entries;
307 *dc_names = names;
308 names = NULL;
309 *dc_ips = ips;
310 ips = NULL;
312 wbcFreeMemory(names);
313 wbcFreeMemory(ips);
314 return wbc_status;
317 wbcErr wbcDcInfo(const char *domain, size_t *num_dcs,
318 const char ***dc_names, const char ***dc_ips)
320 return wbcCtxDcInfo(NULL, domain, num_dcs, dc_names, dc_ips);
323 /* Resolve a NetbiosName via WINS */
324 wbcErr wbcCtxResolveWinsByName(struct wbcContext *ctx,
325 const char *name, char **ip)
327 struct winbindd_request request;
328 struct winbindd_response response;
329 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
330 char *ipaddr;
332 ZERO_STRUCT(request);
333 ZERO_STRUCT(response);
335 /* Send request */
337 strncpy(request.data.winsreq, name,
338 sizeof(request.data.winsreq)-1);
340 wbc_status = wbcRequestResponse(ctx, WINBINDD_WINS_BYNAME,
341 &request,
342 &response);
343 BAIL_ON_WBC_ERROR(wbc_status);
345 /* Display response */
347 ipaddr = wbcStrDup(response.data.winsresp);
348 BAIL_ON_PTR_ERROR(ipaddr, wbc_status);
350 *ip = ipaddr;
351 wbc_status = WBC_ERR_SUCCESS;
353 done:
354 return wbc_status;
357 wbcErr wbcResolveWinsByName(const char *name, char **ip)
359 return wbcCtxResolveWinsByName(NULL, name, ip);
362 /* Resolve an IP address via WINS into a NetbiosName */
363 wbcErr wbcCtxResolveWinsByIP(struct wbcContext *ctx,
364 const char *ip, char **name)
366 struct winbindd_request request;
367 struct winbindd_response response;
368 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
369 char *name_str;
371 ZERO_STRUCT(request);
372 ZERO_STRUCT(response);
374 /* Send request */
376 strncpy(request.data.winsreq, ip,
377 sizeof(request.data.winsreq)-1);
379 wbc_status = wbcRequestResponse(ctx, WINBINDD_WINS_BYIP,
380 &request,
381 &response);
382 BAIL_ON_WBC_ERROR(wbc_status);
384 /* Display response */
386 name_str = wbcStrDup(response.data.winsresp);
387 BAIL_ON_PTR_ERROR(name_str, wbc_status);
389 *name = name_str;
390 wbc_status = WBC_ERR_SUCCESS;
392 done:
393 return wbc_status;
396 wbcErr wbcResolveWinsByIP(const char *ip, char **name)
398 return wbcCtxResolveWinsByIP(NULL, ip, name);
404 static wbcErr process_domain_info_string(struct wbcDomainInfo *info,
405 char *info_string)
407 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
408 char *r = NULL;
409 char *s = NULL;
411 r = info_string;
413 /* Short Name */
414 if ((s = strchr(r, '\\')) == NULL) {
415 wbc_status = WBC_ERR_INVALID_RESPONSE;
416 BAIL_ON_WBC_ERROR(wbc_status);
418 *s = '\0';
419 s++;
421 info->short_name = strdup(r);
422 BAIL_ON_PTR_ERROR(info->short_name, wbc_status);
425 /* DNS Name */
426 r = s;
427 if ((s = strchr(r, '\\')) == NULL) {
428 wbc_status = WBC_ERR_INVALID_RESPONSE;
429 BAIL_ON_WBC_ERROR(wbc_status);
431 *s = '\0';
432 s++;
434 info->dns_name = strdup(r);
435 BAIL_ON_PTR_ERROR(info->dns_name, wbc_status);
437 /* SID */
438 r = s;
439 if ((s = strchr(r, '\\')) == NULL) {
440 wbc_status = WBC_ERR_INVALID_RESPONSE;
441 BAIL_ON_WBC_ERROR(wbc_status);
443 *s = '\0';
444 s++;
446 wbc_status = wbcStringToSid(r, &info->sid);
447 BAIL_ON_WBC_ERROR(wbc_status);
449 /* Trust type */
450 r = s;
451 if ((s = strchr(r, '\\')) == NULL) {
452 wbc_status = WBC_ERR_INVALID_RESPONSE;
453 BAIL_ON_WBC_ERROR(wbc_status);
455 *s = '\0';
456 s++;
458 if (strncmp(r, "Routed", strlen("Routed")) == 0) {
459 info->trust_type = WBC_DOMINFO_TRUSTTYPE_NONE;
460 info->trust_routing = strdup(r);
461 BAIL_ON_PTR_ERROR(info->trust_routing, wbc_status);
462 } else if (strcmp(r, "Local") == 0) {
463 info->trust_type = WBC_DOMINFO_TRUSTTYPE_LOCAL;
464 } else if (strcmp(r, "Workstation") == 0) {
465 info->trust_type = WBC_DOMINFO_TRUSTTYPE_WKSTA;
466 } else if (strcmp(r, "RWDC") == 0) {
467 info->trust_type = WBC_DOMINFO_TRUSTTYPE_RWDC;
468 } else if (strcmp(r, "RODC") == 0) {
469 info->trust_type = WBC_DOMINFO_TRUSTTYPE_RODC;
470 } else if (strcmp(r, "PDC") == 0) {
471 info->trust_type = WBC_DOMINFO_TRUSTTYPE_PDC;
472 } else if (strcmp(r, "External") == 0) {
473 info->trust_type = WBC_DOMINFO_TRUSTTYPE_EXTERNAL;
474 } else if (strcmp(r, "Forest") == 0) {
475 info->trust_type = WBC_DOMINFO_TRUSTTYPE_FOREST;
476 } else if (strcmp(r, "In Forest") == 0) {
477 info->trust_type = WBC_DOMINFO_TRUSTTYPE_IN_FOREST;
478 } else {
479 wbc_status = WBC_ERR_INVALID_RESPONSE;
480 BAIL_ON_WBC_ERROR(wbc_status);
483 /* Transitive */
484 r = s;
485 if ((s = strchr(r, '\\')) == NULL) {
486 wbc_status = WBC_ERR_INVALID_RESPONSE;
487 BAIL_ON_WBC_ERROR(wbc_status);
489 *s = '\0';
490 s++;
492 if (strcmp(r, "Yes") == 0) {
493 info->trust_flags |= WBC_DOMINFO_TRUST_TRANSITIVE;
496 /* Incoming */
497 r = s;
498 if ((s = strchr(r, '\\')) == NULL) {
499 wbc_status = WBC_ERR_INVALID_RESPONSE;
500 BAIL_ON_WBC_ERROR(wbc_status);
502 *s = '\0';
503 s++;
505 if (strcmp(r, "Yes") == 0) {
506 info->trust_flags |= WBC_DOMINFO_TRUST_INCOMING;
509 /* Outgoing */
510 r = s;
511 if ((s = strchr(r, '\\')) == NULL) {
512 wbc_status = WBC_ERR_INVALID_RESPONSE;
513 BAIL_ON_WBC_ERROR(wbc_status);
515 *s = '\0';
516 s++;
518 if (strcmp(r, "Yes") == 0) {
519 info->trust_flags |= WBC_DOMINFO_TRUST_OUTGOING;
522 /* Online/Offline status */
523 r = s;
524 if ( strcmp(r, "Offline") == 0) {
525 info->domain_flags |= WBC_DOMINFO_DOMAIN_OFFLINE;
528 wbc_status = WBC_ERR_SUCCESS;
530 done:
531 return wbc_status;
534 static void wbcDomainInfoListDestructor(void *ptr)
536 struct wbcDomainInfo *i = (struct wbcDomainInfo *)ptr;
538 while (i->short_name != NULL) {
539 free(i->short_name);
540 free(i->dns_name);
541 i += 1;
545 /* Enumerate the domain trusts known by Winbind */
546 wbcErr wbcCtxListTrusts(struct wbcContext *ctx,
547 struct wbcDomainInfo **domains, size_t *num_domains)
549 struct winbindd_response response;
550 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
551 char *p = NULL;
552 char *extra_data = NULL;
553 struct wbcDomainInfo *d_list = NULL;
554 int i = 0;
556 *domains = NULL;
557 *num_domains = 0;
559 ZERO_STRUCT(response);
561 /* Send request */
563 wbc_status = wbcRequestResponse(ctx, WINBINDD_LIST_TRUSTDOM,
564 NULL,
565 &response);
566 BAIL_ON_WBC_ERROR(wbc_status);
568 /* Decode the response */
570 p = (char *)response.extra_data.data;
572 if ((p == NULL) || (strlen(p) == 0)) {
573 /* We should always at least get back our
574 own SAM domain */
576 wbc_status = WBC_ERR_DOMAIN_NOT_FOUND;
577 BAIL_ON_WBC_ERROR(wbc_status);
580 d_list = (struct wbcDomainInfo *)wbcAllocateMemory(
581 response.data.num_entries + 1,sizeof(struct wbcDomainInfo),
582 wbcDomainInfoListDestructor);
583 BAIL_ON_PTR_ERROR(d_list, wbc_status);
585 extra_data = strdup((char*)response.extra_data.data);
586 BAIL_ON_PTR_ERROR(extra_data, wbc_status);
588 p = extra_data;
590 /* Outer loop processes the list of domain information */
592 for (i=0; i<response.data.num_entries && p; i++) {
593 char *next = strchr(p, '\n');
595 if (next) {
596 *next = '\0';
597 next++;
600 wbc_status = process_domain_info_string(&d_list[i], p);
601 BAIL_ON_WBC_ERROR(wbc_status);
603 p = next;
606 *domains = d_list;
607 d_list = NULL;
608 *num_domains = i;
610 done:
611 winbindd_free_response(&response);
612 wbcFreeMemory(d_list);
613 free(extra_data);
614 return wbc_status;
617 wbcErr wbcListTrusts(struct wbcDomainInfo **domains, size_t *num_domains)
619 return wbcCtxListTrusts(NULL, domains, num_domains);
622 static void wbcDomainControllerInfoDestructor(void *ptr)
624 struct wbcDomainControllerInfo *i =
625 (struct wbcDomainControllerInfo *)ptr;
626 free(i->dc_name);
629 /* Enumerate the domain trusts known by Winbind */
630 wbcErr wbcCtxLookupDomainController(struct wbcContext *ctx,
631 const char *domain, uint32_t flags,
632 struct wbcDomainControllerInfo **dc_info)
634 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
635 struct winbindd_request request;
636 struct winbindd_response response;
637 struct wbcDomainControllerInfo *dc = NULL;
639 /* validate input params */
641 if (!domain || !dc_info) {
642 wbc_status = WBC_ERR_INVALID_PARAM;
643 BAIL_ON_WBC_ERROR(wbc_status);
646 ZERO_STRUCT(request);
647 ZERO_STRUCT(response);
649 strncpy(request.data.dsgetdcname.domain_name, domain,
650 sizeof(request.data.dsgetdcname.domain_name)-1);
652 request.flags = flags;
654 dc = (struct wbcDomainControllerInfo *)wbcAllocateMemory(
655 1, sizeof(struct wbcDomainControllerInfo),
656 wbcDomainControllerInfoDestructor);
657 BAIL_ON_PTR_ERROR(dc, wbc_status);
659 /* Send request */
661 wbc_status = wbcRequestResponse(ctx, WINBINDD_DSGETDCNAME,
662 &request,
663 &response);
664 BAIL_ON_WBC_ERROR(wbc_status);
666 dc->dc_name = strdup(response.data.dsgetdcname.dc_unc);
667 BAIL_ON_PTR_ERROR(dc->dc_name, wbc_status);
669 *dc_info = dc;
670 dc = NULL;
672 done:
673 wbcFreeMemory(dc);
674 return wbc_status;
677 wbcErr wbcLookupDomainController(const char *domain, uint32_t flags,
678 struct wbcDomainControllerInfo **dc_info)
680 return wbcCtxLookupDomainController(NULL, domain, flags, dc_info);
683 static void wbcDomainControllerInfoExDestructor(void *ptr)
685 struct wbcDomainControllerInfoEx *i =
686 (struct wbcDomainControllerInfoEx *)ptr;
687 free(discard_const_p(char, i->dc_unc));
688 free(discard_const_p(char, i->dc_address));
689 free(discard_const_p(char, i->domain_guid));
690 free(discard_const_p(char, i->domain_name));
691 free(discard_const_p(char, i->forest_name));
692 free(discard_const_p(char, i->dc_site_name));
693 free(discard_const_p(char, i->client_site_name));
696 static wbcErr wbc_create_domain_controller_info_ex(const struct winbindd_response *resp,
697 struct wbcDomainControllerInfoEx **_i)
699 wbcErr wbc_status = WBC_ERR_SUCCESS;
700 struct wbcDomainControllerInfoEx *i;
701 struct wbcGuid guid;
703 i = (struct wbcDomainControllerInfoEx *)wbcAllocateMemory(
704 1, sizeof(struct wbcDomainControllerInfoEx),
705 wbcDomainControllerInfoExDestructor);
706 BAIL_ON_PTR_ERROR(i, wbc_status);
708 i->dc_unc = strdup(resp->data.dsgetdcname.dc_unc);
709 BAIL_ON_PTR_ERROR(i->dc_unc, wbc_status);
711 i->dc_address = strdup(resp->data.dsgetdcname.dc_address);
712 BAIL_ON_PTR_ERROR(i->dc_address, wbc_status);
714 i->dc_address_type = resp->data.dsgetdcname.dc_address_type;
716 wbc_status = wbcStringToGuid(resp->data.dsgetdcname.domain_guid, &guid);
717 if (WBC_ERROR_IS_OK(wbc_status)) {
718 i->domain_guid = (struct wbcGuid *)malloc(
719 sizeof(struct wbcGuid));
720 BAIL_ON_PTR_ERROR(i->domain_guid, wbc_status);
722 *i->domain_guid = guid;
725 i->domain_name = strdup(resp->data.dsgetdcname.domain_name);
726 BAIL_ON_PTR_ERROR(i->domain_name, wbc_status);
728 if (resp->data.dsgetdcname.forest_name[0] != '\0') {
729 i->forest_name = strdup(resp->data.dsgetdcname.forest_name);
730 BAIL_ON_PTR_ERROR(i->forest_name, wbc_status);
733 i->dc_flags = resp->data.dsgetdcname.dc_flags;
735 if (resp->data.dsgetdcname.dc_site_name[0] != '\0') {
736 i->dc_site_name = strdup(resp->data.dsgetdcname.dc_site_name);
737 BAIL_ON_PTR_ERROR(i->dc_site_name, wbc_status);
740 if (resp->data.dsgetdcname.client_site_name[0] != '\0') {
741 i->client_site_name = strdup(
742 resp->data.dsgetdcname.client_site_name);
743 BAIL_ON_PTR_ERROR(i->client_site_name, wbc_status);
746 *_i = i;
747 i = NULL;
749 done:
750 if (i != NULL) {
751 wbcFreeMemory(i);
753 return wbc_status;
756 /* Get extended domain controller information */
757 wbcErr wbcCtxLookupDomainControllerEx(struct wbcContext *ctx,
758 const char *domain,
759 struct wbcGuid *guid,
760 const char *site,
761 uint32_t flags,
762 struct wbcDomainControllerInfoEx **dc_info)
764 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
765 struct winbindd_request request;
766 struct winbindd_response response;
768 /* validate input params */
770 if (!domain || !dc_info) {
771 wbc_status = WBC_ERR_INVALID_PARAM;
772 BAIL_ON_WBC_ERROR(wbc_status);
775 ZERO_STRUCT(request);
776 ZERO_STRUCT(response);
778 request.data.dsgetdcname.flags = flags;
780 strncpy(request.data.dsgetdcname.domain_name, domain,
781 sizeof(request.data.dsgetdcname.domain_name)-1);
783 if (site) {
784 strncpy(request.data.dsgetdcname.site_name, site,
785 sizeof(request.data.dsgetdcname.site_name)-1);
788 if (guid) {
789 char *str = NULL;
791 wbc_status = wbcGuidToString(guid, &str);
792 BAIL_ON_WBC_ERROR(wbc_status);
794 strncpy(request.data.dsgetdcname.domain_guid, str,
795 sizeof(request.data.dsgetdcname.domain_guid)-1);
797 wbcFreeMemory(str);
800 /* Send request */
802 wbc_status = wbcRequestResponse(ctx, WINBINDD_DSGETDCNAME,
803 &request,
804 &response);
805 BAIL_ON_WBC_ERROR(wbc_status);
807 if (dc_info) {
808 wbc_status = wbc_create_domain_controller_info_ex(&response,
809 dc_info);
810 BAIL_ON_WBC_ERROR(wbc_status);
813 wbc_status = WBC_ERR_SUCCESS;
814 done:
815 return wbc_status;
818 wbcErr wbcLookupDomainControllerEx(const char *domain,
819 struct wbcGuid *guid,
820 const char *site,
821 uint32_t flags,
822 struct wbcDomainControllerInfoEx **dc_info)
824 return wbcCtxLookupDomainControllerEx(NULL, domain, guid, site,
825 flags, dc_info);
828 static void wbcNamedBlobDestructor(void *ptr)
830 struct wbcNamedBlob *b = (struct wbcNamedBlob *)ptr;
832 while (b->name != NULL) {
833 free(discard_const_p(char, b->name));
834 free(b->blob.data);
835 b += 1;
839 /* Initialize a named blob and add to list of blobs */
840 wbcErr wbcAddNamedBlob(size_t *num_blobs,
841 struct wbcNamedBlob **pblobs,
842 const char *name,
843 uint32_t flags,
844 uint8_t *data,
845 size_t length)
847 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
848 struct wbcNamedBlob *blobs, *blob;
850 if (name == NULL) {
851 return WBC_ERR_INVALID_PARAM;
855 * Overallocate the b->name==NULL terminator for
856 * wbcNamedBlobDestructor
858 blobs = (struct wbcNamedBlob *)wbcAllocateMemory(
859 *num_blobs + 2, sizeof(struct wbcNamedBlob),
860 wbcNamedBlobDestructor);
862 if (blobs == NULL) {
863 return WBC_ERR_NO_MEMORY;
866 if (*pblobs != NULL) {
867 struct wbcNamedBlob *old = *pblobs;
868 memcpy(blobs, old, sizeof(struct wbcNamedBlob) * (*num_blobs));
869 if (*num_blobs != 0) {
870 /* end indicator for wbcNamedBlobDestructor */
871 old[0].name = NULL;
873 wbcFreeMemory(old);
875 *pblobs = blobs;
877 blob = &blobs[*num_blobs];
879 blob->name = strdup(name);
880 BAIL_ON_PTR_ERROR(blob->name, wbc_status);
881 blob->flags = flags;
883 blob->blob.length = length;
884 blob->blob.data = (uint8_t *)malloc(length);
885 BAIL_ON_PTR_ERROR(blob->blob.data, wbc_status);
886 memcpy(blob->blob.data, data, length);
888 *num_blobs += 1;
889 *pblobs = blobs;
890 blobs = NULL;
892 wbc_status = WBC_ERR_SUCCESS;
893 done:
894 wbcFreeMemory(blobs);
895 return wbc_status;