2 Unix SMB/CIFS implementation.
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 */
25 #include "libwbclient.h"
29 /** @brief Ping winbindd to see if the daemon is running
36 struct winbindd_request request
;
37 struct winbindd_response response
;
39 /* Initialize request */
42 ZERO_STRUCT(response
);
44 return wbcRequestResponse(WINBINDD_PING
, &request
, &response
);
47 wbcErr
wbcInterfaceDetails(struct wbcInterfaceDetails
**_details
)
49 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
50 struct wbcInterfaceDetails
*info
;
51 struct wbcDomainInfo
*domain
= NULL
;
52 struct winbindd_request request
;
53 struct winbindd_response response
;
55 /* Initialize request */
58 ZERO_STRUCT(response
);
60 info
= talloc(NULL
, struct wbcInterfaceDetails
);
61 BAIL_ON_PTR_ERROR(info
, wbc_status
);
63 /* first the interface version */
64 wbc_status
= wbcRequestResponse(WINBINDD_INTERFACE_VERSION
, NULL
, &response
);
65 BAIL_ON_WBC_ERROR(wbc_status
);
66 info
->interface_version
= response
.data
.interface_version
;
68 /* then the samba version and the winbind separator */
69 wbc_status
= wbcRequestResponse(WINBINDD_INFO
, NULL
, &response
);
70 BAIL_ON_WBC_ERROR(wbc_status
);
72 info
->winbind_version
= talloc_strdup(info
,
73 response
.data
.info
.samba_version
);
74 BAIL_ON_PTR_ERROR(info
->winbind_version
, wbc_status
);
75 info
->winbind_separator
= response
.data
.info
.winbind_separator
;
77 /* then the local netbios name */
78 wbc_status
= wbcRequestResponse(WINBINDD_NETBIOS_NAME
, NULL
, &response
);
79 BAIL_ON_WBC_ERROR(wbc_status
);
81 info
->netbios_name
= talloc_strdup(info
,
82 response
.data
.netbios_name
);
83 BAIL_ON_PTR_ERROR(info
->netbios_name
, wbc_status
);
85 /* then the local workgroup name */
86 wbc_status
= wbcRequestResponse(WINBINDD_DOMAIN_NAME
, NULL
, &response
);
87 BAIL_ON_WBC_ERROR(wbc_status
);
89 info
->netbios_domain
= talloc_strdup(info
,
90 response
.data
.domain_name
);
91 BAIL_ON_PTR_ERROR(info
->netbios_domain
, wbc_status
);
93 wbc_status
= wbcDomainInfo(info
->netbios_domain
, &domain
);
94 if (wbc_status
== WBC_ERR_DOMAIN_NOT_FOUND
) {
95 /* maybe it's a standalone server */
97 wbc_status
= WBC_ERR_SUCCESS
;
99 BAIL_ON_WBC_ERROR(wbc_status
);
103 info
->dns_domain
= talloc_strdup(info
,
105 wbcFreeMemory(domain
);
106 BAIL_ON_PTR_ERROR(info
->dns_domain
, wbc_status
);
108 info
->dns_domain
= NULL
;
114 wbc_status
= WBC_ERR_SUCCESS
;
122 /* Lookup the current status of a trusted domain */
123 wbcErr
wbcDomainInfo(const char *domain
, struct wbcDomainInfo
**dinfo
)
125 struct winbindd_request request
;
126 struct winbindd_response response
;
127 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
128 struct wbcDomainInfo
*info
= NULL
;
130 if (!domain
|| !dinfo
) {
131 wbc_status
= WBC_ERR_INVALID_PARAM
;
132 BAIL_ON_WBC_ERROR(wbc_status
);
135 /* Initialize request */
137 ZERO_STRUCT(request
);
138 ZERO_STRUCT(response
);
140 strncpy(request
.domain_name
, domain
,
141 sizeof(request
.domain_name
)-1);
143 wbc_status
= wbcRequestResponse(WINBINDD_DOMAIN_INFO
,
146 BAIL_ON_WBC_ERROR(wbc_status
);
148 info
= talloc(NULL
, struct wbcDomainInfo
);
149 BAIL_ON_PTR_ERROR(info
, wbc_status
);
151 info
->short_name
= talloc_strdup(info
,
152 response
.data
.domain_info
.name
);
153 BAIL_ON_PTR_ERROR(info
->short_name
, wbc_status
);
155 info
->dns_name
= talloc_strdup(info
,
156 response
.data
.domain_info
.alt_name
);
157 BAIL_ON_PTR_ERROR(info
->dns_name
, wbc_status
);
159 wbc_status
= wbcStringToSid(response
.data
.domain_info
.sid
,
161 BAIL_ON_WBC_ERROR(wbc_status
);
163 if (response
.data
.domain_info
.native_mode
)
164 info
->domain_flags
|= WBC_DOMINFO_DOMAIN_NATIVE
;
165 if (response
.data
.domain_info
.active_directory
)
166 info
->domain_flags
|= WBC_DOMINFO_DOMAIN_AD
;
167 if (response
.data
.domain_info
.primary
)
168 info
->domain_flags
|= WBC_DOMINFO_DOMAIN_PRIMARY
;
172 wbc_status
= WBC_ERR_SUCCESS
;
175 if (!WBC_ERROR_IS_OK(wbc_status
)) {
183 /* Resolve a NetbiosName via WINS */
184 wbcErr
wbcResolveWinsByName(const char *name
, char **ip
)
186 struct winbindd_request request
;
187 struct winbindd_response response
;
188 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
191 ZERO_STRUCT(request
);
192 ZERO_STRUCT(response
);
196 strncpy(request
.data
.winsreq
, name
,
197 sizeof(request
.data
.winsreq
)-1);
199 wbc_status
= wbcRequestResponse(WINBINDD_WINS_BYNAME
,
202 BAIL_ON_WBC_ERROR(wbc_status
);
204 /* Display response */
206 ipaddr
= talloc_strdup(NULL
, response
.data
.winsresp
);
207 BAIL_ON_PTR_ERROR(ipaddr
, wbc_status
);
210 wbc_status
= WBC_ERR_SUCCESS
;
216 /* Resolve an IP address via WINS into a NetbiosName */
217 wbcErr
wbcResolveWinsByIP(const char *ip
, char **name
)
219 struct winbindd_request request
;
220 struct winbindd_response response
;
221 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
224 ZERO_STRUCT(request
);
225 ZERO_STRUCT(response
);
229 strncpy(request
.data
.winsreq
, ip
,
230 sizeof(request
.data
.winsreq
)-1);
232 wbc_status
= wbcRequestResponse(WINBINDD_WINS_BYIP
,
235 BAIL_ON_WBC_ERROR(wbc_status
);
237 /* Display response */
239 name_str
= talloc_strdup(NULL
, response
.data
.winsresp
);
240 BAIL_ON_PTR_ERROR(name_str
, wbc_status
);
243 wbc_status
= WBC_ERR_SUCCESS
;
252 static wbcErr
process_domain_info_string(TALLOC_CTX
*ctx
,
253 struct wbcDomainInfo
*info
,
256 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
260 if (!info
|| !info_string
) {
261 wbc_status
= WBC_ERR_INVALID_PARAM
;
262 BAIL_ON_WBC_ERROR(wbc_status
);
270 if ((s
= strchr(r
, '\\')) == NULL
) {
271 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
272 BAIL_ON_WBC_ERROR(wbc_status
);
277 info
->short_name
= talloc_strdup(ctx
, r
);
278 BAIL_ON_PTR_ERROR(info
->short_name
, wbc_status
);
283 if ((s
= strchr(r
, '\\')) == NULL
) {
284 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
285 BAIL_ON_WBC_ERROR(wbc_status
);
290 info
->dns_name
= talloc_strdup(ctx
, r
);
291 BAIL_ON_PTR_ERROR(info
->dns_name
, wbc_status
);
295 if ((s
= strchr(r
, '\\')) == NULL
) {
296 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
297 BAIL_ON_WBC_ERROR(wbc_status
);
302 wbc_status
= wbcStringToSid(r
, &info
->sid
);
303 BAIL_ON_WBC_ERROR(wbc_status
);
307 if ((s
= strchr(r
, '\\')) == NULL
) {
308 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
309 BAIL_ON_WBC_ERROR(wbc_status
);
314 if (strcmp(r
, "None") == 0) {
315 info
->trust_type
= WBC_DOMINFO_TRUSTTYPE_NONE
;
316 } else if (strcmp(r
, "External") == 0) {
317 info
->trust_type
= WBC_DOMINFO_TRUSTTYPE_EXTERNAL
;
318 } else if (strcmp(r
, "Forest") == 0) {
319 info
->trust_type
= WBC_DOMINFO_TRUSTTYPE_FOREST
;
320 } else if (strcmp(r
, "In Forest") == 0) {
321 info
->trust_type
= WBC_DOMINFO_TRUSTTYPE_IN_FOREST
;
323 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
324 BAIL_ON_WBC_ERROR(wbc_status
);
329 if ((s
= strchr(r
, '\\')) == NULL
) {
330 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
331 BAIL_ON_WBC_ERROR(wbc_status
);
336 if (strcmp(r
, "Yes") == 0) {
337 info
->trust_flags
|= WBC_DOMINFO_TRUST_TRANSITIVE
;
342 if ((s
= strchr(r
, '\\')) == NULL
) {
343 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
344 BAIL_ON_WBC_ERROR(wbc_status
);
349 if (strcmp(r
, "Yes") == 0) {
350 info
->trust_flags
|= WBC_DOMINFO_TRUST_INCOMING
;
355 if ((s
= strchr(r
, '\\')) == NULL
) {
356 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
357 BAIL_ON_WBC_ERROR(wbc_status
);
362 if (strcmp(r
, "Yes") == 0) {
363 info
->trust_flags
|= WBC_DOMINFO_TRUST_OUTGOING
;
366 /* Online/Offline status */
370 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
371 BAIL_ON_WBC_ERROR(wbc_status
);
373 if ( strcmp(r
, "Offline") == 0) {
374 info
->domain_flags
|= WBC_DOMINFO_DOMAIN_OFFLINE
;
377 wbc_status
= WBC_ERR_SUCCESS
;
383 /* Enumerate the domain trusts known by Winbind */
384 wbcErr
wbcListTrusts(struct wbcDomainInfo
**domains
, size_t *num_domains
)
386 struct winbindd_response response
;
387 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
390 char *extra_data
= NULL
;
392 struct wbcDomainInfo
*d_list
= NULL
;
398 ZERO_STRUCT(response
);
402 wbc_status
= wbcRequestResponse(WINBINDD_LIST_TRUSTDOM
,
405 BAIL_ON_WBC_ERROR(wbc_status
);
407 /* Decode the response */
409 p
= (char *)response
.extra_data
.data
;
411 if (strlen(p
) == 0) {
412 /* We should always at least get back our
415 wbc_status
= WBC_ERR_DOMAIN_NOT_FOUND
;
416 BAIL_ON_WBC_ERROR(wbc_status
);
419 /* Count number of domains */
425 if ((q
= strchr(p
, '\n')) != NULL
)
430 d_list
= talloc_array(NULL
, struct wbcDomainInfo
, count
);
431 BAIL_ON_PTR_ERROR(d_list
, wbc_status
);
433 extra_data
= strdup((char*)response
.extra_data
.data
);
434 BAIL_ON_PTR_ERROR(extra_data
, wbc_status
);
438 /* Outer loop processes the list of domain information */
440 for (i
=0; i
<count
&& p
; i
++) {
441 char *next
= strchr(p
, '\n');
448 wbc_status
= process_domain_info_string(d_list
, &d_list
[i
], p
);
449 BAIL_ON_WBC_ERROR(wbc_status
);
458 if (!WBC_ERROR_IS_OK(wbc_status
)) {
468 /* Enumerate the domain trusts known by Winbind */
469 wbcErr
wbcLookupDomainController(const char *domain
,
471 struct wbcDomainControllerInfo
**dc_info
)
473 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
474 struct winbindd_request request
;
475 struct winbindd_response response
;
476 struct wbcDomainControllerInfo
*dc
= NULL
;
478 /* validate input params */
480 if (!domain
|| !dc_info
) {
481 wbc_status
= WBC_ERR_INVALID_PARAM
;
482 BAIL_ON_WBC_ERROR(wbc_status
);
485 ZERO_STRUCT(request
);
486 ZERO_STRUCT(response
);
488 strncpy(request
.domain_name
, domain
, sizeof(request
.domain_name
)-1);
490 request
.flags
= flags
;
492 dc
= talloc(NULL
, struct wbcDomainControllerInfo
);
493 BAIL_ON_PTR_ERROR(dc
, wbc_status
);
497 wbc_status
= wbcRequestResponse(WINBINDD_DSGETDCNAME
,
500 BAIL_ON_WBC_ERROR(wbc_status
);
502 dc
->dc_name
= talloc_strdup(dc
, response
.data
.dc_name
);
503 BAIL_ON_PTR_ERROR(dc
->dc_name
, wbc_status
);
508 if (!WBC_ERROR_IS_OK(wbc_status
)) {
515 static wbcErr
wbc_create_domain_controller_info_ex(TALLOC_CTX
*mem_ctx
,
516 const struct winbindd_response
*resp
,
517 struct wbcDomainControllerInfoEx
**_i
)
519 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
520 struct wbcDomainControllerInfoEx
*i
;
523 i
= talloc(mem_ctx
, struct wbcDomainControllerInfoEx
);
524 BAIL_ON_PTR_ERROR(i
, wbc_status
);
526 i
->dc_unc
= talloc_strdup(i
, resp
->data
.dsgetdcname
.dc_unc
);
527 BAIL_ON_PTR_ERROR(i
->dc_unc
, wbc_status
);
529 i
->dc_address
= talloc_strdup(i
, resp
->data
.dsgetdcname
.dc_address
);
530 BAIL_ON_PTR_ERROR(i
->dc_address
, wbc_status
);
532 i
->dc_address_type
= resp
->data
.dsgetdcname
.dc_address_type
;
534 wbc_status
= wbcStringToGuid(resp
->data
.dsgetdcname
.domain_guid
, &guid
);
535 if (WBC_ERROR_IS_OK(wbc_status
)) {
536 i
->domain_guid
= talloc(i
, struct wbcGuid
);
537 BAIL_ON_PTR_ERROR(i
->domain_guid
, wbc_status
);
539 *i
->domain_guid
= guid
;
541 i
->domain_guid
= NULL
;
544 i
->domain_name
= talloc_strdup(i
, resp
->data
.dsgetdcname
.domain_name
);
545 BAIL_ON_PTR_ERROR(i
->domain_name
, wbc_status
);
547 if (resp
->data
.dsgetdcname
.forest_name
[0] != '\0') {
548 i
->forest_name
= talloc_strdup(i
,
549 resp
->data
.dsgetdcname
.forest_name
);
550 BAIL_ON_PTR_ERROR(i
->forest_name
, wbc_status
);
552 i
->forest_name
= NULL
;
555 i
->dc_flags
= resp
->data
.dsgetdcname
.dc_flags
;
557 if (resp
->data
.dsgetdcname
.dc_site_name
[0] != '\0') {
558 i
->dc_site_name
= talloc_strdup(i
,
559 resp
->data
.dsgetdcname
.dc_site_name
);
560 BAIL_ON_PTR_ERROR(i
->dc_site_name
, wbc_status
);
562 i
->dc_site_name
= NULL
;
565 if (resp
->data
.dsgetdcname
.client_site_name
[0] != '\0') {
566 i
->client_site_name
= talloc_strdup(i
,
567 resp
->data
.dsgetdcname
.client_site_name
);
568 BAIL_ON_PTR_ERROR(i
->client_site_name
, wbc_status
);
570 i
->client_site_name
= NULL
;
581 /* Get extended domain controller information */
582 wbcErr
wbcLookupDomainControllerEx(const char *domain
,
583 struct wbcGuid
*guid
,
586 struct wbcDomainControllerInfoEx
**dc_info
)
588 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
589 struct winbindd_request request
;
590 struct winbindd_response response
;
592 /* validate input params */
594 if (!domain
|| !dc_info
) {
595 wbc_status
= WBC_ERR_INVALID_PARAM
;
596 BAIL_ON_WBC_ERROR(wbc_status
);
599 ZERO_STRUCT(request
);
600 ZERO_STRUCT(response
);
602 request
.data
.dsgetdcname
.flags
= flags
;
604 strncpy(request
.data
.dsgetdcname
.domain_name
, domain
,
605 sizeof(request
.data
.dsgetdcname
.domain_name
)-1);
608 strncpy(request
.data
.dsgetdcname
.site_name
, site
,
609 sizeof(request
.data
.dsgetdcname
.site_name
)-1);
615 wbc_status
= wbcGuidToString(guid
, &str
);
616 BAIL_ON_WBC_ERROR(wbc_status
);
618 strncpy(request
.data
.dsgetdcname
.domain_guid
, str
,
619 sizeof(request
.data
.dsgetdcname
.domain_guid
)-1);
626 wbc_status
= wbcRequestResponse(WINBINDD_DSGETDCNAME
,
629 BAIL_ON_WBC_ERROR(wbc_status
);
632 wbc_status
= wbc_create_domain_controller_info_ex(NULL
,
635 BAIL_ON_WBC_ERROR(wbc_status
);
638 wbc_status
= WBC_ERR_SUCCESS
;
643 /* Initialize a named blob and add to list of blobs */
644 wbcErr
wbcAddNamedBlob(size_t *num_blobs
,
645 struct wbcNamedBlob
**blobs
,
651 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
652 struct wbcNamedBlob blob
;
654 *blobs
= talloc_realloc(NULL
, *blobs
, struct wbcNamedBlob
,
656 BAIL_ON_PTR_ERROR(*blobs
, wbc_status
);
658 blob
.name
= talloc_strdup(*blobs
, name
);
659 BAIL_ON_PTR_ERROR(blob
.name
, wbc_status
);
661 blob
.blob
.length
= length
;
662 blob
.blob
.data
= (uint8_t *)talloc_memdup(*blobs
, data
, length
);
663 BAIL_ON_PTR_ERROR(blob
.blob
.data
, wbc_status
);
665 (*(blobs
))[*num_blobs
] = blob
;
668 wbc_status
= WBC_ERR_SUCCESS
;
670 if (!WBC_ERROR_IS_OK(wbc_status
) && blobs
) {
671 wbcFreeMemory(*blobs
);