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 */
26 #include "libwbclient.h"
30 /** @brief Ping winbindd to see if the daemon is running
37 struct winbindd_request request
;
38 struct winbindd_response response
;
40 /* Initialize request */
43 ZERO_STRUCT(response
);
45 return wbcRequestResponse(WINBINDD_PING
, &request
, &response
);
48 wbcErr
wbcInterfaceDetails(struct wbcInterfaceDetails
**_details
)
50 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
51 struct wbcInterfaceDetails
*info
;
52 struct wbcDomainInfo
*domain
= NULL
;
53 struct winbindd_request request
;
54 struct winbindd_response response
;
56 /* Initialize request */
59 ZERO_STRUCT(response
);
61 info
= talloc(NULL
, struct wbcInterfaceDetails
);
62 BAIL_ON_PTR_ERROR(info
, wbc_status
);
64 /* first the interface version */
65 wbc_status
= wbcRequestResponse(WINBINDD_INTERFACE_VERSION
, NULL
, &response
);
66 BAIL_ON_WBC_ERROR(wbc_status
);
67 info
->interface_version
= response
.data
.interface_version
;
69 /* then the samba version and the winbind separator */
70 wbc_status
= wbcRequestResponse(WINBINDD_INFO
, NULL
, &response
);
71 BAIL_ON_WBC_ERROR(wbc_status
);
73 info
->winbind_version
= talloc_strdup(info
,
74 response
.data
.info
.samba_version
);
75 BAIL_ON_PTR_ERROR(info
->winbind_version
, wbc_status
);
76 info
->winbind_separator
= response
.data
.info
.winbind_separator
;
78 /* then the local netbios name */
79 wbc_status
= wbcRequestResponse(WINBINDD_NETBIOS_NAME
, NULL
, &response
);
80 BAIL_ON_WBC_ERROR(wbc_status
);
82 info
->netbios_name
= talloc_strdup(info
,
83 response
.data
.netbios_name
);
84 BAIL_ON_PTR_ERROR(info
->netbios_name
, wbc_status
);
86 /* then the local workgroup name */
87 wbc_status
= wbcRequestResponse(WINBINDD_DOMAIN_NAME
, NULL
, &response
);
88 BAIL_ON_WBC_ERROR(wbc_status
);
90 info
->netbios_domain
= talloc_strdup(info
,
91 response
.data
.domain_name
);
92 BAIL_ON_PTR_ERROR(info
->netbios_domain
, wbc_status
);
94 wbc_status
= wbcDomainInfo(info
->netbios_domain
, &domain
);
95 if (wbc_status
== WBC_ERR_DOMAIN_NOT_FOUND
) {
96 /* maybe it's a standalone server */
98 wbc_status
= WBC_ERR_SUCCESS
;
100 BAIL_ON_WBC_ERROR(wbc_status
);
104 info
->dns_domain
= talloc_strdup(info
,
106 wbcFreeMemory(domain
);
107 BAIL_ON_PTR_ERROR(info
->dns_domain
, wbc_status
);
109 info
->dns_domain
= NULL
;
115 wbc_status
= WBC_ERR_SUCCESS
;
123 /* Lookup the current status of a trusted domain */
124 wbcErr
wbcDomainInfo(const char *domain
, struct wbcDomainInfo
**dinfo
)
126 struct winbindd_request request
;
127 struct winbindd_response response
;
128 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
129 struct wbcDomainInfo
*info
= NULL
;
131 if (!domain
|| !dinfo
) {
132 wbc_status
= WBC_ERR_INVALID_PARAM
;
133 BAIL_ON_WBC_ERROR(wbc_status
);
136 /* Initialize request */
138 ZERO_STRUCT(request
);
139 ZERO_STRUCT(response
);
141 strncpy(request
.domain_name
, domain
,
142 sizeof(request
.domain_name
)-1);
144 wbc_status
= wbcRequestResponse(WINBINDD_DOMAIN_INFO
,
147 BAIL_ON_WBC_ERROR(wbc_status
);
149 info
= talloc(NULL
, struct wbcDomainInfo
);
150 BAIL_ON_PTR_ERROR(info
, wbc_status
);
152 info
->short_name
= talloc_strdup(info
,
153 response
.data
.domain_info
.name
);
154 BAIL_ON_PTR_ERROR(info
->short_name
, wbc_status
);
156 info
->dns_name
= talloc_strdup(info
,
157 response
.data
.domain_info
.alt_name
);
158 BAIL_ON_PTR_ERROR(info
->dns_name
, wbc_status
);
160 wbc_status
= wbcStringToSid(response
.data
.domain_info
.sid
,
162 BAIL_ON_WBC_ERROR(wbc_status
);
164 if (response
.data
.domain_info
.native_mode
)
165 info
->domain_flags
|= WBC_DOMINFO_DOMAIN_NATIVE
;
166 if (response
.data
.domain_info
.active_directory
)
167 info
->domain_flags
|= WBC_DOMINFO_DOMAIN_AD
;
168 if (response
.data
.domain_info
.primary
)
169 info
->domain_flags
|= WBC_DOMINFO_DOMAIN_PRIMARY
;
173 wbc_status
= WBC_ERR_SUCCESS
;
176 if (!WBC_ERROR_IS_OK(wbc_status
)) {
184 /* Resolve a NetbiosName via WINS */
185 wbcErr
wbcResolveWinsByName(const char *name
, char **ip
)
187 struct winbindd_request request
;
188 struct winbindd_response response
;
189 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
192 ZERO_STRUCT(request
);
193 ZERO_STRUCT(response
);
197 strncpy(request
.data
.winsreq
, name
,
198 sizeof(request
.data
.winsreq
)-1);
200 wbc_status
= wbcRequestResponse(WINBINDD_WINS_BYNAME
,
203 BAIL_ON_WBC_ERROR(wbc_status
);
205 /* Display response */
207 ipaddr
= talloc_strdup(NULL
, response
.data
.winsresp
);
208 BAIL_ON_PTR_ERROR(ipaddr
, wbc_status
);
211 wbc_status
= WBC_ERR_SUCCESS
;
217 /* Resolve an IP address via WINS into a NetbiosName */
218 wbcErr
wbcResolveWinsByIP(const char *ip
, char **name
)
220 struct winbindd_request request
;
221 struct winbindd_response response
;
222 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
225 ZERO_STRUCT(request
);
226 ZERO_STRUCT(response
);
230 strncpy(request
.data
.winsreq
, ip
,
231 sizeof(request
.data
.winsreq
)-1);
233 wbc_status
= wbcRequestResponse(WINBINDD_WINS_BYIP
,
236 BAIL_ON_WBC_ERROR(wbc_status
);
238 /* Display response */
240 name_str
= talloc_strdup(NULL
, response
.data
.winsresp
);
241 BAIL_ON_PTR_ERROR(name_str
, wbc_status
);
244 wbc_status
= WBC_ERR_SUCCESS
;
253 static wbcErr
process_domain_info_string(TALLOC_CTX
*ctx
,
254 struct wbcDomainInfo
*info
,
257 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
261 if (!info
|| !info_string
) {
262 wbc_status
= WBC_ERR_INVALID_PARAM
;
263 BAIL_ON_WBC_ERROR(wbc_status
);
271 if ((s
= strchr(r
, '\\')) == NULL
) {
272 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
273 BAIL_ON_WBC_ERROR(wbc_status
);
278 info
->short_name
= talloc_strdup(ctx
, r
);
279 BAIL_ON_PTR_ERROR(info
->short_name
, wbc_status
);
284 if ((s
= strchr(r
, '\\')) == NULL
) {
285 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
286 BAIL_ON_WBC_ERROR(wbc_status
);
291 info
->dns_name
= talloc_strdup(ctx
, r
);
292 BAIL_ON_PTR_ERROR(info
->dns_name
, wbc_status
);
296 if ((s
= strchr(r
, '\\')) == NULL
) {
297 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
298 BAIL_ON_WBC_ERROR(wbc_status
);
303 wbc_status
= wbcStringToSid(r
, &info
->sid
);
304 BAIL_ON_WBC_ERROR(wbc_status
);
308 if ((s
= strchr(r
, '\\')) == NULL
) {
309 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
310 BAIL_ON_WBC_ERROR(wbc_status
);
315 if (strcmp(r
, "None") == 0) {
316 info
->trust_type
= WBC_DOMINFO_TRUSTTYPE_NONE
;
317 } else if (strcmp(r
, "External") == 0) {
318 info
->trust_type
= WBC_DOMINFO_TRUSTTYPE_EXTERNAL
;
319 } else if (strcmp(r
, "Forest") == 0) {
320 info
->trust_type
= WBC_DOMINFO_TRUSTTYPE_FOREST
;
321 } else if (strcmp(r
, "In Forest") == 0) {
322 info
->trust_type
= WBC_DOMINFO_TRUSTTYPE_IN_FOREST
;
324 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
325 BAIL_ON_WBC_ERROR(wbc_status
);
330 if ((s
= strchr(r
, '\\')) == NULL
) {
331 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
332 BAIL_ON_WBC_ERROR(wbc_status
);
337 if (strcmp(r
, "Yes") == 0) {
338 info
->trust_flags
|= WBC_DOMINFO_TRUST_TRANSITIVE
;
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_INCOMING
;
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_OUTGOING
;
367 /* Online/Offline status */
371 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
372 BAIL_ON_WBC_ERROR(wbc_status
);
374 if ( strcmp(r
, "Offline") == 0) {
375 info
->domain_flags
|= WBC_DOMINFO_DOMAIN_OFFLINE
;
378 wbc_status
= WBC_ERR_SUCCESS
;
384 /* Enumerate the domain trusts known by Winbind */
385 wbcErr
wbcListTrusts(struct wbcDomainInfo
**domains
, size_t *num_domains
)
387 struct winbindd_response response
;
388 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
391 char *extra_data
= NULL
;
393 struct wbcDomainInfo
*d_list
= NULL
;
399 ZERO_STRUCT(response
);
403 wbc_status
= wbcRequestResponse(WINBINDD_LIST_TRUSTDOM
,
406 BAIL_ON_WBC_ERROR(wbc_status
);
408 /* Decode the response */
410 p
= (char *)response
.extra_data
.data
;
412 if ((p
== NULL
) || (strlen(p
) == 0)) {
413 /* We should always at least get back our
416 wbc_status
= WBC_ERR_DOMAIN_NOT_FOUND
;
417 BAIL_ON_WBC_ERROR(wbc_status
);
420 /* Count number of domains */
426 if ((q
= strchr(p
, '\n')) != NULL
)
431 d_list
= talloc_array(NULL
, struct wbcDomainInfo
, count
);
432 BAIL_ON_PTR_ERROR(d_list
, wbc_status
);
434 extra_data
= strdup((char*)response
.extra_data
.data
);
435 BAIL_ON_PTR_ERROR(extra_data
, wbc_status
);
439 /* Outer loop processes the list of domain information */
441 for (i
=0; i
<count
&& p
; i
++) {
442 char *next
= strchr(p
, '\n');
449 wbc_status
= process_domain_info_string(d_list
, &d_list
[i
], p
);
450 BAIL_ON_WBC_ERROR(wbc_status
);
459 if (!WBC_ERROR_IS_OK(wbc_status
)) {
469 /* Enumerate the domain trusts known by Winbind */
470 wbcErr
wbcLookupDomainController(const char *domain
,
472 struct wbcDomainControllerInfo
**dc_info
)
474 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
475 struct winbindd_request request
;
476 struct winbindd_response response
;
477 struct wbcDomainControllerInfo
*dc
= NULL
;
479 /* validate input params */
481 if (!domain
|| !dc_info
) {
482 wbc_status
= WBC_ERR_INVALID_PARAM
;
483 BAIL_ON_WBC_ERROR(wbc_status
);
486 ZERO_STRUCT(request
);
487 ZERO_STRUCT(response
);
489 strncpy(request
.domain_name
, domain
, sizeof(request
.domain_name
)-1);
491 request
.flags
= flags
;
493 dc
= talloc(NULL
, struct wbcDomainControllerInfo
);
494 BAIL_ON_PTR_ERROR(dc
, wbc_status
);
498 wbc_status
= wbcRequestResponse(WINBINDD_DSGETDCNAME
,
501 BAIL_ON_WBC_ERROR(wbc_status
);
503 dc
->dc_name
= talloc_strdup(dc
, response
.data
.dc_name
);
504 BAIL_ON_PTR_ERROR(dc
->dc_name
, wbc_status
);
509 if (!WBC_ERROR_IS_OK(wbc_status
)) {
516 static wbcErr
wbc_create_domain_controller_info_ex(TALLOC_CTX
*mem_ctx
,
517 const struct winbindd_response
*resp
,
518 struct wbcDomainControllerInfoEx
**_i
)
520 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
521 struct wbcDomainControllerInfoEx
*i
;
524 i
= talloc(mem_ctx
, struct wbcDomainControllerInfoEx
);
525 BAIL_ON_PTR_ERROR(i
, wbc_status
);
527 i
->dc_unc
= talloc_strdup(i
, resp
->data
.dsgetdcname
.dc_unc
);
528 BAIL_ON_PTR_ERROR(i
->dc_unc
, wbc_status
);
530 i
->dc_address
= talloc_strdup(i
, resp
->data
.dsgetdcname
.dc_address
);
531 BAIL_ON_PTR_ERROR(i
->dc_address
, wbc_status
);
533 i
->dc_address_type
= resp
->data
.dsgetdcname
.dc_address_type
;
535 wbc_status
= wbcStringToGuid(resp
->data
.dsgetdcname
.domain_guid
, &guid
);
536 if (WBC_ERROR_IS_OK(wbc_status
)) {
537 i
->domain_guid
= talloc(i
, struct wbcGuid
);
538 BAIL_ON_PTR_ERROR(i
->domain_guid
, wbc_status
);
540 *i
->domain_guid
= guid
;
542 i
->domain_guid
= NULL
;
545 i
->domain_name
= talloc_strdup(i
, resp
->data
.dsgetdcname
.domain_name
);
546 BAIL_ON_PTR_ERROR(i
->domain_name
, wbc_status
);
548 if (resp
->data
.dsgetdcname
.forest_name
[0] != '\0') {
549 i
->forest_name
= talloc_strdup(i
,
550 resp
->data
.dsgetdcname
.forest_name
);
551 BAIL_ON_PTR_ERROR(i
->forest_name
, wbc_status
);
553 i
->forest_name
= NULL
;
556 i
->dc_flags
= resp
->data
.dsgetdcname
.dc_flags
;
558 if (resp
->data
.dsgetdcname
.dc_site_name
[0] != '\0') {
559 i
->dc_site_name
= talloc_strdup(i
,
560 resp
->data
.dsgetdcname
.dc_site_name
);
561 BAIL_ON_PTR_ERROR(i
->dc_site_name
, wbc_status
);
563 i
->dc_site_name
= NULL
;
566 if (resp
->data
.dsgetdcname
.client_site_name
[0] != '\0') {
567 i
->client_site_name
= talloc_strdup(i
,
568 resp
->data
.dsgetdcname
.client_site_name
);
569 BAIL_ON_PTR_ERROR(i
->client_site_name
, wbc_status
);
571 i
->client_site_name
= NULL
;
582 /* Get extended domain controller information */
583 wbcErr
wbcLookupDomainControllerEx(const char *domain
,
584 struct wbcGuid
*guid
,
587 struct wbcDomainControllerInfoEx
**dc_info
)
589 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
590 struct winbindd_request request
;
591 struct winbindd_response response
;
593 /* validate input params */
595 if (!domain
|| !dc_info
) {
596 wbc_status
= WBC_ERR_INVALID_PARAM
;
597 BAIL_ON_WBC_ERROR(wbc_status
);
600 ZERO_STRUCT(request
);
601 ZERO_STRUCT(response
);
603 request
.data
.dsgetdcname
.flags
= flags
;
605 strncpy(request
.data
.dsgetdcname
.domain_name
, domain
,
606 sizeof(request
.data
.dsgetdcname
.domain_name
)-1);
609 strncpy(request
.data
.dsgetdcname
.site_name
, site
,
610 sizeof(request
.data
.dsgetdcname
.site_name
)-1);
616 wbc_status
= wbcGuidToString(guid
, &str
);
617 BAIL_ON_WBC_ERROR(wbc_status
);
619 strncpy(request
.data
.dsgetdcname
.domain_guid
, str
,
620 sizeof(request
.data
.dsgetdcname
.domain_guid
)-1);
627 wbc_status
= wbcRequestResponse(WINBINDD_DSGETDCNAME
,
630 BAIL_ON_WBC_ERROR(wbc_status
);
633 wbc_status
= wbc_create_domain_controller_info_ex(NULL
,
636 BAIL_ON_WBC_ERROR(wbc_status
);
639 wbc_status
= WBC_ERR_SUCCESS
;
644 /* Initialize a named blob and add to list of blobs */
645 wbcErr
wbcAddNamedBlob(size_t *num_blobs
,
646 struct wbcNamedBlob
**blobs
,
652 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
653 struct wbcNamedBlob blob
;
655 *blobs
= talloc_realloc(NULL
, *blobs
, struct wbcNamedBlob
,
657 BAIL_ON_PTR_ERROR(*blobs
, wbc_status
);
659 blob
.name
= talloc_strdup(*blobs
, name
);
660 BAIL_ON_PTR_ERROR(blob
.name
, wbc_status
);
662 blob
.blob
.length
= length
;
663 blob
.blob
.data
= (uint8_t *)talloc_memdup(*blobs
, data
, length
);
664 BAIL_ON_PTR_ERROR(blob
.blob
.data
, wbc_status
);
666 (*(blobs
))[*num_blobs
] = blob
;
669 wbc_status
= WBC_ERR_SUCCESS
;
671 if (!WBC_ERROR_IS_OK(wbc_status
) && blobs
) {
672 wbcFreeMemory(*blobs
);