2 Unix SMB/CIFS implementation.
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 */
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);
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);
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;
78 wbc_status = wb_trans_recv(subreq, state, &resp);
80 if (!WBC_ERROR_IS_OK(wbc_status)) {
81 tevent_req_error(req, wbc_status);
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)
100 if (tevent_req_is_wbcerr(req, &wbc_status)) {
101 tevent_req_received(req);
105 tevent_req_received(req);
106 return WBC_ERR_SUCCESS;
109 /** @brief Ping winbindd to see if the daemon is running
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;
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);
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);
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;
177 wbc_status = wb_trans_recv(subreq, state, &resp);
179 if (!WBC_ERROR_IS_OK(wbc_status)) {
180 tevent_req_error(req, wbc_status);
183 state->version = resp->data.interface_version;
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
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);
206 if (tevent_req_is_wbcerr(req, &wbc_status)) {
207 tevent_req_received(req);
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;
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);
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);
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;
268 wbc_status = wb_trans_recv(subreq, state, &resp);
270 if (!WBC_ERROR_IS_OK(wbc_status)) {
271 tevent_req_error(req, wbc_status);
274 state->version_string = talloc_strdup(state,
275 resp->data.info.samba_version);
276 if (tevent_req_nomem(state->version_string, subreq)) {
279 state->separator = resp->data.info.winbind_separator;
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
296 wbcErr wbcInfo_recv(struct tevent_req *req,
298 char *winbind_separator,
299 char **version_string)
301 struct wbc_info_state *state = tevent_req_data(
302 req, struct wbc_info_state);
305 if (tevent_req_is_wbcerr(req, &wbc_status)) {
306 tevent_req_received(req);
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;
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);
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);
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;
367 wbc_status = wb_trans_recv(subreq, state, &resp);
369 if (!WBC_ERROR_IS_OK(wbc_status)) {
370 tevent_req_error(req, wbc_status);
373 state->netbios_name = talloc_strdup(state,
374 resp->data.info.samba_version);
375 if (tevent_req_nomem(state->netbios_name, subreq)) {
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
393 wbcErr wbcNetbiosName_recv(struct tevent_req *req,
397 struct wbc_netbios_name_state *state = tevent_req_data(
398 req, struct wbc_netbios_name_state);
401 if (tevent_req_is_wbcerr(req, &wbc_status)) {
402 tevent_req_received(req);
406 *netbios_name = talloc_steal(mem_ctx, state->netbios_name);
408 tevent_req_received(req);
409 return WBC_ERR_SUCCESS;
412 struct wbc_domain_name_state {
413 struct winbindd_request req;
417 static void wbcDomainName_done(struct tevent_req *subreq);
420 * @brief Request the machine's domain name
422 * @param mem_ctx talloc context to allocate memory from
423 * @param ev tevent context to use for async requests
424 * @param wb_ctx winbind context
426 * @return tevent_req on success, NULL on failure
429 struct tevent_req *wbcDomainName_send(TALLOC_CTX *mem_ctx,
430 struct tevent_context *ev,
431 struct wb_context *wb_ctx)
433 struct tevent_req *req, *subreq;
434 struct wbc_domain_name_state *state;
436 req = tevent_req_create(mem_ctx, &state, struct wbc_domain_name_state);
441 ZERO_STRUCT(state->req);
442 state->req.cmd = WINBINDD_DOMAIN_NAME;
444 subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
445 if (tevent_req_nomem(subreq, req)) {
446 return tevent_req_post(req, ev);
449 tevent_req_set_callback(subreq, wbcDomainName_done, req);
453 static void wbcDomainName_done(struct tevent_req *subreq)
455 struct tevent_req *req = tevent_req_callback_data(
456 subreq, struct tevent_req);
457 struct wbc_domain_name_state *state = tevent_req_data(
458 req, struct wbc_domain_name_state);
459 struct winbindd_response *resp;
462 wbc_status = wb_trans_recv(subreq, state, &resp);
464 if (!WBC_ERROR_IS_OK(wbc_status)) {
465 tevent_req_error(req, wbc_status);
468 state->domain_name = talloc_strdup(state, resp->data.domain_name);
469 if (tevent_req_nomem(state->domain_name, subreq)) {
474 tevent_req_done(req);
478 * @brief Receive the machine's domain name
480 * @param req tevent_req containing the request
481 * @param mem_ctx talloc context to allocate memory from
482 * @param domain_name pointer to a string to hold the domain name
487 wbcErr wbcDomainName_recv(struct tevent_req *req,
491 struct wbc_domain_name_state *state = tevent_req_data(
492 req, struct wbc_domain_name_state);
495 if (tevent_req_is_wbcerr(req, &wbc_status)) {
496 tevent_req_received(req);
500 *domain_name = talloc_steal(mem_ctx, state->domain_name);
502 tevent_req_received(req);
503 return WBC_ERR_SUCCESS;
506 wbcErr wbcInterfaceDetails(struct wbcInterfaceDetails **_details)
508 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
509 struct wbcInterfaceDetails *info;
510 struct wbcDomainInfo *domain = NULL;
511 struct winbindd_request request;
512 struct winbindd_response response;
514 /* Initialize request */
516 ZERO_STRUCT(request);
517 ZERO_STRUCT(response);
519 info = talloc(NULL, struct wbcInterfaceDetails);
520 BAIL_ON_PTR_ERROR(info, wbc_status);
522 /* first the interface version */
523 wbc_status = wbcRequestResponse(WINBINDD_INTERFACE_VERSION, NULL, &response);
524 BAIL_ON_WBC_ERROR(wbc_status);
525 info->interface_version = response.data.interface_version;
527 /* then the samba version and the winbind separator */
528 wbc_status = wbcRequestResponse(WINBINDD_INFO, NULL, &response);
529 BAIL_ON_WBC_ERROR(wbc_status);
531 info->winbind_version = talloc_strdup(info,
532 response.data.info.samba_version);
533 BAIL_ON_PTR_ERROR(info->winbind_version, wbc_status);
534 info->winbind_separator = response.data.info.winbind_separator;
536 /* then the local netbios name */
537 wbc_status = wbcRequestResponse(WINBINDD_NETBIOS_NAME, NULL, &response);
538 BAIL_ON_WBC_ERROR(wbc_status);
540 info->netbios_name = talloc_strdup(info,
541 response.data.netbios_name);
542 BAIL_ON_PTR_ERROR(info->netbios_name, wbc_status);
544 /* then the local workgroup name */
545 wbc_status = wbcRequestResponse(WINBINDD_DOMAIN_NAME, NULL, &response);
546 BAIL_ON_WBC_ERROR(wbc_status);
548 info->netbios_domain = talloc_strdup(info,
549 response.data.domain_name);
550 BAIL_ON_PTR_ERROR(info->netbios_domain, wbc_status);
552 wbc_status = wbcDomainInfo(info->netbios_domain, &domain);
553 if (wbc_status == WBC_ERR_DOMAIN_NOT_FOUND) {
554 /* maybe it's a standalone server */
556 wbc_status = WBC_ERR_SUCCESS;
558 BAIL_ON_WBC_ERROR(wbc_status);
562 info->dns_domain = talloc_strdup(info,
564 wbcFreeMemory(domain);
565 BAIL_ON_PTR_ERROR(info->dns_domain, wbc_status);
567 info->dns_domain = NULL;
573 wbc_status = WBC_ERR_SUCCESS;
581 /* Lookup the current status of a trusted domain */
582 wbcErr wbcDomainInfo(const char *domain, struct wbcDomainInfo **dinfo)
584 struct winbindd_request request;
585 struct winbindd_response response;
586 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
587 struct wbcDomainInfo *info = NULL;
589 if (!domain || !dinfo) {
590 wbc_status = WBC_ERR_INVALID_PARAM;
591 BAIL_ON_WBC_ERROR(wbc_status);
594 /* Initialize request */
596 ZERO_STRUCT(request);
597 ZERO_STRUCT(response);
599 strncpy(request.domain_name, domain,
600 sizeof(request.domain_name)-1);
602 wbc_status = wbcRequestResponse(WINBINDD_DOMAIN_INFO,
605 BAIL_ON_WBC_ERROR(wbc_status);
607 info = talloc(NULL, struct wbcDomainInfo);
608 BAIL_ON_PTR_ERROR(info, wbc_status);
610 info->short_name = talloc_strdup(info,
611 response.data.domain_info.name);
612 BAIL_ON_PTR_ERROR(info->short_name, wbc_status);
614 info->dns_name = talloc_strdup(info,
615 response.data.domain_info.alt_name);
616 BAIL_ON_PTR_ERROR(info->dns_name, wbc_status);
618 wbc_status = wbcStringToSid(response.data.domain_info.sid,
620 BAIL_ON_WBC_ERROR(wbc_status);
622 if (response.data.domain_info.native_mode)
623 info->domain_flags |= WBC_DOMINFO_DOMAIN_NATIVE;
624 if (response.data.domain_info.active_directory)
625 info->domain_flags |= WBC_DOMINFO_DOMAIN_AD;
626 if (response.data.domain_info.primary)
627 info->domain_flags |= WBC_DOMINFO_DOMAIN_PRIMARY;
631 wbc_status = WBC_ERR_SUCCESS;
634 if (!WBC_ERROR_IS_OK(wbc_status)) {
642 /* Resolve a NetbiosName via WINS */
643 wbcErr wbcResolveWinsByName(const char *name, char **ip)
645 struct winbindd_request request;
646 struct winbindd_response response;
647 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
650 ZERO_STRUCT(request);
651 ZERO_STRUCT(response);
655 strncpy(request.data.winsreq, name,
656 sizeof(request.data.winsreq)-1);
658 wbc_status = wbcRequestResponse(WINBINDD_WINS_BYNAME,
661 BAIL_ON_WBC_ERROR(wbc_status);
663 /* Display response */
665 ipaddr = talloc_strdup(NULL, response.data.winsresp);
666 BAIL_ON_PTR_ERROR(ipaddr, wbc_status);
669 wbc_status = WBC_ERR_SUCCESS;
675 /* Resolve an IP address via WINS into a NetbiosName */
676 wbcErr wbcResolveWinsByIP(const char *ip, char **name)
678 struct winbindd_request request;
679 struct winbindd_response response;
680 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
683 ZERO_STRUCT(request);
684 ZERO_STRUCT(response);
688 strncpy(request.data.winsreq, ip,
689 sizeof(request.data.winsreq)-1);
691 wbc_status = wbcRequestResponse(WINBINDD_WINS_BYIP,
694 BAIL_ON_WBC_ERROR(wbc_status);
696 /* Display response */
698 name_str = talloc_strdup(NULL, response.data.winsresp);
699 BAIL_ON_PTR_ERROR(name_str, wbc_status);
702 wbc_status = WBC_ERR_SUCCESS;
711 static wbcErr process_domain_info_string(TALLOC_CTX *ctx,
712 struct wbcDomainInfo *info,
715 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
719 if (!info || !info_string) {
720 wbc_status = WBC_ERR_INVALID_PARAM;
721 BAIL_ON_WBC_ERROR(wbc_status);
729 if ((s = strchr(r, '\\')) == NULL) {
730 wbc_status = WBC_ERR_INVALID_RESPONSE;
731 BAIL_ON_WBC_ERROR(wbc_status);
736 info->short_name = talloc_strdup(ctx, r);
737 BAIL_ON_PTR_ERROR(info->short_name, wbc_status);
742 if ((s = strchr(r, '\\')) == NULL) {
743 wbc_status = WBC_ERR_INVALID_RESPONSE;
744 BAIL_ON_WBC_ERROR(wbc_status);
749 info->dns_name = talloc_strdup(ctx, r);
750 BAIL_ON_PTR_ERROR(info->dns_name, wbc_status);
754 if ((s = strchr(r, '\\')) == NULL) {
755 wbc_status = WBC_ERR_INVALID_RESPONSE;
756 BAIL_ON_WBC_ERROR(wbc_status);
761 wbc_status = wbcStringToSid(r, &info->sid);
762 BAIL_ON_WBC_ERROR(wbc_status);
766 if ((s = strchr(r, '\\')) == NULL) {
767 wbc_status = WBC_ERR_INVALID_RESPONSE;
768 BAIL_ON_WBC_ERROR(wbc_status);
773 if (strcmp(r, "None") == 0) {
774 info->trust_type = WBC_DOMINFO_TRUSTTYPE_NONE;
775 } else if (strcmp(r, "External") == 0) {
776 info->trust_type = WBC_DOMINFO_TRUSTTYPE_EXTERNAL;
777 } else if (strcmp(r, "Forest") == 0) {
778 info->trust_type = WBC_DOMINFO_TRUSTTYPE_FOREST;
779 } else if (strcmp(r, "In Forest") == 0) {
780 info->trust_type = WBC_DOMINFO_TRUSTTYPE_IN_FOREST;
782 wbc_status = WBC_ERR_INVALID_RESPONSE;
783 BAIL_ON_WBC_ERROR(wbc_status);
788 if ((s = strchr(r, '\\')) == NULL) {
789 wbc_status = WBC_ERR_INVALID_RESPONSE;
790 BAIL_ON_WBC_ERROR(wbc_status);
795 if (strcmp(r, "Yes") == 0) {
796 info->trust_flags |= WBC_DOMINFO_TRUST_TRANSITIVE;
801 if ((s = strchr(r, '\\')) == NULL) {
802 wbc_status = WBC_ERR_INVALID_RESPONSE;
803 BAIL_ON_WBC_ERROR(wbc_status);
808 if (strcmp(r, "Yes") == 0) {
809 info->trust_flags |= WBC_DOMINFO_TRUST_INCOMING;
814 if ((s = strchr(r, '\\')) == NULL) {
815 wbc_status = WBC_ERR_INVALID_RESPONSE;
816 BAIL_ON_WBC_ERROR(wbc_status);
821 if (strcmp(r, "Yes") == 0) {
822 info->trust_flags |= WBC_DOMINFO_TRUST_OUTGOING;
825 /* Online/Offline status */
829 wbc_status = WBC_ERR_INVALID_RESPONSE;
830 BAIL_ON_WBC_ERROR(wbc_status);
832 if ( strcmp(r, "Offline") == 0) {
833 info->domain_flags |= WBC_DOMINFO_DOMAIN_OFFLINE;
836 wbc_status = WBC_ERR_SUCCESS;
842 /* Enumerate the domain trusts known by Winbind */
843 wbcErr wbcListTrusts(struct wbcDomainInfo **domains, size_t *num_domains)
845 struct winbindd_response response;
846 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
849 char *extra_data = NULL;
851 struct wbcDomainInfo *d_list = NULL;
857 ZERO_STRUCT(response);
861 wbc_status = wbcRequestResponse(WINBINDD_LIST_TRUSTDOM,
864 BAIL_ON_WBC_ERROR(wbc_status);
866 /* Decode the response */
868 p = (char *)response.extra_data.data;
870 if ((p == NULL) || (strlen(p) == 0)) {
871 /* We should always at least get back our
874 wbc_status = WBC_ERR_DOMAIN_NOT_FOUND;
875 BAIL_ON_WBC_ERROR(wbc_status);
878 /* Count number of domains */
884 if ((q = strchr(p, '\n')) != NULL)
889 d_list = talloc_array(NULL, struct wbcDomainInfo, count);
890 BAIL_ON_PTR_ERROR(d_list, wbc_status);
892 extra_data = strdup((char*)response.extra_data.data);
893 BAIL_ON_PTR_ERROR(extra_data, wbc_status);
897 /* Outer loop processes the list of domain information */
899 for (i=0; i<count && p; i++) {
900 char *next = strchr(p, '\n');
907 wbc_status = process_domain_info_string(d_list, &d_list[i], p);
908 BAIL_ON_WBC_ERROR(wbc_status);
917 if (!WBC_ERROR_IS_OK(wbc_status)) {
927 /* Enumerate the domain trusts known by Winbind */
928 wbcErr wbcLookupDomainController(const char *domain,
930 struct wbcDomainControllerInfo **dc_info)
932 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
933 struct winbindd_request request;
934 struct winbindd_response response;
935 struct wbcDomainControllerInfo *dc = NULL;
937 /* validate input params */
939 if (!domain || !dc_info) {
940 wbc_status = WBC_ERR_INVALID_PARAM;
941 BAIL_ON_WBC_ERROR(wbc_status);
944 ZERO_STRUCT(request);
945 ZERO_STRUCT(response);
947 strncpy(request.data.dsgetdcname.domain_name, domain,
948 sizeof(request.data.dsgetdcname.domain_name)-1);
950 request.flags = flags;
952 dc = talloc(NULL, struct wbcDomainControllerInfo);
953 BAIL_ON_PTR_ERROR(dc, wbc_status);
957 wbc_status = wbcRequestResponse(WINBINDD_DSGETDCNAME,
960 BAIL_ON_WBC_ERROR(wbc_status);
962 dc->dc_name = talloc_strdup(dc, response.data.dsgetdcname.dc_unc);
963 BAIL_ON_PTR_ERROR(dc->dc_name, wbc_status);
968 if (!WBC_ERROR_IS_OK(wbc_status)) {
975 static wbcErr wbc_create_domain_controller_info_ex(TALLOC_CTX *mem_ctx,
976 const struct winbindd_response *resp,
977 struct wbcDomainControllerInfoEx **_i)
979 wbcErr wbc_status = WBC_ERR_SUCCESS;
980 struct wbcDomainControllerInfoEx *i;
983 i = talloc(mem_ctx, struct wbcDomainControllerInfoEx);
984 BAIL_ON_PTR_ERROR(i, wbc_status);
986 i->dc_unc = talloc_strdup(i, resp->data.dsgetdcname.dc_unc);
987 BAIL_ON_PTR_ERROR(i->dc_unc, wbc_status);
989 i->dc_address = talloc_strdup(i, resp->data.dsgetdcname.dc_address);
990 BAIL_ON_PTR_ERROR(i->dc_address, wbc_status);
992 i->dc_address_type = resp->data.dsgetdcname.dc_address_type;
994 wbc_status = wbcStringToGuid(resp->data.dsgetdcname.domain_guid, &guid);
995 if (WBC_ERROR_IS_OK(wbc_status)) {
996 i->domain_guid = talloc(i, struct wbcGuid);
997 BAIL_ON_PTR_ERROR(i->domain_guid, wbc_status);
999 *i->domain_guid = guid;
1001 i->domain_guid = NULL;
1004 i->domain_name = talloc_strdup(i, resp->data.dsgetdcname.domain_name);
1005 BAIL_ON_PTR_ERROR(i->domain_name, wbc_status);
1007 if (resp->data.dsgetdcname.forest_name[0] != '\0') {
1008 i->forest_name = talloc_strdup(i,
1009 resp->data.dsgetdcname.forest_name);
1010 BAIL_ON_PTR_ERROR(i->forest_name, wbc_status);
1012 i->forest_name = NULL;
1015 i->dc_flags = resp->data.dsgetdcname.dc_flags;
1017 if (resp->data.dsgetdcname.dc_site_name[0] != '\0') {
1018 i->dc_site_name = talloc_strdup(i,
1019 resp->data.dsgetdcname.dc_site_name);
1020 BAIL_ON_PTR_ERROR(i->dc_site_name, wbc_status);
1022 i->dc_site_name = NULL;
1025 if (resp->data.dsgetdcname.client_site_name[0] != '\0') {
1026 i->client_site_name = talloc_strdup(i,
1027 resp->data.dsgetdcname.client_site_name);
1028 BAIL_ON_PTR_ERROR(i->client_site_name, wbc_status);
1030 i->client_site_name = NULL;
1041 /* Get extended domain controller information */
1042 wbcErr wbcLookupDomainControllerEx(const char *domain,
1043 struct wbcGuid *guid,
1046 struct wbcDomainControllerInfoEx **dc_info)
1048 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
1049 struct winbindd_request request;
1050 struct winbindd_response response;
1052 /* validate input params */
1054 if (!domain || !dc_info) {
1055 wbc_status = WBC_ERR_INVALID_PARAM;
1056 BAIL_ON_WBC_ERROR(wbc_status);
1059 ZERO_STRUCT(request);
1060 ZERO_STRUCT(response);
1062 request.data.dsgetdcname.flags = flags;
1064 strncpy(request.data.dsgetdcname.domain_name, domain,
1065 sizeof(request.data.dsgetdcname.domain_name)-1);
1068 strncpy(request.data.dsgetdcname.site_name, site,
1069 sizeof(request.data.dsgetdcname.site_name)-1);
1075 wbc_status = wbcGuidToString(guid, &str);
1076 BAIL_ON_WBC_ERROR(wbc_status);
1078 strncpy(request.data.dsgetdcname.domain_guid, str,
1079 sizeof(request.data.dsgetdcname.domain_guid)-1);
1086 wbc_status = wbcRequestResponse(WINBINDD_DSGETDCNAME,
1089 BAIL_ON_WBC_ERROR(wbc_status);
1092 wbc_status = wbc_create_domain_controller_info_ex(NULL,
1095 BAIL_ON_WBC_ERROR(wbc_status);
1098 wbc_status = WBC_ERR_SUCCESS;
1103 /* Initialize a named blob and add to list of blobs */
1104 wbcErr wbcAddNamedBlob(size_t *num_blobs,
1105 struct wbcNamedBlob **blobs,
1111 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
1112 struct wbcNamedBlob blob;
1114 *blobs = talloc_realloc(NULL, *blobs, struct wbcNamedBlob,
1116 BAIL_ON_PTR_ERROR(*blobs, wbc_status);
1118 blob.name = talloc_strdup(*blobs, name);
1119 BAIL_ON_PTR_ERROR(blob.name, wbc_status);
1121 blob.blob.length = length;
1122 blob.blob.data = (uint8_t *)talloc_memdup(*blobs, data, length);
1123 BAIL_ON_PTR_ERROR(blob.blob.data, wbc_status);
1125 (*(blobs))[*num_blobs] = blob;
1128 wbc_status = WBC_ERR_SUCCESS;
1130 if (!WBC_ERROR_IS_OK(wbc_status)) {
1131 wbcFreeMemory(*blobs);