s3-passdb: fix uninitialized variable in local_password_change().
[Samba.git] / nsswitch / libwbclient / wbc_util.c
blob5c5034ee13f4e5006353901c1a5e45d94d7d5916
1 /*
2 Unix SMB/CIFS implementation.
4 Winbind client API
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
31 * @return #wbcErr
32 **/
34 wbcErr wbcPing(void)
36 struct winbindd_request request;
37 struct winbindd_response response;
39 /* Initialize request */
41 ZERO_STRUCT(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 */
57 ZERO_STRUCT(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 */
96 domain = NULL;
97 wbc_status = WBC_ERR_SUCCESS;
98 } else {
99 BAIL_ON_WBC_ERROR(wbc_status);
102 if (domain) {
103 info->dns_domain = talloc_strdup(info,
104 domain->dns_name);
105 wbcFreeMemory(domain);
106 BAIL_ON_PTR_ERROR(info->dns_domain, wbc_status);
107 } else {
108 info->dns_domain = NULL;
111 *_details = info;
112 info = NULL;
114 wbc_status = WBC_ERR_SUCCESS;
116 done:
117 talloc_free(info);
118 return wbc_status;
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,
144 &request,
145 &response);
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,
160 &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;
170 *dinfo = info;
172 wbc_status = WBC_ERR_SUCCESS;
174 done:
175 if (!WBC_ERROR_IS_OK(wbc_status)) {
176 talloc_free(info);
179 return 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;
189 char *ipaddr;
191 ZERO_STRUCT(request);
192 ZERO_STRUCT(response);
194 /* Send request */
196 strncpy(request.data.winsreq, name,
197 sizeof(request.data.winsreq)-1);
199 wbc_status = wbcRequestResponse(WINBINDD_WINS_BYNAME,
200 &request,
201 &response);
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);
209 *ip = ipaddr;
210 wbc_status = WBC_ERR_SUCCESS;
212 done:
213 return wbc_status;
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;
222 char *name_str;
224 ZERO_STRUCT(request);
225 ZERO_STRUCT(response);
227 /* Send request */
229 strncpy(request.data.winsreq, ip,
230 sizeof(request.data.winsreq)-1);
232 wbc_status = wbcRequestResponse(WINBINDD_WINS_BYIP,
233 &request,
234 &response);
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);
242 *name = name_str;
243 wbc_status = WBC_ERR_SUCCESS;
245 done:
246 return wbc_status;
252 static wbcErr process_domain_info_string(TALLOC_CTX *ctx,
253 struct wbcDomainInfo *info,
254 char *info_string)
256 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
257 char *r = NULL;
258 char *s = NULL;
260 if (!info || !info_string) {
261 wbc_status = WBC_ERR_INVALID_PARAM;
262 BAIL_ON_WBC_ERROR(wbc_status);
265 r = info_string;
267 /* Short Name */
268 if ((s = strchr(r, '\\')) == NULL) {
269 wbc_status = WBC_ERR_INVALID_RESPONSE;
270 BAIL_ON_WBC_ERROR(wbc_status);
272 *s = '\0';
273 s++;
275 info->short_name = talloc_strdup(ctx, r);
276 BAIL_ON_PTR_ERROR(info->short_name, wbc_status);
279 /* DNS Name */
280 r = s;
281 if ((s = strchr(r, '\\')) == NULL) {
282 wbc_status = WBC_ERR_INVALID_RESPONSE;
283 BAIL_ON_WBC_ERROR(wbc_status);
285 *s = '\0';
286 s++;
288 info->dns_name = talloc_strdup(ctx, r);
289 BAIL_ON_PTR_ERROR(info->dns_name, wbc_status);
291 /* SID */
292 r = s;
293 if ((s = strchr(r, '\\')) == NULL) {
294 wbc_status = WBC_ERR_INVALID_RESPONSE;
295 BAIL_ON_WBC_ERROR(wbc_status);
297 *s = '\0';
298 s++;
300 wbc_status = wbcStringToSid(r, &info->sid);
301 BAIL_ON_WBC_ERROR(wbc_status);
303 /* Trust type */
304 r = s;
305 if ((s = strchr(r, '\\')) == NULL) {
306 wbc_status = WBC_ERR_INVALID_RESPONSE;
307 BAIL_ON_WBC_ERROR(wbc_status);
309 *s = '\0';
310 s++;
312 if (strcmp(r, "None") == 0) {
313 info->trust_type = WBC_DOMINFO_TRUSTTYPE_NONE;
314 } else if (strcmp(r, "External") == 0) {
315 info->trust_type = WBC_DOMINFO_TRUSTTYPE_EXTERNAL;
316 } else if (strcmp(r, "Forest") == 0) {
317 info->trust_type = WBC_DOMINFO_TRUSTTYPE_FOREST;
318 } else if (strcmp(r, "In Forest") == 0) {
319 info->trust_type = WBC_DOMINFO_TRUSTTYPE_IN_FOREST;
320 } else {
321 wbc_status = WBC_ERR_INVALID_RESPONSE;
322 BAIL_ON_WBC_ERROR(wbc_status);
325 /* Transitive */
326 r = s;
327 if ((s = strchr(r, '\\')) == NULL) {
328 wbc_status = WBC_ERR_INVALID_RESPONSE;
329 BAIL_ON_WBC_ERROR(wbc_status);
331 *s = '\0';
332 s++;
334 if (strcmp(r, "Yes") == 0) {
335 info->trust_flags |= WBC_DOMINFO_TRUST_TRANSITIVE;
338 /* Incoming */
339 r = s;
340 if ((s = strchr(r, '\\')) == NULL) {
341 wbc_status = WBC_ERR_INVALID_RESPONSE;
342 BAIL_ON_WBC_ERROR(wbc_status);
344 *s = '\0';
345 s++;
347 if (strcmp(r, "Yes") == 0) {
348 info->trust_flags |= WBC_DOMINFO_TRUST_INCOMING;
351 /* Outgoing */
352 r = s;
353 if ((s = strchr(r, '\\')) == NULL) {
354 wbc_status = WBC_ERR_INVALID_RESPONSE;
355 BAIL_ON_WBC_ERROR(wbc_status);
357 *s = '\0';
358 s++;
360 if (strcmp(r, "Yes") == 0) {
361 info->trust_flags |= WBC_DOMINFO_TRUST_OUTGOING;
364 /* Online/Offline status */
366 r = s;
367 if (r == NULL) {
368 wbc_status = WBC_ERR_INVALID_RESPONSE;
369 BAIL_ON_WBC_ERROR(wbc_status);
371 if ( strcmp(r, "Offline") == 0) {
372 info->domain_flags |= WBC_DOMINFO_DOMAIN_OFFLINE;
375 wbc_status = WBC_ERR_SUCCESS;
377 done:
378 return wbc_status;
381 /* Enumerate the domain trusts known by Winbind */
382 wbcErr wbcListTrusts(struct wbcDomainInfo **domains, size_t *num_domains)
384 struct winbindd_response response;
385 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
386 char *p = NULL;
387 char *q = NULL;
388 char *extra_data = NULL;
389 int count = 0;
390 struct wbcDomainInfo *d_list = NULL;
391 int i = 0;
393 *domains = NULL;
394 *num_domains = 0;
396 ZERO_STRUCT(response);
398 /* Send request */
400 wbc_status = wbcRequestResponse(WINBINDD_LIST_TRUSTDOM,
401 NULL,
402 &response);
403 BAIL_ON_WBC_ERROR(wbc_status);
405 /* Decode the response */
407 p = (char *)response.extra_data.data;
409 if (strlen(p) == 0) {
410 /* We should always at least get back our
411 own SAM domain */
413 wbc_status = WBC_ERR_DOMAIN_NOT_FOUND;
414 BAIL_ON_WBC_ERROR(wbc_status);
417 /* Count number of domains */
419 count = 0;
420 while (p) {
421 count++;
423 if ((q = strchr(p, '\n')) != NULL)
424 q++;
425 p = q;
428 d_list = talloc_array(NULL, struct wbcDomainInfo, count);
429 BAIL_ON_PTR_ERROR(d_list, wbc_status);
431 extra_data = strdup((char*)response.extra_data.data);
432 BAIL_ON_PTR_ERROR(extra_data, wbc_status);
434 p = extra_data;
436 /* Outer loop processes the list of domain information */
438 for (i=0; i<count && p; i++) {
439 char *next = strchr(p, '\n');
441 if (next) {
442 *next = '\0';
443 next++;
446 wbc_status = process_domain_info_string(d_list, &d_list[i], p);
447 BAIL_ON_WBC_ERROR(wbc_status);
449 p = next;
452 *domains = d_list;
453 *num_domains = i;
455 done:
456 if (!WBC_ERROR_IS_OK(wbc_status)) {
457 if (d_list)
458 talloc_free(d_list);
459 if (extra_data)
460 free(extra_data);
463 return wbc_status;
466 /* Enumerate the domain trusts known by Winbind */
467 wbcErr wbcLookupDomainController(const char *domain,
468 uint32_t flags,
469 struct wbcDomainControllerInfo **dc_info)
471 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
472 struct winbindd_request request;
473 struct winbindd_response response;
474 struct wbcDomainControllerInfo *dc = NULL;
476 /* validate input params */
478 if (!domain || !dc_info) {
479 wbc_status = WBC_ERR_INVALID_PARAM;
480 BAIL_ON_WBC_ERROR(wbc_status);
483 ZERO_STRUCT(request);
484 ZERO_STRUCT(response);
486 strncpy(request.domain_name, domain, sizeof(request.domain_name)-1);
488 request.flags = flags;
490 dc = talloc(NULL, struct wbcDomainControllerInfo);
491 BAIL_ON_PTR_ERROR(dc, wbc_status);
493 /* Send request */
495 wbc_status = wbcRequestResponse(WINBINDD_DSGETDCNAME,
496 &request,
497 &response);
498 BAIL_ON_WBC_ERROR(wbc_status);
500 dc->dc_name = talloc_strdup(dc, response.data.dc_name);
501 BAIL_ON_PTR_ERROR(dc->dc_name, wbc_status);
503 *dc_info = dc;
505 done:
506 if (!WBC_ERROR_IS_OK(wbc_status)) {
507 talloc_free(dc);
510 return wbc_status;
513 static wbcErr wbc_create_domain_controller_info_ex(TALLOC_CTX *mem_ctx,
514 const struct winbindd_response *resp,
515 struct wbcDomainControllerInfoEx **_i)
517 wbcErr wbc_status = WBC_ERR_SUCCESS;
518 struct wbcDomainControllerInfoEx *i;
519 struct wbcGuid guid;
521 i = talloc(mem_ctx, struct wbcDomainControllerInfoEx);
522 BAIL_ON_PTR_ERROR(i, wbc_status);
524 i->dc_unc = talloc_strdup(i, resp->data.dsgetdcname.dc_unc);
525 BAIL_ON_PTR_ERROR(i->dc_unc, wbc_status);
527 i->dc_address = talloc_strdup(i, resp->data.dsgetdcname.dc_address);
528 BAIL_ON_PTR_ERROR(i->dc_address, wbc_status);
530 i->dc_address_type = resp->data.dsgetdcname.dc_address_type;
532 wbc_status = wbcStringToGuid(resp->data.dsgetdcname.domain_guid, &guid);
533 if (WBC_ERROR_IS_OK(wbc_status)) {
534 i->domain_guid = talloc(i, struct wbcGuid);
535 BAIL_ON_PTR_ERROR(i->domain_guid, wbc_status);
537 *i->domain_guid = guid;
538 } else {
539 i->domain_guid = NULL;
542 i->domain_name = talloc_strdup(i, resp->data.dsgetdcname.domain_name);
543 BAIL_ON_PTR_ERROR(i->domain_name, wbc_status);
545 if (resp->data.dsgetdcname.forest_name[0] != '\0') {
546 i->forest_name = talloc_strdup(i,
547 resp->data.dsgetdcname.forest_name);
548 BAIL_ON_PTR_ERROR(i->forest_name, wbc_status);
549 } else {
550 i->forest_name = NULL;
553 i->dc_flags = resp->data.dsgetdcname.dc_flags;
555 if (resp->data.dsgetdcname.dc_site_name[0] != '\0') {
556 i->dc_site_name = talloc_strdup(i,
557 resp->data.dsgetdcname.dc_site_name);
558 BAIL_ON_PTR_ERROR(i->dc_site_name, wbc_status);
559 } else {
560 i->dc_site_name = NULL;
563 if (resp->data.dsgetdcname.client_site_name[0] != '\0') {
564 i->client_site_name = talloc_strdup(i,
565 resp->data.dsgetdcname.client_site_name);
566 BAIL_ON_PTR_ERROR(i->client_site_name, wbc_status);
567 } else {
568 i->client_site_name = NULL;
571 *_i = i;
572 i = NULL;
574 done:
575 talloc_free(i);
576 return wbc_status;
579 /* Get extended domain controller information */
580 wbcErr wbcLookupDomainControllerEx(const char *domain,
581 struct wbcGuid *guid,
582 const char *site,
583 uint32_t flags,
584 struct wbcDomainControllerInfoEx **dc_info)
586 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
587 struct winbindd_request request;
588 struct winbindd_response response;
590 /* validate input params */
592 if (!domain || !dc_info) {
593 wbc_status = WBC_ERR_INVALID_PARAM;
594 BAIL_ON_WBC_ERROR(wbc_status);
597 ZERO_STRUCT(request);
598 ZERO_STRUCT(response);
600 request.data.dsgetdcname.flags = flags;
602 strncpy(request.data.dsgetdcname.domain_name, domain,
603 sizeof(request.data.dsgetdcname.domain_name)-1);
605 if (site) {
606 strncpy(request.data.dsgetdcname.site_name, site,
607 sizeof(request.data.dsgetdcname.site_name)-1);
610 if (guid) {
611 char *str = NULL;
613 wbc_status = wbcGuidToString(guid, &str);
614 BAIL_ON_WBC_ERROR(wbc_status);
616 strncpy(request.data.dsgetdcname.domain_guid, str,
617 sizeof(request.data.dsgetdcname.domain_guid)-1);
619 wbcFreeMemory(str);
622 /* Send request */
624 wbc_status = wbcRequestResponse(WINBINDD_DSGETDCNAME,
625 &request,
626 &response);
627 BAIL_ON_WBC_ERROR(wbc_status);
629 if (dc_info) {
630 wbc_status = wbc_create_domain_controller_info_ex(NULL,
631 &response,
632 dc_info);
633 BAIL_ON_WBC_ERROR(wbc_status);
636 wbc_status = WBC_ERR_SUCCESS;
637 done:
638 return wbc_status;
641 /* Initialize a named blob and add to list of blobs */
642 wbcErr wbcAddNamedBlob(size_t *num_blobs,
643 struct wbcNamedBlob **blobs,
644 const char *name,
645 uint32_t flags,
646 uint8_t *data,
647 size_t length)
649 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
650 struct wbcNamedBlob blob;
652 *blobs = talloc_realloc(NULL, *blobs, struct wbcNamedBlob,
653 *(num_blobs)+1);
654 BAIL_ON_PTR_ERROR(*blobs, wbc_status);
656 blob.name = talloc_strdup(*blobs, name);
657 BAIL_ON_PTR_ERROR(blob.name, wbc_status);
658 blob.flags = flags;
659 blob.blob.length = length;
660 blob.blob.data = (uint8_t *)talloc_memdup(*blobs, data, length);
661 BAIL_ON_PTR_ERROR(blob.blob.data, wbc_status);
663 (*(blobs))[*num_blobs] = blob;
664 *(num_blobs) += 1;
666 wbc_status = WBC_ERR_SUCCESS;
667 done:
668 if (!WBC_ERROR_IS_OK(wbc_status) && blobs) {
669 wbcFreeMemory(*blobs);
671 return wbc_status;