s4:libnet_become_dc - change counter variables to "unsigned" where they count LDB...
[Samba/kamenim.git] / nsswitch / libwbclient / wbc_util.c
blob2a1285e9169653429bf2ba95d4a8b024ef7543e2
1 /*
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 */
25 #include "replace.h"
26 #include "libwbclient.h"
28 /** @brief Ping winbindd to see if the daemon is running
30 * @return #wbcErr
31 **/
32 wbcErr wbcPing(void)
34 struct winbindd_request request;
35 struct winbindd_response response;
37 /* Initialize request */
39 ZERO_STRUCT(request);
40 ZERO_STRUCT(response);
42 return wbcRequestResponse(WINBINDD_PING, &request, &response);
46 /**
47 * @brief Query useful information about the winbind service
49 * @param *_details pointer to hold the struct wbcInterfaceDetails
51 * @return #wbcErr
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 */
64 ZERO_STRUCT(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 */
103 domain = NULL;
104 wbc_status = WBC_ERR_SUCCESS;
105 } else {
106 BAIL_ON_WBC_ERROR(wbc_status);
109 if (domain) {
110 info->dns_domain = talloc_strdup(info,
111 domain->dns_name);
112 wbcFreeMemory(domain);
113 BAIL_ON_PTR_ERROR(info->dns_domain, wbc_status);
114 } else {
115 info->dns_domain = NULL;
118 *_details = info;
119 info = NULL;
121 wbc_status = WBC_ERR_SUCCESS;
123 done:
124 talloc_free(info);
125 return wbc_status;
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
134 * @return #wbcErr
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,
158 &request,
159 &response);
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,
174 &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;
184 *dinfo = info;
186 wbc_status = WBC_ERR_SUCCESS;
188 done:
189 if (!WBC_ERROR_IS_OK(wbc_status)) {
190 talloc_free(info);
193 return 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;
203 char *ipaddr;
205 ZERO_STRUCT(request);
206 ZERO_STRUCT(response);
208 /* Send request */
210 strncpy(request.data.winsreq, name,
211 sizeof(request.data.winsreq)-1);
213 wbc_status = wbcRequestResponse(WINBINDD_WINS_BYNAME,
214 &request,
215 &response);
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);
223 *ip = ipaddr;
224 wbc_status = WBC_ERR_SUCCESS;
226 done:
227 return wbc_status;
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;
236 char *name_str;
238 ZERO_STRUCT(request);
239 ZERO_STRUCT(response);
241 /* Send request */
243 strncpy(request.data.winsreq, ip,
244 sizeof(request.data.winsreq)-1);
246 wbc_status = wbcRequestResponse(WINBINDD_WINS_BYIP,
247 &request,
248 &response);
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);
256 *name = name_str;
257 wbc_status = WBC_ERR_SUCCESS;
259 done:
260 return wbc_status;
266 static wbcErr process_domain_info_string(TALLOC_CTX *ctx,
267 struct wbcDomainInfo *info,
268 char *info_string)
270 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
271 char *r = NULL;
272 char *s = NULL;
274 if (!info || !info_string) {
275 wbc_status = WBC_ERR_INVALID_PARAM;
276 BAIL_ON_WBC_ERROR(wbc_status);
279 ZERO_STRUCTP(info);
281 r = info_string;
283 /* Short Name */
284 if ((s = strchr(r, '\\')) == NULL) {
285 wbc_status = WBC_ERR_INVALID_RESPONSE;
286 BAIL_ON_WBC_ERROR(wbc_status);
288 *s = '\0';
289 s++;
291 info->short_name = talloc_strdup(ctx, r);
292 BAIL_ON_PTR_ERROR(info->short_name, wbc_status);
295 /* DNS Name */
296 r = s;
297 if ((s = strchr(r, '\\')) == NULL) {
298 wbc_status = WBC_ERR_INVALID_RESPONSE;
299 BAIL_ON_WBC_ERROR(wbc_status);
301 *s = '\0';
302 s++;
304 info->dns_name = talloc_strdup(ctx, r);
305 BAIL_ON_PTR_ERROR(info->dns_name, wbc_status);
307 /* SID */
308 r = s;
309 if ((s = strchr(r, '\\')) == NULL) {
310 wbc_status = WBC_ERR_INVALID_RESPONSE;
311 BAIL_ON_WBC_ERROR(wbc_status);
313 *s = '\0';
314 s++;
316 wbc_status = wbcStringToSid(r, &info->sid);
317 BAIL_ON_WBC_ERROR(wbc_status);
319 /* Trust type */
320 r = s;
321 if ((s = strchr(r, '\\')) == NULL) {
322 wbc_status = WBC_ERR_INVALID_RESPONSE;
323 BAIL_ON_WBC_ERROR(wbc_status);
325 *s = '\0';
326 s++;
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;
336 } else {
337 wbc_status = WBC_ERR_INVALID_RESPONSE;
338 BAIL_ON_WBC_ERROR(wbc_status);
341 /* Transitive */
342 r = s;
343 if ((s = strchr(r, '\\')) == NULL) {
344 wbc_status = WBC_ERR_INVALID_RESPONSE;
345 BAIL_ON_WBC_ERROR(wbc_status);
347 *s = '\0';
348 s++;
350 if (strcmp(r, "Yes") == 0) {
351 info->trust_flags |= WBC_DOMINFO_TRUST_TRANSITIVE;
354 /* Incoming */
355 r = s;
356 if ((s = strchr(r, '\\')) == NULL) {
357 wbc_status = WBC_ERR_INVALID_RESPONSE;
358 BAIL_ON_WBC_ERROR(wbc_status);
360 *s = '\0';
361 s++;
363 if (strcmp(r, "Yes") == 0) {
364 info->trust_flags |= WBC_DOMINFO_TRUST_INCOMING;
367 /* Outgoing */
368 r = s;
369 if ((s = strchr(r, '\\')) == NULL) {
370 wbc_status = WBC_ERR_INVALID_RESPONSE;
371 BAIL_ON_WBC_ERROR(wbc_status);
373 *s = '\0';
374 s++;
376 if (strcmp(r, "Yes") == 0) {
377 info->trust_flags |= WBC_DOMINFO_TRUST_OUTGOING;
380 /* Online/Offline status */
382 r = s;
383 if (r == NULL) {
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;
393 done:
394 return wbc_status;
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;
402 char *p = NULL;
403 char *q = NULL;
404 char *extra_data = NULL;
405 int count = 0;
406 struct wbcDomainInfo *d_list = NULL;
407 int i = 0;
409 *domains = NULL;
410 *num_domains = 0;
412 ZERO_STRUCT(response);
414 /* Send request */
416 wbc_status = wbcRequestResponse(WINBINDD_LIST_TRUSTDOM,
417 NULL,
418 &response);
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
427 own SAM domain */
429 wbc_status = WBC_ERR_DOMAIN_NOT_FOUND;
430 BAIL_ON_WBC_ERROR(wbc_status);
433 /* Count number of domains */
435 count = 0;
436 while (p) {
437 count++;
439 if ((q = strchr(p, '\n')) != NULL)
440 q++;
441 p = q;
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);
450 p = extra_data;
452 /* Outer loop processes the list of domain information */
454 for (i=0; i<count && p; i++) {
455 char *next = strchr(p, '\n');
457 if (next) {
458 *next = '\0';
459 next++;
462 wbc_status = process_domain_info_string(d_list, &d_list[i], p);
463 BAIL_ON_WBC_ERROR(wbc_status);
465 p = next;
468 *domains = d_list;
469 *num_domains = i;
471 done:
472 if (!WBC_ERROR_IS_OK(wbc_status)) {
473 if (d_list)
474 talloc_free(d_list);
475 if (extra_data)
476 free(extra_data);
479 return wbc_status;
482 /* Enumerate the domain trusts known by Winbind */
483 wbcErr wbcLookupDomainController(const char *domain,
484 uint32_t flags,
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);
510 /* Send request */
512 wbc_status = wbcRequestResponse(WINBINDD_DSGETDCNAME,
513 &request,
514 &response);
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);
520 *dc_info = dc;
522 done:
523 if (!WBC_ERROR_IS_OK(wbc_status)) {
524 talloc_free(dc);
527 return 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;
536 struct wbcGuid guid;
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;
555 } else {
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);
566 } else {
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);
576 } else {
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);
584 } else {
585 i->client_site_name = NULL;
588 *_i = i;
589 i = NULL;
591 done:
592 talloc_free(i);
593 return wbc_status;
596 /* Get extended domain controller information */
597 wbcErr wbcLookupDomainControllerEx(const char *domain,
598 struct wbcGuid *guid,
599 const char *site,
600 uint32_t flags,
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);
622 if (site) {
623 strncpy(request.data.dsgetdcname.site_name, site,
624 sizeof(request.data.dsgetdcname.site_name)-1);
627 if (guid) {
628 char *str = NULL;
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);
636 wbcFreeMemory(str);
639 /* Send request */
641 wbc_status = wbcRequestResponse(WINBINDD_DSGETDCNAME,
642 &request,
643 &response);
644 BAIL_ON_WBC_ERROR(wbc_status);
646 if (dc_info) {
647 wbc_status = wbc_create_domain_controller_info_ex(NULL,
648 &response,
649 dc_info);
650 BAIL_ON_WBC_ERROR(wbc_status);
653 wbc_status = WBC_ERR_SUCCESS;
654 done:
655 return wbc_status;
658 /* Initialize a named blob and add to list of blobs */
659 wbcErr wbcAddNamedBlob(size_t *num_blobs,
660 struct wbcNamedBlob **blobs,
661 const char *name,
662 uint32_t flags,
663 uint8_t *data,
664 size_t length)
666 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
667 struct wbcNamedBlob blob;
669 *blobs = talloc_realloc(NULL, *blobs, struct wbcNamedBlob,
670 *(num_blobs)+1);
671 BAIL_ON_PTR_ERROR(*blobs, wbc_status);
673 blob.name = talloc_strdup(*blobs, name);
674 BAIL_ON_PTR_ERROR(blob.name, wbc_status);
675 blob.flags = flags;
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;
681 *(num_blobs) += 1;
683 wbc_status = WBC_ERR_SUCCESS;
684 done:
685 if (!WBC_ERROR_IS_OK(wbc_status)) {
686 wbcFreeMemory(*blobs);
688 return wbc_status;