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"
27 struct wbc_ping_state
{
28 struct winbindd_request req
;
31 static void wbcPing_done(struct tevent_req
*subreq
);
33 /** @brief Ping winbind to see if the service is up and running
35 * @param mem_ctx talloc context to allocate the request from
36 * @param ev event context to use for async operation
37 * @param wb_ctx winbind context to use
39 * @return Async request on successful dispatch of the request, NULL on error
42 struct tevent_req
*wbcPing_send(TALLOC_CTX
*mem_ctx
,
43 struct tevent_context
*ev
,
44 struct wb_context
*wb_ctx
)
46 struct tevent_req
*req
, *subreq
;
47 struct wbc_ping_state
*state
;
49 req
= tevent_req_create(mem_ctx
, &state
, struct wbc_ping_state
);
54 ZERO_STRUCT(state
->req
);
56 state
->req
.cmd
= WINBINDD_PING
;
57 subreq
= wb_trans_send(state
, ev
, wb_ctx
, false, &state
->req
);
58 if (tevent_req_nomem(subreq
, req
)) {
59 return tevent_req_post(req
, ev
);
62 tevent_req_set_callback(subreq
, wbcPing_done
, req
);
66 static void wbcPing_done(struct tevent_req
*subreq
)
68 struct tevent_req
*req
= tevent_req_callback_data(
69 subreq
, struct tevent_req
);
70 struct wbc_ping_state
*state
= tevent_req_data(
71 req
, struct wbc_ping_state
);
72 struct winbindd_response
*resp
;
75 wbc_status
= wb_trans_recv(subreq
, state
, &resp
);
77 if (!WBC_ERROR_IS_OK(wbc_status
)) {
78 tevent_req_error(req
, wbc_status
);
86 /** @brief Receive ping response from winbind
88 * @param req async request sent in #wbcPing_send
90 * @return NT_STATUS_OK on success, an error status on error.
93 wbcErr
wbcPing_recv(struct tevent_req
*req
)
97 if (tevent_req_is_wbcerr(req
, &wbc_status
)) {
98 tevent_req_received(req
);
102 tevent_req_received(req
);
103 return WBC_ERR_SUCCESS
;
107 struct wbc_interface_version_state
{
108 struct winbindd_request req
;
112 static void wbcInterfaceVersion_done(struct tevent_req
*subreq
);
115 * @brief Request the interface version from winbind
117 * @param mem_ctx talloc context to allocate memory from
118 * @param ev tevent context to use for async requests
119 * @param wb_ctx winbind context
121 * @return tevevt_req on success, NULL on failure
124 struct tevent_req
*wbcInterfaceVersion_send(TALLOC_CTX
*mem_ctx
,
125 struct tevent_context
*ev
,
126 struct wb_context
*wb_ctx
)
128 struct tevent_req
*req
, *subreq
;
129 struct wbc_interface_version_state
*state
;
131 req
= tevent_req_create(mem_ctx
, &state
, struct wbc_interface_version_state
);
136 ZERO_STRUCT(state
->req
);
137 state
->req
.cmd
= WINBINDD_INTERFACE_VERSION
;
139 subreq
= wb_trans_send(state
, ev
, wb_ctx
, false, &state
->req
);
140 if (tevent_req_nomem(subreq
, req
)) {
141 return tevent_req_post(req
, ev
);
144 tevent_req_set_callback(subreq
, wbcInterfaceVersion_done
, req
);
149 static void wbcInterfaceVersion_done(struct tevent_req
*subreq
)
151 struct tevent_req
*req
= tevent_req_callback_data(
152 subreq
, struct tevent_req
);
153 struct wbc_interface_version_state
*state
= tevent_req_data(
154 req
, struct wbc_interface_version_state
);
155 struct winbindd_response
*resp
;
158 wbc_status
= wb_trans_recv(subreq
, state
, &resp
);
160 if (!WBC_ERROR_IS_OK(wbc_status
)) {
161 tevent_req_error(req
, wbc_status
);
164 state
->version
= resp
->data
.interface_version
;
167 tevent_req_done(req
);
171 * @brief Receive the winbind interface version
173 * @param req tevent_req containing the request
174 * @param interface_version pointer to uint32_t to hold the interface
180 wbcErr
wbcInterfaceVersion_recv(struct tevent_req
*req
,
181 uint32_t *interface_version
)
183 struct wbc_interface_version_state
*state
= tevent_req_data(
184 req
, struct wbc_interface_version_state
);
187 if (tevent_req_is_wbcerr(req
, &wbc_status
)) {
188 tevent_req_received(req
);
192 *interface_version
= state
->version
;
194 tevent_req_received(req
);
195 return WBC_ERR_SUCCESS
;
198 struct wbc_info_state
{
199 struct winbindd_request req
;
201 char *version_string
;
204 static void wbcInfo_done(struct tevent_req
*subreq
);
207 * @brief Request information about the winbind service
209 * @param mem_ctx talloc context to allocate memory from
210 * @param ev tevent context to use for async requests
211 * @param wb_ctx winbind context
213 * @return tevent_req on success, NULL on failure
216 struct tevent_req
*wbcInfo_send(TALLOC_CTX
*mem_ctx
,
217 struct tevent_context
*ev
,
218 struct wb_context
*wb_ctx
)
220 struct tevent_req
*req
, *subreq
;
221 struct wbc_info_state
*state
;
223 req
= tevent_req_create(mem_ctx
, &state
, struct wbc_info_state
);
228 ZERO_STRUCT(state
->req
);
229 state
->req
.cmd
= WINBINDD_INFO
;
231 subreq
= wb_trans_send(state
, ev
, wb_ctx
, false, &state
->req
);
232 if (tevent_req_nomem(subreq
, req
)) {
233 return tevent_req_post(req
, ev
);
236 tevent_req_set_callback(subreq
, wbcInfo_done
, req
);
240 static void wbcInfo_done(struct tevent_req
*subreq
)
242 struct tevent_req
*req
= tevent_req_callback_data(
243 subreq
, struct tevent_req
);
244 struct wbc_info_state
*state
= tevent_req_data(
245 req
, struct wbc_info_state
);
246 struct winbindd_response
*resp
;
249 wbc_status
= wb_trans_recv(subreq
, state
, &resp
);
251 if (!WBC_ERROR_IS_OK(wbc_status
)) {
252 tevent_req_error(req
, wbc_status
);
255 state
->version_string
= talloc_strdup(state
,
256 resp
->data
.info
.samba_version
);
257 if (tevent_req_nomem(state
->version_string
, subreq
)) {
260 state
->separator
= resp
->data
.info
.winbind_separator
;
263 tevent_req_done(req
);
267 * @brief Receive information about the running winbind service
269 * @param req tevent_req containing the request
270 * @param mem_ctx talloc context to allocate memory from
271 * @param winbind_separator pointer to a char to hold the separator
272 * @param version_string pointer to a string to hold the version string
277 wbcErr
wbcInfo_recv(struct tevent_req
*req
,
279 char *winbind_separator
,
280 char **version_string
)
282 struct wbc_info_state
*state
= tevent_req_data(
283 req
, struct wbc_info_state
);
286 if (tevent_req_is_wbcerr(req
, &wbc_status
)) {
287 tevent_req_received(req
);
291 *winbind_separator
= state
->separator
;
292 *version_string
= talloc_steal(mem_ctx
, state
->version_string
);
294 tevent_req_received(req
);
295 return WBC_ERR_SUCCESS
;
298 struct wbc_netbios_name_state
{
299 struct winbindd_request req
;
303 static void wbcNetbiosName_done(struct tevent_req
*subreq
);
306 * @brief Request the machine's netbios name
308 * @param mem_ctx talloc context to allocate memory from
309 * @param ev tevent context to use for async requests
310 * @param wb_ctx winbind context
312 * @return tevent_req on success, NULL on failure
315 struct tevent_req
*wbcNetbiosName_send(TALLOC_CTX
*mem_ctx
,
316 struct tevent_context
*ev
,
317 struct wb_context
*wb_ctx
)
319 struct tevent_req
*req
, *subreq
;
320 struct wbc_netbios_name_state
*state
;
322 req
= tevent_req_create(mem_ctx
, &state
, struct wbc_netbios_name_state
);
327 ZERO_STRUCT(state
->req
);
328 state
->req
.cmd
= WINBINDD_NETBIOS_NAME
;
330 subreq
= wb_trans_send(state
, ev
, wb_ctx
, false, &state
->req
);
331 if (tevent_req_nomem(subreq
, req
)) {
332 return tevent_req_post(req
, ev
);
335 tevent_req_set_callback(subreq
, wbcNetbiosName_done
, req
);
339 static void wbcNetbiosName_done(struct tevent_req
*subreq
)
341 struct tevent_req
*req
= tevent_req_callback_data(
342 subreq
, struct tevent_req
);
343 struct wbc_netbios_name_state
*state
= tevent_req_data(
344 req
, struct wbc_netbios_name_state
);
345 struct winbindd_response
*resp
;
348 wbc_status
= wb_trans_recv(subreq
, state
, &resp
);
350 if (!WBC_ERROR_IS_OK(wbc_status
)) {
351 tevent_req_error(req
, wbc_status
);
354 state
->netbios_name
= talloc_strdup(state
,
355 resp
->data
.info
.samba_version
);
356 if (tevent_req_nomem(state
->netbios_name
, subreq
)) {
361 tevent_req_done(req
);
365 * @brief Receive the machine's netbios name
367 * @param req tevent_req containing the request
368 * @param mem_ctx talloc context to allocate memory from
369 * @param netbios_name pointer to a string to hold the netbios name
374 wbcErr
wbcNetbiosName_recv(struct tevent_req
*req
,
378 struct wbc_netbios_name_state
*state
= tevent_req_data(
379 req
, struct wbc_netbios_name_state
);
382 if (tevent_req_is_wbcerr(req
, &wbc_status
)) {
383 tevent_req_received(req
);
387 *netbios_name
= talloc_steal(mem_ctx
, state
->netbios_name
);
389 tevent_req_received(req
);
390 return WBC_ERR_SUCCESS
;
393 struct wbc_domain_name_state
{
394 struct winbindd_request req
;
398 static void wbcDomainName_done(struct tevent_req
*subreq
);
401 * @brief Request the machine's domain name
403 * @param mem_ctx talloc context to allocate memory from
404 * @param ev tevent context to use for async requests
405 * @param wb_ctx winbind context
407 * @return tevent_req on success, NULL on failure
410 struct tevent_req
*wbcDomainName_send(TALLOC_CTX
*mem_ctx
,
411 struct tevent_context
*ev
,
412 struct wb_context
*wb_ctx
)
414 struct tevent_req
*req
, *subreq
;
415 struct wbc_domain_name_state
*state
;
417 req
= tevent_req_create(mem_ctx
, &state
, struct wbc_domain_name_state
);
422 ZERO_STRUCT(state
->req
);
423 state
->req
.cmd
= WINBINDD_DOMAIN_NAME
;
425 subreq
= wb_trans_send(state
, ev
, wb_ctx
, false, &state
->req
);
426 if (tevent_req_nomem(subreq
, req
)) {
427 return tevent_req_post(req
, ev
);
430 tevent_req_set_callback(subreq
, wbcDomainName_done
, req
);
434 static void wbcDomainName_done(struct tevent_req
*subreq
)
436 struct tevent_req
*req
= tevent_req_callback_data(
437 subreq
, struct tevent_req
);
438 struct wbc_domain_name_state
*state
= tevent_req_data(
439 req
, struct wbc_domain_name_state
);
440 struct winbindd_response
*resp
;
443 wbc_status
= wb_trans_recv(subreq
, state
, &resp
);
445 if (!WBC_ERROR_IS_OK(wbc_status
)) {
446 tevent_req_error(req
, wbc_status
);
449 state
->domain_name
= talloc_strdup(state
, resp
->data
.domain_name
);
450 if (tevent_req_nomem(state
->domain_name
, subreq
)) {
455 tevent_req_done(req
);
459 * @brief Receive the machine's domain name
461 * @param req tevent_req containing the request
462 * @param mem_ctx talloc context to allocate memory from
463 * @param domain_name pointer to a string to hold the domain name
468 wbcErr
wbcDomainName_recv(struct tevent_req
*req
,
472 struct wbc_domain_name_state
*state
= tevent_req_data(
473 req
, struct wbc_domain_name_state
);
476 if (tevent_req_is_wbcerr(req
, &wbc_status
)) {
477 tevent_req_received(req
);
481 *domain_name
= talloc_steal(mem_ctx
, state
->domain_name
);
483 tevent_req_received(req
);
484 return WBC_ERR_SUCCESS
;
487 struct wbc_interface_details_state
{
488 struct tevent_context
*ev
;
489 struct wb_context
*wb_ctx
;
490 struct wbcDomainInfo
*dinfo
;
491 struct wbcInterfaceDetails
*details
;
494 static void wbcInterfaceDetails_version(struct tevent_req
*subreq
);
495 static void wbcInterfaceDetails_info(struct tevent_req
*subreq
);
496 static void wbcInterfaceDetails_netbios_name(struct tevent_req
*subreq
);
497 static void wbcInterfaceDetails_domain_name(struct tevent_req
*subreq
);
498 static void wbcInterfaceDetails_domain_info(struct tevent_req
*subreq
);
501 * @brief Request some useful details about the winbind service
503 * @param mem_ctx talloc context to allocate memory from
504 * @param ev tevent context to use for async requests
505 * @param wb_ctx winbind context
507 * @return tevent_req on success, NULL on failure
510 struct tevent_req
*wbcInterfaceDetails_send(TALLOC_CTX
*mem_ctx
,
511 struct tevent_context
*ev
,
512 struct wb_context
*wb_ctx
)
514 struct tevent_req
*req
, *subreq
;
515 struct wbc_interface_details_state
*state
;
517 req
= tevent_req_create(mem_ctx
, &state
,
518 struct wbc_interface_details_state
);
524 state
->wb_ctx
= wb_ctx
;
525 state
->details
= talloc(state
, struct wbcInterfaceDetails
);
526 if (tevent_req_nomem(state
->details
, req
)) {
527 return tevent_req_post(req
, ev
);
530 subreq
= wbcInterfaceVersion_send(state
, ev
, wb_ctx
);
531 if (tevent_req_nomem(subreq
, req
)) {
532 return tevent_req_post(req
, ev
);
535 tevent_req_set_callback(subreq
, wbcInterfaceDetails_version
, req
);
539 static void wbcInterfaceDetails_version(struct tevent_req
*subreq
)
541 struct tevent_req
*req
= tevent_req_callback_data(
542 subreq
, struct tevent_req
);
543 struct wbc_interface_details_state
*state
= tevent_req_data(
544 req
, struct wbc_interface_details_state
);
548 wbc_status
= wbcInterfaceVersion_recv(subreq
,
549 &state
->details
->interface_version
);
551 if (!WBC_ERROR_IS_OK(wbc_status
)) {
552 tevent_req_error(req
, wbc_status
);
556 subreq
= wbcInfo_send(state
, state
->ev
, state
->wb_ctx
);
557 if (tevent_req_nomem(subreq
, req
)) {
561 tevent_req_set_callback(subreq
, wbcInterfaceDetails_info
, req
);
564 static void wbcInterfaceDetails_info(struct tevent_req
*subreq
)
566 struct tevent_req
*req
= tevent_req_callback_data(
567 subreq
, struct tevent_req
);
568 struct wbc_interface_details_state
*state
= tevent_req_data(
569 req
, struct wbc_interface_details_state
);
572 wbc_status
= wbcInfo_recv(subreq
, state
->details
,
573 &state
->details
->winbind_separator
,
574 &state
->details
->winbind_version
);
576 if (!WBC_ERROR_IS_OK(wbc_status
)) {
577 tevent_req_error(req
, wbc_status
);
581 subreq
= wbcNetbiosName_send(state
, state
->ev
, state
->wb_ctx
);
582 if (tevent_req_nomem(subreq
, req
)) {
586 tevent_req_set_callback(subreq
, wbcInterfaceDetails_netbios_name
, req
);
589 static void wbcInterfaceDetails_netbios_name(struct tevent_req
*subreq
)
591 struct tevent_req
*req
= tevent_req_callback_data(
592 subreq
, struct tevent_req
);
593 struct wbc_interface_details_state
*state
= tevent_req_data(
594 req
, struct wbc_interface_details_state
);
597 wbc_status
= wbcNetbiosName_recv(subreq
, state
->details
,
598 &state
->details
->netbios_name
);
600 if (!WBC_ERROR_IS_OK(wbc_status
)) {
601 tevent_req_error(req
, wbc_status
);
605 subreq
= wbcDomainName_send(state
, state
->ev
, state
->wb_ctx
);
606 if (tevent_req_nomem(subreq
, req
)) {
610 tevent_req_set_callback(subreq
, wbcInterfaceDetails_domain_name
, req
);
613 static void wbcInterfaceDetails_domain_name(struct tevent_req
*subreq
)
615 struct tevent_req
*req
= tevent_req_callback_data(
616 subreq
, struct tevent_req
);
617 struct wbc_interface_details_state
*state
= tevent_req_data(
618 req
, struct wbc_interface_details_state
);
621 wbc_status
= wbcDomainName_recv(subreq
, state
->details
,
622 &state
->details
->netbios_domain
);
624 if (!WBC_ERROR_IS_OK(wbc_status
)) {
625 tevent_req_error(req
, wbc_status
);
629 subreq
= wbcDomainInfo_send(state
, state
->ev
, state
->wb_ctx
,
630 state
->details
->netbios_domain
);
631 if (tevent_req_nomem(subreq
, req
)) {
635 tevent_req_set_callback(subreq
, wbcInterfaceDetails_domain_info
, req
);
638 static void wbcInterfaceDetails_domain_info(struct tevent_req
*subreq
)
640 struct tevent_req
*req
= tevent_req_callback_data(
641 subreq
, struct tevent_req
);
642 struct wbc_interface_details_state
*state
= tevent_req_data(
643 req
, struct wbc_interface_details_state
);
644 struct wbcDomainInfo
*domain
;
647 wbc_status
= wbcDomainInfo_recv(subreq
, state
, &domain
);
649 if (wbc_status
== WBC_ERR_DOMAIN_NOT_FOUND
) {
650 tevent_req_done(req
);
654 if (!WBC_ERROR_IS_OK(wbc_status
)) {
655 tevent_req_error(req
, wbc_status
);
658 state
->details
->dns_domain
= talloc_strdup(state
->details
,
660 if (tevent_req_nomem(state
->details
->dns_domain
, req
)) {
665 tevent_req_done(req
);
669 * @brief Receive useful information about the winbind service
671 * @param req tevent_req containing the request
672 * @param mem_ctx talloc context to allocate memory from
673 * @param *details pointer to hold the struct wbcInterfaceDetails
678 wbcErr
wbcInterfaceDetails_recv(struct tevent_req
*req
,
680 struct wbcInterfaceDetails
**details
)
682 struct wbc_interface_details_state
*state
= tevent_req_data(
683 req
, struct wbc_interface_details_state
);
686 if (tevent_req_is_wbcerr(req
, &wbc_status
)) {
687 tevent_req_received(req
);
691 *details
= talloc_steal(mem_ctx
, state
->details
);
693 tevent_req_received(req
);
694 return WBC_ERR_SUCCESS
;
697 struct wbc_domain_info_state
{
698 struct winbindd_request req
;
699 struct wbcDomainInfo
*info
;
702 static void wbcDomainInfo_done(struct tevent_req
*subreq
);
705 * @brief Request status of a given trusted domain
707 * @param mem_ctx talloc context to allocate memory from
708 * @param ev tevent context to use for async requests
709 * @param wb_ctx winbind context
710 * @param domain domain to request status from
712 * @return tevent_req on success, NULL on failure
715 struct tevent_req
*wbcDomainInfo_send(TALLOC_CTX
*mem_ctx
,
716 struct tevent_context
*ev
,
717 struct wb_context
*wb_ctx
,
720 struct tevent_req
*req
, *subreq
;
721 struct wbc_domain_info_state
*state
;
727 req
= tevent_req_create(mem_ctx
, &state
, struct wbc_domain_info_state
);
732 state
->info
= talloc(state
, struct wbcDomainInfo
);
733 if (tevent_req_nomem(state
->info
, req
)) {
734 return tevent_req_post(req
, ev
);
737 ZERO_STRUCT(state
->req
);
739 strncpy(state
->req
.domain_name
, domain
,
740 sizeof(state
->req
.domain_name
)-1);
742 state
->req
.cmd
= WINBINDD_DOMAIN_INFO
;
744 subreq
= wb_trans_send(state
, ev
, wb_ctx
, false, &state
->req
);
745 if (tevent_req_nomem(subreq
, req
)) {
746 return tevent_req_post(req
, ev
);
749 tevent_req_set_callback(subreq
, wbcDomainInfo_done
, req
);
753 static void wbcDomainInfo_done(struct tevent_req
*subreq
)
755 struct tevent_req
*req
= tevent_req_callback_data(
756 subreq
, struct tevent_req
);
757 struct wbc_domain_info_state
*state
= tevent_req_data(
758 req
, struct wbc_domain_info_state
);
759 struct winbindd_response
*resp
;
762 wbc_status
= wb_trans_recv(subreq
, state
, &resp
);
764 if (!WBC_ERROR_IS_OK(wbc_status
)) {
765 tevent_req_error(req
, wbc_status
);
769 state
->info
->short_name
= talloc_strdup(state
->info
,
770 resp
->data
.domain_info
.name
);
771 if (tevent_req_nomem(state
->info
->short_name
, req
)) {
775 state
->info
->dns_name
= talloc_strdup(state
->info
,
776 resp
->data
.domain_info
.alt_name
);
777 if (tevent_req_nomem(state
->info
->dns_name
, req
)) {
781 wbc_status
= wbcStringToSid(resp
->data
.domain_info
.sid
,
783 if (!WBC_ERROR_IS_OK(wbc_status
)) {
784 tevent_req_error(req
, wbc_status
);
788 if (resp
->data
.domain_info
.native_mode
) {
789 state
->info
->domain_flags
|= WBC_DOMINFO_DOMAIN_NATIVE
;
791 if (resp
->data
.domain_info
.active_directory
) {
792 state
->info
->domain_flags
|= WBC_DOMINFO_DOMAIN_AD
;
794 if (resp
->data
.domain_info
.primary
) {
795 state
->info
->domain_flags
|= WBC_DOMINFO_DOMAIN_PRIMARY
;
800 tevent_req_done(req
);
804 * @brief Receive information about a trusted domain
806 * @param req tevent_req containing the request
807 * @param mem_ctx talloc context to allocate memory from
808 * @param *dinfo pointer to returned struct wbcDomainInfo
813 wbcErr
wbcDomainInfo_recv(struct tevent_req
*req
,
815 struct wbcDomainInfo
**dinfo
)
817 struct wbc_domain_info_state
*state
= tevent_req_data(
818 req
, struct wbc_domain_info_state
);
821 if (tevent_req_is_wbcerr(req
, &wbc_status
)) {
822 tevent_req_received(req
);
827 tevent_req_received(req
);
828 return WBC_ERR_INVALID_PARAM
;
831 *dinfo
= talloc_steal(mem_ctx
, state
->info
);
833 tevent_req_received(req
);
834 return WBC_ERR_SUCCESS
;