libwbclient: add wbcInterfaceVersion send/recv calls
[Samba/gebeck_regimport.git] / nsswitch / libwbclient / wbc_util.c
blobf72f4fc7493d4323f3273950a42fbb2b94280cd7
1 /*
2 Unix SMB/CIFS implementation.
4 Winbind client API
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"
30 struct wbc_ping_state {
31 struct winbindd_request req;
34 static void wbcPing_done(struct tevent_req *subreq);
36 /** @brief Ping winbind to see if the service is up and running
38 * @param mem_ctx talloc context to allocate the request from
39 * @param ev event context to use for async operation
40 * @param wb_ctx winbind context to use
42 * @return Async request on successful dispatch of the request, NULL on error
45 struct tevent_req *wbcPing_send(TALLOC_CTX *mem_ctx,
46 struct tevent_context *ev,
47 struct wb_context *wb_ctx)
49 struct tevent_req *req, *subreq;
50 struct wbc_ping_state *state;
52 req = tevent_req_create(mem_ctx, &state, struct wbc_ping_state);
53 if (req == NULL) {
54 return NULL;
57 ZERO_STRUCT(state->req);
59 state->req.cmd = WINBINDD_PING;
60 subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
61 if (tevent_req_nomem(subreq, req)) {
62 return tevent_req_post(req, ev);
65 tevent_req_set_callback(subreq, wbcPing_done, req);
66 return req;
69 static void wbcPing_done(struct tevent_req *subreq)
71 struct tevent_req *req = tevent_req_callback_data(
72 subreq, struct tevent_req);
73 struct wbc_ping_state *state = tevent_req_data(
74 req, struct wbc_ping_state);
75 struct winbindd_response *resp;
76 wbcErr wbc_status;
78 wbc_status = wb_trans_recv(subreq, state, &resp);
79 TALLOC_FREE(subreq);
80 if (!WBC_ERROR_IS_OK(wbc_status)) {
81 tevent_req_error(req, wbc_status);
82 return;
84 TALLOC_FREE(resp);
86 tevent_req_done(req);
89 /** @brief Receive ping response from winbind
91 * @param req async request sent in #wbcPing_send
93 * @return NT_STATUS_OK on success, an error status on error.
96 wbcErr wbcPing_recv(struct tevent_req *req)
98 wbcErr wbc_status;
100 if (tevent_req_is_wbcerr(req, &wbc_status)) {
101 tevent_req_received(req);
102 return wbc_status;
105 tevent_req_received(req);
106 return WBC_ERR_SUCCESS;
109 /** @brief Ping winbindd to see if the daemon is running
111 * @return #wbcErr
113 wbcErr wbcPing(void)
115 struct winbindd_request request;
116 struct winbindd_response response;
118 /* Initialize request */
120 ZERO_STRUCT(request);
121 ZERO_STRUCT(response);
123 return wbcRequestResponse(WINBINDD_PING, &request, &response);
126 struct wbc_interface_version_state {
127 struct winbindd_request req;
128 uint32_t version;
131 static void wbcInterfaceVersion_done(struct tevent_req *subreq);
134 * @brief Request the interface version from winbind
136 * @param mem_ctx talloc context to allocate memory from
137 * @param ev tevent context to use for async requests
138 * @param wb_ctx winbind context
140 * @return tevevt_req on success, NULL on failure
143 struct tevent_req *wbcInterfaceVersion_send(TALLOC_CTX *mem_ctx,
144 struct tevent_context *ev,
145 struct wb_context *wb_ctx)
147 struct tevent_req *req, *subreq;
148 struct wbc_interface_version_state *state;
150 req = tevent_req_create(mem_ctx, &state, struct wbc_interface_version_state);
151 if (req == NULL) {
152 return NULL;
155 ZERO_STRUCT(state->req);
156 state->req.cmd = WINBINDD_INTERFACE_VERSION;
158 subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
159 if (tevent_req_nomem(subreq, req)) {
160 return tevent_req_post(req, ev);
163 tevent_req_set_callback(subreq, wbcInterfaceVersion_done, req);
165 return req;
168 static void wbcInterfaceVersion_done(struct tevent_req *subreq)
170 struct tevent_req *req = tevent_req_callback_data(
171 subreq, struct tevent_req);
172 struct wbc_interface_version_state *state = tevent_req_data(
173 req, struct wbc_interface_version_state);
174 struct winbindd_response *resp;
175 wbcErr wbc_status;
177 wbc_status = wb_trans_recv(subreq, state, &resp);
178 TALLOC_FREE(subreq);
179 if (!WBC_ERROR_IS_OK(wbc_status)) {
180 tevent_req_error(req, wbc_status);
181 return;
183 state->version = resp->data.interface_version;
184 TALLOC_FREE(resp);
186 tevent_req_done(req);
190 * @brief Receive the winbind interface version
192 * @param req tevent_req containing the request
193 * @param interface_version pointer to uint32_t to hold the interface
194 * version
196 * @return #wbcErr
199 wbcErr wbcInterfaceVersion_recv(struct tevent_req *req,
200 uint32_t *interface_version)
202 struct wbc_interface_version_state *state = tevent_req_data(
203 req, struct wbc_interface_version_state);
204 wbcErr wbc_status;
206 if (tevent_req_is_wbcerr(req, &wbc_status)) {
207 tevent_req_received(req);
208 return wbc_status;
211 *interface_version = state->version;
213 tevent_req_received(req);
214 return WBC_ERR_SUCCESS;
218 wbcErr wbcInterfaceDetails(struct wbcInterfaceDetails **_details)
220 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
221 struct wbcInterfaceDetails *info;
222 struct wbcDomainInfo *domain = NULL;
223 struct winbindd_request request;
224 struct winbindd_response response;
226 /* Initialize request */
228 ZERO_STRUCT(request);
229 ZERO_STRUCT(response);
231 info = talloc(NULL, struct wbcInterfaceDetails);
232 BAIL_ON_PTR_ERROR(info, wbc_status);
234 /* first the interface version */
235 wbc_status = wbcRequestResponse(WINBINDD_INTERFACE_VERSION, NULL, &response);
236 BAIL_ON_WBC_ERROR(wbc_status);
237 info->interface_version = response.data.interface_version;
239 /* then the samba version and the winbind separator */
240 wbc_status = wbcRequestResponse(WINBINDD_INFO, NULL, &response);
241 BAIL_ON_WBC_ERROR(wbc_status);
243 info->winbind_version = talloc_strdup(info,
244 response.data.info.samba_version);
245 BAIL_ON_PTR_ERROR(info->winbind_version, wbc_status);
246 info->winbind_separator = response.data.info.winbind_separator;
248 /* then the local netbios name */
249 wbc_status = wbcRequestResponse(WINBINDD_NETBIOS_NAME, NULL, &response);
250 BAIL_ON_WBC_ERROR(wbc_status);
252 info->netbios_name = talloc_strdup(info,
253 response.data.netbios_name);
254 BAIL_ON_PTR_ERROR(info->netbios_name, wbc_status);
256 /* then the local workgroup name */
257 wbc_status = wbcRequestResponse(WINBINDD_DOMAIN_NAME, NULL, &response);
258 BAIL_ON_WBC_ERROR(wbc_status);
260 info->netbios_domain = talloc_strdup(info,
261 response.data.domain_name);
262 BAIL_ON_PTR_ERROR(info->netbios_domain, wbc_status);
264 wbc_status = wbcDomainInfo(info->netbios_domain, &domain);
265 if (wbc_status == WBC_ERR_DOMAIN_NOT_FOUND) {
266 /* maybe it's a standalone server */
267 domain = NULL;
268 wbc_status = WBC_ERR_SUCCESS;
269 } else {
270 BAIL_ON_WBC_ERROR(wbc_status);
273 if (domain) {
274 info->dns_domain = talloc_strdup(info,
275 domain->dns_name);
276 wbcFreeMemory(domain);
277 BAIL_ON_PTR_ERROR(info->dns_domain, wbc_status);
278 } else {
279 info->dns_domain = NULL;
282 *_details = info;
283 info = NULL;
285 wbc_status = WBC_ERR_SUCCESS;
287 done:
288 talloc_free(info);
289 return wbc_status;
293 /* Lookup the current status of a trusted domain */
294 wbcErr wbcDomainInfo(const char *domain, struct wbcDomainInfo **dinfo)
296 struct winbindd_request request;
297 struct winbindd_response response;
298 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
299 struct wbcDomainInfo *info = NULL;
301 if (!domain || !dinfo) {
302 wbc_status = WBC_ERR_INVALID_PARAM;
303 BAIL_ON_WBC_ERROR(wbc_status);
306 /* Initialize request */
308 ZERO_STRUCT(request);
309 ZERO_STRUCT(response);
311 strncpy(request.domain_name, domain,
312 sizeof(request.domain_name)-1);
314 wbc_status = wbcRequestResponse(WINBINDD_DOMAIN_INFO,
315 &request,
316 &response);
317 BAIL_ON_WBC_ERROR(wbc_status);
319 info = talloc(NULL, struct wbcDomainInfo);
320 BAIL_ON_PTR_ERROR(info, wbc_status);
322 info->short_name = talloc_strdup(info,
323 response.data.domain_info.name);
324 BAIL_ON_PTR_ERROR(info->short_name, wbc_status);
326 info->dns_name = talloc_strdup(info,
327 response.data.domain_info.alt_name);
328 BAIL_ON_PTR_ERROR(info->dns_name, wbc_status);
330 wbc_status = wbcStringToSid(response.data.domain_info.sid,
331 &info->sid);
332 BAIL_ON_WBC_ERROR(wbc_status);
334 if (response.data.domain_info.native_mode)
335 info->domain_flags |= WBC_DOMINFO_DOMAIN_NATIVE;
336 if (response.data.domain_info.active_directory)
337 info->domain_flags |= WBC_DOMINFO_DOMAIN_AD;
338 if (response.data.domain_info.primary)
339 info->domain_flags |= WBC_DOMINFO_DOMAIN_PRIMARY;
341 *dinfo = info;
343 wbc_status = WBC_ERR_SUCCESS;
345 done:
346 if (!WBC_ERROR_IS_OK(wbc_status)) {
347 talloc_free(info);
350 return wbc_status;
354 /* Resolve a NetbiosName via WINS */
355 wbcErr wbcResolveWinsByName(const char *name, char **ip)
357 struct winbindd_request request;
358 struct winbindd_response response;
359 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
360 char *ipaddr;
362 ZERO_STRUCT(request);
363 ZERO_STRUCT(response);
365 /* Send request */
367 strncpy(request.data.winsreq, name,
368 sizeof(request.data.winsreq)-1);
370 wbc_status = wbcRequestResponse(WINBINDD_WINS_BYNAME,
371 &request,
372 &response);
373 BAIL_ON_WBC_ERROR(wbc_status);
375 /* Display response */
377 ipaddr = talloc_strdup(NULL, response.data.winsresp);
378 BAIL_ON_PTR_ERROR(ipaddr, wbc_status);
380 *ip = ipaddr;
381 wbc_status = WBC_ERR_SUCCESS;
383 done:
384 return wbc_status;
387 /* Resolve an IP address via WINS into a NetbiosName */
388 wbcErr wbcResolveWinsByIP(const char *ip, char **name)
390 struct winbindd_request request;
391 struct winbindd_response response;
392 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
393 char *name_str;
395 ZERO_STRUCT(request);
396 ZERO_STRUCT(response);
398 /* Send request */
400 strncpy(request.data.winsreq, ip,
401 sizeof(request.data.winsreq)-1);
403 wbc_status = wbcRequestResponse(WINBINDD_WINS_BYIP,
404 &request,
405 &response);
406 BAIL_ON_WBC_ERROR(wbc_status);
408 /* Display response */
410 name_str = talloc_strdup(NULL, response.data.winsresp);
411 BAIL_ON_PTR_ERROR(name_str, wbc_status);
413 *name = name_str;
414 wbc_status = WBC_ERR_SUCCESS;
416 done:
417 return wbc_status;
423 static wbcErr process_domain_info_string(TALLOC_CTX *ctx,
424 struct wbcDomainInfo *info,
425 char *info_string)
427 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
428 char *r = NULL;
429 char *s = NULL;
431 if (!info || !info_string) {
432 wbc_status = WBC_ERR_INVALID_PARAM;
433 BAIL_ON_WBC_ERROR(wbc_status);
436 ZERO_STRUCTP(info);
438 r = info_string;
440 /* Short Name */
441 if ((s = strchr(r, '\\')) == NULL) {
442 wbc_status = WBC_ERR_INVALID_RESPONSE;
443 BAIL_ON_WBC_ERROR(wbc_status);
445 *s = '\0';
446 s++;
448 info->short_name = talloc_strdup(ctx, r);
449 BAIL_ON_PTR_ERROR(info->short_name, wbc_status);
452 /* DNS Name */
453 r = s;
454 if ((s = strchr(r, '\\')) == NULL) {
455 wbc_status = WBC_ERR_INVALID_RESPONSE;
456 BAIL_ON_WBC_ERROR(wbc_status);
458 *s = '\0';
459 s++;
461 info->dns_name = talloc_strdup(ctx, r);
462 BAIL_ON_PTR_ERROR(info->dns_name, wbc_status);
464 /* SID */
465 r = s;
466 if ((s = strchr(r, '\\')) == NULL) {
467 wbc_status = WBC_ERR_INVALID_RESPONSE;
468 BAIL_ON_WBC_ERROR(wbc_status);
470 *s = '\0';
471 s++;
473 wbc_status = wbcStringToSid(r, &info->sid);
474 BAIL_ON_WBC_ERROR(wbc_status);
476 /* Trust type */
477 r = s;
478 if ((s = strchr(r, '\\')) == NULL) {
479 wbc_status = WBC_ERR_INVALID_RESPONSE;
480 BAIL_ON_WBC_ERROR(wbc_status);
482 *s = '\0';
483 s++;
485 if (strcmp(r, "None") == 0) {
486 info->trust_type = WBC_DOMINFO_TRUSTTYPE_NONE;
487 } else if (strcmp(r, "External") == 0) {
488 info->trust_type = WBC_DOMINFO_TRUSTTYPE_EXTERNAL;
489 } else if (strcmp(r, "Forest") == 0) {
490 info->trust_type = WBC_DOMINFO_TRUSTTYPE_FOREST;
491 } else if (strcmp(r, "In Forest") == 0) {
492 info->trust_type = WBC_DOMINFO_TRUSTTYPE_IN_FOREST;
493 } else {
494 wbc_status = WBC_ERR_INVALID_RESPONSE;
495 BAIL_ON_WBC_ERROR(wbc_status);
498 /* Transitive */
499 r = s;
500 if ((s = strchr(r, '\\')) == NULL) {
501 wbc_status = WBC_ERR_INVALID_RESPONSE;
502 BAIL_ON_WBC_ERROR(wbc_status);
504 *s = '\0';
505 s++;
507 if (strcmp(r, "Yes") == 0) {
508 info->trust_flags |= WBC_DOMINFO_TRUST_TRANSITIVE;
511 /* Incoming */
512 r = s;
513 if ((s = strchr(r, '\\')) == NULL) {
514 wbc_status = WBC_ERR_INVALID_RESPONSE;
515 BAIL_ON_WBC_ERROR(wbc_status);
517 *s = '\0';
518 s++;
520 if (strcmp(r, "Yes") == 0) {
521 info->trust_flags |= WBC_DOMINFO_TRUST_INCOMING;
524 /* Outgoing */
525 r = s;
526 if ((s = strchr(r, '\\')) == NULL) {
527 wbc_status = WBC_ERR_INVALID_RESPONSE;
528 BAIL_ON_WBC_ERROR(wbc_status);
530 *s = '\0';
531 s++;
533 if (strcmp(r, "Yes") == 0) {
534 info->trust_flags |= WBC_DOMINFO_TRUST_OUTGOING;
537 /* Online/Offline status */
539 r = s;
540 if (r == NULL) {
541 wbc_status = WBC_ERR_INVALID_RESPONSE;
542 BAIL_ON_WBC_ERROR(wbc_status);
544 if ( strcmp(r, "Offline") == 0) {
545 info->domain_flags |= WBC_DOMINFO_DOMAIN_OFFLINE;
548 wbc_status = WBC_ERR_SUCCESS;
550 done:
551 return wbc_status;
554 /* Enumerate the domain trusts known by Winbind */
555 wbcErr wbcListTrusts(struct wbcDomainInfo **domains, size_t *num_domains)
557 struct winbindd_response response;
558 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
559 char *p = NULL;
560 char *q = NULL;
561 char *extra_data = NULL;
562 int count = 0;
563 struct wbcDomainInfo *d_list = NULL;
564 int i = 0;
566 *domains = NULL;
567 *num_domains = 0;
569 ZERO_STRUCT(response);
571 /* Send request */
573 wbc_status = wbcRequestResponse(WINBINDD_LIST_TRUSTDOM,
574 NULL,
575 &response);
576 BAIL_ON_WBC_ERROR(wbc_status);
578 /* Decode the response */
580 p = (char *)response.extra_data.data;
582 if ((p == NULL) || (strlen(p) == 0)) {
583 /* We should always at least get back our
584 own SAM domain */
586 wbc_status = WBC_ERR_DOMAIN_NOT_FOUND;
587 BAIL_ON_WBC_ERROR(wbc_status);
590 /* Count number of domains */
592 count = 0;
593 while (p) {
594 count++;
596 if ((q = strchr(p, '\n')) != NULL)
597 q++;
598 p = q;
601 d_list = talloc_array(NULL, struct wbcDomainInfo, count);
602 BAIL_ON_PTR_ERROR(d_list, wbc_status);
604 extra_data = strdup((char*)response.extra_data.data);
605 BAIL_ON_PTR_ERROR(extra_data, wbc_status);
607 p = extra_data;
609 /* Outer loop processes the list of domain information */
611 for (i=0; i<count && p; i++) {
612 char *next = strchr(p, '\n');
614 if (next) {
615 *next = '\0';
616 next++;
619 wbc_status = process_domain_info_string(d_list, &d_list[i], p);
620 BAIL_ON_WBC_ERROR(wbc_status);
622 p = next;
625 *domains = d_list;
626 *num_domains = i;
628 done:
629 if (!WBC_ERROR_IS_OK(wbc_status)) {
630 if (d_list)
631 talloc_free(d_list);
632 if (extra_data)
633 free(extra_data);
636 return wbc_status;
639 /* Enumerate the domain trusts known by Winbind */
640 wbcErr wbcLookupDomainController(const char *domain,
641 uint32_t flags,
642 struct wbcDomainControllerInfo **dc_info)
644 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
645 struct winbindd_request request;
646 struct winbindd_response response;
647 struct wbcDomainControllerInfo *dc = NULL;
649 /* validate input params */
651 if (!domain || !dc_info) {
652 wbc_status = WBC_ERR_INVALID_PARAM;
653 BAIL_ON_WBC_ERROR(wbc_status);
656 ZERO_STRUCT(request);
657 ZERO_STRUCT(response);
659 strncpy(request.data.dsgetdcname.domain_name, domain,
660 sizeof(request.data.dsgetdcname.domain_name)-1);
662 request.flags = flags;
664 dc = talloc(NULL, struct wbcDomainControllerInfo);
665 BAIL_ON_PTR_ERROR(dc, wbc_status);
667 /* Send request */
669 wbc_status = wbcRequestResponse(WINBINDD_DSGETDCNAME,
670 &request,
671 &response);
672 BAIL_ON_WBC_ERROR(wbc_status);
674 dc->dc_name = talloc_strdup(dc, response.data.dsgetdcname.dc_unc);
675 BAIL_ON_PTR_ERROR(dc->dc_name, wbc_status);
677 *dc_info = dc;
679 done:
680 if (!WBC_ERROR_IS_OK(wbc_status)) {
681 talloc_free(dc);
684 return wbc_status;
687 static wbcErr wbc_create_domain_controller_info_ex(TALLOC_CTX *mem_ctx,
688 const struct winbindd_response *resp,
689 struct wbcDomainControllerInfoEx **_i)
691 wbcErr wbc_status = WBC_ERR_SUCCESS;
692 struct wbcDomainControllerInfoEx *i;
693 struct wbcGuid guid;
695 i = talloc(mem_ctx, struct wbcDomainControllerInfoEx);
696 BAIL_ON_PTR_ERROR(i, wbc_status);
698 i->dc_unc = talloc_strdup(i, resp->data.dsgetdcname.dc_unc);
699 BAIL_ON_PTR_ERROR(i->dc_unc, wbc_status);
701 i->dc_address = talloc_strdup(i, resp->data.dsgetdcname.dc_address);
702 BAIL_ON_PTR_ERROR(i->dc_address, wbc_status);
704 i->dc_address_type = resp->data.dsgetdcname.dc_address_type;
706 wbc_status = wbcStringToGuid(resp->data.dsgetdcname.domain_guid, &guid);
707 if (WBC_ERROR_IS_OK(wbc_status)) {
708 i->domain_guid = talloc(i, struct wbcGuid);
709 BAIL_ON_PTR_ERROR(i->domain_guid, wbc_status);
711 *i->domain_guid = guid;
712 } else {
713 i->domain_guid = NULL;
716 i->domain_name = talloc_strdup(i, resp->data.dsgetdcname.domain_name);
717 BAIL_ON_PTR_ERROR(i->domain_name, wbc_status);
719 if (resp->data.dsgetdcname.forest_name[0] != '\0') {
720 i->forest_name = talloc_strdup(i,
721 resp->data.dsgetdcname.forest_name);
722 BAIL_ON_PTR_ERROR(i->forest_name, wbc_status);
723 } else {
724 i->forest_name = NULL;
727 i->dc_flags = resp->data.dsgetdcname.dc_flags;
729 if (resp->data.dsgetdcname.dc_site_name[0] != '\0') {
730 i->dc_site_name = talloc_strdup(i,
731 resp->data.dsgetdcname.dc_site_name);
732 BAIL_ON_PTR_ERROR(i->dc_site_name, wbc_status);
733 } else {
734 i->dc_site_name = NULL;
737 if (resp->data.dsgetdcname.client_site_name[0] != '\0') {
738 i->client_site_name = talloc_strdup(i,
739 resp->data.dsgetdcname.client_site_name);
740 BAIL_ON_PTR_ERROR(i->client_site_name, wbc_status);
741 } else {
742 i->client_site_name = NULL;
745 *_i = i;
746 i = NULL;
748 done:
749 talloc_free(i);
750 return wbc_status;
753 /* Get extended domain controller information */
754 wbcErr wbcLookupDomainControllerEx(const char *domain,
755 struct wbcGuid *guid,
756 const char *site,
757 uint32_t flags,
758 struct wbcDomainControllerInfoEx **dc_info)
760 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
761 struct winbindd_request request;
762 struct winbindd_response response;
764 /* validate input params */
766 if (!domain || !dc_info) {
767 wbc_status = WBC_ERR_INVALID_PARAM;
768 BAIL_ON_WBC_ERROR(wbc_status);
771 ZERO_STRUCT(request);
772 ZERO_STRUCT(response);
774 request.data.dsgetdcname.flags = flags;
776 strncpy(request.data.dsgetdcname.domain_name, domain,
777 sizeof(request.data.dsgetdcname.domain_name)-1);
779 if (site) {
780 strncpy(request.data.dsgetdcname.site_name, site,
781 sizeof(request.data.dsgetdcname.site_name)-1);
784 if (guid) {
785 char *str = NULL;
787 wbc_status = wbcGuidToString(guid, &str);
788 BAIL_ON_WBC_ERROR(wbc_status);
790 strncpy(request.data.dsgetdcname.domain_guid, str,
791 sizeof(request.data.dsgetdcname.domain_guid)-1);
793 wbcFreeMemory(str);
796 /* Send request */
798 wbc_status = wbcRequestResponse(WINBINDD_DSGETDCNAME,
799 &request,
800 &response);
801 BAIL_ON_WBC_ERROR(wbc_status);
803 if (dc_info) {
804 wbc_status = wbc_create_domain_controller_info_ex(NULL,
805 &response,
806 dc_info);
807 BAIL_ON_WBC_ERROR(wbc_status);
810 wbc_status = WBC_ERR_SUCCESS;
811 done:
812 return wbc_status;
815 /* Initialize a named blob and add to list of blobs */
816 wbcErr wbcAddNamedBlob(size_t *num_blobs,
817 struct wbcNamedBlob **blobs,
818 const char *name,
819 uint32_t flags,
820 uint8_t *data,
821 size_t length)
823 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
824 struct wbcNamedBlob blob;
826 *blobs = talloc_realloc(NULL, *blobs, struct wbcNamedBlob,
827 *(num_blobs)+1);
828 BAIL_ON_PTR_ERROR(*blobs, wbc_status);
830 blob.name = talloc_strdup(*blobs, name);
831 BAIL_ON_PTR_ERROR(blob.name, wbc_status);
832 blob.flags = flags;
833 blob.blob.length = length;
834 blob.blob.data = (uint8_t *)talloc_memdup(*blobs, data, length);
835 BAIL_ON_PTR_ERROR(blob.blob.data, wbc_status);
837 (*(blobs))[*num_blobs] = blob;
838 *(num_blobs) += 1;
840 wbc_status = WBC_ERR_SUCCESS;
841 done:
842 if (!WBC_ERROR_IS_OK(wbc_status)) {
843 wbcFreeMemory(*blobs);
845 return wbc_status;