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
);
46 static void wbcInterfaceDetailsDestructor(void *ptr
)
48 struct wbcInterfaceDetails
*i
= (struct wbcInterfaceDetails
*)ptr
;
49 free(i
->winbind_version
);
50 free(i
->netbios_name
);
51 free(i
->netbios_domain
);
56 * @brief Query useful information about the winbind service
58 * @param *_details pointer to hold the struct wbcInterfaceDetails
63 wbcErr
wbcInterfaceDetails(struct wbcInterfaceDetails
**_details
)
65 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
66 struct wbcInterfaceDetails
*info
;
67 struct wbcDomainInfo
*domain
= NULL
;
68 struct winbindd_request request
;
69 struct winbindd_response response
;
71 /* Initialize request */
74 ZERO_STRUCT(response
);
76 info
= (struct wbcInterfaceDetails
*)wbcAllocateMemory(
77 sizeof(struct wbcInterfaceDetails
), 1,
78 wbcInterfaceDetailsDestructor
);
79 BAIL_ON_PTR_ERROR(info
, wbc_status
);
81 /* first the interface version */
82 wbc_status
= wbcRequestResponse(WINBINDD_INTERFACE_VERSION
, NULL
, &response
);
83 BAIL_ON_WBC_ERROR(wbc_status
);
84 info
->interface_version
= response
.data
.interface_version
;
86 /* then the samba version and the winbind separator */
87 wbc_status
= wbcRequestResponse(WINBINDD_INFO
, NULL
, &response
);
88 BAIL_ON_WBC_ERROR(wbc_status
);
90 info
->winbind_version
= strdup(response
.data
.info
.samba_version
);
91 BAIL_ON_PTR_ERROR(info
->winbind_version
, wbc_status
);
92 info
->winbind_separator
= response
.data
.info
.winbind_separator
;
94 /* then the local netbios name */
95 wbc_status
= wbcRequestResponse(WINBINDD_NETBIOS_NAME
, NULL
, &response
);
96 BAIL_ON_WBC_ERROR(wbc_status
);
98 info
->netbios_name
= strdup(response
.data
.netbios_name
);
99 BAIL_ON_PTR_ERROR(info
->netbios_name
, wbc_status
);
101 /* then the local workgroup name */
102 wbc_status
= wbcRequestResponse(WINBINDD_DOMAIN_NAME
, NULL
, &response
);
103 BAIL_ON_WBC_ERROR(wbc_status
);
105 info
->netbios_domain
= strdup(response
.data
.domain_name
);
106 BAIL_ON_PTR_ERROR(info
->netbios_domain
, wbc_status
);
108 wbc_status
= wbcDomainInfo(info
->netbios_domain
, &domain
);
109 if (wbc_status
== WBC_ERR_DOMAIN_NOT_FOUND
) {
110 /* maybe it's a standalone server */
112 wbc_status
= WBC_ERR_SUCCESS
;
114 BAIL_ON_WBC_ERROR(wbc_status
);
118 info
->dns_domain
= strdup(domain
->dns_name
);
119 wbcFreeMemory(domain
);
120 BAIL_ON_PTR_ERROR(info
->dns_domain
, wbc_status
);
122 info
->dns_domain
= NULL
;
128 wbc_status
= WBC_ERR_SUCCESS
;
135 static void wbcDomainInfoDestructor(void *ptr
)
137 struct wbcDomainInfo
*i
= (struct wbcDomainInfo
*)ptr
;
142 /** @brief Lookup the current status of a trusted domain, sync wrapper
144 * @param domain Domain to query
145 * @param *dinfo Pointer to returned struct wbcDomainInfo
150 wbcErr
wbcDomainInfo(const char *domain
, struct wbcDomainInfo
**dinfo
)
152 struct winbindd_request request
;
153 struct winbindd_response response
;
154 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
155 struct wbcDomainInfo
*info
= NULL
;
157 if (!domain
|| !dinfo
) {
158 wbc_status
= WBC_ERR_INVALID_PARAM
;
159 BAIL_ON_WBC_ERROR(wbc_status
);
162 /* Initialize request */
164 ZERO_STRUCT(request
);
165 ZERO_STRUCT(response
);
167 strncpy(request
.domain_name
, domain
,
168 sizeof(request
.domain_name
)-1);
170 wbc_status
= wbcRequestResponse(WINBINDD_DOMAIN_INFO
,
173 BAIL_ON_WBC_ERROR(wbc_status
);
175 info
= (struct wbcDomainInfo
*)wbcAllocateMemory(
176 sizeof(struct wbcDomainInfo
), 1, wbcDomainInfoDestructor
);
177 BAIL_ON_PTR_ERROR(info
, wbc_status
);
179 info
->short_name
= strdup(response
.data
.domain_info
.name
);
180 BAIL_ON_PTR_ERROR(info
->short_name
, wbc_status
);
182 info
->dns_name
= strdup(response
.data
.domain_info
.alt_name
);
183 BAIL_ON_PTR_ERROR(info
->dns_name
, wbc_status
);
185 wbc_status
= wbcStringToSid(response
.data
.domain_info
.sid
,
187 BAIL_ON_WBC_ERROR(wbc_status
);
189 if (response
.data
.domain_info
.native_mode
)
190 info
->domain_flags
|= WBC_DOMINFO_DOMAIN_NATIVE
;
191 if (response
.data
.domain_info
.active_directory
)
192 info
->domain_flags
|= WBC_DOMINFO_DOMAIN_AD
;
193 if (response
.data
.domain_info
.primary
)
194 info
->domain_flags
|= WBC_DOMINFO_DOMAIN_PRIMARY
;
199 wbc_status
= WBC_ERR_SUCCESS
;
207 /* Resolve a NetbiosName via WINS */
208 wbcErr
wbcResolveWinsByName(const char *name
, char **ip
)
210 struct winbindd_request request
;
211 struct winbindd_response response
;
212 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
215 ZERO_STRUCT(request
);
216 ZERO_STRUCT(response
);
220 strncpy(request
.data
.winsreq
, name
,
221 sizeof(request
.data
.winsreq
)-1);
223 wbc_status
= wbcRequestResponse(WINBINDD_WINS_BYNAME
,
226 BAIL_ON_WBC_ERROR(wbc_status
);
228 /* Display response */
230 ipaddr
= talloc_strdup(NULL
, response
.data
.winsresp
);
231 BAIL_ON_PTR_ERROR(ipaddr
, wbc_status
);
234 wbc_status
= WBC_ERR_SUCCESS
;
240 /* Resolve an IP address via WINS into a NetbiosName */
241 wbcErr
wbcResolveWinsByIP(const char *ip
, char **name
)
243 struct winbindd_request request
;
244 struct winbindd_response response
;
245 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
248 ZERO_STRUCT(request
);
249 ZERO_STRUCT(response
);
253 strncpy(request
.data
.winsreq
, ip
,
254 sizeof(request
.data
.winsreq
)-1);
256 wbc_status
= wbcRequestResponse(WINBINDD_WINS_BYIP
,
259 BAIL_ON_WBC_ERROR(wbc_status
);
261 /* Display response */
263 name_str
= talloc_strdup(NULL
, response
.data
.winsresp
);
264 BAIL_ON_PTR_ERROR(name_str
, wbc_status
);
267 wbc_status
= WBC_ERR_SUCCESS
;
276 static wbcErr
process_domain_info_string(TALLOC_CTX
*ctx
,
277 struct wbcDomainInfo
*info
,
280 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
284 if (!info
|| !info_string
) {
285 wbc_status
= WBC_ERR_INVALID_PARAM
;
286 BAIL_ON_WBC_ERROR(wbc_status
);
294 if ((s
= strchr(r
, '\\')) == NULL
) {
295 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
296 BAIL_ON_WBC_ERROR(wbc_status
);
301 info
->short_name
= talloc_strdup(ctx
, r
);
302 BAIL_ON_PTR_ERROR(info
->short_name
, wbc_status
);
307 if ((s
= strchr(r
, '\\')) == NULL
) {
308 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
309 BAIL_ON_WBC_ERROR(wbc_status
);
314 info
->dns_name
= talloc_strdup(ctx
, r
);
315 BAIL_ON_PTR_ERROR(info
->dns_name
, wbc_status
);
319 if ((s
= strchr(r
, '\\')) == NULL
) {
320 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
321 BAIL_ON_WBC_ERROR(wbc_status
);
326 wbc_status
= wbcStringToSid(r
, &info
->sid
);
327 BAIL_ON_WBC_ERROR(wbc_status
);
331 if ((s
= strchr(r
, '\\')) == NULL
) {
332 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
333 BAIL_ON_WBC_ERROR(wbc_status
);
338 if (strcmp(r
, "None") == 0) {
339 info
->trust_type
= WBC_DOMINFO_TRUSTTYPE_NONE
;
340 } else if (strcmp(r
, "External") == 0) {
341 info
->trust_type
= WBC_DOMINFO_TRUSTTYPE_EXTERNAL
;
342 } else if (strcmp(r
, "Forest") == 0) {
343 info
->trust_type
= WBC_DOMINFO_TRUSTTYPE_FOREST
;
344 } else if (strcmp(r
, "In Forest") == 0) {
345 info
->trust_type
= WBC_DOMINFO_TRUSTTYPE_IN_FOREST
;
347 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
348 BAIL_ON_WBC_ERROR(wbc_status
);
353 if ((s
= strchr(r
, '\\')) == NULL
) {
354 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
355 BAIL_ON_WBC_ERROR(wbc_status
);
360 if (strcmp(r
, "Yes") == 0) {
361 info
->trust_flags
|= WBC_DOMINFO_TRUST_TRANSITIVE
;
366 if ((s
= strchr(r
, '\\')) == NULL
) {
367 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
368 BAIL_ON_WBC_ERROR(wbc_status
);
373 if (strcmp(r
, "Yes") == 0) {
374 info
->trust_flags
|= WBC_DOMINFO_TRUST_INCOMING
;
379 if ((s
= strchr(r
, '\\')) == NULL
) {
380 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
381 BAIL_ON_WBC_ERROR(wbc_status
);
386 if (strcmp(r
, "Yes") == 0) {
387 info
->trust_flags
|= WBC_DOMINFO_TRUST_OUTGOING
;
390 /* Online/Offline status */
394 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
395 BAIL_ON_WBC_ERROR(wbc_status
);
397 if ( strcmp(r
, "Offline") == 0) {
398 info
->domain_flags
|= WBC_DOMINFO_DOMAIN_OFFLINE
;
401 wbc_status
= WBC_ERR_SUCCESS
;
407 /* Enumerate the domain trusts known by Winbind */
408 wbcErr
wbcListTrusts(struct wbcDomainInfo
**domains
, size_t *num_domains
)
410 struct winbindd_response response
;
411 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
414 char *extra_data
= NULL
;
416 struct wbcDomainInfo
*d_list
= NULL
;
422 ZERO_STRUCT(response
);
426 wbc_status
= wbcRequestResponse(WINBINDD_LIST_TRUSTDOM
,
429 BAIL_ON_WBC_ERROR(wbc_status
);
431 /* Decode the response */
433 p
= (char *)response
.extra_data
.data
;
435 if ((p
== NULL
) || (strlen(p
) == 0)) {
436 /* We should always at least get back our
439 wbc_status
= WBC_ERR_DOMAIN_NOT_FOUND
;
440 BAIL_ON_WBC_ERROR(wbc_status
);
443 /* Count number of domains */
449 if ((q
= strchr(p
, '\n')) != NULL
)
454 d_list
= talloc_array(NULL
, struct wbcDomainInfo
, count
);
455 BAIL_ON_PTR_ERROR(d_list
, wbc_status
);
457 extra_data
= strdup((char*)response
.extra_data
.data
);
458 BAIL_ON_PTR_ERROR(extra_data
, wbc_status
);
462 /* Outer loop processes the list of domain information */
464 for (i
=0; i
<count
&& p
; i
++) {
465 char *next
= strchr(p
, '\n');
472 wbc_status
= process_domain_info_string(d_list
, &d_list
[i
], p
);
473 BAIL_ON_WBC_ERROR(wbc_status
);
483 winbindd_free_response(&response
);
489 /* Enumerate the domain trusts known by Winbind */
490 wbcErr
wbcLookupDomainController(const char *domain
,
492 struct wbcDomainControllerInfo
**dc_info
)
494 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
495 struct winbindd_request request
;
496 struct winbindd_response response
;
497 struct wbcDomainControllerInfo
*dc
= NULL
;
499 /* validate input params */
501 if (!domain
|| !dc_info
) {
502 wbc_status
= WBC_ERR_INVALID_PARAM
;
503 BAIL_ON_WBC_ERROR(wbc_status
);
506 ZERO_STRUCT(request
);
507 ZERO_STRUCT(response
);
509 strncpy(request
.data
.dsgetdcname
.domain_name
, domain
,
510 sizeof(request
.data
.dsgetdcname
.domain_name
)-1);
512 request
.flags
= flags
;
514 dc
= talloc(NULL
, struct wbcDomainControllerInfo
);
515 BAIL_ON_PTR_ERROR(dc
, wbc_status
);
519 wbc_status
= wbcRequestResponse(WINBINDD_DSGETDCNAME
,
522 BAIL_ON_WBC_ERROR(wbc_status
);
524 dc
->dc_name
= talloc_strdup(dc
, response
.data
.dsgetdcname
.dc_unc
);
525 BAIL_ON_PTR_ERROR(dc
->dc_name
, wbc_status
);
530 if (!WBC_ERROR_IS_OK(wbc_status
)) {
537 static wbcErr
wbc_create_domain_controller_info_ex(TALLOC_CTX
*mem_ctx
,
538 const struct winbindd_response
*resp
,
539 struct wbcDomainControllerInfoEx
**_i
)
541 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
542 struct wbcDomainControllerInfoEx
*i
;
545 i
= talloc(mem_ctx
, struct wbcDomainControllerInfoEx
);
546 BAIL_ON_PTR_ERROR(i
, wbc_status
);
548 i
->dc_unc
= talloc_strdup(i
, resp
->data
.dsgetdcname
.dc_unc
);
549 BAIL_ON_PTR_ERROR(i
->dc_unc
, wbc_status
);
551 i
->dc_address
= talloc_strdup(i
, resp
->data
.dsgetdcname
.dc_address
);
552 BAIL_ON_PTR_ERROR(i
->dc_address
, wbc_status
);
554 i
->dc_address_type
= resp
->data
.dsgetdcname
.dc_address_type
;
556 wbc_status
= wbcStringToGuid(resp
->data
.dsgetdcname
.domain_guid
, &guid
);
557 if (WBC_ERROR_IS_OK(wbc_status
)) {
558 i
->domain_guid
= talloc(i
, struct wbcGuid
);
559 BAIL_ON_PTR_ERROR(i
->domain_guid
, wbc_status
);
561 *i
->domain_guid
= guid
;
563 i
->domain_guid
= NULL
;
566 i
->domain_name
= talloc_strdup(i
, resp
->data
.dsgetdcname
.domain_name
);
567 BAIL_ON_PTR_ERROR(i
->domain_name
, wbc_status
);
569 if (resp
->data
.dsgetdcname
.forest_name
[0] != '\0') {
570 i
->forest_name
= talloc_strdup(i
,
571 resp
->data
.dsgetdcname
.forest_name
);
572 BAIL_ON_PTR_ERROR(i
->forest_name
, wbc_status
);
574 i
->forest_name
= NULL
;
577 i
->dc_flags
= resp
->data
.dsgetdcname
.dc_flags
;
579 if (resp
->data
.dsgetdcname
.dc_site_name
[0] != '\0') {
580 i
->dc_site_name
= talloc_strdup(i
,
581 resp
->data
.dsgetdcname
.dc_site_name
);
582 BAIL_ON_PTR_ERROR(i
->dc_site_name
, wbc_status
);
584 i
->dc_site_name
= NULL
;
587 if (resp
->data
.dsgetdcname
.client_site_name
[0] != '\0') {
588 i
->client_site_name
= talloc_strdup(i
,
589 resp
->data
.dsgetdcname
.client_site_name
);
590 BAIL_ON_PTR_ERROR(i
->client_site_name
, wbc_status
);
592 i
->client_site_name
= NULL
;
603 /* Get extended domain controller information */
604 wbcErr
wbcLookupDomainControllerEx(const char *domain
,
605 struct wbcGuid
*guid
,
608 struct wbcDomainControllerInfoEx
**dc_info
)
610 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
611 struct winbindd_request request
;
612 struct winbindd_response response
;
614 /* validate input params */
616 if (!domain
|| !dc_info
) {
617 wbc_status
= WBC_ERR_INVALID_PARAM
;
618 BAIL_ON_WBC_ERROR(wbc_status
);
621 ZERO_STRUCT(request
);
622 ZERO_STRUCT(response
);
624 request
.data
.dsgetdcname
.flags
= flags
;
626 strncpy(request
.data
.dsgetdcname
.domain_name
, domain
,
627 sizeof(request
.data
.dsgetdcname
.domain_name
)-1);
630 strncpy(request
.data
.dsgetdcname
.site_name
, site
,
631 sizeof(request
.data
.dsgetdcname
.site_name
)-1);
637 wbc_status
= wbcGuidToString(guid
, &str
);
638 BAIL_ON_WBC_ERROR(wbc_status
);
640 strncpy(request
.data
.dsgetdcname
.domain_guid
, str
,
641 sizeof(request
.data
.dsgetdcname
.domain_guid
)-1);
648 wbc_status
= wbcRequestResponse(WINBINDD_DSGETDCNAME
,
651 BAIL_ON_WBC_ERROR(wbc_status
);
654 wbc_status
= wbc_create_domain_controller_info_ex(NULL
,
657 BAIL_ON_WBC_ERROR(wbc_status
);
660 wbc_status
= WBC_ERR_SUCCESS
;
665 /* Initialize a named blob and add to list of blobs */
666 wbcErr
wbcAddNamedBlob(size_t *num_blobs
,
667 struct wbcNamedBlob
**blobs
,
673 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
674 struct wbcNamedBlob blob
;
676 *blobs
= talloc_realloc(NULL
, *blobs
, struct wbcNamedBlob
,
678 BAIL_ON_PTR_ERROR(*blobs
, wbc_status
);
680 blob
.name
= talloc_strdup(*blobs
, name
);
681 BAIL_ON_PTR_ERROR(blob
.name
, wbc_status
);
683 blob
.blob
.length
= length
;
684 blob
.blob
.data
= (uint8_t *)talloc_memdup(*blobs
, data
, length
);
685 BAIL_ON_PTR_ERROR(blob
.blob
.data
, wbc_status
);
687 (*(blobs
))[*num_blobs
] = blob
;
690 wbc_status
= WBC_ERR_SUCCESS
;
692 if (!WBC_ERROR_IS_OK(wbc_status
)) {
693 wbcFreeMemory(*blobs
);