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"
28 /** @brief Ping winbindd to see if the daemon is running
34 struct winbindd_request request
;
35 struct winbindd_response response
;
37 /* Initialize request */
40 ZERO_STRUCT(response
);
42 return wbcRequestResponse(WINBINDD_PING
, &request
, &response
);
47 * @brief Query useful information about the winbind service
49 * @param *_details pointer to hold the struct wbcInterfaceDetails
54 wbcErr
wbcInterfaceDetails(struct wbcInterfaceDetails
**_details
)
56 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
57 struct wbcInterfaceDetails
*info
;
58 struct wbcDomainInfo
*domain
= NULL
;
59 struct winbindd_request request
;
60 struct winbindd_response response
;
62 /* Initialize request */
65 ZERO_STRUCT(response
);
67 info
= talloc(NULL
, struct wbcInterfaceDetails
);
68 BAIL_ON_PTR_ERROR(info
, wbc_status
);
70 /* first the interface version */
71 wbc_status
= wbcRequestResponse(WINBINDD_INTERFACE_VERSION
, NULL
, &response
);
72 BAIL_ON_WBC_ERROR(wbc_status
);
73 info
->interface_version
= response
.data
.interface_version
;
75 /* then the samba version and the winbind separator */
76 wbc_status
= wbcRequestResponse(WINBINDD_INFO
, NULL
, &response
);
77 BAIL_ON_WBC_ERROR(wbc_status
);
79 info
->winbind_version
= talloc_strdup(info
,
80 response
.data
.info
.samba_version
);
81 BAIL_ON_PTR_ERROR(info
->winbind_version
, wbc_status
);
82 info
->winbind_separator
= response
.data
.info
.winbind_separator
;
84 /* then the local netbios name */
85 wbc_status
= wbcRequestResponse(WINBINDD_NETBIOS_NAME
, NULL
, &response
);
86 BAIL_ON_WBC_ERROR(wbc_status
);
88 info
->netbios_name
= talloc_strdup(info
,
89 response
.data
.netbios_name
);
90 BAIL_ON_PTR_ERROR(info
->netbios_name
, wbc_status
);
92 /* then the local workgroup name */
93 wbc_status
= wbcRequestResponse(WINBINDD_DOMAIN_NAME
, NULL
, &response
);
94 BAIL_ON_WBC_ERROR(wbc_status
);
96 info
->netbios_domain
= talloc_strdup(info
,
97 response
.data
.domain_name
);
98 BAIL_ON_PTR_ERROR(info
->netbios_domain
, wbc_status
);
100 wbc_status
= wbcDomainInfo(info
->netbios_domain
, &domain
);
101 if (wbc_status
== WBC_ERR_DOMAIN_NOT_FOUND
) {
102 /* maybe it's a standalone server */
104 wbc_status
= WBC_ERR_SUCCESS
;
106 BAIL_ON_WBC_ERROR(wbc_status
);
110 info
->dns_domain
= talloc_strdup(info
,
112 wbcFreeMemory(domain
);
113 BAIL_ON_PTR_ERROR(info
->dns_domain
, wbc_status
);
115 info
->dns_domain
= NULL
;
121 wbc_status
= WBC_ERR_SUCCESS
;
129 /** @brief Lookup the current status of a trusted domain, sync wrapper
131 * @param domain Domain to query
132 * @param *dinfo Pointer to returned struct wbcDomainInfo
137 wbcErr
wbcDomainInfo(const char *domain
, struct wbcDomainInfo
**dinfo
)
139 struct winbindd_request request
;
140 struct winbindd_response response
;
141 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
142 struct wbcDomainInfo
*info
= NULL
;
144 if (!domain
|| !dinfo
) {
145 wbc_status
= WBC_ERR_INVALID_PARAM
;
146 BAIL_ON_WBC_ERROR(wbc_status
);
149 /* Initialize request */
151 ZERO_STRUCT(request
);
152 ZERO_STRUCT(response
);
154 strncpy(request
.domain_name
, domain
,
155 sizeof(request
.domain_name
)-1);
157 wbc_status
= wbcRequestResponse(WINBINDD_DOMAIN_INFO
,
160 BAIL_ON_WBC_ERROR(wbc_status
);
162 info
= talloc(NULL
, struct wbcDomainInfo
);
163 BAIL_ON_PTR_ERROR(info
, wbc_status
);
165 info
->short_name
= talloc_strdup(info
,
166 response
.data
.domain_info
.name
);
167 BAIL_ON_PTR_ERROR(info
->short_name
, wbc_status
);
169 info
->dns_name
= talloc_strdup(info
,
170 response
.data
.domain_info
.alt_name
);
171 BAIL_ON_PTR_ERROR(info
->dns_name
, wbc_status
);
173 wbc_status
= wbcStringToSid(response
.data
.domain_info
.sid
,
175 BAIL_ON_WBC_ERROR(wbc_status
);
177 if (response
.data
.domain_info
.native_mode
)
178 info
->domain_flags
|= WBC_DOMINFO_DOMAIN_NATIVE
;
179 if (response
.data
.domain_info
.active_directory
)
180 info
->domain_flags
|= WBC_DOMINFO_DOMAIN_AD
;
181 if (response
.data
.domain_info
.primary
)
182 info
->domain_flags
|= WBC_DOMINFO_DOMAIN_PRIMARY
;
186 wbc_status
= WBC_ERR_SUCCESS
;
189 if (!WBC_ERROR_IS_OK(wbc_status
)) {
197 /* Resolve a NetbiosName via WINS */
198 wbcErr
wbcResolveWinsByName(const char *name
, char **ip
)
200 struct winbindd_request request
;
201 struct winbindd_response response
;
202 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
205 ZERO_STRUCT(request
);
206 ZERO_STRUCT(response
);
210 strncpy(request
.data
.winsreq
, name
,
211 sizeof(request
.data
.winsreq
)-1);
213 wbc_status
= wbcRequestResponse(WINBINDD_WINS_BYNAME
,
216 BAIL_ON_WBC_ERROR(wbc_status
);
218 /* Display response */
220 ipaddr
= talloc_strdup(NULL
, response
.data
.winsresp
);
221 BAIL_ON_PTR_ERROR(ipaddr
, wbc_status
);
224 wbc_status
= WBC_ERR_SUCCESS
;
230 /* Resolve an IP address via WINS into a NetbiosName */
231 wbcErr
wbcResolveWinsByIP(const char *ip
, char **name
)
233 struct winbindd_request request
;
234 struct winbindd_response response
;
235 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
238 ZERO_STRUCT(request
);
239 ZERO_STRUCT(response
);
243 strncpy(request
.data
.winsreq
, ip
,
244 sizeof(request
.data
.winsreq
)-1);
246 wbc_status
= wbcRequestResponse(WINBINDD_WINS_BYIP
,
249 BAIL_ON_WBC_ERROR(wbc_status
);
251 /* Display response */
253 name_str
= talloc_strdup(NULL
, response
.data
.winsresp
);
254 BAIL_ON_PTR_ERROR(name_str
, wbc_status
);
257 wbc_status
= WBC_ERR_SUCCESS
;
266 static wbcErr
process_domain_info_string(TALLOC_CTX
*ctx
,
267 struct wbcDomainInfo
*info
,
270 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
274 if (!info
|| !info_string
) {
275 wbc_status
= WBC_ERR_INVALID_PARAM
;
276 BAIL_ON_WBC_ERROR(wbc_status
);
284 if ((s
= strchr(r
, '\\')) == NULL
) {
285 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
286 BAIL_ON_WBC_ERROR(wbc_status
);
291 info
->short_name
= talloc_strdup(ctx
, r
);
292 BAIL_ON_PTR_ERROR(info
->short_name
, wbc_status
);
297 if ((s
= strchr(r
, '\\')) == NULL
) {
298 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
299 BAIL_ON_WBC_ERROR(wbc_status
);
304 info
->dns_name
= talloc_strdup(ctx
, r
);
305 BAIL_ON_PTR_ERROR(info
->dns_name
, wbc_status
);
309 if ((s
= strchr(r
, '\\')) == NULL
) {
310 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
311 BAIL_ON_WBC_ERROR(wbc_status
);
316 wbc_status
= wbcStringToSid(r
, &info
->sid
);
317 BAIL_ON_WBC_ERROR(wbc_status
);
321 if ((s
= strchr(r
, '\\')) == NULL
) {
322 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
323 BAIL_ON_WBC_ERROR(wbc_status
);
328 if (strcmp(r
, "None") == 0) {
329 info
->trust_type
= WBC_DOMINFO_TRUSTTYPE_NONE
;
330 } else if (strcmp(r
, "External") == 0) {
331 info
->trust_type
= WBC_DOMINFO_TRUSTTYPE_EXTERNAL
;
332 } else if (strcmp(r
, "Forest") == 0) {
333 info
->trust_type
= WBC_DOMINFO_TRUSTTYPE_FOREST
;
334 } else if (strcmp(r
, "In Forest") == 0) {
335 info
->trust_type
= WBC_DOMINFO_TRUSTTYPE_IN_FOREST
;
337 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
338 BAIL_ON_WBC_ERROR(wbc_status
);
343 if ((s
= strchr(r
, '\\')) == NULL
) {
344 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
345 BAIL_ON_WBC_ERROR(wbc_status
);
350 if (strcmp(r
, "Yes") == 0) {
351 info
->trust_flags
|= WBC_DOMINFO_TRUST_TRANSITIVE
;
356 if ((s
= strchr(r
, '\\')) == NULL
) {
357 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
358 BAIL_ON_WBC_ERROR(wbc_status
);
363 if (strcmp(r
, "Yes") == 0) {
364 info
->trust_flags
|= WBC_DOMINFO_TRUST_INCOMING
;
369 if ((s
= strchr(r
, '\\')) == NULL
) {
370 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
371 BAIL_ON_WBC_ERROR(wbc_status
);
376 if (strcmp(r
, "Yes") == 0) {
377 info
->trust_flags
|= WBC_DOMINFO_TRUST_OUTGOING
;
380 /* Online/Offline status */
384 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
385 BAIL_ON_WBC_ERROR(wbc_status
);
387 if ( strcmp(r
, "Offline") == 0) {
388 info
->domain_flags
|= WBC_DOMINFO_DOMAIN_OFFLINE
;
391 wbc_status
= WBC_ERR_SUCCESS
;
397 /* Enumerate the domain trusts known by Winbind */
398 wbcErr
wbcListTrusts(struct wbcDomainInfo
**domains
, size_t *num_domains
)
400 struct winbindd_response response
;
401 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
404 char *extra_data
= NULL
;
406 struct wbcDomainInfo
*d_list
= NULL
;
412 ZERO_STRUCT(response
);
416 wbc_status
= wbcRequestResponse(WINBINDD_LIST_TRUSTDOM
,
419 BAIL_ON_WBC_ERROR(wbc_status
);
421 /* Decode the response */
423 p
= (char *)response
.extra_data
.data
;
425 if ((p
== NULL
) || (strlen(p
) == 0)) {
426 /* We should always at least get back our
429 wbc_status
= WBC_ERR_DOMAIN_NOT_FOUND
;
430 BAIL_ON_WBC_ERROR(wbc_status
);
433 /* Count number of domains */
439 if ((q
= strchr(p
, '\n')) != NULL
)
444 d_list
= talloc_array(NULL
, struct wbcDomainInfo
, count
);
445 BAIL_ON_PTR_ERROR(d_list
, wbc_status
);
447 extra_data
= strdup((char*)response
.extra_data
.data
);
448 BAIL_ON_PTR_ERROR(extra_data
, wbc_status
);
452 /* Outer loop processes the list of domain information */
454 for (i
=0; i
<count
&& p
; i
++) {
455 char *next
= strchr(p
, '\n');
462 wbc_status
= process_domain_info_string(d_list
, &d_list
[i
], p
);
463 BAIL_ON_WBC_ERROR(wbc_status
);
472 if (!WBC_ERROR_IS_OK(wbc_status
)) {
482 /* Enumerate the domain trusts known by Winbind */
483 wbcErr
wbcLookupDomainController(const char *domain
,
485 struct wbcDomainControllerInfo
**dc_info
)
487 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
488 struct winbindd_request request
;
489 struct winbindd_response response
;
490 struct wbcDomainControllerInfo
*dc
= NULL
;
492 /* validate input params */
494 if (!domain
|| !dc_info
) {
495 wbc_status
= WBC_ERR_INVALID_PARAM
;
496 BAIL_ON_WBC_ERROR(wbc_status
);
499 ZERO_STRUCT(request
);
500 ZERO_STRUCT(response
);
502 strncpy(request
.data
.dsgetdcname
.domain_name
, domain
,
503 sizeof(request
.data
.dsgetdcname
.domain_name
)-1);
505 request
.flags
= flags
;
507 dc
= talloc(NULL
, struct wbcDomainControllerInfo
);
508 BAIL_ON_PTR_ERROR(dc
, wbc_status
);
512 wbc_status
= wbcRequestResponse(WINBINDD_DSGETDCNAME
,
515 BAIL_ON_WBC_ERROR(wbc_status
);
517 dc
->dc_name
= talloc_strdup(dc
, response
.data
.dsgetdcname
.dc_unc
);
518 BAIL_ON_PTR_ERROR(dc
->dc_name
, wbc_status
);
523 if (!WBC_ERROR_IS_OK(wbc_status
)) {
530 static wbcErr
wbc_create_domain_controller_info_ex(TALLOC_CTX
*mem_ctx
,
531 const struct winbindd_response
*resp
,
532 struct wbcDomainControllerInfoEx
**_i
)
534 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
535 struct wbcDomainControllerInfoEx
*i
;
538 i
= talloc(mem_ctx
, struct wbcDomainControllerInfoEx
);
539 BAIL_ON_PTR_ERROR(i
, wbc_status
);
541 i
->dc_unc
= talloc_strdup(i
, resp
->data
.dsgetdcname
.dc_unc
);
542 BAIL_ON_PTR_ERROR(i
->dc_unc
, wbc_status
);
544 i
->dc_address
= talloc_strdup(i
, resp
->data
.dsgetdcname
.dc_address
);
545 BAIL_ON_PTR_ERROR(i
->dc_address
, wbc_status
);
547 i
->dc_address_type
= resp
->data
.dsgetdcname
.dc_address_type
;
549 wbc_status
= wbcStringToGuid(resp
->data
.dsgetdcname
.domain_guid
, &guid
);
550 if (WBC_ERROR_IS_OK(wbc_status
)) {
551 i
->domain_guid
= talloc(i
, struct wbcGuid
);
552 BAIL_ON_PTR_ERROR(i
->domain_guid
, wbc_status
);
554 *i
->domain_guid
= guid
;
556 i
->domain_guid
= NULL
;
559 i
->domain_name
= talloc_strdup(i
, resp
->data
.dsgetdcname
.domain_name
);
560 BAIL_ON_PTR_ERROR(i
->domain_name
, wbc_status
);
562 if (resp
->data
.dsgetdcname
.forest_name
[0] != '\0') {
563 i
->forest_name
= talloc_strdup(i
,
564 resp
->data
.dsgetdcname
.forest_name
);
565 BAIL_ON_PTR_ERROR(i
->forest_name
, wbc_status
);
567 i
->forest_name
= NULL
;
570 i
->dc_flags
= resp
->data
.dsgetdcname
.dc_flags
;
572 if (resp
->data
.dsgetdcname
.dc_site_name
[0] != '\0') {
573 i
->dc_site_name
= talloc_strdup(i
,
574 resp
->data
.dsgetdcname
.dc_site_name
);
575 BAIL_ON_PTR_ERROR(i
->dc_site_name
, wbc_status
);
577 i
->dc_site_name
= NULL
;
580 if (resp
->data
.dsgetdcname
.client_site_name
[0] != '\0') {
581 i
->client_site_name
= talloc_strdup(i
,
582 resp
->data
.dsgetdcname
.client_site_name
);
583 BAIL_ON_PTR_ERROR(i
->client_site_name
, wbc_status
);
585 i
->client_site_name
= NULL
;
596 /* Get extended domain controller information */
597 wbcErr
wbcLookupDomainControllerEx(const char *domain
,
598 struct wbcGuid
*guid
,
601 struct wbcDomainControllerInfoEx
**dc_info
)
603 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
604 struct winbindd_request request
;
605 struct winbindd_response response
;
607 /* validate input params */
609 if (!domain
|| !dc_info
) {
610 wbc_status
= WBC_ERR_INVALID_PARAM
;
611 BAIL_ON_WBC_ERROR(wbc_status
);
614 ZERO_STRUCT(request
);
615 ZERO_STRUCT(response
);
617 request
.data
.dsgetdcname
.flags
= flags
;
619 strncpy(request
.data
.dsgetdcname
.domain_name
, domain
,
620 sizeof(request
.data
.dsgetdcname
.domain_name
)-1);
623 strncpy(request
.data
.dsgetdcname
.site_name
, site
,
624 sizeof(request
.data
.dsgetdcname
.site_name
)-1);
630 wbc_status
= wbcGuidToString(guid
, &str
);
631 BAIL_ON_WBC_ERROR(wbc_status
);
633 strncpy(request
.data
.dsgetdcname
.domain_guid
, str
,
634 sizeof(request
.data
.dsgetdcname
.domain_guid
)-1);
641 wbc_status
= wbcRequestResponse(WINBINDD_DSGETDCNAME
,
644 BAIL_ON_WBC_ERROR(wbc_status
);
647 wbc_status
= wbc_create_domain_controller_info_ex(NULL
,
650 BAIL_ON_WBC_ERROR(wbc_status
);
653 wbc_status
= WBC_ERR_SUCCESS
;
658 /* Initialize a named blob and add to list of blobs */
659 wbcErr
wbcAddNamedBlob(size_t *num_blobs
,
660 struct wbcNamedBlob
**blobs
,
666 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
667 struct wbcNamedBlob blob
;
669 *blobs
= talloc_realloc(NULL
, *blobs
, struct wbcNamedBlob
,
671 BAIL_ON_PTR_ERROR(*blobs
, wbc_status
);
673 blob
.name
= talloc_strdup(*blobs
, name
);
674 BAIL_ON_PTR_ERROR(blob
.name
, wbc_status
);
676 blob
.blob
.length
= length
;
677 blob
.blob
.data
= (uint8_t *)talloc_memdup(*blobs
, data
, length
);
678 BAIL_ON_PTR_ERROR(blob
.blob
.data
, wbc_status
);
680 (*(blobs
))[*num_blobs
] = blob
;
683 wbc_status
= WBC_ERR_SUCCESS
;
685 if (!WBC_ERROR_IS_OK(wbc_status
)) {
686 wbcFreeMemory(*blobs
);