CVE-2020-1472(ZeroLogon): libcli/auth: make use of netlogon_creds_random_challenge...
[Samba.git] / nsswitch / libwbclient / wbc_util.c
blobbd2d0f8b399730e1b5319572a4d968ec8ffe86e7
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"
27 #include "../winbind_client.h"
29 /** @brief Ping winbindd to see if the daemon is running
31 * @param *ctx wbclient Context
33 * @return #wbcErr
34 **/
35 wbcErr wbcCtxPing(struct wbcContext *ctx)
37 struct winbindd_request request;
38 struct winbindd_response response;
40 /* Initialize request */
42 ZERO_STRUCT(request);
43 ZERO_STRUCT(response);
45 return wbcRequestResponse(ctx, WINBINDD_PING, &request, &response);
48 wbcErr wbcPing(void)
50 return wbcCtxPing(NULL);
53 static void wbcInterfaceDetailsDestructor(void *ptr)
55 struct wbcInterfaceDetails *i = (struct wbcInterfaceDetails *)ptr;
56 free(i->winbind_version);
57 free(i->netbios_name);
58 free(i->netbios_domain);
59 free(i->dns_domain);
62 /**
63 * @brief Query useful information about the winbind service
65 * @param *_details pointer to hold the struct wbcInterfaceDetails
67 * @return #wbcErr
70 wbcErr wbcCtxInterfaceDetails(struct wbcContext *ctx,
71 struct wbcInterfaceDetails **_details)
73 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
74 struct wbcInterfaceDetails *info;
75 struct wbcDomainInfo *domain = NULL;
76 struct winbindd_request request;
77 struct winbindd_response response;
79 /* Initialize request */
81 ZERO_STRUCT(request);
82 ZERO_STRUCT(response);
84 info = (struct wbcInterfaceDetails *)wbcAllocateMemory(
85 1, sizeof(struct wbcInterfaceDetails),
86 wbcInterfaceDetailsDestructor);
87 BAIL_ON_PTR_ERROR(info, wbc_status);
89 /* first the interface version */
90 wbc_status = wbcRequestResponse(ctx, WINBINDD_INTERFACE_VERSION,
91 NULL, &response);
92 BAIL_ON_WBC_ERROR(wbc_status);
93 info->interface_version = response.data.interface_version;
95 /* then the samba version and the winbind separator */
96 wbc_status = wbcRequestResponse(ctx, WINBINDD_INFO, NULL, &response);
97 BAIL_ON_WBC_ERROR(wbc_status);
99 info->winbind_version = strdup(response.data.info.samba_version);
100 BAIL_ON_PTR_ERROR(info->winbind_version, wbc_status);
101 info->winbind_separator = response.data.info.winbind_separator;
103 /* then the local netbios name */
104 wbc_status = wbcRequestResponse(ctx, WINBINDD_NETBIOS_NAME,
105 NULL, &response);
106 BAIL_ON_WBC_ERROR(wbc_status);
108 info->netbios_name = strdup(response.data.netbios_name);
109 BAIL_ON_PTR_ERROR(info->netbios_name, wbc_status);
111 /* then the local workgroup name */
112 wbc_status = wbcRequestResponse(ctx, WINBINDD_DOMAIN_NAME,
113 NULL, &response);
114 BAIL_ON_WBC_ERROR(wbc_status);
116 info->netbios_domain = strdup(response.data.domain_name);
117 BAIL_ON_PTR_ERROR(info->netbios_domain, wbc_status);
119 wbc_status = wbcCtxDomainInfo(ctx, info->netbios_domain, &domain);
120 if (wbc_status == WBC_ERR_DOMAIN_NOT_FOUND) {
121 /* maybe it's a standalone server */
122 domain = NULL;
123 } else {
124 BAIL_ON_WBC_ERROR(wbc_status);
127 if (domain) {
128 info->dns_domain = strdup(domain->dns_name);
129 wbcFreeMemory(domain);
130 BAIL_ON_PTR_ERROR(info->dns_domain, wbc_status);
131 } else {
132 info->dns_domain = NULL;
135 *_details = info;
136 info = NULL;
138 wbc_status = WBC_ERR_SUCCESS;
140 done:
141 wbcFreeMemory(info);
142 return wbc_status;
145 wbcErr wbcInterfaceDetails(struct wbcInterfaceDetails **_details)
147 return wbcCtxInterfaceDetails(NULL, _details);
150 static void wbcDomainInfoDestructor(void *ptr)
152 struct wbcDomainInfo *i = (struct wbcDomainInfo *)ptr;
153 free(i->short_name);
154 free(i->dns_name);
157 /** @brief Lookup the current status of a trusted domain, sync wrapper
159 * @param domain Domain to query
160 * @param *dinfo Pointer to returned struct wbcDomainInfo
162 * @return #wbcErr
165 wbcErr wbcCtxDomainInfo(struct wbcContext *ctx,
166 const char *domain,
167 struct wbcDomainInfo **dinfo)
169 struct winbindd_request request;
170 struct winbindd_response response;
171 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
172 struct wbcDomainInfo *info = NULL;
174 if (!domain || !dinfo) {
175 wbc_status = WBC_ERR_INVALID_PARAM;
176 BAIL_ON_WBC_ERROR(wbc_status);
179 /* Initialize request */
181 ZERO_STRUCT(request);
182 ZERO_STRUCT(response);
184 strncpy(request.domain_name, domain,
185 sizeof(request.domain_name)-1);
187 wbc_status = wbcRequestResponse(ctx, WINBINDD_DOMAIN_INFO,
188 &request,
189 &response);
190 BAIL_ON_WBC_ERROR(wbc_status);
192 info = (struct wbcDomainInfo *)wbcAllocateMemory(
193 1, sizeof(struct wbcDomainInfo), wbcDomainInfoDestructor);
194 BAIL_ON_PTR_ERROR(info, wbc_status);
196 info->short_name = strdup(response.data.domain_info.name);
197 BAIL_ON_PTR_ERROR(info->short_name, wbc_status);
199 info->dns_name = strdup(response.data.domain_info.alt_name);
200 BAIL_ON_PTR_ERROR(info->dns_name, wbc_status);
202 wbc_status = wbcStringToSid(response.data.domain_info.sid,
203 &info->sid);
204 BAIL_ON_WBC_ERROR(wbc_status);
206 if (response.data.domain_info.native_mode)
207 info->domain_flags |= WBC_DOMINFO_DOMAIN_NATIVE;
208 if (response.data.domain_info.active_directory)
209 info->domain_flags |= WBC_DOMINFO_DOMAIN_AD;
210 if (response.data.domain_info.primary)
211 info->domain_flags |= WBC_DOMINFO_DOMAIN_PRIMARY;
213 *dinfo = info;
214 info = NULL;
216 wbc_status = WBC_ERR_SUCCESS;
218 done:
219 wbcFreeMemory(info);
220 return wbc_status;
223 wbcErr wbcDomainInfo(const char *domain, struct wbcDomainInfo **dinfo)
225 return wbcCtxDomainInfo(NULL, domain, dinfo);
228 /* Get the list of current DCs */
229 wbcErr wbcCtxDcInfo(struct wbcContext *ctx,
230 const char *domain, size_t *num_dcs,
231 const char ***dc_names, const char ***dc_ips)
233 struct winbindd_request request;
234 struct winbindd_response response;
235 const char **names = NULL;
236 const char **ips = NULL;
237 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
238 size_t extra_len;
239 int i;
240 char *p;
242 /* Initialise request */
244 ZERO_STRUCT(request);
245 ZERO_STRUCT(response);
247 if (domain != NULL) {
248 strncpy(request.domain_name, domain,
249 sizeof(request.domain_name) - 1);
252 wbc_status = wbcRequestResponse(ctx, WINBINDD_DC_INFO,
253 &request, &response);
254 BAIL_ON_WBC_ERROR(wbc_status);
256 names = wbcAllocateStringArray(response.data.num_entries);
257 BAIL_ON_PTR_ERROR(names, wbc_status);
259 ips = wbcAllocateStringArray(response.data.num_entries);
260 BAIL_ON_PTR_ERROR(ips, wbc_status);
262 wbc_status = WBC_ERR_INVALID_RESPONSE;
264 p = (char *)response.extra_data.data;
266 if (response.length < (sizeof(struct winbindd_response)+1)) {
267 goto done;
270 extra_len = response.length - sizeof(struct winbindd_response);
272 if (p[extra_len-1] != '\0') {
273 goto done;
276 for (i=0; i<response.data.num_entries; i++) {
277 char *q;
279 q = strchr(p, '\n');
280 if (q == NULL) {
281 goto done;
283 names[i] = strndup(p, q-p);
284 BAIL_ON_PTR_ERROR(names[i], wbc_status);
285 p = q+1;
287 q = strchr(p, '\n');
288 if (q == NULL) {
289 goto done;
291 ips[i] = strndup(p, q-p);
292 BAIL_ON_PTR_ERROR(ips[i], wbc_status);
293 p = q+1;
295 if (p[0] != '\0') {
296 goto done;
299 wbc_status = WBC_ERR_SUCCESS;
300 done:
301 if (response.extra_data.data)
302 free(response.extra_data.data);
304 if (WBC_ERROR_IS_OK(wbc_status)) {
305 *num_dcs = response.data.num_entries;
306 *dc_names = names;
307 names = NULL;
308 *dc_ips = ips;
309 ips = NULL;
311 wbcFreeMemory(names);
312 wbcFreeMemory(ips);
313 return wbc_status;
316 wbcErr wbcDcInfo(const char *domain, size_t *num_dcs,
317 const char ***dc_names, const char ***dc_ips)
319 return wbcCtxDcInfo(NULL, domain, num_dcs, dc_names, dc_ips);
322 /* Resolve a NetbiosName via WINS */
323 wbcErr wbcCtxResolveWinsByName(struct wbcContext *ctx,
324 const char *name, char **ip)
326 struct winbindd_request request;
327 struct winbindd_response response;
328 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
329 char *ipaddr;
331 ZERO_STRUCT(request);
332 ZERO_STRUCT(response);
334 /* Send request */
336 strncpy(request.data.winsreq, name,
337 sizeof(request.data.winsreq)-1);
339 wbc_status = wbcRequestResponse(ctx, WINBINDD_WINS_BYNAME,
340 &request,
341 &response);
342 BAIL_ON_WBC_ERROR(wbc_status);
344 /* Display response */
346 ipaddr = wbcStrDup(response.data.winsresp);
347 BAIL_ON_PTR_ERROR(ipaddr, wbc_status);
349 *ip = ipaddr;
350 wbc_status = WBC_ERR_SUCCESS;
352 done:
353 return wbc_status;
356 wbcErr wbcResolveWinsByName(const char *name, char **ip)
358 return wbcCtxResolveWinsByName(NULL, name, ip);
361 /* Resolve an IP address via WINS into a NetbiosName */
362 wbcErr wbcCtxResolveWinsByIP(struct wbcContext *ctx,
363 const char *ip, char **name)
365 struct winbindd_request request;
366 struct winbindd_response response;
367 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
368 char *name_str;
370 ZERO_STRUCT(request);
371 ZERO_STRUCT(response);
373 /* Send request */
375 strncpy(request.data.winsreq, ip,
376 sizeof(request.data.winsreq)-1);
378 wbc_status = wbcRequestResponse(ctx, WINBINDD_WINS_BYIP,
379 &request,
380 &response);
381 BAIL_ON_WBC_ERROR(wbc_status);
383 /* Display response */
385 name_str = wbcStrDup(response.data.winsresp);
386 BAIL_ON_PTR_ERROR(name_str, wbc_status);
388 *name = name_str;
389 wbc_status = WBC_ERR_SUCCESS;
391 done:
392 return wbc_status;
395 wbcErr wbcResolveWinsByIP(const char *ip, char **name)
397 return wbcCtxResolveWinsByIP(NULL, ip, name);
403 static wbcErr process_domain_info_string(struct wbcDomainInfo *info,
404 char *info_string)
406 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
407 char *r = NULL;
408 char *s = NULL;
410 r = info_string;
412 /* Short Name */
413 if ((s = strchr(r, '\\')) == NULL) {
414 wbc_status = WBC_ERR_INVALID_RESPONSE;
415 BAIL_ON_WBC_ERROR(wbc_status);
417 *s = '\0';
418 s++;
420 info->short_name = strdup(r);
421 BAIL_ON_PTR_ERROR(info->short_name, wbc_status);
424 /* DNS Name */
425 r = s;
426 if ((s = strchr(r, '\\')) == NULL) {
427 wbc_status = WBC_ERR_INVALID_RESPONSE;
428 BAIL_ON_WBC_ERROR(wbc_status);
430 *s = '\0';
431 s++;
433 info->dns_name = strdup(r);
434 BAIL_ON_PTR_ERROR(info->dns_name, wbc_status);
436 /* SID */
437 r = s;
438 if ((s = strchr(r, '\\')) == NULL) {
439 wbc_status = WBC_ERR_INVALID_RESPONSE;
440 BAIL_ON_WBC_ERROR(wbc_status);
442 *s = '\0';
443 s++;
445 wbc_status = wbcStringToSid(r, &info->sid);
446 BAIL_ON_WBC_ERROR(wbc_status);
448 /* Trust type */
449 r = s;
450 if ((s = strchr(r, '\\')) == NULL) {
451 wbc_status = WBC_ERR_INVALID_RESPONSE;
452 BAIL_ON_WBC_ERROR(wbc_status);
454 *s = '\0';
455 s++;
457 if (strncmp(r, "Routed", strlen("Routed")) == 0) {
458 info->trust_type = WBC_DOMINFO_TRUSTTYPE_NONE;
459 info->trust_routing = strdup(r);
460 BAIL_ON_PTR_ERROR(info->trust_routing, wbc_status);
461 } else if (strcmp(r, "Local") == 0) {
462 info->trust_type = WBC_DOMINFO_TRUSTTYPE_LOCAL;
463 } else if (strcmp(r, "Workstation") == 0) {
464 info->trust_type = WBC_DOMINFO_TRUSTTYPE_WKSTA;
465 } else if (strcmp(r, "RWDC") == 0) {
466 info->trust_type = WBC_DOMINFO_TRUSTTYPE_RWDC;
467 } else if (strcmp(r, "RODC") == 0) {
468 info->trust_type = WBC_DOMINFO_TRUSTTYPE_RODC;
469 } else if (strcmp(r, "PDC") == 0) {
470 info->trust_type = WBC_DOMINFO_TRUSTTYPE_PDC;
471 } else if (strcmp(r, "External") == 0) {
472 info->trust_type = WBC_DOMINFO_TRUSTTYPE_EXTERNAL;
473 } else if (strcmp(r, "Forest") == 0) {
474 info->trust_type = WBC_DOMINFO_TRUSTTYPE_FOREST;
475 } else if (strcmp(r, "In Forest") == 0) {
476 info->trust_type = WBC_DOMINFO_TRUSTTYPE_IN_FOREST;
477 } else {
478 wbc_status = WBC_ERR_INVALID_RESPONSE;
479 BAIL_ON_WBC_ERROR(wbc_status);
482 /* Transitive */
483 r = s;
484 if ((s = strchr(r, '\\')) == NULL) {
485 wbc_status = WBC_ERR_INVALID_RESPONSE;
486 BAIL_ON_WBC_ERROR(wbc_status);
488 *s = '\0';
489 s++;
491 if (strcmp(r, "Yes") == 0) {
492 info->trust_flags |= WBC_DOMINFO_TRUST_TRANSITIVE;
495 /* Incoming */
496 r = s;
497 if ((s = strchr(r, '\\')) == NULL) {
498 wbc_status = WBC_ERR_INVALID_RESPONSE;
499 BAIL_ON_WBC_ERROR(wbc_status);
501 *s = '\0';
502 s++;
504 if (strcmp(r, "Yes") == 0) {
505 info->trust_flags |= WBC_DOMINFO_TRUST_INCOMING;
508 /* Outgoing */
509 r = s;
510 if ((s = strchr(r, '\\')) == NULL) {
511 wbc_status = WBC_ERR_INVALID_RESPONSE;
512 BAIL_ON_WBC_ERROR(wbc_status);
514 *s = '\0';
515 s++;
517 if (strcmp(r, "Yes") == 0) {
518 info->trust_flags |= WBC_DOMINFO_TRUST_OUTGOING;
521 /* Online/Offline status */
522 r = s;
523 if ( strcmp(r, "Offline") == 0) {
524 info->domain_flags |= WBC_DOMINFO_DOMAIN_OFFLINE;
527 wbc_status = WBC_ERR_SUCCESS;
529 done:
530 return wbc_status;
533 static void wbcDomainInfoListDestructor(void *ptr)
535 struct wbcDomainInfo *i = (struct wbcDomainInfo *)ptr;
537 while (i->short_name != NULL) {
538 free(i->short_name);
539 free(i->dns_name);
540 i += 1;
544 /* Enumerate the domain trusts known by Winbind */
545 wbcErr wbcCtxListTrusts(struct wbcContext *ctx,
546 struct wbcDomainInfo **domains, size_t *num_domains)
548 struct winbindd_response response;
549 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
550 char *p = NULL;
551 char *extra_data = NULL;
552 struct wbcDomainInfo *d_list = NULL;
553 int i = 0;
555 *domains = NULL;
556 *num_domains = 0;
558 ZERO_STRUCT(response);
560 /* Send request */
562 wbc_status = wbcRequestResponse(ctx, WINBINDD_LIST_TRUSTDOM,
563 NULL,
564 &response);
565 BAIL_ON_WBC_ERROR(wbc_status);
567 /* Decode the response */
569 p = (char *)response.extra_data.data;
571 if ((p == NULL) || (strlen(p) == 0)) {
572 /* We should always at least get back our
573 own SAM domain */
575 wbc_status = WBC_ERR_DOMAIN_NOT_FOUND;
576 BAIL_ON_WBC_ERROR(wbc_status);
579 d_list = (struct wbcDomainInfo *)wbcAllocateMemory(
580 response.data.num_entries + 1,sizeof(struct wbcDomainInfo),
581 wbcDomainInfoListDestructor);
582 BAIL_ON_PTR_ERROR(d_list, wbc_status);
584 extra_data = strdup((char*)response.extra_data.data);
585 BAIL_ON_PTR_ERROR(extra_data, wbc_status);
587 p = extra_data;
589 /* Outer loop processes the list of domain information */
591 for (i=0; i<response.data.num_entries && p; i++) {
592 char *next = strchr(p, '\n');
594 if (next) {
595 *next = '\0';
596 next++;
599 wbc_status = process_domain_info_string(&d_list[i], p);
600 BAIL_ON_WBC_ERROR(wbc_status);
602 p = next;
605 *domains = d_list;
606 d_list = NULL;
607 *num_domains = i;
609 done:
610 winbindd_free_response(&response);
611 wbcFreeMemory(d_list);
612 free(extra_data);
613 return wbc_status;
616 wbcErr wbcListTrusts(struct wbcDomainInfo **domains, size_t *num_domains)
618 return wbcCtxListTrusts(NULL, domains, num_domains);
621 static void wbcDomainControllerInfoDestructor(void *ptr)
623 struct wbcDomainControllerInfo *i =
624 (struct wbcDomainControllerInfo *)ptr;
625 free(i->dc_name);
628 /* Enumerate the domain trusts known by Winbind */
629 wbcErr wbcCtxLookupDomainController(struct wbcContext *ctx,
630 const char *domain, uint32_t flags,
631 struct wbcDomainControllerInfo **dc_info)
633 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
634 struct winbindd_request request;
635 struct winbindd_response response;
636 struct wbcDomainControllerInfo *dc = NULL;
638 /* validate input params */
640 if (!domain || !dc_info) {
641 wbc_status = WBC_ERR_INVALID_PARAM;
642 BAIL_ON_WBC_ERROR(wbc_status);
645 ZERO_STRUCT(request);
646 ZERO_STRUCT(response);
648 strncpy(request.data.dsgetdcname.domain_name, domain,
649 sizeof(request.data.dsgetdcname.domain_name)-1);
651 request.flags = flags;
653 dc = (struct wbcDomainControllerInfo *)wbcAllocateMemory(
654 1, sizeof(struct wbcDomainControllerInfo),
655 wbcDomainControllerInfoDestructor);
656 BAIL_ON_PTR_ERROR(dc, wbc_status);
658 /* Send request */
660 wbc_status = wbcRequestResponse(ctx, WINBINDD_DSGETDCNAME,
661 &request,
662 &response);
663 BAIL_ON_WBC_ERROR(wbc_status);
665 dc->dc_name = strdup(response.data.dsgetdcname.dc_unc);
666 BAIL_ON_PTR_ERROR(dc->dc_name, wbc_status);
668 *dc_info = dc;
669 dc = NULL;
671 done:
672 wbcFreeMemory(dc);
673 return wbc_status;
676 wbcErr wbcLookupDomainController(const char *domain, uint32_t flags,
677 struct wbcDomainControllerInfo **dc_info)
679 return wbcCtxLookupDomainController(NULL, domain, flags, dc_info);
682 static void wbcDomainControllerInfoExDestructor(void *ptr)
684 struct wbcDomainControllerInfoEx *i =
685 (struct wbcDomainControllerInfoEx *)ptr;
686 free(discard_const_p(char, i->dc_unc));
687 free(discard_const_p(char, i->dc_address));
688 free(discard_const_p(char, i->domain_guid));
689 free(discard_const_p(char, i->domain_name));
690 free(discard_const_p(char, i->forest_name));
691 free(discard_const_p(char, i->dc_site_name));
692 free(discard_const_p(char, i->client_site_name));
695 static wbcErr wbc_create_domain_controller_info_ex(const struct winbindd_response *resp,
696 struct wbcDomainControllerInfoEx **_i)
698 wbcErr wbc_status = WBC_ERR_SUCCESS;
699 struct wbcDomainControllerInfoEx *i;
700 struct wbcGuid guid;
702 i = (struct wbcDomainControllerInfoEx *)wbcAllocateMemory(
703 1, sizeof(struct wbcDomainControllerInfoEx),
704 wbcDomainControllerInfoExDestructor);
705 BAIL_ON_PTR_ERROR(i, wbc_status);
707 i->dc_unc = strdup(resp->data.dsgetdcname.dc_unc);
708 BAIL_ON_PTR_ERROR(i->dc_unc, wbc_status);
710 i->dc_address = strdup(resp->data.dsgetdcname.dc_address);
711 BAIL_ON_PTR_ERROR(i->dc_address, wbc_status);
713 i->dc_address_type = resp->data.dsgetdcname.dc_address_type;
715 wbc_status = wbcStringToGuid(resp->data.dsgetdcname.domain_guid, &guid);
716 if (WBC_ERROR_IS_OK(wbc_status)) {
717 i->domain_guid = (struct wbcGuid *)malloc(
718 sizeof(struct wbcGuid));
719 BAIL_ON_PTR_ERROR(i->domain_guid, wbc_status);
721 *i->domain_guid = guid;
724 i->domain_name = strdup(resp->data.dsgetdcname.domain_name);
725 BAIL_ON_PTR_ERROR(i->domain_name, wbc_status);
727 if (resp->data.dsgetdcname.forest_name[0] != '\0') {
728 i->forest_name = strdup(resp->data.dsgetdcname.forest_name);
729 BAIL_ON_PTR_ERROR(i->forest_name, wbc_status);
732 i->dc_flags = resp->data.dsgetdcname.dc_flags;
734 if (resp->data.dsgetdcname.dc_site_name[0] != '\0') {
735 i->dc_site_name = strdup(resp->data.dsgetdcname.dc_site_name);
736 BAIL_ON_PTR_ERROR(i->dc_site_name, wbc_status);
739 if (resp->data.dsgetdcname.client_site_name[0] != '\0') {
740 i->client_site_name = strdup(
741 resp->data.dsgetdcname.client_site_name);
742 BAIL_ON_PTR_ERROR(i->client_site_name, wbc_status);
745 *_i = i;
746 i = NULL;
748 done:
749 if (i != NULL) {
750 wbcFreeMemory(i);
752 return wbc_status;
755 /* Get extended domain controller information */
756 wbcErr wbcCtxLookupDomainControllerEx(struct wbcContext *ctx,
757 const char *domain,
758 struct wbcGuid *guid,
759 const char *site,
760 uint32_t flags,
761 struct wbcDomainControllerInfoEx **dc_info)
763 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
764 struct winbindd_request request;
765 struct winbindd_response response;
767 /* validate input params */
769 if (!domain || !dc_info) {
770 wbc_status = WBC_ERR_INVALID_PARAM;
771 BAIL_ON_WBC_ERROR(wbc_status);
774 ZERO_STRUCT(request);
775 ZERO_STRUCT(response);
777 request.data.dsgetdcname.flags = flags;
779 strncpy(request.data.dsgetdcname.domain_name, domain,
780 sizeof(request.data.dsgetdcname.domain_name)-1);
782 if (site) {
783 strncpy(request.data.dsgetdcname.site_name, site,
784 sizeof(request.data.dsgetdcname.site_name)-1);
787 if (guid) {
788 char *str = NULL;
790 wbc_status = wbcGuidToString(guid, &str);
791 BAIL_ON_WBC_ERROR(wbc_status);
793 strncpy(request.data.dsgetdcname.domain_guid, str,
794 sizeof(request.data.dsgetdcname.domain_guid)-1);
796 wbcFreeMemory(str);
799 /* Send request */
801 wbc_status = wbcRequestResponse(ctx, WINBINDD_DSGETDCNAME,
802 &request,
803 &response);
804 BAIL_ON_WBC_ERROR(wbc_status);
806 if (dc_info) {
807 wbc_status = wbc_create_domain_controller_info_ex(&response,
808 dc_info);
809 BAIL_ON_WBC_ERROR(wbc_status);
812 wbc_status = WBC_ERR_SUCCESS;
813 done:
814 return wbc_status;
817 wbcErr wbcLookupDomainControllerEx(const char *domain,
818 struct wbcGuid *guid,
819 const char *site,
820 uint32_t flags,
821 struct wbcDomainControllerInfoEx **dc_info)
823 return wbcCtxLookupDomainControllerEx(NULL, domain, guid, site,
824 flags, dc_info);
827 static void wbcNamedBlobDestructor(void *ptr)
829 struct wbcNamedBlob *b = (struct wbcNamedBlob *)ptr;
831 while (b->name != NULL) {
832 free(discard_const_p(char, b->name));
833 free(b->blob.data);
834 b += 1;
838 /* Initialize a named blob and add to list of blobs */
839 wbcErr wbcAddNamedBlob(size_t *num_blobs,
840 struct wbcNamedBlob **pblobs,
841 const char *name,
842 uint32_t flags,
843 uint8_t *data,
844 size_t length)
846 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
847 struct wbcNamedBlob *blobs, *blob;
849 if (name == NULL) {
850 return WBC_ERR_INVALID_PARAM;
854 * Overallocate the b->name==NULL terminator for
855 * wbcNamedBlobDestructor
857 blobs = (struct wbcNamedBlob *)wbcAllocateMemory(
858 *num_blobs + 2, sizeof(struct wbcNamedBlob),
859 wbcNamedBlobDestructor);
861 if (blobs == NULL) {
862 return WBC_ERR_NO_MEMORY;
865 if (*pblobs != NULL) {
866 struct wbcNamedBlob *old = *pblobs;
867 memcpy(blobs, old, sizeof(struct wbcNamedBlob) * (*num_blobs));
868 if (*num_blobs != 0) {
869 /* end indicator for wbcNamedBlobDestructor */
870 old[0].name = NULL;
872 wbcFreeMemory(old);
874 *pblobs = blobs;
876 blob = &blobs[*num_blobs];
878 blob->name = strdup(name);
879 BAIL_ON_PTR_ERROR(blob->name, wbc_status);
880 blob->flags = flags;
882 blob->blob.length = length;
883 blob->blob.data = (uint8_t *)malloc(length);
884 BAIL_ON_PTR_ERROR(blob->blob.data, wbc_status);
885 memcpy(blob->blob.data, data, length);
887 *num_blobs += 1;
888 *pblobs = blobs;
889 blobs = NULL;
891 wbc_status = WBC_ERR_SUCCESS;
892 done:
893 wbcFreeMemory(blobs);
894 return wbc_status;
897 void wbcSetClientProcessName(const char *name)
899 winbind_set_client_name(name);