2 Unix SMB/CIFS implementation.
4 Winbind client asynchronous API, utility functions
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"
27 #include "../winbind_client.h"
29 /** @brief Ping winbindd to see if the daemon is running
35 struct winbindd_request request
;
36 struct winbindd_response response
;
38 /* Initialize request */
41 ZERO_STRUCT(response
);
43 return wbcRequestResponse(WINBINDD_PING
, &request
, &response
);
48 * @brief Query useful information about the winbind service
50 * @param *_details pointer to hold the struct wbcInterfaceDetails
55 wbcErr
wbcInterfaceDetails(struct wbcInterfaceDetails
**_details
)
57 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
58 struct wbcInterfaceDetails
*info
;
59 struct wbcDomainInfo
*domain
= NULL
;
60 struct winbindd_request request
;
61 struct winbindd_response response
;
63 /* Initialize request */
66 ZERO_STRUCT(response
);
68 info
= talloc(NULL
, struct wbcInterfaceDetails
);
69 BAIL_ON_PTR_ERROR(info
, wbc_status
);
71 /* first the interface version */
72 wbc_status
= wbcRequestResponse(WINBINDD_INTERFACE_VERSION
, NULL
, &response
);
73 BAIL_ON_WBC_ERROR(wbc_status
);
74 info
->interface_version
= response
.data
.interface_version
;
76 /* then the samba version and the winbind separator */
77 wbc_status
= wbcRequestResponse(WINBINDD_INFO
, NULL
, &response
);
78 BAIL_ON_WBC_ERROR(wbc_status
);
80 info
->winbind_version
= talloc_strdup(info
,
81 response
.data
.info
.samba_version
);
82 BAIL_ON_PTR_ERROR(info
->winbind_version
, wbc_status
);
83 info
->winbind_separator
= response
.data
.info
.winbind_separator
;
85 /* then the local netbios name */
86 wbc_status
= wbcRequestResponse(WINBINDD_NETBIOS_NAME
, NULL
, &response
);
87 BAIL_ON_WBC_ERROR(wbc_status
);
89 info
->netbios_name
= talloc_strdup(info
,
90 response
.data
.netbios_name
);
91 BAIL_ON_PTR_ERROR(info
->netbios_name
, wbc_status
);
93 /* then the local workgroup name */
94 wbc_status
= wbcRequestResponse(WINBINDD_DOMAIN_NAME
, NULL
, &response
);
95 BAIL_ON_WBC_ERROR(wbc_status
);
97 info
->netbios_domain
= talloc_strdup(info
,
98 response
.data
.domain_name
);
99 BAIL_ON_PTR_ERROR(info
->netbios_domain
, wbc_status
);
101 wbc_status
= wbcDomainInfo(info
->netbios_domain
, &domain
);
102 if (wbc_status
== WBC_ERR_DOMAIN_NOT_FOUND
) {
103 /* maybe it's a standalone server */
105 wbc_status
= WBC_ERR_SUCCESS
;
107 BAIL_ON_WBC_ERROR(wbc_status
);
111 info
->dns_domain
= talloc_strdup(info
,
113 wbcFreeMemory(domain
);
114 BAIL_ON_PTR_ERROR(info
->dns_domain
, wbc_status
);
116 info
->dns_domain
= NULL
;
122 wbc_status
= WBC_ERR_SUCCESS
;
130 /** @brief Lookup the current status of a trusted domain, sync wrapper
132 * @param domain Domain to query
133 * @param *dinfo Pointer to returned struct wbcDomainInfo
138 wbcErr
wbcDomainInfo(const char *domain
, struct wbcDomainInfo
**dinfo
)
140 struct winbindd_request request
;
141 struct winbindd_response response
;
142 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
143 struct wbcDomainInfo
*info
= NULL
;
145 if (!domain
|| !dinfo
) {
146 wbc_status
= WBC_ERR_INVALID_PARAM
;
147 BAIL_ON_WBC_ERROR(wbc_status
);
150 /* Initialize request */
152 ZERO_STRUCT(request
);
153 ZERO_STRUCT(response
);
155 strncpy(request
.domain_name
, domain
,
156 sizeof(request
.domain_name
)-1);
158 wbc_status
= wbcRequestResponse(WINBINDD_DOMAIN_INFO
,
161 BAIL_ON_WBC_ERROR(wbc_status
);
163 info
= talloc(NULL
, struct wbcDomainInfo
);
164 BAIL_ON_PTR_ERROR(info
, wbc_status
);
166 info
->short_name
= talloc_strdup(info
,
167 response
.data
.domain_info
.name
);
168 BAIL_ON_PTR_ERROR(info
->short_name
, wbc_status
);
170 info
->dns_name
= talloc_strdup(info
,
171 response
.data
.domain_info
.alt_name
);
172 BAIL_ON_PTR_ERROR(info
->dns_name
, wbc_status
);
174 wbc_status
= wbcStringToSid(response
.data
.domain_info
.sid
,
176 BAIL_ON_WBC_ERROR(wbc_status
);
178 if (response
.data
.domain_info
.native_mode
)
179 info
->domain_flags
|= WBC_DOMINFO_DOMAIN_NATIVE
;
180 if (response
.data
.domain_info
.active_directory
)
181 info
->domain_flags
|= WBC_DOMINFO_DOMAIN_AD
;
182 if (response
.data
.domain_info
.primary
)
183 info
->domain_flags
|= WBC_DOMINFO_DOMAIN_PRIMARY
;
187 wbc_status
= WBC_ERR_SUCCESS
;
190 if (!WBC_ERROR_IS_OK(wbc_status
)) {
198 /* Resolve a NetbiosName via WINS */
199 wbcErr
wbcResolveWinsByName(const char *name
, char **ip
)
201 struct winbindd_request request
;
202 struct winbindd_response response
;
203 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
206 ZERO_STRUCT(request
);
207 ZERO_STRUCT(response
);
211 strncpy(request
.data
.winsreq
, name
,
212 sizeof(request
.data
.winsreq
)-1);
214 wbc_status
= wbcRequestResponse(WINBINDD_WINS_BYNAME
,
217 BAIL_ON_WBC_ERROR(wbc_status
);
219 /* Display response */
221 ipaddr
= talloc_strdup(NULL
, response
.data
.winsresp
);
222 BAIL_ON_PTR_ERROR(ipaddr
, wbc_status
);
225 wbc_status
= WBC_ERR_SUCCESS
;
231 /* Resolve an IP address via WINS into a NetbiosName */
232 wbcErr
wbcResolveWinsByIP(const char *ip
, char **name
)
234 struct winbindd_request request
;
235 struct winbindd_response response
;
236 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
239 ZERO_STRUCT(request
);
240 ZERO_STRUCT(response
);
244 strncpy(request
.data
.winsreq
, ip
,
245 sizeof(request
.data
.winsreq
)-1);
247 wbc_status
= wbcRequestResponse(WINBINDD_WINS_BYIP
,
250 BAIL_ON_WBC_ERROR(wbc_status
);
252 /* Display response */
254 name_str
= talloc_strdup(NULL
, response
.data
.winsresp
);
255 BAIL_ON_PTR_ERROR(name_str
, wbc_status
);
258 wbc_status
= WBC_ERR_SUCCESS
;
267 static wbcErr
process_domain_info_string(TALLOC_CTX
*ctx
,
268 struct wbcDomainInfo
*info
,
271 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
275 if (!info
|| !info_string
) {
276 wbc_status
= WBC_ERR_INVALID_PARAM
;
277 BAIL_ON_WBC_ERROR(wbc_status
);
285 if ((s
= strchr(r
, '\\')) == NULL
) {
286 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
287 BAIL_ON_WBC_ERROR(wbc_status
);
292 info
->short_name
= talloc_strdup(ctx
, r
);
293 BAIL_ON_PTR_ERROR(info
->short_name
, wbc_status
);
298 if ((s
= strchr(r
, '\\')) == NULL
) {
299 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
300 BAIL_ON_WBC_ERROR(wbc_status
);
305 info
->dns_name
= talloc_strdup(ctx
, r
);
306 BAIL_ON_PTR_ERROR(info
->dns_name
, wbc_status
);
310 if ((s
= strchr(r
, '\\')) == NULL
) {
311 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
312 BAIL_ON_WBC_ERROR(wbc_status
);
317 wbc_status
= wbcStringToSid(r
, &info
->sid
);
318 BAIL_ON_WBC_ERROR(wbc_status
);
322 if ((s
= strchr(r
, '\\')) == NULL
) {
323 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
324 BAIL_ON_WBC_ERROR(wbc_status
);
329 if (strcmp(r
, "None") == 0) {
330 info
->trust_type
= WBC_DOMINFO_TRUSTTYPE_NONE
;
331 } else if (strcmp(r
, "External") == 0) {
332 info
->trust_type
= WBC_DOMINFO_TRUSTTYPE_EXTERNAL
;
333 } else if (strcmp(r
, "Forest") == 0) {
334 info
->trust_type
= WBC_DOMINFO_TRUSTTYPE_FOREST
;
335 } else if (strcmp(r
, "In Forest") == 0) {
336 info
->trust_type
= WBC_DOMINFO_TRUSTTYPE_IN_FOREST
;
338 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
339 BAIL_ON_WBC_ERROR(wbc_status
);
344 if ((s
= strchr(r
, '\\')) == NULL
) {
345 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
346 BAIL_ON_WBC_ERROR(wbc_status
);
351 if (strcmp(r
, "Yes") == 0) {
352 info
->trust_flags
|= WBC_DOMINFO_TRUST_TRANSITIVE
;
357 if ((s
= strchr(r
, '\\')) == NULL
) {
358 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
359 BAIL_ON_WBC_ERROR(wbc_status
);
364 if (strcmp(r
, "Yes") == 0) {
365 info
->trust_flags
|= WBC_DOMINFO_TRUST_INCOMING
;
370 if ((s
= strchr(r
, '\\')) == NULL
) {
371 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
372 BAIL_ON_WBC_ERROR(wbc_status
);
377 if (strcmp(r
, "Yes") == 0) {
378 info
->trust_flags
|= WBC_DOMINFO_TRUST_OUTGOING
;
381 /* Online/Offline status */
385 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
386 BAIL_ON_WBC_ERROR(wbc_status
);
388 if ( strcmp(r
, "Offline") == 0) {
389 info
->domain_flags
|= WBC_DOMINFO_DOMAIN_OFFLINE
;
392 wbc_status
= WBC_ERR_SUCCESS
;
398 /* Enumerate the domain trusts known by Winbind */
399 wbcErr
wbcListTrusts(struct wbcDomainInfo
**domains
, size_t *num_domains
)
401 struct winbindd_response response
;
402 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
405 char *extra_data
= NULL
;
407 struct wbcDomainInfo
*d_list
= NULL
;
413 ZERO_STRUCT(response
);
417 wbc_status
= wbcRequestResponse(WINBINDD_LIST_TRUSTDOM
,
420 BAIL_ON_WBC_ERROR(wbc_status
);
422 /* Decode the response */
424 p
= (char *)response
.extra_data
.data
;
426 if ((p
== NULL
) || (strlen(p
) == 0)) {
427 /* We should always at least get back our
430 wbc_status
= WBC_ERR_DOMAIN_NOT_FOUND
;
431 BAIL_ON_WBC_ERROR(wbc_status
);
434 /* Count number of domains */
440 if ((q
= strchr(p
, '\n')) != NULL
)
445 d_list
= talloc_array(NULL
, struct wbcDomainInfo
, count
);
446 BAIL_ON_PTR_ERROR(d_list
, wbc_status
);
448 extra_data
= strdup((char*)response
.extra_data
.data
);
449 BAIL_ON_PTR_ERROR(extra_data
, wbc_status
);
453 /* Outer loop processes the list of domain information */
455 for (i
=0; i
<count
&& p
; i
++) {
456 char *next
= strchr(p
, '\n');
463 wbc_status
= process_domain_info_string(d_list
, &d_list
[i
], p
);
464 BAIL_ON_WBC_ERROR(wbc_status
);
474 winbindd_free_response(&response
);
480 /* Enumerate the domain trusts known by Winbind */
481 wbcErr
wbcLookupDomainController(const char *domain
,
483 struct wbcDomainControllerInfo
**dc_info
)
485 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
486 struct winbindd_request request
;
487 struct winbindd_response response
;
488 struct wbcDomainControllerInfo
*dc
= NULL
;
490 /* validate input params */
492 if (!domain
|| !dc_info
) {
493 wbc_status
= WBC_ERR_INVALID_PARAM
;
494 BAIL_ON_WBC_ERROR(wbc_status
);
497 ZERO_STRUCT(request
);
498 ZERO_STRUCT(response
);
500 strncpy(request
.data
.dsgetdcname
.domain_name
, domain
,
501 sizeof(request
.data
.dsgetdcname
.domain_name
)-1);
503 request
.flags
= flags
;
505 dc
= talloc(NULL
, struct wbcDomainControllerInfo
);
506 BAIL_ON_PTR_ERROR(dc
, wbc_status
);
510 wbc_status
= wbcRequestResponse(WINBINDD_DSGETDCNAME
,
513 BAIL_ON_WBC_ERROR(wbc_status
);
515 dc
->dc_name
= talloc_strdup(dc
, response
.data
.dsgetdcname
.dc_unc
);
516 BAIL_ON_PTR_ERROR(dc
->dc_name
, wbc_status
);
521 if (!WBC_ERROR_IS_OK(wbc_status
)) {
528 static wbcErr
wbc_create_domain_controller_info_ex(TALLOC_CTX
*mem_ctx
,
529 const struct winbindd_response
*resp
,
530 struct wbcDomainControllerInfoEx
**_i
)
532 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
533 struct wbcDomainControllerInfoEx
*i
;
536 i
= talloc(mem_ctx
, struct wbcDomainControllerInfoEx
);
537 BAIL_ON_PTR_ERROR(i
, wbc_status
);
539 i
->dc_unc
= talloc_strdup(i
, resp
->data
.dsgetdcname
.dc_unc
);
540 BAIL_ON_PTR_ERROR(i
->dc_unc
, wbc_status
);
542 i
->dc_address
= talloc_strdup(i
, resp
->data
.dsgetdcname
.dc_address
);
543 BAIL_ON_PTR_ERROR(i
->dc_address
, wbc_status
);
545 i
->dc_address_type
= resp
->data
.dsgetdcname
.dc_address_type
;
547 wbc_status
= wbcStringToGuid(resp
->data
.dsgetdcname
.domain_guid
, &guid
);
548 if (WBC_ERROR_IS_OK(wbc_status
)) {
549 i
->domain_guid
= talloc(i
, struct wbcGuid
);
550 BAIL_ON_PTR_ERROR(i
->domain_guid
, wbc_status
);
552 *i
->domain_guid
= guid
;
554 i
->domain_guid
= NULL
;
557 i
->domain_name
= talloc_strdup(i
, resp
->data
.dsgetdcname
.domain_name
);
558 BAIL_ON_PTR_ERROR(i
->domain_name
, wbc_status
);
560 if (resp
->data
.dsgetdcname
.forest_name
[0] != '\0') {
561 i
->forest_name
= talloc_strdup(i
,
562 resp
->data
.dsgetdcname
.forest_name
);
563 BAIL_ON_PTR_ERROR(i
->forest_name
, wbc_status
);
565 i
->forest_name
= NULL
;
568 i
->dc_flags
= resp
->data
.dsgetdcname
.dc_flags
;
570 if (resp
->data
.dsgetdcname
.dc_site_name
[0] != '\0') {
571 i
->dc_site_name
= talloc_strdup(i
,
572 resp
->data
.dsgetdcname
.dc_site_name
);
573 BAIL_ON_PTR_ERROR(i
->dc_site_name
, wbc_status
);
575 i
->dc_site_name
= NULL
;
578 if (resp
->data
.dsgetdcname
.client_site_name
[0] != '\0') {
579 i
->client_site_name
= talloc_strdup(i
,
580 resp
->data
.dsgetdcname
.client_site_name
);
581 BAIL_ON_PTR_ERROR(i
->client_site_name
, wbc_status
);
583 i
->client_site_name
= NULL
;
594 /* Get extended domain controller information */
595 wbcErr
wbcLookupDomainControllerEx(const char *domain
,
596 struct wbcGuid
*guid
,
599 struct wbcDomainControllerInfoEx
**dc_info
)
601 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
602 struct winbindd_request request
;
603 struct winbindd_response response
;
605 /* validate input params */
607 if (!domain
|| !dc_info
) {
608 wbc_status
= WBC_ERR_INVALID_PARAM
;
609 BAIL_ON_WBC_ERROR(wbc_status
);
612 ZERO_STRUCT(request
);
613 ZERO_STRUCT(response
);
615 request
.data
.dsgetdcname
.flags
= flags
;
617 strncpy(request
.data
.dsgetdcname
.domain_name
, domain
,
618 sizeof(request
.data
.dsgetdcname
.domain_name
)-1);
621 strncpy(request
.data
.dsgetdcname
.site_name
, site
,
622 sizeof(request
.data
.dsgetdcname
.site_name
)-1);
628 wbc_status
= wbcGuidToString(guid
, &str
);
629 BAIL_ON_WBC_ERROR(wbc_status
);
631 strncpy(request
.data
.dsgetdcname
.domain_guid
, str
,
632 sizeof(request
.data
.dsgetdcname
.domain_guid
)-1);
639 wbc_status
= wbcRequestResponse(WINBINDD_DSGETDCNAME
,
642 BAIL_ON_WBC_ERROR(wbc_status
);
645 wbc_status
= wbc_create_domain_controller_info_ex(NULL
,
648 BAIL_ON_WBC_ERROR(wbc_status
);
651 wbc_status
= WBC_ERR_SUCCESS
;
656 /* Initialize a named blob and add to list of blobs */
657 wbcErr
wbcAddNamedBlob(size_t *num_blobs
,
658 struct wbcNamedBlob
**blobs
,
664 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
665 struct wbcNamedBlob blob
;
667 *blobs
= talloc_realloc(NULL
, *blobs
, struct wbcNamedBlob
,
669 BAIL_ON_PTR_ERROR(*blobs
, wbc_status
);
671 blob
.name
= talloc_strdup(*blobs
, name
);
672 BAIL_ON_PTR_ERROR(blob
.name
, wbc_status
);
674 blob
.blob
.length
= length
;
675 blob
.blob
.data
= (uint8_t *)talloc_memdup(*blobs
, data
, length
);
676 BAIL_ON_PTR_ERROR(blob
.blob
.data
, wbc_status
);
678 (*(blobs
))[*num_blobs
] = blob
;
681 wbc_status
= WBC_ERR_SUCCESS
;
683 if (!WBC_ERROR_IS_OK(wbc_status
)) {
684 wbcFreeMemory(*blobs
);