Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : Winbind client asynchronous API, utility functions
5 :
6 : Copyright (C) Gerald (Jerry) Carter 2007-2008
7 :
8 :
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.
13 :
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.
18 :
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/>.
21 : */
22 :
23 : /* Required Headers */
24 :
25 : #include "replace.h"
26 : #include "libwbclient.h"
27 : #include "../winbind_client.h"
28 :
29 : /** @brief Ping winbindd to see if the daemon is running
30 : *
31 : * @param *ctx wbclient Context
32 : *
33 : * @return #wbcErr
34 : **/
35 : _PUBLIC_
36 141122 : wbcErr wbcCtxPing(struct wbcContext *ctx)
37 : {
38 0 : struct winbindd_request request;
39 0 : struct winbindd_response response;
40 :
41 : /* Initialize request */
42 :
43 141122 : ZERO_STRUCT(request);
44 141122 : ZERO_STRUCT(response);
45 :
46 141122 : return wbcRequestResponse(ctx, WINBINDD_PING, &request, &response);
47 : }
48 :
49 : _PUBLIC_
50 141122 : wbcErr wbcPing(void)
51 : {
52 141122 : return wbcCtxPing(NULL);
53 : }
54 :
55 492 : static void wbcInterfaceDetailsDestructor(void *ptr)
56 : {
57 492 : struct wbcInterfaceDetails *i = (struct wbcInterfaceDetails *)ptr;
58 492 : free(i->winbind_version);
59 492 : free(i->netbios_name);
60 492 : free(i->netbios_domain);
61 492 : free(i->dns_domain);
62 492 : }
63 :
64 : /**
65 : * @brief Query useful information about the winbind service
66 : *
67 : * @param *_details pointer to hold the struct wbcInterfaceDetails
68 : *
69 : * @return #wbcErr
70 : */
71 :
72 : _PUBLIC_
73 1260 : wbcErr wbcCtxInterfaceDetails(struct wbcContext *ctx,
74 : struct wbcInterfaceDetails **_details)
75 : {
76 1260 : wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
77 2 : struct wbcInterfaceDetails *info;
78 1260 : struct wbcDomainInfo *domain = NULL;
79 2 : struct winbindd_request request;
80 2 : struct winbindd_response response;
81 :
82 : /* Initialize request */
83 :
84 1260 : ZERO_STRUCT(request);
85 1260 : ZERO_STRUCT(response);
86 :
87 1260 : info = (struct wbcInterfaceDetails *)wbcAllocateMemory(
88 : 1, sizeof(struct wbcInterfaceDetails),
89 : wbcInterfaceDetailsDestructor);
90 1260 : BAIL_ON_PTR_ERROR(info, wbc_status);
91 :
92 : /* first the interface version */
93 1260 : wbc_status = wbcRequestResponse(ctx, WINBINDD_INTERFACE_VERSION,
94 : NULL, &response);
95 1260 : BAIL_ON_WBC_ERROR(wbc_status);
96 1254 : info->interface_version = response.data.interface_version;
97 :
98 : /* then the samba version and the winbind separator */
99 1254 : wbc_status = wbcRequestResponse(ctx, WINBINDD_INFO, NULL, &response);
100 1254 : BAIL_ON_WBC_ERROR(wbc_status);
101 :
102 1254 : info->winbind_version = strdup(response.data.info.samba_version);
103 1254 : BAIL_ON_PTR_ERROR(info->winbind_version, wbc_status);
104 1254 : info->winbind_separator = response.data.info.winbind_separator;
105 :
106 : /* then the local netbios name */
107 1254 : wbc_status = wbcRequestResponse(ctx, WINBINDD_NETBIOS_NAME,
108 : NULL, &response);
109 1254 : BAIL_ON_WBC_ERROR(wbc_status);
110 :
111 1254 : info->netbios_name = strdup(response.data.netbios_name);
112 1254 : BAIL_ON_PTR_ERROR(info->netbios_name, wbc_status);
113 :
114 : /* then the local workgroup name */
115 1254 : wbc_status = wbcRequestResponse(ctx, WINBINDD_DOMAIN_NAME,
116 : NULL, &response);
117 1254 : BAIL_ON_WBC_ERROR(wbc_status);
118 :
119 1254 : info->netbios_domain = strdup(response.data.domain_name);
120 1254 : BAIL_ON_PTR_ERROR(info->netbios_domain, wbc_status);
121 :
122 1254 : wbc_status = wbcCtxDomainInfo(ctx, info->netbios_domain, &domain);
123 1254 : if (wbc_status == WBC_ERR_DOMAIN_NOT_FOUND) {
124 : /* maybe it's a standalone server */
125 0 : domain = NULL;
126 : } else {
127 1254 : BAIL_ON_WBC_ERROR(wbc_status);
128 : }
129 :
130 1254 : if (domain) {
131 1254 : info->dns_domain = strdup(domain->dns_name);
132 1254 : wbcFreeMemory(domain);
133 1254 : BAIL_ON_PTR_ERROR(info->dns_domain, wbc_status);
134 : } else {
135 0 : info->dns_domain = NULL;
136 : }
137 :
138 1254 : *_details = info;
139 1254 : info = NULL;
140 :
141 1254 : wbc_status = WBC_ERR_SUCCESS;
142 :
143 1260 : done:
144 1260 : wbcFreeMemory(info);
145 1260 : return wbc_status;
146 : }
147 :
148 : _PUBLIC_
149 1116 : wbcErr wbcInterfaceDetails(struct wbcInterfaceDetails **_details)
150 : {
151 1116 : return wbcCtxInterfaceDetails(NULL, _details);
152 : }
153 :
154 1296 : static void wbcDomainInfoDestructor(void *ptr)
155 : {
156 1296 : struct wbcDomainInfo *i = (struct wbcDomainInfo *)ptr;
157 1296 : free(i->short_name);
158 1296 : free(i->dns_name);
159 1296 : }
160 :
161 : /** @brief Lookup the current status of a trusted domain, sync wrapper
162 : *
163 : * @param domain Domain to query
164 : * @param *dinfo Pointer to returned struct wbcDomainInfo
165 : *
166 : * @return #wbcErr
167 : */
168 :
169 : _PUBLIC_
170 1296 : wbcErr wbcCtxDomainInfo(struct wbcContext *ctx,
171 : const char *domain,
172 : struct wbcDomainInfo **dinfo)
173 : {
174 2 : struct winbindd_request request;
175 2 : struct winbindd_response response;
176 1296 : wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
177 1296 : struct wbcDomainInfo *info = NULL;
178 :
179 1296 : if (!domain || !dinfo) {
180 0 : wbc_status = WBC_ERR_INVALID_PARAM;
181 0 : BAIL_ON_WBC_ERROR(wbc_status);
182 : }
183 :
184 : /* Initialize request */
185 :
186 1296 : ZERO_STRUCT(request);
187 1296 : ZERO_STRUCT(response);
188 :
189 1296 : strncpy(request.domain_name, domain,
190 : sizeof(request.domain_name)-1);
191 :
192 1296 : wbc_status = wbcRequestResponse(ctx, WINBINDD_DOMAIN_INFO,
193 : &request,
194 : &response);
195 1296 : BAIL_ON_WBC_ERROR(wbc_status);
196 :
197 1296 : info = (struct wbcDomainInfo *)wbcAllocateMemory(
198 : 1, sizeof(struct wbcDomainInfo), wbcDomainInfoDestructor);
199 1296 : BAIL_ON_PTR_ERROR(info, wbc_status);
200 :
201 1296 : info->short_name = strdup(response.data.domain_info.name);
202 1296 : BAIL_ON_PTR_ERROR(info->short_name, wbc_status);
203 :
204 1296 : info->dns_name = strdup(response.data.domain_info.alt_name);
205 1296 : BAIL_ON_PTR_ERROR(info->dns_name, wbc_status);
206 :
207 1296 : wbc_status = wbcStringToSid(response.data.domain_info.sid,
208 : &info->sid);
209 1296 : BAIL_ON_WBC_ERROR(wbc_status);
210 :
211 1296 : if (response.data.domain_info.native_mode)
212 476 : info->domain_flags |= WBC_DOMINFO_DOMAIN_NATIVE;
213 1296 : if (response.data.domain_info.active_directory)
214 1005 : info->domain_flags |= WBC_DOMINFO_DOMAIN_AD;
215 1296 : if (response.data.domain_info.primary)
216 1286 : info->domain_flags |= WBC_DOMINFO_DOMAIN_PRIMARY;
217 :
218 1296 : *dinfo = info;
219 1296 : info = NULL;
220 :
221 1296 : wbc_status = WBC_ERR_SUCCESS;
222 :
223 1296 : done:
224 1296 : wbcFreeMemory(info);
225 1296 : return wbc_status;
226 : }
227 :
228 : _PUBLIC_
229 42 : wbcErr wbcDomainInfo(const char *domain, struct wbcDomainInfo **dinfo)
230 : {
231 42 : return wbcCtxDomainInfo(NULL, domain, dinfo);
232 : }
233 :
234 : /* Get the list of current DCs */
235 : _PUBLIC_
236 4 : wbcErr wbcCtxDcInfo(struct wbcContext *ctx,
237 : const char *domain, size_t *num_dcs,
238 : const char ***dc_names, const char ***dc_ips)
239 : {
240 0 : struct winbindd_request request;
241 0 : struct winbindd_response response;
242 4 : const char **names = NULL;
243 4 : const char **ips = NULL;
244 4 : wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
245 0 : size_t extra_len;
246 0 : int i;
247 0 : char *p;
248 :
249 : /* Initialise request */
250 :
251 4 : ZERO_STRUCT(request);
252 4 : ZERO_STRUCT(response);
253 :
254 4 : if (domain != NULL) {
255 4 : strncpy(request.domain_name, domain,
256 : sizeof(request.domain_name) - 1);
257 : }
258 :
259 4 : wbc_status = wbcRequestResponse(ctx, WINBINDD_DC_INFO,
260 : &request, &response);
261 4 : BAIL_ON_WBC_ERROR(wbc_status);
262 :
263 4 : names = wbcAllocateStringArray(response.data.num_entries);
264 4 : BAIL_ON_PTR_ERROR(names, wbc_status);
265 :
266 4 : ips = wbcAllocateStringArray(response.data.num_entries);
267 4 : BAIL_ON_PTR_ERROR(ips, wbc_status);
268 :
269 4 : wbc_status = WBC_ERR_INVALID_RESPONSE;
270 :
271 4 : p = (char *)response.extra_data.data;
272 :
273 4 : if (response.length < (sizeof(struct winbindd_response)+1)) {
274 0 : goto done;
275 : }
276 :
277 4 : extra_len = response.length - sizeof(struct winbindd_response);
278 :
279 4 : if (p[extra_len-1] != '\0') {
280 0 : goto done;
281 : }
282 :
283 8 : for (i=0; i<response.data.num_entries; i++) {
284 0 : char *q;
285 :
286 4 : q = strchr(p, '\n');
287 4 : if (q == NULL) {
288 0 : goto done;
289 : }
290 4 : names[i] = strndup(p, q-p);
291 4 : BAIL_ON_PTR_ERROR(names[i], wbc_status);
292 4 : p = q+1;
293 :
294 4 : q = strchr(p, '\n');
295 4 : if (q == NULL) {
296 0 : goto done;
297 : }
298 4 : ips[i] = strndup(p, q-p);
299 4 : BAIL_ON_PTR_ERROR(ips[i], wbc_status);
300 4 : p = q+1;
301 : }
302 4 : if (p[0] != '\0') {
303 0 : goto done;
304 : }
305 :
306 4 : wbc_status = WBC_ERR_SUCCESS;
307 4 : done:
308 4 : if (response.extra_data.data)
309 4 : free(response.extra_data.data);
310 :
311 4 : if (WBC_ERROR_IS_OK(wbc_status)) {
312 4 : *num_dcs = response.data.num_entries;
313 4 : *dc_names = names;
314 4 : names = NULL;
315 4 : *dc_ips = ips;
316 4 : ips = NULL;
317 : }
318 4 : wbcFreeMemory(names);
319 4 : wbcFreeMemory(ips);
320 4 : return wbc_status;
321 : }
322 :
323 : _PUBLIC_
324 4 : wbcErr wbcDcInfo(const char *domain, size_t *num_dcs,
325 : const char ***dc_names, const char ***dc_ips)
326 : {
327 4 : return wbcCtxDcInfo(NULL, domain, num_dcs, dc_names, dc_ips);
328 : }
329 :
330 : /* Resolve a NetbiosName via WINS */
331 : _PUBLIC_
332 12 : wbcErr wbcCtxResolveWinsByName(struct wbcContext *ctx,
333 : const char *name, char **ip)
334 : {
335 0 : struct winbindd_request request;
336 0 : struct winbindd_response response;
337 12 : wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
338 0 : char *ipaddr;
339 :
340 12 : ZERO_STRUCT(request);
341 12 : ZERO_STRUCT(response);
342 :
343 : /* Send request */
344 :
345 12 : strncpy(request.data.winsreq, name,
346 : sizeof(request.data.winsreq)-1);
347 :
348 12 : wbc_status = wbcRequestResponse(ctx, WINBINDD_WINS_BYNAME,
349 : &request,
350 : &response);
351 12 : BAIL_ON_WBC_ERROR(wbc_status);
352 :
353 : /* Display response */
354 :
355 12 : ipaddr = wbcStrDup(response.data.winsresp);
356 12 : BAIL_ON_PTR_ERROR(ipaddr, wbc_status);
357 :
358 12 : *ip = ipaddr;
359 12 : wbc_status = WBC_ERR_SUCCESS;
360 :
361 12 : done:
362 12 : return wbc_status;
363 : }
364 :
365 : _PUBLIC_
366 12 : wbcErr wbcResolveWinsByName(const char *name, char **ip)
367 : {
368 12 : return wbcCtxResolveWinsByName(NULL, name, ip);
369 : }
370 :
371 : /* Resolve an IP address via WINS into a NetbiosName */
372 : _PUBLIC_
373 12 : wbcErr wbcCtxResolveWinsByIP(struct wbcContext *ctx,
374 : const char *ip, char **name)
375 : {
376 0 : struct winbindd_request request;
377 0 : struct winbindd_response response;
378 12 : wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
379 0 : char *name_str;
380 :
381 12 : ZERO_STRUCT(request);
382 12 : ZERO_STRUCT(response);
383 :
384 : /* Send request */
385 :
386 12 : strncpy(request.data.winsreq, ip,
387 : sizeof(request.data.winsreq)-1);
388 :
389 12 : wbc_status = wbcRequestResponse(ctx, WINBINDD_WINS_BYIP,
390 : &request,
391 : &response);
392 12 : BAIL_ON_WBC_ERROR(wbc_status);
393 :
394 : /* Display response */
395 :
396 12 : name_str = wbcStrDup(response.data.winsresp);
397 12 : BAIL_ON_PTR_ERROR(name_str, wbc_status);
398 :
399 12 : *name = name_str;
400 12 : wbc_status = WBC_ERR_SUCCESS;
401 :
402 12 : done:
403 12 : return wbc_status;
404 : }
405 :
406 : _PUBLIC_
407 12 : wbcErr wbcResolveWinsByIP(const char *ip, char **name)
408 : {
409 12 : return wbcCtxResolveWinsByIP(NULL, ip, name);
410 : }
411 :
412 : /**
413 : */
414 :
415 246 : static wbcErr process_domain_info_string(struct wbcDomainInfo *info,
416 : char *info_string)
417 : {
418 246 : wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
419 246 : char *r = NULL;
420 246 : char *s = NULL;
421 :
422 246 : r = info_string;
423 :
424 : /* Short Name */
425 246 : if ((s = strchr(r, '\\')) == NULL) {
426 0 : wbc_status = WBC_ERR_INVALID_RESPONSE;
427 0 : BAIL_ON_WBC_ERROR(wbc_status);
428 : }
429 246 : *s = '\0';
430 246 : s++;
431 :
432 246 : info->short_name = strdup(r);
433 246 : BAIL_ON_PTR_ERROR(info->short_name, wbc_status);
434 :
435 :
436 : /* DNS Name */
437 246 : r = s;
438 246 : if ((s = strchr(r, '\\')) == NULL) {
439 0 : wbc_status = WBC_ERR_INVALID_RESPONSE;
440 0 : BAIL_ON_WBC_ERROR(wbc_status);
441 : }
442 246 : *s = '\0';
443 246 : s++;
444 :
445 246 : info->dns_name = strdup(r);
446 246 : BAIL_ON_PTR_ERROR(info->dns_name, wbc_status);
447 :
448 : /* SID */
449 246 : r = s;
450 246 : if ((s = strchr(r, '\\')) == NULL) {
451 0 : wbc_status = WBC_ERR_INVALID_RESPONSE;
452 0 : BAIL_ON_WBC_ERROR(wbc_status);
453 : }
454 246 : *s = '\0';
455 246 : s++;
456 :
457 246 : wbc_status = wbcStringToSid(r, &info->sid);
458 246 : BAIL_ON_WBC_ERROR(wbc_status);
459 :
460 : /* Trust type */
461 246 : r = s;
462 246 : if ((s = strchr(r, '\\')) == NULL) {
463 0 : wbc_status = WBC_ERR_INVALID_RESPONSE;
464 0 : BAIL_ON_WBC_ERROR(wbc_status);
465 : }
466 246 : *s = '\0';
467 246 : s++;
468 :
469 246 : if (strncmp(r, "Routed", strlen("Routed")) == 0) {
470 36 : info->trust_type = WBC_DOMINFO_TRUSTTYPE_NONE;
471 36 : info->trust_routing = strdup(r);
472 36 : BAIL_ON_PTR_ERROR(info->trust_routing, wbc_status);
473 210 : } else if (strcmp(r, "Local") == 0) {
474 118 : info->trust_type = WBC_DOMINFO_TRUSTTYPE_LOCAL;
475 92 : } else if (strcmp(r, "Workstation") == 0) {
476 34 : info->trust_type = WBC_DOMINFO_TRUSTTYPE_WKSTA;
477 58 : } else if (strcmp(r, "RWDC") == 0) {
478 28 : info->trust_type = WBC_DOMINFO_TRUSTTYPE_RWDC;
479 30 : } else if (strcmp(r, "RODC") == 0) {
480 8 : info->trust_type = WBC_DOMINFO_TRUSTTYPE_RODC;
481 22 : } else if (strcmp(r, "PDC") == 0) {
482 14 : info->trust_type = WBC_DOMINFO_TRUSTTYPE_PDC;
483 8 : } else if (strcmp(r, "External") == 0) {
484 2 : info->trust_type = WBC_DOMINFO_TRUSTTYPE_EXTERNAL;
485 6 : } else if (strcmp(r, "Forest") == 0) {
486 6 : info->trust_type = WBC_DOMINFO_TRUSTTYPE_FOREST;
487 0 : } else if (strcmp(r, "In Forest") == 0) {
488 0 : info->trust_type = WBC_DOMINFO_TRUSTTYPE_IN_FOREST;
489 : } else {
490 0 : wbc_status = WBC_ERR_INVALID_RESPONSE;
491 0 : BAIL_ON_WBC_ERROR(wbc_status);
492 : }
493 :
494 : /* Transitive */
495 246 : r = s;
496 246 : if ((s = strchr(r, '\\')) == NULL) {
497 0 : wbc_status = WBC_ERR_INVALID_RESPONSE;
498 0 : BAIL_ON_WBC_ERROR(wbc_status);
499 : }
500 246 : *s = '\0';
501 246 : s++;
502 :
503 246 : if (strcmp(r, "Yes") == 0) {
504 94 : info->trust_flags |= WBC_DOMINFO_TRUST_TRANSITIVE;
505 : }
506 :
507 : /* Incoming */
508 246 : r = s;
509 246 : if ((s = strchr(r, '\\')) == NULL) {
510 0 : wbc_status = WBC_ERR_INVALID_RESPONSE;
511 0 : BAIL_ON_WBC_ERROR(wbc_status);
512 : }
513 246 : *s = '\0';
514 246 : s++;
515 :
516 246 : if (strcmp(r, "Yes") == 0) {
517 12 : info->trust_flags |= WBC_DOMINFO_TRUST_INCOMING;
518 : }
519 :
520 : /* Outgoing */
521 246 : r = s;
522 246 : if ((s = strchr(r, '\\')) == NULL) {
523 0 : wbc_status = WBC_ERR_INVALID_RESPONSE;
524 0 : BAIL_ON_WBC_ERROR(wbc_status);
525 : }
526 246 : *s = '\0';
527 246 : s++;
528 :
529 246 : if (strcmp(r, "Yes") == 0) {
530 160 : info->trust_flags |= WBC_DOMINFO_TRUST_OUTGOING;
531 : }
532 :
533 : /* Online/Offline status */
534 246 : r = s;
535 246 : if ( strcmp(r, "Offline") == 0) {
536 6 : info->domain_flags |= WBC_DOMINFO_DOMAIN_OFFLINE;
537 : }
538 :
539 246 : wbc_status = WBC_ERR_SUCCESS;
540 :
541 246 : done:
542 246 : return wbc_status;
543 : }
544 :
545 84 : static void wbcDomainInfoListDestructor(void *ptr)
546 : {
547 84 : struct wbcDomainInfo *i = (struct wbcDomainInfo *)ptr;
548 :
549 330 : while (i->short_name != NULL) {
550 246 : free(i->short_name);
551 246 : free(i->dns_name);
552 246 : i += 1;
553 : }
554 84 : }
555 :
556 : /* Enumerate the domain trusts known by Winbind */
557 : _PUBLIC_
558 84 : wbcErr wbcCtxListTrusts(struct wbcContext *ctx,
559 : struct wbcDomainInfo **domains, size_t *num_domains)
560 : {
561 0 : struct winbindd_response response;
562 84 : wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
563 84 : char *p = NULL;
564 84 : char *extra_data = NULL;
565 84 : struct wbcDomainInfo *d_list = NULL;
566 84 : int i = 0;
567 :
568 84 : *domains = NULL;
569 84 : *num_domains = 0;
570 :
571 84 : ZERO_STRUCT(response);
572 :
573 : /* Send request */
574 :
575 84 : wbc_status = wbcRequestResponse(ctx, WINBINDD_LIST_TRUSTDOM,
576 : NULL,
577 : &response);
578 84 : BAIL_ON_WBC_ERROR(wbc_status);
579 :
580 : /* Decode the response */
581 :
582 84 : p = (char *)response.extra_data.data;
583 :
584 84 : if ((p == NULL) || (strlen(p) == 0)) {
585 : /* We should always at least get back our
586 : own SAM domain */
587 :
588 0 : wbc_status = WBC_ERR_DOMAIN_NOT_FOUND;
589 0 : BAIL_ON_WBC_ERROR(wbc_status);
590 : }
591 :
592 84 : d_list = (struct wbcDomainInfo *)wbcAllocateMemory(
593 84 : response.data.num_entries + 1,sizeof(struct wbcDomainInfo),
594 : wbcDomainInfoListDestructor);
595 84 : BAIL_ON_PTR_ERROR(d_list, wbc_status);
596 :
597 84 : extra_data = strdup((char*)response.extra_data.data);
598 84 : BAIL_ON_PTR_ERROR(extra_data, wbc_status);
599 :
600 84 : p = extra_data;
601 :
602 : /* Outer loop processes the list of domain information */
603 :
604 330 : for (i=0; i<response.data.num_entries && p; i++) {
605 246 : char *next = strchr(p, '\n');
606 :
607 246 : if (next) {
608 162 : *next = '\0';
609 162 : next++;
610 : }
611 :
612 246 : wbc_status = process_domain_info_string(&d_list[i], p);
613 246 : BAIL_ON_WBC_ERROR(wbc_status);
614 :
615 246 : p = next;
616 : }
617 :
618 84 : *domains = d_list;
619 84 : d_list = NULL;
620 84 : *num_domains = i;
621 :
622 84 : done:
623 84 : winbindd_free_response(&response);
624 84 : wbcFreeMemory(d_list);
625 84 : free(extra_data);
626 84 : return wbc_status;
627 : }
628 :
629 : _PUBLIC_
630 84 : wbcErr wbcListTrusts(struct wbcDomainInfo **domains, size_t *num_domains)
631 : {
632 84 : return wbcCtxListTrusts(NULL, domains, num_domains);
633 : }
634 :
635 4 : static void wbcDomainControllerInfoDestructor(void *ptr)
636 : {
637 4 : struct wbcDomainControllerInfo *i =
638 : (struct wbcDomainControllerInfo *)ptr;
639 4 : free(i->dc_name);
640 4 : }
641 :
642 : /* Enumerate the domain trusts known by Winbind */
643 : _PUBLIC_
644 4 : wbcErr wbcCtxLookupDomainController(struct wbcContext *ctx,
645 : const char *domain, uint32_t flags,
646 : struct wbcDomainControllerInfo **dc_info)
647 : {
648 4 : wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
649 0 : struct winbindd_request request;
650 0 : struct winbindd_response response;
651 4 : struct wbcDomainControllerInfo *dc = NULL;
652 :
653 : /* validate input params */
654 :
655 4 : if (!domain || !dc_info) {
656 0 : wbc_status = WBC_ERR_INVALID_PARAM;
657 0 : BAIL_ON_WBC_ERROR(wbc_status);
658 : }
659 :
660 4 : ZERO_STRUCT(request);
661 4 : ZERO_STRUCT(response);
662 :
663 4 : strncpy(request.data.dsgetdcname.domain_name, domain,
664 : sizeof(request.data.dsgetdcname.domain_name)-1);
665 :
666 4 : request.flags = flags;
667 :
668 4 : dc = (struct wbcDomainControllerInfo *)wbcAllocateMemory(
669 : 1, sizeof(struct wbcDomainControllerInfo),
670 : wbcDomainControllerInfoDestructor);
671 4 : BAIL_ON_PTR_ERROR(dc, wbc_status);
672 :
673 : /* Send request */
674 :
675 4 : wbc_status = wbcRequestResponse(ctx, WINBINDD_DSGETDCNAME,
676 : &request,
677 : &response);
678 4 : BAIL_ON_WBC_ERROR(wbc_status);
679 :
680 4 : dc->dc_name = strdup(response.data.dsgetdcname.dc_unc);
681 4 : BAIL_ON_PTR_ERROR(dc->dc_name, wbc_status);
682 :
683 4 : *dc_info = dc;
684 4 : dc = NULL;
685 :
686 4 : done:
687 4 : wbcFreeMemory(dc);
688 4 : return wbc_status;
689 : }
690 :
691 : _PUBLIC_
692 4 : wbcErr wbcLookupDomainController(const char *domain, uint32_t flags,
693 : struct wbcDomainControllerInfo **dc_info)
694 : {
695 4 : return wbcCtxLookupDomainController(NULL, domain, flags, dc_info);
696 : }
697 :
698 4 : static void wbcDomainControllerInfoExDestructor(void *ptr)
699 : {
700 4 : struct wbcDomainControllerInfoEx *i =
701 : (struct wbcDomainControllerInfoEx *)ptr;
702 4 : free(discard_const_p(char, i->dc_unc));
703 4 : free(discard_const_p(char, i->dc_address));
704 4 : free(discard_const_p(char, i->domain_guid));
705 4 : free(discard_const_p(char, i->domain_name));
706 4 : free(discard_const_p(char, i->forest_name));
707 4 : free(discard_const_p(char, i->dc_site_name));
708 4 : free(discard_const_p(char, i->client_site_name));
709 4 : }
710 :
711 4 : static wbcErr wbc_create_domain_controller_info_ex(const struct winbindd_response *resp,
712 : struct wbcDomainControllerInfoEx **_i)
713 : {
714 4 : wbcErr wbc_status = WBC_ERR_SUCCESS;
715 0 : struct wbcDomainControllerInfoEx *i;
716 0 : struct wbcGuid guid;
717 :
718 4 : i = (struct wbcDomainControllerInfoEx *)wbcAllocateMemory(
719 : 1, sizeof(struct wbcDomainControllerInfoEx),
720 : wbcDomainControllerInfoExDestructor);
721 4 : BAIL_ON_PTR_ERROR(i, wbc_status);
722 :
723 4 : i->dc_unc = strdup(resp->data.dsgetdcname.dc_unc);
724 4 : BAIL_ON_PTR_ERROR(i->dc_unc, wbc_status);
725 :
726 4 : i->dc_address = strdup(resp->data.dsgetdcname.dc_address);
727 4 : BAIL_ON_PTR_ERROR(i->dc_address, wbc_status);
728 :
729 4 : i->dc_address_type = resp->data.dsgetdcname.dc_address_type;
730 :
731 4 : wbc_status = wbcStringToGuid(resp->data.dsgetdcname.domain_guid, &guid);
732 4 : if (WBC_ERROR_IS_OK(wbc_status)) {
733 4 : i->domain_guid = (struct wbcGuid *)malloc(
734 : sizeof(struct wbcGuid));
735 4 : BAIL_ON_PTR_ERROR(i->domain_guid, wbc_status);
736 :
737 4 : *i->domain_guid = guid;
738 : }
739 :
740 4 : i->domain_name = strdup(resp->data.dsgetdcname.domain_name);
741 4 : BAIL_ON_PTR_ERROR(i->domain_name, wbc_status);
742 :
743 4 : if (resp->data.dsgetdcname.forest_name[0] != '\0') {
744 2 : i->forest_name = strdup(resp->data.dsgetdcname.forest_name);
745 2 : BAIL_ON_PTR_ERROR(i->forest_name, wbc_status);
746 : }
747 :
748 4 : i->dc_flags = resp->data.dsgetdcname.dc_flags;
749 :
750 4 : if (resp->data.dsgetdcname.dc_site_name[0] != '\0') {
751 2 : i->dc_site_name = strdup(resp->data.dsgetdcname.dc_site_name);
752 2 : BAIL_ON_PTR_ERROR(i->dc_site_name, wbc_status);
753 : }
754 :
755 4 : if (resp->data.dsgetdcname.client_site_name[0] != '\0') {
756 2 : i->client_site_name = strdup(
757 2 : resp->data.dsgetdcname.client_site_name);
758 2 : BAIL_ON_PTR_ERROR(i->client_site_name, wbc_status);
759 : }
760 :
761 4 : *_i = i;
762 4 : i = NULL;
763 :
764 4 : done:
765 4 : if (i != NULL) {
766 0 : wbcFreeMemory(i);
767 : }
768 4 : return wbc_status;
769 : }
770 :
771 : /* Get extended domain controller information */
772 : _PUBLIC_
773 4 : wbcErr wbcCtxLookupDomainControllerEx(struct wbcContext *ctx,
774 : const char *domain,
775 : struct wbcGuid *guid,
776 : const char *site,
777 : uint32_t flags,
778 : struct wbcDomainControllerInfoEx **dc_info)
779 : {
780 4 : wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
781 0 : struct winbindd_request request;
782 0 : struct winbindd_response response;
783 :
784 : /* validate input params */
785 :
786 4 : if (!domain || !dc_info) {
787 0 : wbc_status = WBC_ERR_INVALID_PARAM;
788 0 : BAIL_ON_WBC_ERROR(wbc_status);
789 : }
790 :
791 4 : ZERO_STRUCT(request);
792 4 : ZERO_STRUCT(response);
793 :
794 4 : request.data.dsgetdcname.flags = flags;
795 :
796 4 : strncpy(request.data.dsgetdcname.domain_name, domain,
797 : sizeof(request.data.dsgetdcname.domain_name)-1);
798 :
799 4 : if (site) {
800 0 : strncpy(request.data.dsgetdcname.site_name, site,
801 : sizeof(request.data.dsgetdcname.site_name)-1);
802 : }
803 :
804 4 : if (guid) {
805 0 : char *str = NULL;
806 :
807 0 : wbc_status = wbcGuidToString(guid, &str);
808 0 : BAIL_ON_WBC_ERROR(wbc_status);
809 :
810 0 : strncpy(request.data.dsgetdcname.domain_guid, str,
811 : sizeof(request.data.dsgetdcname.domain_guid)-1);
812 :
813 0 : wbcFreeMemory(str);
814 : }
815 :
816 : /* Send request */
817 :
818 4 : wbc_status = wbcRequestResponse(ctx, WINBINDD_DSGETDCNAME,
819 : &request,
820 : &response);
821 4 : BAIL_ON_WBC_ERROR(wbc_status);
822 :
823 4 : if (dc_info) {
824 4 : wbc_status = wbc_create_domain_controller_info_ex(&response,
825 : dc_info);
826 4 : BAIL_ON_WBC_ERROR(wbc_status);
827 : }
828 :
829 4 : wbc_status = WBC_ERR_SUCCESS;
830 4 : done:
831 4 : return wbc_status;
832 : }
833 :
834 : _PUBLIC_
835 4 : wbcErr wbcLookupDomainControllerEx(const char *domain,
836 : struct wbcGuid *guid,
837 : const char *site,
838 : uint32_t flags,
839 : struct wbcDomainControllerInfoEx **dc_info)
840 : {
841 4 : return wbcCtxLookupDomainControllerEx(NULL, domain, guid, site,
842 : flags, dc_info);
843 : }
844 :
845 1194 : static void wbcNamedBlobDestructor(void *ptr)
846 : {
847 1194 : struct wbcNamedBlob *b = (struct wbcNamedBlob *)ptr;
848 :
849 2388 : while (b->name != NULL) {
850 1194 : free(discard_const_p(char, b->name));
851 1194 : free(b->blob.data);
852 1194 : b += 1;
853 : }
854 1194 : }
855 :
856 : /* Initialize a named blob and add to list of blobs */
857 : _PUBLIC_
858 1202 : wbcErr wbcAddNamedBlob(size_t *num_blobs,
859 : struct wbcNamedBlob **pblobs,
860 : const char *name,
861 : uint32_t flags,
862 : uint8_t *data,
863 : size_t length)
864 : {
865 1202 : wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
866 0 : struct wbcNamedBlob *blobs, *blob;
867 :
868 1202 : if (name == NULL) {
869 0 : return WBC_ERR_INVALID_PARAM;
870 : }
871 :
872 : /*
873 : * Overallocate the b->name==NULL terminator for
874 : * wbcNamedBlobDestructor
875 : */
876 1202 : blobs = (struct wbcNamedBlob *)wbcAllocateMemory(
877 1202 : *num_blobs + 2, sizeof(struct wbcNamedBlob),
878 : wbcNamedBlobDestructor);
879 :
880 1202 : if (blobs == NULL) {
881 0 : return WBC_ERR_NO_MEMORY;
882 : }
883 :
884 1202 : if (*pblobs != NULL) {
885 630 : struct wbcNamedBlob *old = *pblobs;
886 630 : memcpy(blobs, old, sizeof(struct wbcNamedBlob) * (*num_blobs));
887 630 : if (*num_blobs != 0) {
888 : /* end indicator for wbcNamedBlobDestructor */
889 630 : old[0].name = NULL;
890 : }
891 630 : wbcFreeMemory(old);
892 : }
893 1202 : *pblobs = blobs;
894 :
895 1202 : blob = &blobs[*num_blobs];
896 :
897 1202 : blob->name = strdup(name);
898 1202 : BAIL_ON_PTR_ERROR(blob->name, wbc_status);
899 1202 : blob->flags = flags;
900 :
901 1202 : blob->blob.length = length;
902 1202 : blob->blob.data = (uint8_t *)malloc(length);
903 1202 : BAIL_ON_PTR_ERROR(blob->blob.data, wbc_status);
904 1202 : memcpy(blob->blob.data, data, length);
905 :
906 1202 : *num_blobs += 1;
907 1202 : *pblobs = blobs;
908 1202 : blobs = NULL;
909 :
910 1202 : wbc_status = WBC_ERR_SUCCESS;
911 1202 : done:
912 1202 : wbcFreeMemory(blobs);
913 1202 : return wbc_status;
914 : }
915 :
916 : _PUBLIC_
917 266 : void wbcSetClientProcessName(const char *name)
918 : {
919 266 : winbind_set_client_name(name);
920 266 : }
|