2 Unix SMB/CIFS implementation.
6 Copyright (C) 2009,2010 Kai Blin <kai@samba.org>
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 3 of the License, or (at your option) any later version.
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Library General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 /* Required Headers */
25 #include "libwbclient.h"
26 #include "wbc_async.h"
28 struct wbc_ping_state
{
29 struct winbindd_request req
;
32 static void wbcPing_done(struct tevent_req
*subreq
);
34 /** @brief Ping winbind to see if the service is up and running
36 * @param mem_ctx talloc context to allocate the request from
37 * @param ev event context to use for async operation
38 * @param wb_ctx winbind context to use
40 * @return Async request on successful dispatch of the request, NULL on error
43 struct tevent_req
*wbcPing_send(TALLOC_CTX
*mem_ctx
,
44 struct tevent_context
*ev
,
45 struct wb_context
*wb_ctx
)
47 struct tevent_req
*req
, *subreq
;
48 struct wbc_ping_state
*state
;
50 req
= tevent_req_create(mem_ctx
, &state
, struct wbc_ping_state
);
55 ZERO_STRUCT(state
->req
);
57 state
->req
.cmd
= WINBINDD_PING
;
58 subreq
= wb_trans_send(state
, ev
, wb_ctx
, false, &state
->req
);
59 if (tevent_req_nomem(subreq
, req
)) {
60 return tevent_req_post(req
, ev
);
63 tevent_req_set_callback(subreq
, wbcPing_done
, req
);
67 static void wbcPing_done(struct tevent_req
*subreq
)
69 struct tevent_req
*req
= tevent_req_callback_data(
70 subreq
, struct tevent_req
);
71 struct wbc_ping_state
*state
= tevent_req_data(
72 req
, struct wbc_ping_state
);
73 struct winbindd_response
*resp
;
76 wbc_status
= wb_trans_recv(subreq
, state
, &resp
);
78 if (!WBC_ERROR_IS_OK(wbc_status
)) {
79 tevent_req_error(req
, wbc_status
);
87 /** @brief Receive ping response from winbind
89 * @param req async request sent in #wbcPing_send
91 * @return NT_STATUS_OK on success, an error status on error.
94 wbcErr
wbcPing_recv(struct tevent_req
*req
)
98 if (tevent_req_is_wbcerr(req
, &wbc_status
)) {
99 tevent_req_received(req
);
103 tevent_req_received(req
);
104 return WBC_ERR_SUCCESS
;
108 struct wbc_interface_version_state
{
109 struct winbindd_request req
;
113 static void wbcInterfaceVersion_done(struct tevent_req
*subreq
);
116 * @brief Request the interface version from winbind
118 * @param mem_ctx talloc context to allocate memory from
119 * @param ev tevent context to use for async requests
120 * @param wb_ctx winbind context
122 * @return tevevt_req on success, NULL on failure
125 struct tevent_req
*wbcInterfaceVersion_send(TALLOC_CTX
*mem_ctx
,
126 struct tevent_context
*ev
,
127 struct wb_context
*wb_ctx
)
129 struct tevent_req
*req
, *subreq
;
130 struct wbc_interface_version_state
*state
;
132 req
= tevent_req_create(mem_ctx
, &state
, struct wbc_interface_version_state
);
137 ZERO_STRUCT(state
->req
);
138 state
->req
.cmd
= WINBINDD_INTERFACE_VERSION
;
140 subreq
= wb_trans_send(state
, ev
, wb_ctx
, false, &state
->req
);
141 if (tevent_req_nomem(subreq
, req
)) {
142 return tevent_req_post(req
, ev
);
145 tevent_req_set_callback(subreq
, wbcInterfaceVersion_done
, req
);
150 static void wbcInterfaceVersion_done(struct tevent_req
*subreq
)
152 struct tevent_req
*req
= tevent_req_callback_data(
153 subreq
, struct tevent_req
);
154 struct wbc_interface_version_state
*state
= tevent_req_data(
155 req
, struct wbc_interface_version_state
);
156 struct winbindd_response
*resp
;
159 wbc_status
= wb_trans_recv(subreq
, state
, &resp
);
161 if (!WBC_ERROR_IS_OK(wbc_status
)) {
162 tevent_req_error(req
, wbc_status
);
165 state
->version
= resp
->data
.interface_version
;
168 tevent_req_done(req
);
172 * @brief Receive the winbind interface version
174 * @param req tevent_req containing the request
175 * @param interface_version pointer to uint32_t to hold the interface
181 wbcErr
wbcInterfaceVersion_recv(struct tevent_req
*req
,
182 uint32_t *interface_version
)
184 struct wbc_interface_version_state
*state
= tevent_req_data(
185 req
, struct wbc_interface_version_state
);
188 if (tevent_req_is_wbcerr(req
, &wbc_status
)) {
189 tevent_req_received(req
);
193 *interface_version
= state
->version
;
195 tevent_req_received(req
);
196 return WBC_ERR_SUCCESS
;
199 struct wbc_info_state
{
200 struct winbindd_request req
;
202 char *version_string
;
205 static void wbcInfo_done(struct tevent_req
*subreq
);
208 * @brief Request information about the winbind service
210 * @param mem_ctx talloc context to allocate memory from
211 * @param ev tevent context to use for async requests
212 * @param wb_ctx winbind context
214 * @return tevent_req on success, NULL on failure
217 struct tevent_req
*wbcInfo_send(TALLOC_CTX
*mem_ctx
,
218 struct tevent_context
*ev
,
219 struct wb_context
*wb_ctx
)
221 struct tevent_req
*req
, *subreq
;
222 struct wbc_info_state
*state
;
224 req
= tevent_req_create(mem_ctx
, &state
, struct wbc_info_state
);
229 ZERO_STRUCT(state
->req
);
230 state
->req
.cmd
= WINBINDD_INFO
;
232 subreq
= wb_trans_send(state
, ev
, wb_ctx
, false, &state
->req
);
233 if (tevent_req_nomem(subreq
, req
)) {
234 return tevent_req_post(req
, ev
);
237 tevent_req_set_callback(subreq
, wbcInfo_done
, req
);
241 static void wbcInfo_done(struct tevent_req
*subreq
)
243 struct tevent_req
*req
= tevent_req_callback_data(
244 subreq
, struct tevent_req
);
245 struct wbc_info_state
*state
= tevent_req_data(
246 req
, struct wbc_info_state
);
247 struct winbindd_response
*resp
;
250 wbc_status
= wb_trans_recv(subreq
, state
, &resp
);
252 if (!WBC_ERROR_IS_OK(wbc_status
)) {
253 tevent_req_error(req
, wbc_status
);
256 state
->version_string
= talloc_strdup(state
,
257 resp
->data
.info
.samba_version
);
258 if (tevent_req_nomem(state
->version_string
, subreq
)) {
261 state
->separator
= resp
->data
.info
.winbind_separator
;
264 tevent_req_done(req
);
268 * @brief Receive information about the running winbind service
270 * @param req tevent_req containing the request
271 * @param mem_ctx talloc context to allocate memory from
272 * @param winbind_separator pointer to a char to hold the separator
273 * @param version_string pointer to a string to hold the version string
278 wbcErr
wbcInfo_recv(struct tevent_req
*req
,
280 char *winbind_separator
,
281 char **version_string
)
283 struct wbc_info_state
*state
= tevent_req_data(
284 req
, struct wbc_info_state
);
287 if (tevent_req_is_wbcerr(req
, &wbc_status
)) {
288 tevent_req_received(req
);
292 *winbind_separator
= state
->separator
;
293 *version_string
= talloc_steal(mem_ctx
, state
->version_string
);
295 tevent_req_received(req
);
296 return WBC_ERR_SUCCESS
;
299 struct wbc_netbios_name_state
{
300 struct winbindd_request req
;
304 static void wbcNetbiosName_done(struct tevent_req
*subreq
);
307 * @brief Request the machine's netbios name
309 * @param mem_ctx talloc context to allocate memory from
310 * @param ev tevent context to use for async requests
311 * @param wb_ctx winbind context
313 * @return tevent_req on success, NULL on failure
316 struct tevent_req
*wbcNetbiosName_send(TALLOC_CTX
*mem_ctx
,
317 struct tevent_context
*ev
,
318 struct wb_context
*wb_ctx
)
320 struct tevent_req
*req
, *subreq
;
321 struct wbc_netbios_name_state
*state
;
323 req
= tevent_req_create(mem_ctx
, &state
, struct wbc_netbios_name_state
);
328 ZERO_STRUCT(state
->req
);
329 state
->req
.cmd
= WINBINDD_NETBIOS_NAME
;
331 subreq
= wb_trans_send(state
, ev
, wb_ctx
, false, &state
->req
);
332 if (tevent_req_nomem(subreq
, req
)) {
333 return tevent_req_post(req
, ev
);
336 tevent_req_set_callback(subreq
, wbcNetbiosName_done
, req
);
340 static void wbcNetbiosName_done(struct tevent_req
*subreq
)
342 struct tevent_req
*req
= tevent_req_callback_data(
343 subreq
, struct tevent_req
);
344 struct wbc_netbios_name_state
*state
= tevent_req_data(
345 req
, struct wbc_netbios_name_state
);
346 struct winbindd_response
*resp
;
349 wbc_status
= wb_trans_recv(subreq
, state
, &resp
);
351 if (!WBC_ERROR_IS_OK(wbc_status
)) {
352 tevent_req_error(req
, wbc_status
);
355 state
->netbios_name
= talloc_strdup(state
,
356 resp
->data
.info
.samba_version
);
357 if (tevent_req_nomem(state
->netbios_name
, subreq
)) {
362 tevent_req_done(req
);
366 * @brief Receive the machine's netbios name
368 * @param req tevent_req containing the request
369 * @param mem_ctx talloc context to allocate memory from
370 * @param netbios_name pointer to a string to hold the netbios name
375 wbcErr
wbcNetbiosName_recv(struct tevent_req
*req
,
379 struct wbc_netbios_name_state
*state
= tevent_req_data(
380 req
, struct wbc_netbios_name_state
);
383 if (tevent_req_is_wbcerr(req
, &wbc_status
)) {
384 tevent_req_received(req
);
388 *netbios_name
= talloc_steal(mem_ctx
, state
->netbios_name
);
390 tevent_req_received(req
);
391 return WBC_ERR_SUCCESS
;
394 struct wbc_domain_name_state
{
395 struct winbindd_request req
;
399 static void wbcDomainName_done(struct tevent_req
*subreq
);
402 * @brief Request the machine's domain name
404 * @param mem_ctx talloc context to allocate memory from
405 * @param ev tevent context to use for async requests
406 * @param wb_ctx winbind context
408 * @return tevent_req on success, NULL on failure
411 struct tevent_req
*wbcDomainName_send(TALLOC_CTX
*mem_ctx
,
412 struct tevent_context
*ev
,
413 struct wb_context
*wb_ctx
)
415 struct tevent_req
*req
, *subreq
;
416 struct wbc_domain_name_state
*state
;
418 req
= tevent_req_create(mem_ctx
, &state
, struct wbc_domain_name_state
);
423 ZERO_STRUCT(state
->req
);
424 state
->req
.cmd
= WINBINDD_DOMAIN_NAME
;
426 subreq
= wb_trans_send(state
, ev
, wb_ctx
, false, &state
->req
);
427 if (tevent_req_nomem(subreq
, req
)) {
428 return tevent_req_post(req
, ev
);
431 tevent_req_set_callback(subreq
, wbcDomainName_done
, req
);
435 static void wbcDomainName_done(struct tevent_req
*subreq
)
437 struct tevent_req
*req
= tevent_req_callback_data(
438 subreq
, struct tevent_req
);
439 struct wbc_domain_name_state
*state
= tevent_req_data(
440 req
, struct wbc_domain_name_state
);
441 struct winbindd_response
*resp
;
444 wbc_status
= wb_trans_recv(subreq
, state
, &resp
);
446 if (!WBC_ERROR_IS_OK(wbc_status
)) {
447 tevent_req_error(req
, wbc_status
);
450 state
->domain_name
= talloc_strdup(state
, resp
->data
.domain_name
);
451 if (tevent_req_nomem(state
->domain_name
, subreq
)) {
456 tevent_req_done(req
);
460 * @brief Receive the machine's domain name
462 * @param req tevent_req containing the request
463 * @param mem_ctx talloc context to allocate memory from
464 * @param domain_name pointer to a string to hold the domain name
469 wbcErr
wbcDomainName_recv(struct tevent_req
*req
,
473 struct wbc_domain_name_state
*state
= tevent_req_data(
474 req
, struct wbc_domain_name_state
);
477 if (tevent_req_is_wbcerr(req
, &wbc_status
)) {
478 tevent_req_received(req
);
482 *domain_name
= talloc_steal(mem_ctx
, state
->domain_name
);
484 tevent_req_received(req
);
485 return WBC_ERR_SUCCESS
;
488 struct wbc_interface_details_state
{
489 struct tevent_context
*ev
;
490 struct wb_context
*wb_ctx
;
491 struct wbcDomainInfo
*dinfo
;
492 struct wbcInterfaceDetails
*details
;
495 static void wbcInterfaceDetails_version(struct tevent_req
*subreq
);
496 static void wbcInterfaceDetails_info(struct tevent_req
*subreq
);
497 static void wbcInterfaceDetails_netbios_name(struct tevent_req
*subreq
);
498 static void wbcInterfaceDetails_domain_name(struct tevent_req
*subreq
);
499 static void wbcInterfaceDetails_domain_info(struct tevent_req
*subreq
);
502 * @brief Request some useful details about the winbind service
504 * @param mem_ctx talloc context to allocate memory from
505 * @param ev tevent context to use for async requests
506 * @param wb_ctx winbind context
508 * @return tevent_req on success, NULL on failure
511 struct tevent_req
*wbcInterfaceDetails_send(TALLOC_CTX
*mem_ctx
,
512 struct tevent_context
*ev
,
513 struct wb_context
*wb_ctx
)
515 struct tevent_req
*req
, *subreq
;
516 struct wbc_interface_details_state
*state
;
518 req
= tevent_req_create(mem_ctx
, &state
,
519 struct wbc_interface_details_state
);
525 state
->wb_ctx
= wb_ctx
;
526 state
->details
= talloc(state
, struct wbcInterfaceDetails
);
527 if (tevent_req_nomem(state
->details
, req
)) {
528 return tevent_req_post(req
, ev
);
531 subreq
= wbcInterfaceVersion_send(state
, ev
, wb_ctx
);
532 if (tevent_req_nomem(subreq
, req
)) {
533 return tevent_req_post(req
, ev
);
536 tevent_req_set_callback(subreq
, wbcInterfaceDetails_version
, req
);
540 static void wbcInterfaceDetails_version(struct tevent_req
*subreq
)
542 struct tevent_req
*req
= tevent_req_callback_data(
543 subreq
, struct tevent_req
);
544 struct wbc_interface_details_state
*state
= tevent_req_data(
545 req
, struct wbc_interface_details_state
);
549 wbc_status
= wbcInterfaceVersion_recv(subreq
,
550 &state
->details
->interface_version
);
552 if (!WBC_ERROR_IS_OK(wbc_status
)) {
553 tevent_req_error(req
, wbc_status
);
557 subreq
= wbcInfo_send(state
, state
->ev
, state
->wb_ctx
);
558 if (tevent_req_nomem(subreq
, req
)) {
562 tevent_req_set_callback(subreq
, wbcInterfaceDetails_info
, req
);
565 static void wbcInterfaceDetails_info(struct tevent_req
*subreq
)
567 struct tevent_req
*req
= tevent_req_callback_data(
568 subreq
, struct tevent_req
);
569 struct wbc_interface_details_state
*state
= tevent_req_data(
570 req
, struct wbc_interface_details_state
);
573 wbc_status
= wbcInfo_recv(subreq
, state
->details
,
574 &state
->details
->winbind_separator
,
575 &state
->details
->winbind_version
);
577 if (!WBC_ERROR_IS_OK(wbc_status
)) {
578 tevent_req_error(req
, wbc_status
);
582 subreq
= wbcNetbiosName_send(state
, state
->ev
, state
->wb_ctx
);
583 if (tevent_req_nomem(subreq
, req
)) {
587 tevent_req_set_callback(subreq
, wbcInterfaceDetails_netbios_name
, req
);
590 static void wbcInterfaceDetails_netbios_name(struct tevent_req
*subreq
)
592 struct tevent_req
*req
= tevent_req_callback_data(
593 subreq
, struct tevent_req
);
594 struct wbc_interface_details_state
*state
= tevent_req_data(
595 req
, struct wbc_interface_details_state
);
598 wbc_status
= wbcNetbiosName_recv(subreq
, state
->details
,
599 &state
->details
->netbios_name
);
601 if (!WBC_ERROR_IS_OK(wbc_status
)) {
602 tevent_req_error(req
, wbc_status
);
606 subreq
= wbcDomainName_send(state
, state
->ev
, state
->wb_ctx
);
607 if (tevent_req_nomem(subreq
, req
)) {
611 tevent_req_set_callback(subreq
, wbcInterfaceDetails_domain_name
, req
);
614 static void wbcInterfaceDetails_domain_name(struct tevent_req
*subreq
)
616 struct tevent_req
*req
= tevent_req_callback_data(
617 subreq
, struct tevent_req
);
618 struct wbc_interface_details_state
*state
= tevent_req_data(
619 req
, struct wbc_interface_details_state
);
622 wbc_status
= wbcDomainName_recv(subreq
, state
->details
,
623 &state
->details
->netbios_domain
);
625 if (!WBC_ERROR_IS_OK(wbc_status
)) {
626 tevent_req_error(req
, wbc_status
);
630 subreq
= wbcDomainInfo_send(state
, state
->ev
, state
->wb_ctx
,
631 state
->details
->netbios_domain
);
632 if (tevent_req_nomem(subreq
, req
)) {
636 tevent_req_set_callback(subreq
, wbcInterfaceDetails_domain_info
, req
);
639 static void wbcInterfaceDetails_domain_info(struct tevent_req
*subreq
)
641 struct tevent_req
*req
= tevent_req_callback_data(
642 subreq
, struct tevent_req
);
643 struct wbc_interface_details_state
*state
= tevent_req_data(
644 req
, struct wbc_interface_details_state
);
645 struct wbcDomainInfo
*domain
;
648 wbc_status
= wbcDomainInfo_recv(subreq
, state
, &domain
);
650 if (wbc_status
== WBC_ERR_DOMAIN_NOT_FOUND
) {
651 tevent_req_done(req
);
655 if (!WBC_ERROR_IS_OK(wbc_status
)) {
656 tevent_req_error(req
, wbc_status
);
659 state
->details
->dns_domain
= talloc_strdup(state
->details
,
661 if (tevent_req_nomem(state
->details
->dns_domain
, req
)) {
666 tevent_req_done(req
);
670 * @brief Receive useful information about the winbind service
672 * @param req tevent_req containing the request
673 * @param mem_ctx talloc context to allocate memory from
674 * @param *details pointer to hold the struct wbcInterfaceDetails
679 wbcErr
wbcInterfaceDetails_recv(struct tevent_req
*req
,
681 struct wbcInterfaceDetails
**details
)
683 struct wbc_interface_details_state
*state
= tevent_req_data(
684 req
, struct wbc_interface_details_state
);
687 if (tevent_req_is_wbcerr(req
, &wbc_status
)) {
688 tevent_req_received(req
);
692 *details
= talloc_steal(mem_ctx
, state
->details
);
694 tevent_req_received(req
);
695 return WBC_ERR_SUCCESS
;
698 struct wbc_domain_info_state
{
699 struct winbindd_request req
;
700 struct wbcDomainInfo
*info
;
703 static void wbcDomainInfo_done(struct tevent_req
*subreq
);
706 * @brief Request status of a given trusted domain
708 * @param mem_ctx talloc context to allocate memory from
709 * @param ev tevent context to use for async requests
710 * @param wb_ctx winbind context
711 * @param domain domain to request status from
713 * @return tevent_req on success, NULL on failure
716 struct tevent_req
*wbcDomainInfo_send(TALLOC_CTX
*mem_ctx
,
717 struct tevent_context
*ev
,
718 struct wb_context
*wb_ctx
,
721 struct tevent_req
*req
, *subreq
;
722 struct wbc_domain_info_state
*state
;
728 req
= tevent_req_create(mem_ctx
, &state
, struct wbc_domain_info_state
);
733 state
->info
= talloc(state
, struct wbcDomainInfo
);
734 if (tevent_req_nomem(state
->info
, req
)) {
735 return tevent_req_post(req
, ev
);
738 ZERO_STRUCT(state
->req
);
740 strncpy(state
->req
.domain_name
, domain
,
741 sizeof(state
->req
.domain_name
)-1);
743 state
->req
.cmd
= WINBINDD_DOMAIN_INFO
;
745 subreq
= wb_trans_send(state
, ev
, wb_ctx
, false, &state
->req
);
746 if (tevent_req_nomem(subreq
, req
)) {
747 return tevent_req_post(req
, ev
);
750 tevent_req_set_callback(subreq
, wbcDomainInfo_done
, req
);
754 static void wbcDomainInfo_done(struct tevent_req
*subreq
)
756 struct tevent_req
*req
= tevent_req_callback_data(
757 subreq
, struct tevent_req
);
758 struct wbc_domain_info_state
*state
= tevent_req_data(
759 req
, struct wbc_domain_info_state
);
760 struct winbindd_response
*resp
;
763 wbc_status
= wb_trans_recv(subreq
, state
, &resp
);
765 if (!WBC_ERROR_IS_OK(wbc_status
)) {
766 tevent_req_error(req
, wbc_status
);
770 state
->info
->short_name
= talloc_strdup(state
->info
,
771 resp
->data
.domain_info
.name
);
772 if (tevent_req_nomem(state
->info
->short_name
, req
)) {
776 state
->info
->dns_name
= talloc_strdup(state
->info
,
777 resp
->data
.domain_info
.alt_name
);
778 if (tevent_req_nomem(state
->info
->dns_name
, req
)) {
782 wbc_status
= wbcStringToSid(resp
->data
.domain_info
.sid
,
784 if (!WBC_ERROR_IS_OK(wbc_status
)) {
785 tevent_req_error(req
, wbc_status
);
789 if (resp
->data
.domain_info
.native_mode
) {
790 state
->info
->domain_flags
|= WBC_DOMINFO_DOMAIN_NATIVE
;
792 if (resp
->data
.domain_info
.active_directory
) {
793 state
->info
->domain_flags
|= WBC_DOMINFO_DOMAIN_AD
;
795 if (resp
->data
.domain_info
.primary
) {
796 state
->info
->domain_flags
|= WBC_DOMINFO_DOMAIN_PRIMARY
;
801 tevent_req_done(req
);
805 * @brief Receive information about a trusted domain
807 * @param req tevent_req containing the request
808 * @param mem_ctx talloc context to allocate memory from
809 * @param *dinfo pointer to returned struct wbcDomainInfo
814 wbcErr
wbcDomainInfo_recv(struct tevent_req
*req
,
816 struct wbcDomainInfo
**dinfo
)
818 struct wbc_domain_info_state
*state
= tevent_req_data(
819 req
, struct wbc_domain_info_state
);
822 if (tevent_req_is_wbcerr(req
, &wbc_status
)) {
823 tevent_req_received(req
);
828 tevent_req_received(req
);
829 return WBC_ERR_INVALID_PARAM
;
832 *dinfo
= talloc_steal(mem_ctx
, state
->info
);
834 tevent_req_received(req
);
835 return WBC_ERR_SUCCESS
;