libwbclient: Add wbcNetbiosName_send/recv calls
[Samba/gebeck_regimport.git] / nsswitch / libwbclient / wbc_util.c
blobfca0b061af3090ba6f373bda145b4c610b366251
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;
217 struct wbc_info_state {
218 struct winbindd_request req;
219 char separator;
220 char *version_string;
223 static void wbcInfo_done(struct tevent_req *subreq);
226 * @brief Request information about the winbind service
228 * @param mem_ctx talloc context to allocate memory from
229 * @param ev tevent context to use for async requests
230 * @param wb_ctx winbind context
232 * @return tevent_req on success, NULL on failure
235 struct tevent_req *wbcInfo_send(TALLOC_CTX *mem_ctx,
236 struct tevent_context *ev,
237 struct wb_context *wb_ctx)
239 struct tevent_req *req, *subreq;
240 struct wbc_info_state *state;
242 req = tevent_req_create(mem_ctx, &state, struct wbc_info_state);
243 if (req == NULL) {
244 return NULL;
247 ZERO_STRUCT(state->req);
248 state->req.cmd = WINBINDD_INFO;
250 subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
251 if (tevent_req_nomem(subreq, req)) {
252 return tevent_req_post(req, ev);
255 tevent_req_set_callback(subreq, wbcInfo_done, req);
256 return req;
259 static void wbcInfo_done(struct tevent_req *subreq)
261 struct tevent_req *req = tevent_req_callback_data(
262 subreq, struct tevent_req);
263 struct wbc_info_state *state = tevent_req_data(
264 req, struct wbc_info_state);
265 struct winbindd_response *resp;
266 wbcErr wbc_status;
268 wbc_status = wb_trans_recv(subreq, state, &resp);
269 TALLOC_FREE(subreq);
270 if (!WBC_ERROR_IS_OK(wbc_status)) {
271 tevent_req_error(req, wbc_status);
272 return;
274 state->version_string = talloc_strdup(state,
275 resp->data.info.samba_version);
276 if (tevent_req_nomem(state->version_string, subreq)) {
277 return;
279 state->separator = resp->data.info.winbind_separator;
280 TALLOC_FREE(resp);
282 tevent_req_done(req);
286 * @brief Receive information about the running winbind service
288 * @param req tevent_req containing the request
289 * @param mem_ctx talloc context to allocate memory from
290 * @param winbind_separator pointer to a char to hold the separator
291 * @param version_string pointer to a string to hold the version string
293 * @return #wbcErr
296 wbcErr wbcInfo_recv(struct tevent_req *req,
297 TALLOC_CTX *mem_ctx,
298 char *winbind_separator,
299 char **version_string)
301 struct wbc_info_state *state = tevent_req_data(
302 req, struct wbc_info_state);
303 wbcErr wbc_status;
305 if (tevent_req_is_wbcerr(req, &wbc_status)) {
306 tevent_req_received(req);
307 return wbc_status;
310 *winbind_separator = state->separator;
311 *version_string = talloc_steal(mem_ctx, state->version_string);
313 tevent_req_received(req);
314 return WBC_ERR_SUCCESS;
317 struct wbc_netbios_name_state {
318 struct winbindd_request req;
319 char *netbios_name;
322 static void wbcNetbiosName_done(struct tevent_req *subreq);
325 * @brief Request the machine's netbios name
327 * @param mem_ctx talloc context to allocate memory from
328 * @param ev tevent context to use for async requests
329 * @param wb_ctx winbind context
331 * @return tevent_req on success, NULL on failure
334 struct tevent_req *wbcNetbiosName_send(TALLOC_CTX *mem_ctx,
335 struct tevent_context *ev,
336 struct wb_context *wb_ctx)
338 struct tevent_req *req, *subreq;
339 struct wbc_netbios_name_state *state;
341 req = tevent_req_create(mem_ctx, &state, struct wbc_netbios_name_state);
342 if (req == NULL) {
343 return NULL;
346 ZERO_STRUCT(state->req);
347 state->req.cmd = WINBINDD_NETBIOS_NAME;
349 subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
350 if (tevent_req_nomem(subreq, req)) {
351 return tevent_req_post(req, ev);
354 tevent_req_set_callback(subreq, wbcNetbiosName_done, req);
355 return req;
358 static void wbcNetbiosName_done(struct tevent_req *subreq)
360 struct tevent_req *req = tevent_req_callback_data(
361 subreq, struct tevent_req);
362 struct wbc_netbios_name_state *state = tevent_req_data(
363 req, struct wbc_netbios_name_state);
364 struct winbindd_response *resp;
365 wbcErr wbc_status;
367 wbc_status = wb_trans_recv(subreq, state, &resp);
368 TALLOC_FREE(subreq);
369 if (!WBC_ERROR_IS_OK(wbc_status)) {
370 tevent_req_error(req, wbc_status);
371 return;
373 state->netbios_name = talloc_strdup(state,
374 resp->data.info.samba_version);
375 if (tevent_req_nomem(state->netbios_name, subreq)) {
376 return;
378 TALLOC_FREE(resp);
380 tevent_req_done(req);
384 * @brief Receive the machine's netbios name
386 * @param req tevent_req containing the request
387 * @param mem_ctx talloc context to allocate memory from
388 * @param netbios_name pointer to a string to hold the netbios name
390 * @return #wbcErr
393 wbcErr wbcNetbiosName_recv(struct tevent_req *req,
394 TALLOC_CTX *mem_ctx,
395 char **netbios_name)
397 struct wbc_netbios_name_state *state = tevent_req_data(
398 req, struct wbc_netbios_name_state);
399 wbcErr wbc_status;
401 if (tevent_req_is_wbcerr(req, &wbc_status)) {
402 tevent_req_received(req);
403 return wbc_status;
406 *netbios_name = talloc_steal(mem_ctx, state->netbios_name);
408 tevent_req_received(req);
409 return WBC_ERR_SUCCESS;
412 wbcErr wbcInterfaceDetails(struct wbcInterfaceDetails **_details)
414 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
415 struct wbcInterfaceDetails *info;
416 struct wbcDomainInfo *domain = NULL;
417 struct winbindd_request request;
418 struct winbindd_response response;
420 /* Initialize request */
422 ZERO_STRUCT(request);
423 ZERO_STRUCT(response);
425 info = talloc(NULL, struct wbcInterfaceDetails);
426 BAIL_ON_PTR_ERROR(info, wbc_status);
428 /* first the interface version */
429 wbc_status = wbcRequestResponse(WINBINDD_INTERFACE_VERSION, NULL, &response);
430 BAIL_ON_WBC_ERROR(wbc_status);
431 info->interface_version = response.data.interface_version;
433 /* then the samba version and the winbind separator */
434 wbc_status = wbcRequestResponse(WINBINDD_INFO, NULL, &response);
435 BAIL_ON_WBC_ERROR(wbc_status);
437 info->winbind_version = talloc_strdup(info,
438 response.data.info.samba_version);
439 BAIL_ON_PTR_ERROR(info->winbind_version, wbc_status);
440 info->winbind_separator = response.data.info.winbind_separator;
442 /* then the local netbios name */
443 wbc_status = wbcRequestResponse(WINBINDD_NETBIOS_NAME, NULL, &response);
444 BAIL_ON_WBC_ERROR(wbc_status);
446 info->netbios_name = talloc_strdup(info,
447 response.data.netbios_name);
448 BAIL_ON_PTR_ERROR(info->netbios_name, wbc_status);
450 /* then the local workgroup name */
451 wbc_status = wbcRequestResponse(WINBINDD_DOMAIN_NAME, NULL, &response);
452 BAIL_ON_WBC_ERROR(wbc_status);
454 info->netbios_domain = talloc_strdup(info,
455 response.data.domain_name);
456 BAIL_ON_PTR_ERROR(info->netbios_domain, wbc_status);
458 wbc_status = wbcDomainInfo(info->netbios_domain, &domain);
459 if (wbc_status == WBC_ERR_DOMAIN_NOT_FOUND) {
460 /* maybe it's a standalone server */
461 domain = NULL;
462 wbc_status = WBC_ERR_SUCCESS;
463 } else {
464 BAIL_ON_WBC_ERROR(wbc_status);
467 if (domain) {
468 info->dns_domain = talloc_strdup(info,
469 domain->dns_name);
470 wbcFreeMemory(domain);
471 BAIL_ON_PTR_ERROR(info->dns_domain, wbc_status);
472 } else {
473 info->dns_domain = NULL;
476 *_details = info;
477 info = NULL;
479 wbc_status = WBC_ERR_SUCCESS;
481 done:
482 talloc_free(info);
483 return wbc_status;
487 /* Lookup the current status of a trusted domain */
488 wbcErr wbcDomainInfo(const char *domain, struct wbcDomainInfo **dinfo)
490 struct winbindd_request request;
491 struct winbindd_response response;
492 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
493 struct wbcDomainInfo *info = NULL;
495 if (!domain || !dinfo) {
496 wbc_status = WBC_ERR_INVALID_PARAM;
497 BAIL_ON_WBC_ERROR(wbc_status);
500 /* Initialize request */
502 ZERO_STRUCT(request);
503 ZERO_STRUCT(response);
505 strncpy(request.domain_name, domain,
506 sizeof(request.domain_name)-1);
508 wbc_status = wbcRequestResponse(WINBINDD_DOMAIN_INFO,
509 &request,
510 &response);
511 BAIL_ON_WBC_ERROR(wbc_status);
513 info = talloc(NULL, struct wbcDomainInfo);
514 BAIL_ON_PTR_ERROR(info, wbc_status);
516 info->short_name = talloc_strdup(info,
517 response.data.domain_info.name);
518 BAIL_ON_PTR_ERROR(info->short_name, wbc_status);
520 info->dns_name = talloc_strdup(info,
521 response.data.domain_info.alt_name);
522 BAIL_ON_PTR_ERROR(info->dns_name, wbc_status);
524 wbc_status = wbcStringToSid(response.data.domain_info.sid,
525 &info->sid);
526 BAIL_ON_WBC_ERROR(wbc_status);
528 if (response.data.domain_info.native_mode)
529 info->domain_flags |= WBC_DOMINFO_DOMAIN_NATIVE;
530 if (response.data.domain_info.active_directory)
531 info->domain_flags |= WBC_DOMINFO_DOMAIN_AD;
532 if (response.data.domain_info.primary)
533 info->domain_flags |= WBC_DOMINFO_DOMAIN_PRIMARY;
535 *dinfo = info;
537 wbc_status = WBC_ERR_SUCCESS;
539 done:
540 if (!WBC_ERROR_IS_OK(wbc_status)) {
541 talloc_free(info);
544 return wbc_status;
548 /* Resolve a NetbiosName via WINS */
549 wbcErr wbcResolveWinsByName(const char *name, char **ip)
551 struct winbindd_request request;
552 struct winbindd_response response;
553 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
554 char *ipaddr;
556 ZERO_STRUCT(request);
557 ZERO_STRUCT(response);
559 /* Send request */
561 strncpy(request.data.winsreq, name,
562 sizeof(request.data.winsreq)-1);
564 wbc_status = wbcRequestResponse(WINBINDD_WINS_BYNAME,
565 &request,
566 &response);
567 BAIL_ON_WBC_ERROR(wbc_status);
569 /* Display response */
571 ipaddr = talloc_strdup(NULL, response.data.winsresp);
572 BAIL_ON_PTR_ERROR(ipaddr, wbc_status);
574 *ip = ipaddr;
575 wbc_status = WBC_ERR_SUCCESS;
577 done:
578 return wbc_status;
581 /* Resolve an IP address via WINS into a NetbiosName */
582 wbcErr wbcResolveWinsByIP(const char *ip, char **name)
584 struct winbindd_request request;
585 struct winbindd_response response;
586 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
587 char *name_str;
589 ZERO_STRUCT(request);
590 ZERO_STRUCT(response);
592 /* Send request */
594 strncpy(request.data.winsreq, ip,
595 sizeof(request.data.winsreq)-1);
597 wbc_status = wbcRequestResponse(WINBINDD_WINS_BYIP,
598 &request,
599 &response);
600 BAIL_ON_WBC_ERROR(wbc_status);
602 /* Display response */
604 name_str = talloc_strdup(NULL, response.data.winsresp);
605 BAIL_ON_PTR_ERROR(name_str, wbc_status);
607 *name = name_str;
608 wbc_status = WBC_ERR_SUCCESS;
610 done:
611 return wbc_status;
617 static wbcErr process_domain_info_string(TALLOC_CTX *ctx,
618 struct wbcDomainInfo *info,
619 char *info_string)
621 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
622 char *r = NULL;
623 char *s = NULL;
625 if (!info || !info_string) {
626 wbc_status = WBC_ERR_INVALID_PARAM;
627 BAIL_ON_WBC_ERROR(wbc_status);
630 ZERO_STRUCTP(info);
632 r = info_string;
634 /* Short Name */
635 if ((s = strchr(r, '\\')) == NULL) {
636 wbc_status = WBC_ERR_INVALID_RESPONSE;
637 BAIL_ON_WBC_ERROR(wbc_status);
639 *s = '\0';
640 s++;
642 info->short_name = talloc_strdup(ctx, r);
643 BAIL_ON_PTR_ERROR(info->short_name, wbc_status);
646 /* DNS Name */
647 r = s;
648 if ((s = strchr(r, '\\')) == NULL) {
649 wbc_status = WBC_ERR_INVALID_RESPONSE;
650 BAIL_ON_WBC_ERROR(wbc_status);
652 *s = '\0';
653 s++;
655 info->dns_name = talloc_strdup(ctx, r);
656 BAIL_ON_PTR_ERROR(info->dns_name, wbc_status);
658 /* SID */
659 r = s;
660 if ((s = strchr(r, '\\')) == NULL) {
661 wbc_status = WBC_ERR_INVALID_RESPONSE;
662 BAIL_ON_WBC_ERROR(wbc_status);
664 *s = '\0';
665 s++;
667 wbc_status = wbcStringToSid(r, &info->sid);
668 BAIL_ON_WBC_ERROR(wbc_status);
670 /* Trust type */
671 r = s;
672 if ((s = strchr(r, '\\')) == NULL) {
673 wbc_status = WBC_ERR_INVALID_RESPONSE;
674 BAIL_ON_WBC_ERROR(wbc_status);
676 *s = '\0';
677 s++;
679 if (strcmp(r, "None") == 0) {
680 info->trust_type = WBC_DOMINFO_TRUSTTYPE_NONE;
681 } else if (strcmp(r, "External") == 0) {
682 info->trust_type = WBC_DOMINFO_TRUSTTYPE_EXTERNAL;
683 } else if (strcmp(r, "Forest") == 0) {
684 info->trust_type = WBC_DOMINFO_TRUSTTYPE_FOREST;
685 } else if (strcmp(r, "In Forest") == 0) {
686 info->trust_type = WBC_DOMINFO_TRUSTTYPE_IN_FOREST;
687 } else {
688 wbc_status = WBC_ERR_INVALID_RESPONSE;
689 BAIL_ON_WBC_ERROR(wbc_status);
692 /* Transitive */
693 r = s;
694 if ((s = strchr(r, '\\')) == NULL) {
695 wbc_status = WBC_ERR_INVALID_RESPONSE;
696 BAIL_ON_WBC_ERROR(wbc_status);
698 *s = '\0';
699 s++;
701 if (strcmp(r, "Yes") == 0) {
702 info->trust_flags |= WBC_DOMINFO_TRUST_TRANSITIVE;
705 /* Incoming */
706 r = s;
707 if ((s = strchr(r, '\\')) == NULL) {
708 wbc_status = WBC_ERR_INVALID_RESPONSE;
709 BAIL_ON_WBC_ERROR(wbc_status);
711 *s = '\0';
712 s++;
714 if (strcmp(r, "Yes") == 0) {
715 info->trust_flags |= WBC_DOMINFO_TRUST_INCOMING;
718 /* Outgoing */
719 r = s;
720 if ((s = strchr(r, '\\')) == NULL) {
721 wbc_status = WBC_ERR_INVALID_RESPONSE;
722 BAIL_ON_WBC_ERROR(wbc_status);
724 *s = '\0';
725 s++;
727 if (strcmp(r, "Yes") == 0) {
728 info->trust_flags |= WBC_DOMINFO_TRUST_OUTGOING;
731 /* Online/Offline status */
733 r = s;
734 if (r == NULL) {
735 wbc_status = WBC_ERR_INVALID_RESPONSE;
736 BAIL_ON_WBC_ERROR(wbc_status);
738 if ( strcmp(r, "Offline") == 0) {
739 info->domain_flags |= WBC_DOMINFO_DOMAIN_OFFLINE;
742 wbc_status = WBC_ERR_SUCCESS;
744 done:
745 return wbc_status;
748 /* Enumerate the domain trusts known by Winbind */
749 wbcErr wbcListTrusts(struct wbcDomainInfo **domains, size_t *num_domains)
751 struct winbindd_response response;
752 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
753 char *p = NULL;
754 char *q = NULL;
755 char *extra_data = NULL;
756 int count = 0;
757 struct wbcDomainInfo *d_list = NULL;
758 int i = 0;
760 *domains = NULL;
761 *num_domains = 0;
763 ZERO_STRUCT(response);
765 /* Send request */
767 wbc_status = wbcRequestResponse(WINBINDD_LIST_TRUSTDOM,
768 NULL,
769 &response);
770 BAIL_ON_WBC_ERROR(wbc_status);
772 /* Decode the response */
774 p = (char *)response.extra_data.data;
776 if ((p == NULL) || (strlen(p) == 0)) {
777 /* We should always at least get back our
778 own SAM domain */
780 wbc_status = WBC_ERR_DOMAIN_NOT_FOUND;
781 BAIL_ON_WBC_ERROR(wbc_status);
784 /* Count number of domains */
786 count = 0;
787 while (p) {
788 count++;
790 if ((q = strchr(p, '\n')) != NULL)
791 q++;
792 p = q;
795 d_list = talloc_array(NULL, struct wbcDomainInfo, count);
796 BAIL_ON_PTR_ERROR(d_list, wbc_status);
798 extra_data = strdup((char*)response.extra_data.data);
799 BAIL_ON_PTR_ERROR(extra_data, wbc_status);
801 p = extra_data;
803 /* Outer loop processes the list of domain information */
805 for (i=0; i<count && p; i++) {
806 char *next = strchr(p, '\n');
808 if (next) {
809 *next = '\0';
810 next++;
813 wbc_status = process_domain_info_string(d_list, &d_list[i], p);
814 BAIL_ON_WBC_ERROR(wbc_status);
816 p = next;
819 *domains = d_list;
820 *num_domains = i;
822 done:
823 if (!WBC_ERROR_IS_OK(wbc_status)) {
824 if (d_list)
825 talloc_free(d_list);
826 if (extra_data)
827 free(extra_data);
830 return wbc_status;
833 /* Enumerate the domain trusts known by Winbind */
834 wbcErr wbcLookupDomainController(const char *domain,
835 uint32_t flags,
836 struct wbcDomainControllerInfo **dc_info)
838 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
839 struct winbindd_request request;
840 struct winbindd_response response;
841 struct wbcDomainControllerInfo *dc = NULL;
843 /* validate input params */
845 if (!domain || !dc_info) {
846 wbc_status = WBC_ERR_INVALID_PARAM;
847 BAIL_ON_WBC_ERROR(wbc_status);
850 ZERO_STRUCT(request);
851 ZERO_STRUCT(response);
853 strncpy(request.data.dsgetdcname.domain_name, domain,
854 sizeof(request.data.dsgetdcname.domain_name)-1);
856 request.flags = flags;
858 dc = talloc(NULL, struct wbcDomainControllerInfo);
859 BAIL_ON_PTR_ERROR(dc, wbc_status);
861 /* Send request */
863 wbc_status = wbcRequestResponse(WINBINDD_DSGETDCNAME,
864 &request,
865 &response);
866 BAIL_ON_WBC_ERROR(wbc_status);
868 dc->dc_name = talloc_strdup(dc, response.data.dsgetdcname.dc_unc);
869 BAIL_ON_PTR_ERROR(dc->dc_name, wbc_status);
871 *dc_info = dc;
873 done:
874 if (!WBC_ERROR_IS_OK(wbc_status)) {
875 talloc_free(dc);
878 return wbc_status;
881 static wbcErr wbc_create_domain_controller_info_ex(TALLOC_CTX *mem_ctx,
882 const struct winbindd_response *resp,
883 struct wbcDomainControllerInfoEx **_i)
885 wbcErr wbc_status = WBC_ERR_SUCCESS;
886 struct wbcDomainControllerInfoEx *i;
887 struct wbcGuid guid;
889 i = talloc(mem_ctx, struct wbcDomainControllerInfoEx);
890 BAIL_ON_PTR_ERROR(i, wbc_status);
892 i->dc_unc = talloc_strdup(i, resp->data.dsgetdcname.dc_unc);
893 BAIL_ON_PTR_ERROR(i->dc_unc, wbc_status);
895 i->dc_address = talloc_strdup(i, resp->data.dsgetdcname.dc_address);
896 BAIL_ON_PTR_ERROR(i->dc_address, wbc_status);
898 i->dc_address_type = resp->data.dsgetdcname.dc_address_type;
900 wbc_status = wbcStringToGuid(resp->data.dsgetdcname.domain_guid, &guid);
901 if (WBC_ERROR_IS_OK(wbc_status)) {
902 i->domain_guid = talloc(i, struct wbcGuid);
903 BAIL_ON_PTR_ERROR(i->domain_guid, wbc_status);
905 *i->domain_guid = guid;
906 } else {
907 i->domain_guid = NULL;
910 i->domain_name = talloc_strdup(i, resp->data.dsgetdcname.domain_name);
911 BAIL_ON_PTR_ERROR(i->domain_name, wbc_status);
913 if (resp->data.dsgetdcname.forest_name[0] != '\0') {
914 i->forest_name = talloc_strdup(i,
915 resp->data.dsgetdcname.forest_name);
916 BAIL_ON_PTR_ERROR(i->forest_name, wbc_status);
917 } else {
918 i->forest_name = NULL;
921 i->dc_flags = resp->data.dsgetdcname.dc_flags;
923 if (resp->data.dsgetdcname.dc_site_name[0] != '\0') {
924 i->dc_site_name = talloc_strdup(i,
925 resp->data.dsgetdcname.dc_site_name);
926 BAIL_ON_PTR_ERROR(i->dc_site_name, wbc_status);
927 } else {
928 i->dc_site_name = NULL;
931 if (resp->data.dsgetdcname.client_site_name[0] != '\0') {
932 i->client_site_name = talloc_strdup(i,
933 resp->data.dsgetdcname.client_site_name);
934 BAIL_ON_PTR_ERROR(i->client_site_name, wbc_status);
935 } else {
936 i->client_site_name = NULL;
939 *_i = i;
940 i = NULL;
942 done:
943 talloc_free(i);
944 return wbc_status;
947 /* Get extended domain controller information */
948 wbcErr wbcLookupDomainControllerEx(const char *domain,
949 struct wbcGuid *guid,
950 const char *site,
951 uint32_t flags,
952 struct wbcDomainControllerInfoEx **dc_info)
954 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
955 struct winbindd_request request;
956 struct winbindd_response response;
958 /* validate input params */
960 if (!domain || !dc_info) {
961 wbc_status = WBC_ERR_INVALID_PARAM;
962 BAIL_ON_WBC_ERROR(wbc_status);
965 ZERO_STRUCT(request);
966 ZERO_STRUCT(response);
968 request.data.dsgetdcname.flags = flags;
970 strncpy(request.data.dsgetdcname.domain_name, domain,
971 sizeof(request.data.dsgetdcname.domain_name)-1);
973 if (site) {
974 strncpy(request.data.dsgetdcname.site_name, site,
975 sizeof(request.data.dsgetdcname.site_name)-1);
978 if (guid) {
979 char *str = NULL;
981 wbc_status = wbcGuidToString(guid, &str);
982 BAIL_ON_WBC_ERROR(wbc_status);
984 strncpy(request.data.dsgetdcname.domain_guid, str,
985 sizeof(request.data.dsgetdcname.domain_guid)-1);
987 wbcFreeMemory(str);
990 /* Send request */
992 wbc_status = wbcRequestResponse(WINBINDD_DSGETDCNAME,
993 &request,
994 &response);
995 BAIL_ON_WBC_ERROR(wbc_status);
997 if (dc_info) {
998 wbc_status = wbc_create_domain_controller_info_ex(NULL,
999 &response,
1000 dc_info);
1001 BAIL_ON_WBC_ERROR(wbc_status);
1004 wbc_status = WBC_ERR_SUCCESS;
1005 done:
1006 return wbc_status;
1009 /* Initialize a named blob and add to list of blobs */
1010 wbcErr wbcAddNamedBlob(size_t *num_blobs,
1011 struct wbcNamedBlob **blobs,
1012 const char *name,
1013 uint32_t flags,
1014 uint8_t *data,
1015 size_t length)
1017 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
1018 struct wbcNamedBlob blob;
1020 *blobs = talloc_realloc(NULL, *blobs, struct wbcNamedBlob,
1021 *(num_blobs)+1);
1022 BAIL_ON_PTR_ERROR(*blobs, wbc_status);
1024 blob.name = talloc_strdup(*blobs, name);
1025 BAIL_ON_PTR_ERROR(blob.name, wbc_status);
1026 blob.flags = flags;
1027 blob.blob.length = length;
1028 blob.blob.data = (uint8_t *)talloc_memdup(*blobs, data, length);
1029 BAIL_ON_PTR_ERROR(blob.blob.data, wbc_status);
1031 (*(blobs))[*num_blobs] = blob;
1032 *(num_blobs) += 1;
1034 wbc_status = WBC_ERR_SUCCESS;
1035 done:
1036 if (!WBC_ERROR_IS_OK(wbc_status)) {
1037 wbcFreeMemory(*blobs);
1039 return wbc_status;