/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- wbcPing
- wbcInterfaceDetails
- wbcDomainInfo
- wbcResolveWinsByName
- wbcResolveWinsByIP
- process_domain_info_string
- wbcListTrusts
- wbcLookupDomainController
- wbc_create_domain_controller_info_ex
- wbcLookupDomainControllerEx
- wbcAddNamedBlob
1 /*
2 Unix SMB/CIFS implementation.
3
4 Winbind client API
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 "libwbclient.h"
26
27
28
29 /** @brief Ping winbindd to see if the daemon is running
30 *
31 * @return #wbcErr
32 **/
33
34 wbcErr wbcPing(void)
/* [<][>][^][v][top][bottom][index][help] */
35 {
36 struct winbindd_request request;
37 struct winbindd_response response;
38
39 /* Initialize request */
40
41 ZERO_STRUCT(request);
42 ZERO_STRUCT(response);
43
44 return wbcRequestResponse(WINBINDD_PING, &request, &response);
45 }
46
47 wbcErr wbcInterfaceDetails(struct wbcInterfaceDetails **_details)
/* [<][>][^][v][top][bottom][index][help] */
48 {
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;
54
55 /* Initialize request */
56
57 ZERO_STRUCT(request);
58 ZERO_STRUCT(response);
59
60 info = talloc(NULL, struct wbcInterfaceDetails);
61 BAIL_ON_PTR_ERROR(info, wbc_status);
62
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;
67
68 /* then the samba version and the winbind separator */
69 wbc_status = wbcRequestResponse(WINBINDD_INFO, NULL, &response);
70 BAIL_ON_WBC_ERROR(wbc_status);
71
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;
76
77 /* then the local netbios name */
78 wbc_status = wbcRequestResponse(WINBINDD_NETBIOS_NAME, NULL, &response);
79 BAIL_ON_WBC_ERROR(wbc_status);
80
81 info->netbios_name = talloc_strdup(info,
82 response.data.netbios_name);
83 BAIL_ON_PTR_ERROR(info->netbios_name, wbc_status);
84
85 /* then the local workgroup name */
86 wbc_status = wbcRequestResponse(WINBINDD_DOMAIN_NAME, NULL, &response);
87 BAIL_ON_WBC_ERROR(wbc_status);
88
89 info->netbios_domain = talloc_strdup(info,
90 response.data.domain_name);
91 BAIL_ON_PTR_ERROR(info->netbios_domain, wbc_status);
92
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);
100 }
101
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;
109 }
110
111 *_details = info;
112 info = NULL;
113
114 wbc_status = WBC_ERR_SUCCESS;
115
116 done:
117 talloc_free(info);
118 return wbc_status;
119 }
120
121
122 /* Lookup the current status of a trusted domain */
123 wbcErr wbcDomainInfo(const char *domain, struct wbcDomainInfo **dinfo)
/* [<][>][^][v][top][bottom][index][help] */
124 {
125 struct winbindd_request request;
126 struct winbindd_response response;
127 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
128 struct wbcDomainInfo *info = NULL;
129
130 if (!domain || !dinfo) {
131 wbc_status = WBC_ERR_INVALID_PARAM;
132 BAIL_ON_WBC_ERROR(wbc_status);
133 }
134
135 /* Initialize request */
136
137 ZERO_STRUCT(request);
138 ZERO_STRUCT(response);
139
140 strncpy(request.domain_name, domain,
141 sizeof(request.domain_name)-1);
142
143 wbc_status = wbcRequestResponse(WINBINDD_DOMAIN_INFO,
144 &request,
145 &response);
146 BAIL_ON_WBC_ERROR(wbc_status);
147
148 info = talloc(NULL, struct wbcDomainInfo);
149 BAIL_ON_PTR_ERROR(info, wbc_status);
150
151 info->short_name = talloc_strdup(info,
152 response.data.domain_info.name);
153 BAIL_ON_PTR_ERROR(info->short_name, wbc_status);
154
155 info->dns_name = talloc_strdup(info,
156 response.data.domain_info.alt_name);
157 BAIL_ON_PTR_ERROR(info->dns_name, wbc_status);
158
159 wbc_status = wbcStringToSid(response.data.domain_info.sid,
160 &info->sid);
161 BAIL_ON_WBC_ERROR(wbc_status);
162
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;
169
170 *dinfo = info;
171
172 wbc_status = WBC_ERR_SUCCESS;
173
174 done:
175 if (!WBC_ERROR_IS_OK(wbc_status)) {
176 talloc_free(info);
177 }
178
179 return wbc_status;
180 }
181
182
183 /* Resolve a NetbiosName via WINS */
184 wbcErr wbcResolveWinsByName(const char *name, char **ip)
/* [<][>][^][v][top][bottom][index][help] */
185 {
186 struct winbindd_request request;
187 struct winbindd_response response;
188 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
189 char *ipaddr;
190
191 ZERO_STRUCT(request);
192 ZERO_STRUCT(response);
193
194 /* Send request */
195
196 strncpy(request.data.winsreq, name,
197 sizeof(request.data.winsreq)-1);
198
199 wbc_status = wbcRequestResponse(WINBINDD_WINS_BYNAME,
200 &request,
201 &response);
202 BAIL_ON_WBC_ERROR(wbc_status);
203
204 /* Display response */
205
206 ipaddr = talloc_strdup(NULL, response.data.winsresp);
207 BAIL_ON_PTR_ERROR(ipaddr, wbc_status);
208
209 *ip = ipaddr;
210 wbc_status = WBC_ERR_SUCCESS;
211
212 done:
213 return wbc_status;
214 }
215
216 /* Resolve an IP address via WINS into a NetbiosName */
217 wbcErr wbcResolveWinsByIP(const char *ip, char **name)
/* [<][>][^][v][top][bottom][index][help] */
218 {
219 struct winbindd_request request;
220 struct winbindd_response response;
221 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
222 char *name_str;
223
224 ZERO_STRUCT(request);
225 ZERO_STRUCT(response);
226
227 /* Send request */
228
229 strncpy(request.data.winsreq, ip,
230 sizeof(request.data.winsreq)-1);
231
232 wbc_status = wbcRequestResponse(WINBINDD_WINS_BYIP,
233 &request,
234 &response);
235 BAIL_ON_WBC_ERROR(wbc_status);
236
237 /* Display response */
238
239 name_str = talloc_strdup(NULL, response.data.winsresp);
240 BAIL_ON_PTR_ERROR(name_str, wbc_status);
241
242 *name = name_str;
243 wbc_status = WBC_ERR_SUCCESS;
244
245 done:
246 return wbc_status;
247 }
248
249 /**
250 */
251
252 static wbcErr process_domain_info_string(TALLOC_CTX *ctx,
/* [<][>][^][v][top][bottom][index][help] */
253 struct wbcDomainInfo *info,
254 char *info_string)
255 {
256 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
257 char *r = NULL;
258 char *s = NULL;
259
260 if (!info || !info_string) {
261 wbc_status = WBC_ERR_INVALID_PARAM;
262 BAIL_ON_WBC_ERROR(wbc_status);
263 }
264
265 ZERO_STRUCTP(info);
266
267 r = info_string;
268
269 /* Short Name */
270 if ((s = strchr(r, '\\')) == NULL) {
271 wbc_status = WBC_ERR_INVALID_RESPONSE;
272 BAIL_ON_WBC_ERROR(wbc_status);
273 }
274 *s = '\0';
275 s++;
276
277 info->short_name = talloc_strdup(ctx, r);
278 BAIL_ON_PTR_ERROR(info->short_name, wbc_status);
279
280
281 /* DNS Name */
282 r = s;
283 if ((s = strchr(r, '\\')) == NULL) {
284 wbc_status = WBC_ERR_INVALID_RESPONSE;
285 BAIL_ON_WBC_ERROR(wbc_status);
286 }
287 *s = '\0';
288 s++;
289
290 info->dns_name = talloc_strdup(ctx, r);
291 BAIL_ON_PTR_ERROR(info->dns_name, wbc_status);
292
293 /* SID */
294 r = s;
295 if ((s = strchr(r, '\\')) == NULL) {
296 wbc_status = WBC_ERR_INVALID_RESPONSE;
297 BAIL_ON_WBC_ERROR(wbc_status);
298 }
299 *s = '\0';
300 s++;
301
302 wbc_status = wbcStringToSid(r, &info->sid);
303 BAIL_ON_WBC_ERROR(wbc_status);
304
305 /* Trust type */
306 r = s;
307 if ((s = strchr(r, '\\')) == NULL) {
308 wbc_status = WBC_ERR_INVALID_RESPONSE;
309 BAIL_ON_WBC_ERROR(wbc_status);
310 }
311 *s = '\0';
312 s++;
313
314 if (strcmp(r, "None") == 0) {
315 info->trust_type = WBC_DOMINFO_TRUSTTYPE_NONE;
316 } else if (strcmp(r, "External") == 0) {
317 info->trust_type = WBC_DOMINFO_TRUSTTYPE_EXTERNAL;
318 } else if (strcmp(r, "Forest") == 0) {
319 info->trust_type = WBC_DOMINFO_TRUSTTYPE_FOREST;
320 } else if (strcmp(r, "In Forest") == 0) {
321 info->trust_type = WBC_DOMINFO_TRUSTTYPE_IN_FOREST;
322 } else {
323 wbc_status = WBC_ERR_INVALID_RESPONSE;
324 BAIL_ON_WBC_ERROR(wbc_status);
325 }
326
327 /* Transitive */
328 r = s;
329 if ((s = strchr(r, '\\')) == NULL) {
330 wbc_status = WBC_ERR_INVALID_RESPONSE;
331 BAIL_ON_WBC_ERROR(wbc_status);
332 }
333 *s = '\0';
334 s++;
335
336 if (strcmp(r, "Yes") == 0) {
337 info->trust_flags |= WBC_DOMINFO_TRUST_TRANSITIVE;
338 }
339
340 /* Incoming */
341 r = s;
342 if ((s = strchr(r, '\\')) == NULL) {
343 wbc_status = WBC_ERR_INVALID_RESPONSE;
344 BAIL_ON_WBC_ERROR(wbc_status);
345 }
346 *s = '\0';
347 s++;
348
349 if (strcmp(r, "Yes") == 0) {
350 info->trust_flags |= WBC_DOMINFO_TRUST_INCOMING;
351 }
352
353 /* Outgoing */
354 r = s;
355 if ((s = strchr(r, '\\')) == NULL) {
356 wbc_status = WBC_ERR_INVALID_RESPONSE;
357 BAIL_ON_WBC_ERROR(wbc_status);
358 }
359 *s = '\0';
360 s++;
361
362 if (strcmp(r, "Yes") == 0) {
363 info->trust_flags |= WBC_DOMINFO_TRUST_OUTGOING;
364 }
365
366 /* Online/Offline status */
367
368 r = s;
369 if (r == NULL) {
370 wbc_status = WBC_ERR_INVALID_RESPONSE;
371 BAIL_ON_WBC_ERROR(wbc_status);
372 }
373 if ( strcmp(r, "Offline") == 0) {
374 info->domain_flags |= WBC_DOMINFO_DOMAIN_OFFLINE;
375 }
376
377 wbc_status = WBC_ERR_SUCCESS;
378
379 done:
380 return wbc_status;
381 }
382
383 /* Enumerate the domain trusts known by Winbind */
384 wbcErr wbcListTrusts(struct wbcDomainInfo **domains, size_t *num_domains)
/* [<][>][^][v][top][bottom][index][help] */
385 {
386 struct winbindd_response response;
387 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
388 char *p = NULL;
389 char *q = NULL;
390 char *extra_data = NULL;
391 int count = 0;
392 struct wbcDomainInfo *d_list = NULL;
393 int i = 0;
394
395 *domains = NULL;
396 *num_domains = 0;
397
398 ZERO_STRUCT(response);
399
400 /* Send request */
401
402 wbc_status = wbcRequestResponse(WINBINDD_LIST_TRUSTDOM,
403 NULL,
404 &response);
405 BAIL_ON_WBC_ERROR(wbc_status);
406
407 /* Decode the response */
408
409 p = (char *)response.extra_data.data;
410
411 if (strlen(p) == 0) {
412 /* We should always at least get back our
413 own SAM domain */
414
415 wbc_status = WBC_ERR_DOMAIN_NOT_FOUND;
416 BAIL_ON_WBC_ERROR(wbc_status);
417 }
418
419 /* Count number of domains */
420
421 count = 0;
422 while (p) {
423 count++;
424
425 if ((q = strchr(p, '\n')) != NULL)
426 q++;
427 p = q;
428 }
429
430 d_list = talloc_array(NULL, struct wbcDomainInfo, count);
431 BAIL_ON_PTR_ERROR(d_list, wbc_status);
432
433 extra_data = strdup((char*)response.extra_data.data);
434 BAIL_ON_PTR_ERROR(extra_data, wbc_status);
435
436 p = extra_data;
437
438 /* Outer loop processes the list of domain information */
439
440 for (i=0; i<count && p; i++) {
441 char *next = strchr(p, '\n');
442
443 if (next) {
444 *next = '\0';
445 next++;
446 }
447
448 wbc_status = process_domain_info_string(d_list, &d_list[i], p);
449 BAIL_ON_WBC_ERROR(wbc_status);
450
451 p = next;
452 }
453
454 *domains = d_list;
455 *num_domains = i;
456
457 done:
458 if (!WBC_ERROR_IS_OK(wbc_status)) {
459 if (d_list)
460 talloc_free(d_list);
461 if (extra_data)
462 free(extra_data);
463 }
464
465 return wbc_status;
466 }
467
468 /* Enumerate the domain trusts known by Winbind */
469 wbcErr wbcLookupDomainController(const char *domain,
/* [<][>][^][v][top][bottom][index][help] */
470 uint32_t flags,
471 struct wbcDomainControllerInfo **dc_info)
472 {
473 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
474 struct winbindd_request request;
475 struct winbindd_response response;
476 struct wbcDomainControllerInfo *dc = NULL;
477
478 /* validate input params */
479
480 if (!domain || !dc_info) {
481 wbc_status = WBC_ERR_INVALID_PARAM;
482 BAIL_ON_WBC_ERROR(wbc_status);
483 }
484
485 ZERO_STRUCT(request);
486 ZERO_STRUCT(response);
487
488 strncpy(request.domain_name, domain, sizeof(request.domain_name)-1);
489
490 request.flags = flags;
491
492 dc = talloc(NULL, struct wbcDomainControllerInfo);
493 BAIL_ON_PTR_ERROR(dc, wbc_status);
494
495 /* Send request */
496
497 wbc_status = wbcRequestResponse(WINBINDD_DSGETDCNAME,
498 &request,
499 &response);
500 BAIL_ON_WBC_ERROR(wbc_status);
501
502 dc->dc_name = talloc_strdup(dc, response.data.dc_name);
503 BAIL_ON_PTR_ERROR(dc->dc_name, wbc_status);
504
505 *dc_info = dc;
506
507 done:
508 if (!WBC_ERROR_IS_OK(wbc_status)) {
509 talloc_free(dc);
510 }
511
512 return wbc_status;
513 }
514
515 static wbcErr wbc_create_domain_controller_info_ex(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
516 const struct winbindd_response *resp,
517 struct wbcDomainControllerInfoEx **_i)
518 {
519 wbcErr wbc_status = WBC_ERR_SUCCESS;
520 struct wbcDomainControllerInfoEx *i;
521 struct wbcGuid guid;
522
523 i = talloc(mem_ctx, struct wbcDomainControllerInfoEx);
524 BAIL_ON_PTR_ERROR(i, wbc_status);
525
526 i->dc_unc = talloc_strdup(i, resp->data.dsgetdcname.dc_unc);
527 BAIL_ON_PTR_ERROR(i->dc_unc, wbc_status);
528
529 i->dc_address = talloc_strdup(i, resp->data.dsgetdcname.dc_address);
530 BAIL_ON_PTR_ERROR(i->dc_address, wbc_status);
531
532 i->dc_address_type = resp->data.dsgetdcname.dc_address_type;
533
534 wbc_status = wbcStringToGuid(resp->data.dsgetdcname.domain_guid, &guid);
535 if (WBC_ERROR_IS_OK(wbc_status)) {
536 i->domain_guid = talloc(i, struct wbcGuid);
537 BAIL_ON_PTR_ERROR(i->domain_guid, wbc_status);
538
539 *i->domain_guid = guid;
540 } else {
541 i->domain_guid = NULL;
542 }
543
544 i->domain_name = talloc_strdup(i, resp->data.dsgetdcname.domain_name);
545 BAIL_ON_PTR_ERROR(i->domain_name, wbc_status);
546
547 if (resp->data.dsgetdcname.forest_name[0] != '\0') {
548 i->forest_name = talloc_strdup(i,
549 resp->data.dsgetdcname.forest_name);
550 BAIL_ON_PTR_ERROR(i->forest_name, wbc_status);
551 } else {
552 i->forest_name = NULL;
553 }
554
555 i->dc_flags = resp->data.dsgetdcname.dc_flags;
556
557 if (resp->data.dsgetdcname.dc_site_name[0] != '\0') {
558 i->dc_site_name = talloc_strdup(i,
559 resp->data.dsgetdcname.dc_site_name);
560 BAIL_ON_PTR_ERROR(i->dc_site_name, wbc_status);
561 } else {
562 i->dc_site_name = NULL;
563 }
564
565 if (resp->data.dsgetdcname.client_site_name[0] != '\0') {
566 i->client_site_name = talloc_strdup(i,
567 resp->data.dsgetdcname.client_site_name);
568 BAIL_ON_PTR_ERROR(i->client_site_name, wbc_status);
569 } else {
570 i->client_site_name = NULL;
571 }
572
573 *_i = i;
574 i = NULL;
575
576 done:
577 talloc_free(i);
578 return wbc_status;
579 }
580
581 /* Get extended domain controller information */
582 wbcErr wbcLookupDomainControllerEx(const char *domain,
/* [<][>][^][v][top][bottom][index][help] */
583 struct wbcGuid *guid,
584 const char *site,
585 uint32_t flags,
586 struct wbcDomainControllerInfoEx **dc_info)
587 {
588 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
589 struct winbindd_request request;
590 struct winbindd_response response;
591
592 /* validate input params */
593
594 if (!domain || !dc_info) {
595 wbc_status = WBC_ERR_INVALID_PARAM;
596 BAIL_ON_WBC_ERROR(wbc_status);
597 }
598
599 ZERO_STRUCT(request);
600 ZERO_STRUCT(response);
601
602 request.data.dsgetdcname.flags = flags;
603
604 strncpy(request.data.dsgetdcname.domain_name, domain,
605 sizeof(request.data.dsgetdcname.domain_name)-1);
606
607 if (site) {
608 strncpy(request.data.dsgetdcname.site_name, site,
609 sizeof(request.data.dsgetdcname.site_name)-1);
610 }
611
612 if (guid) {
613 char *str = NULL;
614
615 wbc_status = wbcGuidToString(guid, &str);
616 BAIL_ON_WBC_ERROR(wbc_status);
617
618 strncpy(request.data.dsgetdcname.domain_guid, str,
619 sizeof(request.data.dsgetdcname.domain_guid)-1);
620
621 wbcFreeMemory(str);
622 }
623
624 /* Send request */
625
626 wbc_status = wbcRequestResponse(WINBINDD_DSGETDCNAME,
627 &request,
628 &response);
629 BAIL_ON_WBC_ERROR(wbc_status);
630
631 if (dc_info) {
632 wbc_status = wbc_create_domain_controller_info_ex(NULL,
633 &response,
634 dc_info);
635 BAIL_ON_WBC_ERROR(wbc_status);
636 }
637
638 wbc_status = WBC_ERR_SUCCESS;
639 done:
640 return wbc_status;
641 }
642
643 /* Initialize a named blob and add to list of blobs */
644 wbcErr wbcAddNamedBlob(size_t *num_blobs,
/* [<][>][^][v][top][bottom][index][help] */
645 struct wbcNamedBlob **blobs,
646 const char *name,
647 uint32_t flags,
648 uint8_t *data,
649 size_t length)
650 {
651 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
652 struct wbcNamedBlob blob;
653
654 *blobs = talloc_realloc(NULL, *blobs, struct wbcNamedBlob,
655 *(num_blobs)+1);
656 BAIL_ON_PTR_ERROR(*blobs, wbc_status);
657
658 blob.name = talloc_strdup(*blobs, name);
659 BAIL_ON_PTR_ERROR(blob.name, wbc_status);
660 blob.flags = flags;
661 blob.blob.length = length;
662 blob.blob.data = (uint8_t *)talloc_memdup(*blobs, data, length);
663 BAIL_ON_PTR_ERROR(blob.blob.data, wbc_status);
664
665 (*(blobs))[*num_blobs] = blob;
666 *(num_blobs) += 1;
667
668 wbc_status = WBC_ERR_SUCCESS;
669 done:
670 if (!WBC_ERROR_IS_OK(wbc_status) && blobs) {
671 wbcFreeMemory(*blobs);
672 }
673 return wbc_status;
674 }