Print this page
NEX-20555 idmap fall-back to DC discovery is broken
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-3155 idmap in a loop spamming its svc log
Reviewed by: Bayard Bell <bayard.bell@nexenta.com>
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Tony Nguyen <tony.nguyen@nexenta.com>
NEX-2892 NexentaStor losing connectivity to multihomed AD servers
Reviewed by: Bayard Bell <bayard.bell@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-2225 Unable to join NexentaStor to 2008 AD
NEX-1638 Updated DC Locator
Includes work by: matt.barden@nexenta.com, kevin.crowe@nexenta.com
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/lib/libadutils/common/addisc.c
+++ new/usr/src/lib/libadutils/common/addisc.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
|
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24 - * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
24 + * Copyright 2019 Nexenta Systems, Inc. All rights reserved.
25 25 */
26 26
27 27 /*
28 28 * Active Directory Auto-Discovery.
29 29 *
30 30 * This [project private] API allows the caller to provide whatever
31 31 * details it knows a priori (i.e., provided via configuration so as to
32 32 * override auto-discovery) and in any order. Then the caller can ask
33 33 * for any of the auto-discoverable parameters in any order.
34 34 *
35 35 * But there is an actual order in which discovery must be done. Given
36 36 * the discovery mechanism implemented here, that order is:
37 37 *
38 38 * - the domain name joined must be discovered first
39 39 * - then the domain controllers
40 40 * - then the forest name and site name
41 41 * - then the global catalog servers, and site-specific domain
42 42 * controllers and global catalog servers.
43 43 *
44 44 * The API does not require it be called in the same order because there
45 45 * may be other discovery mechanisms in the future, and exposing
46 46 * ordering requirements of the current mechanism now can create trouble
47 47 * down the line. Also, this makes the API easier to use now, which
48 48 * means less work to do some day when we make this a public API.
49 49 *
50 50 * Domain discovery is done by res_nsearch() of the DNS SRV RR name for
51 51 * domain controllers. As long as the joined domain appears in the DNS
52 52 * resolver's search list then we'll find it.
53 53 *
54 54 * Domain controller discovery is a matter of formatting the DNS SRV RR
55 55 * FQDN for domain controllers and doing a lookup for them. Knowledge
56 56 * of the domain name is not fundamentally required, but we separate the
57 57 * two processes, which in practice can lead to one more DNS lookup than
58 58 * is strictly required.
59 59 *
60 60 * Forest and site name discovery require an LDAP search of the AD
61 61 * "configuration partition" at a domain controller for the joined
62 62 * domain. Forest and site name discovery depend on knowing the joined
63 63 * domain name and domain controllers for that domain.
64 64 *
65 65 * Global catalog server discovery requires knowledge of the forest
66 66 * name in order to format the DNS SRV RR FQDN to lookup. Site-specific
67 67 * domain controller discovery depends on knowing the site name (and,
68 68 * therefore, joined domain, ...). Site-specific global catalog server
69 69 * discovery depends on knowledge of the forest and site names, which
70 70 * depend on...
71 71 *
72 72 * All the work of discovering particular items is done by functions
73 73 * named validate_<item>(). Each such function calls validate_<item>()
74 74 * for any items that it depends on.
75 75 *
76 76 * This API is not thread-safe.
77 77 */
78 78
79 79
80 80 #include <stdio.h>
81 81 #include <string.h>
82 82 #include <strings.h>
83 83 #include <unistd.h>
84 84 #include <assert.h>
85 85 #include <stdlib.h>
86 86 #include <net/if.h>
87 87 #include <sys/types.h>
88 88 #include <sys/socket.h>
89 89 #include <sys/sockio.h>
90 90 #include <netinet/in.h>
91 91 #include <arpa/inet.h>
92 92 #include <arpa/nameser.h>
93 93 #include <resolv.h>
94 94 #include <netdb.h>
95 95 #include <ctype.h>
96 96 #include <errno.h>
97 97 #include <ldap.h>
98 98 #include <note.h>
99 99 #include <sasl/sasl.h>
100 100 #include <sys/u8_textprep.h>
101 101 #include <syslog.h>
102 102 #include <uuid/uuid.h>
103 103 #include <ads/dsgetdc.h>
104 104 #include "adutils_impl.h"
105 105 #include "addisc_impl.h"
106 106
107 107 /*
108 108 * These set some sanity policies for discovery. After a discovery
109 109 * cycle, we will consider the results (successful or unsuccessful)
110 110 * to be valid for at least MINIMUM_TTL seconds, and for at most
111 111 * MAXIMUM_TTL seconds. Note that the caller is free to request
112 112 * discovery cycles sooner than MINIMUM_TTL if it has reason to believe
113 113 * that the situation has changed.
114 114 */
115 115 #define MINIMUM_TTL (5 * 60)
116 116 #define MAXIMUM_TTL (20 * 60)
117 117
118 118
119 119 #define DNS_MAX_NAME NS_MAXDNAME
120 120
121 121 #define GC_PORT 3268
122 122
123 123 /* SRV RR names for various queries */
124 124 #define LDAP_SRV_HEAD "_ldap._tcp."
125 125 #define SITE_SRV_MIDDLE "%s._sites."
126 126 #define GC_SRV_TAIL "gc._msdcs"
127 127 #define DC_SRV_TAIL "dc._msdcs"
128 128 #define ALL_GC_SRV_TAIL "_gc._tcp"
129 129 #define PDC_SRV "_ldap._tcp.pdc._msdcs.%s"
130 130
131 131 /* A RR name for all GCs -- last resort this works */
132 132 #define GC_ALL_A_NAME_FSTR "gc._msdcs.%s."
133 133
134 134
135 135 /*
136 136 * We try res_ninit() whenever we don't have one. res_ninit() fails if
137 137 * idmapd is running before the network is up!
138 138 */
139 139 #define DO_RES_NINIT(ctx) \
140 140 if (!(ctx)->res_ninitted) \
141 141 (void) do_res_ninit(ctx)
142 142
143 143 #define DO_GETNAMEINFO(b, l, s) \
144 144 if (ad_disc_getnameinfo(b, l, s) != 0) \
145 145 (void) strlcpy(b, "?", l)
146 146
147 147 #define DEBUG1STATUS(ctx, ...) do { \
148 148 if (DBG(DISC, 1)) \
149 149 logger(LOG_DEBUG, __VA_ARGS__); \
150 150 if (ctx->status_fp) { \
151 151 (void) fprintf(ctx->status_fp, __VA_ARGS__); \
152 152 (void) fprintf(ctx->status_fp, "\n"); \
153 153 } \
154 154 _NOTE(CONSTCOND) \
155 155 } while (0)
156 156
157 157 #define is_fixed(item) \
158 158 ((item)->state == AD_STATE_FIXED)
159 159
160 160 #define is_changed(item, num, param) \
161 161 ((item)->param_version[num] != (param)->version)
162 162
163 163 void * uuid_dup(void *);
164 164
165 165 static ad_item_t *validate_SiteName(ad_disc_t ctx);
166 166 static ad_item_t *validate_PreferredDC(ad_disc_t ctx);
167 167
168 168 /*
169 169 * Function definitions
170 170 */
171 171
172 172
173 173 static int
174 174 do_res_ninit(ad_disc_t ctx)
175 175 {
176 176 int rc;
177 177
178 178 rc = res_ninit(&ctx->res_state);
179 179 if (rc != 0)
180 180 return (rc);
181 181 ctx->res_ninitted = 1;
182 182 /*
183 183 * The SRV records returnd by AD can be larger than 512 bytes,
184 184 * so we'd like to use TCP for those searches. Unfortunately,
185 185 * the TCP connect timeout seen by the resolver is very long
186 186 * (more than a couple minutes) and we can't wait that long.
187 187 * Don't do use TCP until we can override the timeout.
188 188 *
189 189 * Note that some queries will try TCP anyway.
190 190 */
191 191 #if 0
192 192 ctx->res_state.options |= RES_USEVC;
193 193 #endif
194 194 return (0);
195 195 }
196 196
197 197 /*
198 198 * Private getnameinfo(3socket) variant tailored to our needs.
199 199 */
200 200 int
201 201 ad_disc_getnameinfo(char *obuf, int olen, struct sockaddr_storage *ss)
202 202 {
203 203 struct sockaddr *sa;
204 204 int eai, slen;
205 205
206 206 sa = (void *)ss;
207 207 switch (sa->sa_family) {
208 208 case AF_INET:
209 209 slen = sizeof (struct sockaddr_in);
210 210 break;
211 211 case AF_INET6:
212 212 slen = sizeof (struct sockaddr_in6);
213 213 break;
214 214 default:
215 215 return (EAI_FAMILY);
216 216 }
217 217
218 218 eai = getnameinfo(sa, slen, obuf, olen, NULL, 0, NI_NUMERICHOST);
219 219
220 220 return (eai);
221 221 }
222 222
223 223 static void
224 224 update_version(ad_item_t *item, int num, ad_item_t *param)
225 225 {
226 226 item->param_version[num] = param->version;
227 227 }
228 228
229 229
230 230
231 231 static boolean_t
232 232 is_valid(ad_item_t *item)
233 233 {
234 234 if (item->value != NULL) {
235 235 if (item->state == AD_STATE_FIXED)
236 236 return (B_TRUE);
237 237 if (item->state == AD_STATE_AUTO &&
238 238 (item->expires == 0 || item->expires > time(NULL)))
239 239 return (B_TRUE);
240 240 }
241 241 return (B_FALSE);
242 242 }
243 243
244 244
245 245 static void
246 246 update_item(ad_item_t *item, void *value, enum ad_item_state state,
247 247 uint32_t ttl)
248 248 {
249 249 if (item->value != NULL && value != NULL) {
250 250 if ((item->type == AD_STRING &&
251 251 strcmp(item->value, value) != 0) ||
252 252 (item->type == AD_UUID &&
253 253 ad_disc_compare_uuid(item->value, value) != 0)||
254 254 (item->type == AD_DIRECTORY &&
255 255 ad_disc_compare_ds(item->value, value) != 0)||
256 256 (item->type == AD_DOMAINS_IN_FOREST &&
257 257 ad_disc_compare_domainsinforest(item->value, value) != 0) ||
258 258 (item->type == AD_TRUSTED_DOMAINS &&
259 259 ad_disc_compare_trusteddomains(item->value, value) != 0))
260 260 item->version++;
261 261 } else if (item->value != value)
262 262 item->version++;
263 263
264 264 if (item->value != NULL)
265 265 free(item->value);
266 266
267 267 item->value = value;
268 268 item->state = state;
269 269
270 270 if (ttl == 0)
271 271 item->expires = 0;
272 272 else
273 273 item->expires = time(NULL) + ttl;
274 274 }
275 275
276 276 /* Compare UUIDs */
277 277 int
278 278 ad_disc_compare_uuid(uuid_t *u1, uuid_t *u2)
279 279 {
280 280 int rc;
281 281
282 282 rc = memcmp(u1, u2, UUID_LEN);
283 283 return (rc);
284 284 }
285 285
286 286 void *
287 287 uuid_dup(void *src)
288 288 {
289 289 void *dst;
290 290 dst = malloc(UUID_LEN);
291 291 if (dst != NULL)
292 292 (void) memcpy(dst, src, UUID_LEN);
293 293 return (dst);
294 294 }
295 295
296 296 /* Compare DS lists */
297 297 int
298 298 ad_disc_compare_ds(ad_disc_ds_t *ds1, ad_disc_ds_t *ds2)
299 299 {
300 300 int i, j;
301 301 int num_ds1;
302 302 int num_ds2;
303 303 boolean_t match;
304 304
305 305 for (i = 0; ds1[i].host[0] != '\0'; i++)
306 306 continue;
307 307 num_ds1 = i;
308 308 for (j = 0; ds2[j].host[0] != '\0'; j++)
309 309 continue;
310 310 num_ds2 = j;
311 311 if (num_ds1 != num_ds2)
312 312 return (1);
313 313
314 314 for (i = 0; i < num_ds1; i++) {
315 315 match = B_FALSE;
316 316 for (j = 0; j < num_ds2; j++) {
317 317 if (strcmp(ds1[i].host, ds2[j].host) == 0 &&
318 318 ds1[i].port == ds2[j].port) {
319 319 match = B_TRUE;
320 320 break;
321 321 }
322 322 }
323 323 if (!match)
324 324 return (1);
325 325 }
326 326 return (0);
327 327 }
328 328
329 329
330 330 /* Copy a list of DSs */
331 331 static ad_disc_ds_t *
332 332 ds_dup(const ad_disc_ds_t *srv)
333 333 {
334 334 int i;
335 335 int size;
336 336 ad_disc_ds_t *new = NULL;
337 337
338 338 for (i = 0; srv[i].host[0] != '\0'; i++)
339 339 continue;
340 340
341 341 size = (i + 1) * sizeof (ad_disc_ds_t);
342 342 new = malloc(size);
343 343 if (new != NULL)
344 344 (void) memcpy(new, srv, size);
345 345 return (new);
346 346 }
347 347
348 348
349 349 int
350 350 ad_disc_compare_trusteddomains(ad_disc_trusteddomains_t *td1,
351 351 ad_disc_trusteddomains_t *td2)
352 352 {
353 353 int i, j;
354 354 int num_td1;
355 355 int num_td2;
356 356 boolean_t match;
357 357
358 358 for (i = 0; td1[i].domain[0] != '\0'; i++)
359 359 continue;
360 360 num_td1 = i;
361 361
362 362 for (j = 0; td2[j].domain[0] != '\0'; j++)
363 363 continue;
364 364 num_td2 = j;
365 365
366 366 if (num_td1 != num_td2)
367 367 return (1);
368 368
369 369 for (i = 0; i < num_td1; i++) {
370 370 match = B_FALSE;
371 371 for (j = 0; j < num_td2; j++) {
372 372 if (domain_eq(td1[i].domain, td2[j].domain)) {
373 373 match = B_TRUE;
374 374 break;
375 375 }
376 376 }
377 377 if (!match)
378 378 return (1);
379 379 }
380 380 return (0);
381 381 }
382 382
383 383
384 384
385 385 /* Copy a list of Trusted Domains */
386 386 static ad_disc_trusteddomains_t *
387 387 td_dup(const ad_disc_trusteddomains_t *td)
388 388 {
389 389 int i;
390 390 int size;
391 391 ad_disc_trusteddomains_t *new = NULL;
392 392
393 393 for (i = 0; td[i].domain[0] != '\0'; i++)
394 394 continue;
395 395
396 396 size = (i + 1) * sizeof (ad_disc_trusteddomains_t);
397 397 new = malloc(size);
398 398 if (new != NULL)
399 399 (void) memcpy(new, td, size);
400 400 return (new);
401 401 }
402 402
403 403
404 404
405 405 int
406 406 ad_disc_compare_domainsinforest(ad_disc_domainsinforest_t *df1,
407 407 ad_disc_domainsinforest_t *df2)
408 408 {
409 409 int i, j;
410 410 int num_df1;
411 411 int num_df2;
412 412 boolean_t match;
413 413
414 414 for (i = 0; df1[i].domain[0] != '\0'; i++)
415 415 continue;
416 416 num_df1 = i;
417 417
418 418 for (j = 0; df2[j].domain[0] != '\0'; j++)
419 419 continue;
420 420 num_df2 = j;
421 421
422 422 if (num_df1 != num_df2)
423 423 return (1);
424 424
425 425 for (i = 0; i < num_df1; i++) {
426 426 match = B_FALSE;
427 427 for (j = 0; j < num_df2; j++) {
428 428 if (domain_eq(df1[i].domain, df2[j].domain) &&
429 429 strcmp(df1[i].sid, df2[j].sid) == 0) {
430 430 match = B_TRUE;
431 431 break;
432 432 }
433 433 }
434 434 if (!match)
435 435 return (1);
436 436 }
437 437 return (0);
438 438 }
439 439
440 440
441 441
442 442 /* Copy a list of Trusted Domains */
443 443 static ad_disc_domainsinforest_t *
444 444 df_dup(const ad_disc_domainsinforest_t *df)
445 445 {
446 446 int i;
447 447 int size;
448 448 ad_disc_domainsinforest_t *new = NULL;
449 449
450 450 for (i = 0; df[i].domain[0] != '\0'; i++)
451 451 continue;
452 452
453 453 size = (i + 1) * sizeof (ad_disc_domainsinforest_t);
454 454 new = malloc(size);
455 455 if (new != NULL)
456 456 (void) memcpy(new, df, size);
457 457 return (new);
458 458 }
459 459
460 460
461 461
462 462
463 463
464 464 /*
465 465 * Returns an array of IPv4 address/prefix length
466 466 * The last subnet is NULL
467 467 */
468 468 static ad_subnet_t *
469 469 find_subnets()
470 470 {
471 471 int sock, n, i;
472 472 struct lifconf lifc;
473 473 struct lifreq lifr, *lifrp;
474 474 struct lifnum lifn;
475 475 uint32_t prefix_len;
476 476 char *s;
477 477 ad_subnet_t *results;
478 478
479 479 lifrp = &lifr;
480 480
481 481 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
482 482 logger(LOG_ERR, "Failed to open IPv4 socket for "
483 483 "listing network interfaces (%s)", strerror(errno));
484 484 return (NULL);
485 485 }
486 486
487 487 lifn.lifn_family = AF_INET;
488 488 lifn.lifn_flags = 0;
489 489 if (ioctl(sock, SIOCGLIFNUM, (char *)&lifn) < 0) {
490 490 logger(LOG_ERR,
491 491 "Failed to find the number of network interfaces (%s)",
492 492 strerror(errno));
493 493 (void) close(sock);
494 494 return (NULL);
495 495 }
496 496
497 497 if (lifn.lifn_count < 1) {
498 498 logger(LOG_ERR, "No IPv4 network interfaces found");
499 499 (void) close(sock);
500 500 return (NULL);
501 501 }
502 502
503 503 lifc.lifc_family = AF_INET;
504 504 lifc.lifc_flags = 0;
505 505 lifc.lifc_len = lifn.lifn_count * sizeof (struct lifreq);
506 506 lifc.lifc_buf = malloc(lifc.lifc_len);
507 507
508 508 if (lifc.lifc_buf == NULL) {
509 509 logger(LOG_ERR, "Out of memory");
510 510 (void) close(sock);
511 511 return (NULL);
512 512 }
513 513
514 514 if (ioctl(sock, SIOCGLIFCONF, (char *)&lifc) < 0) {
515 515 logger(LOG_ERR, "Failed to list network interfaces (%s)",
516 516 strerror(errno));
517 517 free(lifc.lifc_buf);
518 518 (void) close(sock);
519 519 return (NULL);
520 520 }
521 521
522 522 n = lifc.lifc_len / (int)sizeof (struct lifreq);
523 523
524 524 if ((results = calloc(n + 1, sizeof (ad_subnet_t))) == NULL) {
525 525 free(lifc.lifc_buf);
526 526 (void) close(sock);
527 527 return (NULL);
528 528 }
529 529
530 530 for (i = 0, lifrp = lifc.lifc_req; i < n; i++, lifrp++) {
531 531 if (ioctl(sock, SIOCGLIFFLAGS, lifrp) < 0)
532 532 continue;
533 533
534 534 if ((lifrp->lifr_flags & IFF_UP) == 0)
535 535 continue;
536 536
537 537 if (ioctl(sock, SIOCGLIFSUBNET, lifrp) < 0)
538 538 continue;
539 539
540 540 prefix_len = lifrp->lifr_addrlen;
541 541
542 542 s = inet_ntoa(((struct sockaddr_in *)
543 543 &lifrp->lifr_addr)->sin_addr);
544 544
545 545 (void) snprintf(results[i].subnet, sizeof (ad_subnet_t),
546 546 "%s/%d", s, prefix_len);
547 547 }
548 548
549 549 free(lifc.lifc_buf);
550 550 (void) close(sock);
551 551
552 552 return (results);
553 553 }
554 554
555 555 static int
556 556 cmpsubnets(ad_subnet_t *subnets1, ad_subnet_t *subnets2)
557 557 {
558 558 int num_subnets1;
559 559 int num_subnets2;
560 560 boolean_t matched;
561 561 int i, j;
562 562
563 563 for (i = 0; subnets1[i].subnet[0] != '\0'; i++)
564 564 continue;
565 565 num_subnets1 = i;
566 566
567 567 for (i = 0; subnets2[i].subnet[0] != '\0'; i++)
568 568 continue;
569 569 num_subnets2 = i;
570 570
571 571 if (num_subnets1 != num_subnets2)
572 572 return (1);
573 573
574 574 for (i = 0; i < num_subnets1; i++) {
575 575 matched = B_FALSE;
576 576 for (j = 0; j < num_subnets2; j++) {
577 577 if (strcmp(subnets1[i].subnet,
578 578 subnets2[j].subnet) == 0) {
579 579 matched = B_TRUE;
580 580 break;
581 581 }
582 582 }
583 583 if (!matched)
584 584 return (1);
585 585 }
586 586 return (0);
587 587 }
588 588
589 589
590 590
591 591
592 592 /* Convert a DN's DC components into a DNS domainname */
593 593 char *
594 594 DN_to_DNS(const char *dn_name)
595 595 {
596 596 char dns[DNS_MAX_NAME];
597 597 char *dns_name;
598 598 int i, j;
599 599 int num = 0;
600 600
601 601 j = 0;
602 602 i = 0;
603 603
604 604 if (dn_name == NULL)
605 605 return (NULL);
606 606 /*
607 607 * Find all DC=<value> and form DNS name of the
608 608 * form <value1>.<value2>...
609 609 */
610 610 while (dn_name[i] != '\0') {
611 611 if (strncasecmp(&dn_name[i], "DC=", 3) == 0) {
612 612 i += 3;
613 613 if (dn_name[i] != '\0' && num > 0)
614 614 dns[j++] = '.';
615 615 while (dn_name[i] != '\0' &&
616 616 dn_name[i] != ',' && dn_name[i] != '+')
617 617 dns[j++] = dn_name[i++];
618 618 num++;
619 619 } else {
620 620 /* Skip attr=value as it is not DC= */
621 621 while (dn_name[i] != '\0' &&
622 622 dn_name[i] != ',' && dn_name[i] != '+')
623 623 i++;
624 624 }
625 625 /* Skip over separator ',' or '+' */
626 626 if (dn_name[i] != '\0') i++;
627 627 }
628 628 dns[j] = '\0';
629 629 dns_name = malloc(j + 1);
630 630 if (dns_name != NULL)
631 631 (void) strlcpy(dns_name, dns, j + 1);
632 632 return (dns_name);
633 633 }
634 634
635 635
636 636 /*
637 637 * A utility function to bind to a Directory server
638 638 */
639 639
640 640 static
641 641 LDAP *
642 642 ldap_lookup_init(ad_disc_ds_t *ds)
643 643 {
644 644 int i;
645 645 int rc, ldversion;
646 646 int zero = 0;
647 647 int timeoutms = 5 * 1000;
648 648 char *saslmech = "GSSAPI";
649 649 uint32_t saslflags = LDAP_SASL_INTERACTIVE;
650 650 LDAP *ld = NULL;
651 651
652 652 for (i = 0; ds[i].host[0] != '\0'; i++) {
653 653 if (DBG(LDAP, 2)) {
654 654 logger(LOG_DEBUG, "adutils: ldap_lookup_init, host %s",
655 655 ds[i].host);
656 656 }
657 657
658 658 ld = ldap_init(ds[i].host, ds[i].port);
659 659 if (ld == NULL) {
660 660 if (DBG(LDAP, 1)) {
661 661 logger(LOG_DEBUG,
662 662 "Couldn't connect to AD DC %s:%d (%s)",
663 663 ds[i].host, ds[i].port,
664 664 strerror(errno));
665 665 }
666 666 continue;
667 667 }
668 668
669 669 ldversion = LDAP_VERSION3;
670 670 (void) ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION,
671 671 &ldversion);
672 672 (void) ldap_set_option(ld, LDAP_OPT_REFERRALS,
673 673 LDAP_OPT_OFF);
674 674 (void) ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &zero);
675 675 (void) ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &zero);
676 676 /* setup TCP/IP connect timeout */
677 677 (void) ldap_set_option(ld, LDAP_X_OPT_CONNECT_TIMEOUT,
678 678 &timeoutms);
679 679 (void) ldap_set_option(ld, LDAP_OPT_RESTART,
680 680 LDAP_OPT_ON);
681 681
682 682 rc = adutils_set_thread_functions(ld);
683 683 if (rc != LDAP_SUCCESS) {
684 684 /* Error has already been logged */
685 685 (void) ldap_unbind(ld);
686 686 ld = NULL;
687 687 continue;
688 688 }
689 689
690 690 rc = ldap_sasl_interactive_bind_s(ld, "" /* binddn */,
691 691 saslmech, NULL, NULL, saslflags, &saslcallback,
692 692 NULL /* defaults */);
693 693 if (rc == LDAP_SUCCESS)
694 694 break;
695 695
696 696 if (DBG(LDAP, 0)) {
697 697 logger(LOG_INFO, "LDAP: %s:%d: %s",
698 698 ds[i].host, ds[i].port, ldap_err2string(rc));
699 699 ldap_perror(ld, ds[i].host);
700 700 }
701 701 (void) ldap_unbind(ld);
702 702 ld = NULL;
703 703 }
704 704 return (ld);
705 705 }
706 706
707 707
708 708
709 709 /*
710 710 * Lookup the trusted domains in the global catalog.
711 711 *
712 712 * Returns:
713 713 * array of trusted domains which is terminated by
714 714 * an empty trusted domain.
715 715 * NULL an error occured
716 716 */
717 717 ad_disc_trusteddomains_t *
718 718 ldap_lookup_trusted_domains(LDAP **ld, ad_disc_ds_t *globalCatalog,
719 719 char *base_dn)
720 720 {
721 721 int scope = LDAP_SCOPE_SUBTREE;
722 722 char *attrs[3];
723 723 int rc;
724 724 LDAPMessage *results = NULL;
725 725 LDAPMessage *entry;
726 726 char *filter;
727 727 char **partner = NULL;
728 728 char **direction = NULL;
729 729 int num = 0;
730 730 ad_disc_trusteddomains_t *trusted_domains = NULL;
731 731
732 732 if (DBG(DISC, 1))
733 733 logger(LOG_DEBUG, "Looking for trusted domains...");
734 734
735 735 if (*ld == NULL)
736 736 *ld = ldap_lookup_init(globalCatalog);
737 737
738 738 if (*ld == NULL) {
739 739 logger(LOG_ERR, "adutils: ldap_lookup_init failed");
740 740 return (NULL);
741 741 }
742 742
743 743 attrs[0] = "trustPartner";
744 744 attrs[1] = "trustDirection";
745 745 attrs[2] = NULL;
746 746
747 747 /*
748 748 * Trust direction values:
749 749 * 1 - inbound (they trust us)
750 750 * 2 - outbound (we trust them)
751 751 * 3 - bidirectional (we trust each other)
752 752 */
753 753 filter = "(&(objectclass=trustedDomain)"
754 754 "(|(trustDirection=3)(trustDirection=2)))";
755 755
756 756 rc = ldap_search_s(*ld, base_dn, scope, filter, attrs, 0, &results);
757 757 if (DBG(DISC, 1))
758 758 logger(LOG_DEBUG, "Trusted domains:");
759 759 if (rc == LDAP_SUCCESS) {
760 760 for (entry = ldap_first_entry(*ld, results);
761 761 entry != NULL; entry = ldap_next_entry(*ld, entry)) {
762 762 partner = ldap_get_values(*ld, entry, "trustPartner");
763 763 direction = ldap_get_values(
764 764 *ld, entry, "trustDirection");
765 765
766 766 if (partner != NULL && direction != NULL) {
767 767 if (DBG(DISC, 1)) {
768 768 logger(LOG_DEBUG, " %s (%s)",
769 769 partner[0], direction[0]);
770 770 }
771 771 num++;
772 772 void *tmp = realloc(trusted_domains,
773 773 (num + 1) *
774 774 sizeof (ad_disc_trusteddomains_t));
775 775 if (tmp == NULL) {
776 776 free(trusted_domains);
777 777 ldap_value_free(partner);
778 778 ldap_value_free(direction);
779 779 (void) ldap_msgfree(results);
780 780 return (NULL);
781 781 }
782 782 trusted_domains = tmp;
783 783 /* Last element should be zero */
784 784 (void) memset(&trusted_domains[num], 0,
785 785 sizeof (ad_disc_trusteddomains_t));
786 786 (void) strcpy(trusted_domains[num - 1].domain,
787 787 partner[0]);
788 788 trusted_domains[num - 1].direction =
789 789 atoi(direction[0]);
790 790 }
791 791 if (partner != NULL)
792 792 ldap_value_free(partner);
793 793 if (direction != NULL)
794 794 ldap_value_free(direction);
795 795 }
796 796 } else if (rc == LDAP_NO_RESULTS_RETURNED) {
797 797 /* This is not an error - return empty trusted domain */
798 798 trusted_domains = calloc(1, sizeof (ad_disc_trusteddomains_t));
799 799 if (DBG(DISC, 1))
800 800 logger(LOG_DEBUG, " not found");
801 801 } else {
802 802 if (DBG(DISC, 1))
803 803 logger(LOG_DEBUG, " rc=%d", rc);
804 804 }
805 805 if (results != NULL)
806 806 (void) ldap_msgfree(results);
807 807
808 808 return (trusted_domains);
809 809 }
810 810
811 811
812 812 /*
813 813 * This functions finds all the domains in a forest.
814 814 */
815 815 ad_disc_domainsinforest_t *
816 816 ldap_lookup_domains_in_forest(LDAP **ld, ad_disc_ds_t *globalCatalogs)
817 817 {
818 818 static char *attrs[] = {
819 819 "objectSid",
820 820 NULL,
821 821 };
822 822 int rc;
823 823 LDAPMessage *result = NULL;
824 824 LDAPMessage *entry;
825 825 int ndomains = 0;
826 826 int nresults;
827 827 ad_disc_domainsinforest_t *domains = NULL;
828 828
829 829 if (DBG(DISC, 1))
830 830 logger(LOG_DEBUG, "Looking for domains in forest...");
831 831
832 832 if (*ld == NULL)
833 833 *ld = ldap_lookup_init(globalCatalogs);
834 834
835 835 if (*ld == NULL) {
836 836 logger(LOG_ERR, "adutils: ldap_lookup_init failed");
837 837 return (NULL);
838 838 }
839 839
840 840 /* Find domains */
841 841 rc = ldap_search_s(*ld, "", LDAP_SCOPE_SUBTREE,
842 842 "(objectClass=Domain)", attrs, 0, &result);
843 843 if (rc != LDAP_SUCCESS) {
844 844 logger(LOG_ERR, "adutils: ldap_search, rc=%d", rc);
845 845 goto err;
846 846 }
847 847 if (DBG(DISC, 1))
848 848 logger(LOG_DEBUG, "Domains in forest:");
849 849
850 850 nresults = ldap_count_entries(*ld, result);
851 851 domains = calloc(nresults + 1, sizeof (*domains));
852 852 if (domains == NULL) {
853 853 if (DBG(DISC, 1))
854 854 logger(LOG_DEBUG, " (nomem)");
855 855 goto err;
856 856 }
857 857
858 858 for (entry = ldap_first_entry(*ld, result);
859 859 entry != NULL;
860 860 entry = ldap_next_entry(*ld, entry)) {
861 861 struct berval **sid_ber;
862 862 adutils_sid_t sid;
863 863 char *sid_str;
864 864 char *name;
865 865 char *dn;
866 866
867 867 sid_ber = ldap_get_values_len(*ld, entry,
868 868 "objectSid");
869 869 if (sid_ber == NULL)
870 870 continue;
871 871
872 872 rc = adutils_getsid(sid_ber[0], &sid);
873 873 ldap_value_free_len(sid_ber);
874 874 if (rc < 0)
875 875 goto err;
876 876
877 877 if ((sid_str = adutils_sid2txt(&sid)) == NULL)
878 878 goto err;
879 879
880 880 (void) strcpy(domains[ndomains].sid, sid_str);
881 881 free(sid_str);
882 882
883 883 dn = ldap_get_dn(*ld, entry);
884 884 name = DN_to_DNS(dn);
885 885 free(dn);
886 886 if (name == NULL)
887 887 goto err;
888 888
889 889 (void) strcpy(domains[ndomains].domain, name);
890 890 free(name);
891 891
892 892 if (DBG(DISC, 1))
893 893 logger(LOG_DEBUG, " %s", domains[ndomains].domain);
894 894
895 895 ndomains++;
896 896 }
897 897
898 898 if (ndomains == 0) {
899 899 if (DBG(DISC, 1))
900 900 logger(LOG_DEBUG, " not found");
901 901 goto err;
902 902 }
903 903
904 904 if (ndomains < nresults) {
905 905 ad_disc_domainsinforest_t *tmp;
906 906 tmp = realloc(domains, (ndomains + 1) * sizeof (*domains));
907 907 if (tmp == NULL)
908 908 goto err;
909 909 domains = tmp;
910 910 }
911 911
912 912 if (result != NULL)
913 913 (void) ldap_msgfree(result);
914 914
915 915 return (domains);
916 916
917 917 err:
918 918 free(domains);
919 919 if (result != NULL)
920 920 (void) ldap_msgfree(result);
921 921 return (NULL);
922 922 }
923 923
924 924
925 925 ad_disc_t
926 926 ad_disc_init(void)
927 927 {
928 928 struct ad_disc *ctx;
929 929 ctx = calloc(1, sizeof (struct ad_disc));
930 930 if (ctx != NULL)
931 931 DO_RES_NINIT(ctx);
932 932
933 933 ctx->domain_name.type = AD_STRING;
934 934 ctx->domain_guid.type = AD_UUID;
935 935 ctx->domain_controller.type = AD_DIRECTORY;
936 936 ctx->preferred_dc.type = AD_DIRECTORY;
937 937 ctx->site_name.type = AD_STRING;
938 938 ctx->forest_name.type = AD_STRING;
939 939 ctx->global_catalog.type = AD_DIRECTORY;
940 940 ctx->domains_in_forest.type = AD_DOMAINS_IN_FOREST;
941 941 ctx->trusted_domains.type = AD_TRUSTED_DOMAINS;
942 942 /* Site specific versions */
943 943 ctx->site_domain_controller.type = AD_DIRECTORY;
944 944 ctx->site_global_catalog.type = AD_DIRECTORY;
945 945 return (ctx);
946 946 }
947 947
948 948 void
949 949 ad_disc_fini(ad_disc_t ctx)
950 950 {
951 951 if (ctx == NULL)
952 952 return;
953 953
954 954 if (ctx->res_ninitted)
955 955 res_ndestroy(&ctx->res_state);
956 956
957 957 if (ctx->subnets != NULL)
958 958 free(ctx->subnets);
959 959
960 960 if (ctx->domain_name.value != NULL)
961 961 free(ctx->domain_name.value);
962 962
963 963 if (ctx->domain_guid.value != NULL)
964 964 free(ctx->domain_guid.value);
965 965
966 966 if (ctx->domain_controller.value != NULL)
967 967 free(ctx->domain_controller.value);
968 968
969 969 if (ctx->preferred_dc.value != NULL)
970 970 free(ctx->preferred_dc.value);
971 971
972 972 if (ctx->site_name.value != NULL)
973 973 free(ctx->site_name.value);
974 974
975 975 if (ctx->forest_name.value != NULL)
976 976 free(ctx->forest_name.value);
977 977
978 978 if (ctx->global_catalog.value != NULL)
979 979 free(ctx->global_catalog.value);
980 980
981 981 if (ctx->domains_in_forest.value != NULL)
982 982 free(ctx->domains_in_forest.value);
983 983
984 984 if (ctx->trusted_domains.value != NULL)
985 985 free(ctx->trusted_domains.value);
986 986
987 987 /* Site specific versions */
988 988 if (ctx->site_domain_controller.value != NULL)
989 989 free(ctx->site_domain_controller.value);
990 990
991 991 if (ctx->site_global_catalog.value != NULL)
992 992 free(ctx->site_global_catalog.value);
993 993
994 994 free(ctx);
995 995 }
996 996
997 997 void
998 998 ad_disc_refresh(ad_disc_t ctx)
999 999 {
1000 1000 if (ctx->res_ninitted) {
1001 1001 res_ndestroy(&ctx->res_state);
1002 1002 ctx->res_ninitted = 0;
1003 1003 }
1004 1004 (void) memset(&ctx->res_state, 0, sizeof (ctx->res_state));
1005 1005 DO_RES_NINIT(ctx);
1006 1006
1007 1007 if (ctx->domain_name.state == AD_STATE_AUTO)
1008 1008 ctx->domain_name.state = AD_STATE_INVALID;
1009 1009
1010 1010 if (ctx->domain_guid.state == AD_STATE_AUTO)
1011 1011 ctx->domain_guid.state = AD_STATE_INVALID;
1012 1012
1013 1013 if (ctx->domain_controller.state == AD_STATE_AUTO)
1014 1014 ctx->domain_controller.state = AD_STATE_INVALID;
1015 1015
1016 1016 if (ctx->preferred_dc.state == AD_STATE_AUTO)
1017 1017 ctx->preferred_dc.state = AD_STATE_INVALID;
1018 1018
1019 1019 if (ctx->site_name.state == AD_STATE_AUTO)
1020 1020 ctx->site_name.state = AD_STATE_INVALID;
1021 1021
1022 1022 if (ctx->forest_name.state == AD_STATE_AUTO)
1023 1023 ctx->forest_name.state = AD_STATE_INVALID;
1024 1024
1025 1025 if (ctx->global_catalog.state == AD_STATE_AUTO)
1026 1026 ctx->global_catalog.state = AD_STATE_INVALID;
1027 1027
1028 1028 if (ctx->domains_in_forest.state == AD_STATE_AUTO)
1029 1029 ctx->domains_in_forest.state = AD_STATE_INVALID;
1030 1030
1031 1031 if (ctx->trusted_domains.state == AD_STATE_AUTO)
1032 1032 ctx->trusted_domains.state = AD_STATE_INVALID;
1033 1033
1034 1034 if (ctx->site_domain_controller.state == AD_STATE_AUTO)
1035 1035 ctx->site_domain_controller.state = AD_STATE_INVALID;
1036 1036
1037 1037 if (ctx->site_global_catalog.state == AD_STATE_AUTO)
1038 1038 ctx->site_global_catalog.state = AD_STATE_INVALID;
1039 1039 }
1040 1040
1041 1041
1042 1042 /*
1043 1043 * Called when the discovery cycle is done. Sets a master TTL
1044 1044 * that will avoid doing new time-based discoveries too soon after
1045 1045 * the last discovery cycle. Most interesting when the discovery
1046 1046 * cycle failed, because then the TTLs on the individual items will
1047 1047 * not be updated and may go stale.
1048 1048 */
1049 1049 void
1050 1050 ad_disc_done(ad_disc_t ctx)
1051 1051 {
1052 1052 time_t now = time(NULL);
1053 1053
1054 1054 ctx->expires_not_before = now + MINIMUM_TTL;
1055 1055 ctx->expires_not_after = now + MAXIMUM_TTL;
1056 1056 }
1057 1057
1058 1058 static void
1059 1059 log_cds(ad_disc_t ctx, ad_disc_cds_t *cds)
1060 1060 {
1061 1061 char buf[INET6_ADDRSTRLEN];
1062 1062 struct addrinfo *ai;
1063 1063
1064 1064 if (!DBG(DISC, 1) && ctx->status_fp == NULL)
1065 1065 return;
1066 1066
1067 1067 DEBUG1STATUS(ctx, "Candidate servers:");
1068 1068 if (cds->cds_ds.host[0] == '\0') {
1069 1069 DEBUG1STATUS(ctx, " (empty list)");
1070 1070 return;
1071 1071 }
1072 1072
1073 1073 while (cds->cds_ds.host[0] != '\0') {
1074 1074
1075 1075 DEBUG1STATUS(ctx, " %s p=%d w=%d",
1076 1076 cds->cds_ds.host,
1077 1077 cds->cds_ds.priority,
1078 1078 cds->cds_ds.weight);
1079 1079
1080 1080 ai = cds->cds_ai;
1081 1081 if (ai == NULL) {
1082 1082 DEBUG1STATUS(ctx, " (no address)");
1083 1083 }
1084 1084 while (ai != NULL) {
1085 1085 int eai;
1086 1086
1087 1087 eai = getnameinfo(ai->ai_addr, ai->ai_addrlen,
1088 1088 buf, sizeof (buf), NULL, 0, NI_NUMERICHOST);
1089 1089 if (eai != 0)
1090 1090 (void) strlcpy(buf, "?", sizeof (buf));
1091 1091
1092 1092 DEBUG1STATUS(ctx, " %s", buf);
1093 1093 ai = ai->ai_next;
1094 1094 }
1095 1095 cds++;
1096 1096 }
1097 1097 }
1098 1098
1099 1099 static void
1100 1100 log_ds(ad_disc_t ctx, ad_disc_ds_t *ds)
1101 1101 {
1102 1102 char buf[INET6_ADDRSTRLEN];
1103 1103
1104 1104 if (!DBG(DISC, 1) && ctx->status_fp == NULL)
1105 1105 return;
1106 1106
1107 1107 DEBUG1STATUS(ctx, "Responding servers:");
1108 1108 if (ds->host[0] == '\0') {
1109 1109 DEBUG1STATUS(ctx, " (empty list)");
1110 1110 return;
1111 1111 }
1112 1112
1113 1113 while (ds->host[0] != '\0') {
1114 1114
1115 1115 DEBUG1STATUS(ctx, " %s", ds->host);
1116 1116 DO_GETNAMEINFO(buf, sizeof (buf), &ds->addr);
1117 1117 DEBUG1STATUS(ctx, " %s", buf);
1118 1118
1119 1119 ds++;
1120 1120 }
1121 1121 }
1122 1122
1123 1123 /* Discover joined Active Directory domainName */
1124 1124 static ad_item_t *
1125 1125 validate_DomainName(ad_disc_t ctx)
1126 1126 {
1127 1127 char *dname, *srvname;
1128 1128 int len, rc;
1129 1129
1130 1130 if (is_valid(&ctx->domain_name))
1131 1131 return (&ctx->domain_name);
1132 1132
1133 1133
1134 1134 /* Try to find our domain by searching for DCs for it */
1135 1135 DO_RES_NINIT(ctx);
1136 1136 if (DBG(DISC, 1))
1137 1137 logger(LOG_DEBUG, "Looking for our AD domain name...");
1138 1138 rc = srv_getdom(&ctx->res_state,
1139 1139 LDAP_SRV_HEAD DC_SRV_TAIL, &srvname);
1140 1140
1141 1141 /*
1142 1142 * If we can't find DCs by via res_nsearch() then there's no
1143 1143 * point in trying anything else to discover the AD domain name.
1144 1144 */
1145 1145 if (rc < 0) {
1146 1146 if (DBG(DISC, 1))
1147 1147 logger(LOG_DEBUG, "Can't find our domain name.");
1148 1148 return (NULL);
1149 1149 }
1150 1150
1151 1151 /*
1152 1152 * We have the FQDN of the SRV RR name, so now we extract the
1153 1153 * domainname suffix from it.
1154 1154 */
1155 1155 dname = strdup(srvname + strlen(LDAP_SRV_HEAD DC_SRV_TAIL) +
1156 1156 1 /* for the dot between RR name and domainname */);
1157 1157
1158 1158 free(srvname);
1159 1159
1160 1160 if (dname == NULL) {
1161 1161 logger(LOG_ERR, "Out of memory");
1162 1162 return (NULL);
1163 1163 }
1164 1164
1165 1165 /* Eat any trailing dot */
1166 1166 len = strlen(dname);
1167 1167 if (len > 0 && dname[len - 1] == '.')
1168 1168 dname[len - 1] = '\0';
1169 1169
1170 1170 if (DBG(DISC, 1))
1171 1171 logger(LOG_DEBUG, "Our domain name: %s", dname);
1172 1172
1173 1173 /*
1174 1174 * There is no "time to live" on the discovered domain,
1175 1175 * so passing zero as TTL here, making it non-expiring.
1176 1176 * Note that current consumers do not auto-discover the
1177 1177 * domain name, though a future installer could.
1178 1178 */
1179 1179 update_item(&ctx->domain_name, dname, AD_STATE_AUTO, 0);
1180 1180
1181 1181 return (&ctx->domain_name);
1182 1182 }
1183 1183
1184 1184
1185 1185 char *
1186 1186 ad_disc_get_DomainName(ad_disc_t ctx, boolean_t *auto_discovered)
1187 1187 {
1188 1188 char *domain_name = NULL;
1189 1189 ad_item_t *domain_name_item;
1190 1190
1191 1191 domain_name_item = validate_DomainName(ctx);
1192 1192
1193 1193 if (domain_name_item) {
1194 1194 domain_name = strdup(domain_name_item->value);
1195 1195 if (auto_discovered != NULL)
1196 1196 *auto_discovered =
1197 1197 (domain_name_item->state == AD_STATE_AUTO);
1198 1198 } else if (auto_discovered != NULL)
1199 1199 *auto_discovered = B_FALSE;
1200 1200
1201 1201 return (domain_name);
1202 1202 }
1203 1203
1204 1204
1205 1205 /* Discover domain controllers */
1206 1206 static ad_item_t *
1207 1207 validate_DomainController(ad_disc_t ctx, enum ad_disc_req req)
1208 1208 {
1209 1209 ad_disc_ds_t *dc = NULL;
1210 1210 ad_disc_cds_t *cdc = NULL;
1211 1211 boolean_t validate_global = B_FALSE;
1212 1212 boolean_t validate_site = B_FALSE;
1213 1213 ad_item_t *domain_name_item;
1214 1214 char *domain_name;
|
↓ open down ↓ |
1180 lines elided |
↑ open up ↑ |
1215 1215 ad_item_t *site_name_item = NULL;
1216 1216 char *site_name;
1217 1217 ad_item_t *prefer_dc_item;
1218 1218 ad_disc_ds_t *prefer_dc = NULL;
1219 1219
1220 1220 /* If the values is fixed there will not be a site specific version */
1221 1221 if (is_fixed(&ctx->domain_controller))
1222 1222 return (&ctx->domain_controller);
1223 1223
1224 1224 domain_name_item = validate_DomainName(ctx);
1225 - if (domain_name_item == NULL)
1225 + if (domain_name_item == NULL) {
1226 + DEBUG1STATUS(ctx, "(no domain name)");
1226 1227 return (NULL);
1228 + }
1227 1229 domain_name = (char *)domain_name_item->value;
1228 1230
1229 1231 /* Get (optional) preferred DC. */
1230 1232 prefer_dc_item = validate_PreferredDC(ctx);
1231 1233 if (prefer_dc_item != NULL)
1232 1234 prefer_dc = prefer_dc_item->value;
1233 1235
1234 1236 if (req == AD_DISC_GLOBAL)
1235 1237 validate_global = B_TRUE;
1236 1238 else {
1237 1239 if (is_fixed(&ctx->site_name))
1238 1240 validate_site = B_TRUE;
1239 - else if (req == AD_DISC_PREFER_SITE)
1241 + if (req == AD_DISC_PREFER_SITE)
1240 1242 validate_global = B_TRUE;
1241 1243 }
1242 1244
1243 - if (validate_global) {
1244 - if (!is_valid(&ctx->domain_controller) ||
1245 - is_changed(&ctx->domain_controller, PARAM1,
1246 - domain_name_item)) {
1245 + /*
1246 + * If we're trying both site-specific and global,
1247 + * try the site-specific first, then fall-back.
1248 + */
1249 + if (validate_site) {
1250 + site_name_item = &ctx->site_name;
1251 + site_name = (char *)site_name_item->value;
1247 1252
1253 + if (!is_valid(&ctx->site_domain_controller) ||
1254 + is_changed(&ctx->site_domain_controller, PARAM1,
1255 + domain_name_item) ||
1256 + is_changed(&ctx->site_domain_controller, PARAM2,
1257 + site_name_item)) {
1258 + char rr_name[DNS_MAX_NAME];
1259 +
1248 1260 /*
1249 1261 * Lookup DNS SRV RR named
1250 - * _ldap._tcp.dc._msdcs.<DomainName>
1262 + * _ldap._tcp.<SiteName>._sites.dc._msdcs.<DomainName>
1251 1263 */
1252 - DEBUG1STATUS(ctx, "DNS SRV query, dom=%s",
1253 - domain_name);
1264 + DEBUG1STATUS(ctx, "DNS SRV query, dom=%s, site=%s",
1265 + domain_name, site_name);
1266 + (void) snprintf(rr_name, sizeof (rr_name),
1267 + LDAP_SRV_HEAD SITE_SRV_MIDDLE DC_SRV_TAIL,
1268 + site_name);
1254 1269 DO_RES_NINIT(ctx);
1255 - cdc = srv_query(&ctx->res_state,
1256 - LDAP_SRV_HEAD DC_SRV_TAIL,
1270 + cdc = srv_query(&ctx->res_state, rr_name,
1257 1271 domain_name, prefer_dc);
1258 1272
1259 1273 if (cdc == NULL) {
1260 1274 DEBUG1STATUS(ctx, "(no DNS response)");
1261 - return (NULL);
1275 + goto try_global;
1262 1276 }
1263 1277 log_cds(ctx, cdc);
1264 1278
1265 1279 /*
1266 1280 * Filter out unresponsive servers, and
1267 1281 * save the domain info we get back.
1268 1282 */
1269 1283 dc = ldap_ping(
1270 1284 ctx,
1271 1285 cdc,
1272 1286 domain_name,
1273 1287 DS_DS_FLAG);
1274 1288 srv_free(cdc);
1275 1289 cdc = NULL;
1276 1290
1277 1291 if (dc == NULL) {
1278 1292 DEBUG1STATUS(ctx, "(no LDAP response)");
1279 - return (NULL);
1293 + goto try_global;
1280 1294 }
1281 1295 log_ds(ctx, dc);
1282 1296
1283 - update_item(&ctx->domain_controller, dc,
1297 + update_item(&ctx->site_domain_controller, dc,
1284 1298 AD_STATE_AUTO, dc->ttl);
1285 - update_version(&ctx->domain_controller, PARAM1,
1299 + update_version(&ctx->site_domain_controller, PARAM1,
1286 1300 domain_name_item);
1301 + update_version(&ctx->site_domain_controller, PARAM2,
1302 + site_name_item);
1287 1303 }
1288 - return (&ctx->domain_controller);
1304 + return (&ctx->site_domain_controller);
1289 1305 }
1290 1306
1291 - if (validate_site) {
1292 - site_name_item = &ctx->site_name;
1293 - site_name = (char *)site_name_item->value;
1307 +try_global:
1294 1308
1295 - if (!is_valid(&ctx->site_domain_controller) ||
1296 - is_changed(&ctx->site_domain_controller, PARAM1,
1297 - domain_name_item) ||
1298 - is_changed(&ctx->site_domain_controller, PARAM2,
1299 - site_name_item)) {
1300 - char rr_name[DNS_MAX_NAME];
1309 + if (validate_global) {
1310 + if (!is_valid(&ctx->domain_controller) ||
1311 + is_changed(&ctx->domain_controller, PARAM1,
1312 + domain_name_item)) {
1301 1313
1302 1314 /*
1303 1315 * Lookup DNS SRV RR named
1304 - * _ldap._tcp.<SiteName>._sites.dc._msdcs.<DomainName>
1316 + * _ldap._tcp.dc._msdcs.<DomainName>
1305 1317 */
1306 - DEBUG1STATUS(ctx, "DNS SRV query, dom=%s, site=%s",
1307 - domain_name, site_name);
1308 - (void) snprintf(rr_name, sizeof (rr_name),
1309 - LDAP_SRV_HEAD SITE_SRV_MIDDLE DC_SRV_TAIL,
1310 - site_name);
1318 + DEBUG1STATUS(ctx, "DNS SRV query, dom=%s",
1319 + domain_name);
1311 1320 DO_RES_NINIT(ctx);
1312 - cdc = srv_query(&ctx->res_state, rr_name,
1321 + cdc = srv_query(&ctx->res_state,
1322 + LDAP_SRV_HEAD DC_SRV_TAIL,
1313 1323 domain_name, prefer_dc);
1314 1324
1315 1325 if (cdc == NULL) {
1316 1326 DEBUG1STATUS(ctx, "(no DNS response)");
1317 1327 return (NULL);
1318 1328 }
1319 1329 log_cds(ctx, cdc);
1320 1330
1321 1331 /*
1322 1332 * Filter out unresponsive servers, and
1323 1333 * save the domain info we get back.
1324 1334 */
1325 1335 dc = ldap_ping(
1326 1336 ctx,
1327 1337 cdc,
1328 1338 domain_name,
|
↓ open down ↓ |
6 lines elided |
↑ open up ↑ |
1329 1339 DS_DS_FLAG);
1330 1340 srv_free(cdc);
1331 1341 cdc = NULL;
1332 1342
1333 1343 if (dc == NULL) {
1334 1344 DEBUG1STATUS(ctx, "(no LDAP response)");
1335 1345 return (NULL);
1336 1346 }
1337 1347 log_ds(ctx, dc);
1338 1348
1339 - update_item(&ctx->site_domain_controller, dc,
1349 + update_item(&ctx->domain_controller, dc,
1340 1350 AD_STATE_AUTO, dc->ttl);
1341 - update_version(&ctx->site_domain_controller, PARAM1,
1351 + update_version(&ctx->domain_controller, PARAM1,
1342 1352 domain_name_item);
1343 - update_version(&ctx->site_domain_controller, PARAM2,
1344 - site_name_item);
1345 1353 }
1346 - return (&ctx->site_domain_controller);
1354 + return (&ctx->domain_controller);
1347 1355 }
1356 +
1348 1357 return (NULL);
1349 1358 }
1350 1359
1351 1360 ad_disc_ds_t *
1352 1361 ad_disc_get_DomainController(ad_disc_t ctx, enum ad_disc_req req,
1353 1362 boolean_t *auto_discovered)
1354 1363 {
1355 1364 ad_item_t *domain_controller_item;
1356 1365 ad_disc_ds_t *domain_controller = NULL;
1357 1366
1358 1367 domain_controller_item = validate_DomainController(ctx, req);
1359 1368
1360 1369 if (domain_controller_item != NULL) {
1361 1370 domain_controller = ds_dup(domain_controller_item->value);
1362 1371 if (auto_discovered != NULL)
1363 1372 *auto_discovered =
1364 1373 (domain_controller_item->state == AD_STATE_AUTO);
1365 1374 } else if (auto_discovered != NULL)
1366 1375 *auto_discovered = B_FALSE;
1367 1376
1368 1377 return (domain_controller);
1369 1378 }
1370 1379
1371 1380
1372 1381 /*
1373 1382 * Discover the Domain GUID
1374 1383 * This info comes from validate_DomainController()
1375 1384 */
1376 1385 static ad_item_t *
1377 1386 validate_DomainGUID(ad_disc_t ctx)
1378 1387 {
1379 1388 ad_item_t *domain_controller_item;
1380 1389
1381 1390 if (is_fixed(&ctx->domain_guid))
1382 1391 return (&ctx->domain_guid);
1383 1392
1384 1393 domain_controller_item = validate_DomainController(ctx, AD_DISC_GLOBAL);
1385 1394 if (domain_controller_item == NULL)
1386 1395 return (NULL);
1387 1396
1388 1397 if (!is_valid(&ctx->domain_guid))
1389 1398 return (NULL);
1390 1399
1391 1400 return (&ctx->domain_guid);
1392 1401 }
1393 1402
1394 1403
1395 1404 uchar_t *
1396 1405 ad_disc_get_DomainGUID(ad_disc_t ctx, boolean_t *auto_discovered)
1397 1406 {
1398 1407 ad_item_t *domain_guid_item;
1399 1408 uchar_t *domain_guid = NULL;
1400 1409
1401 1410 domain_guid_item = validate_DomainGUID(ctx);
1402 1411 if (domain_guid_item != NULL) {
1403 1412 domain_guid = uuid_dup(domain_guid_item->value);
1404 1413 if (auto_discovered != NULL)
1405 1414 *auto_discovered =
1406 1415 (domain_guid_item->state == AD_STATE_AUTO);
1407 1416 } else if (auto_discovered != NULL)
1408 1417 *auto_discovered = B_FALSE;
1409 1418
1410 1419 return (domain_guid);
1411 1420 }
1412 1421
1413 1422
1414 1423 /*
1415 1424 * Discover site name (for multi-homed systems the first one found wins)
1416 1425 * This info comes from validate_DomainController()
1417 1426 */
1418 1427 static ad_item_t *
1419 1428 validate_SiteName(ad_disc_t ctx)
1420 1429 {
1421 1430 ad_item_t *domain_controller_item;
1422 1431
1423 1432 if (is_fixed(&ctx->site_name))
1424 1433 return (&ctx->site_name);
1425 1434
1426 1435 domain_controller_item = validate_DomainController(ctx, AD_DISC_GLOBAL);
1427 1436 if (domain_controller_item == NULL)
1428 1437 return (NULL);
1429 1438
1430 1439 if (!is_valid(&ctx->site_name))
1431 1440 return (NULL);
1432 1441
1433 1442 return (&ctx->site_name);
1434 1443 }
1435 1444
1436 1445
1437 1446 char *
1438 1447 ad_disc_get_SiteName(ad_disc_t ctx, boolean_t *auto_discovered)
1439 1448 {
1440 1449 ad_item_t *site_name_item;
1441 1450 char *site_name = NULL;
1442 1451
1443 1452 site_name_item = validate_SiteName(ctx);
1444 1453 if (site_name_item != NULL) {
1445 1454 site_name = strdup(site_name_item->value);
1446 1455 if (auto_discovered != NULL)
1447 1456 *auto_discovered =
1448 1457 (site_name_item->state == AD_STATE_AUTO);
1449 1458 } else if (auto_discovered != NULL)
1450 1459 *auto_discovered = B_FALSE;
1451 1460
1452 1461 return (site_name);
1453 1462 }
1454 1463
1455 1464
1456 1465
1457 1466 /*
1458 1467 * Discover forest name
1459 1468 * This info comes from validate_DomainController()
1460 1469 */
1461 1470 static ad_item_t *
1462 1471 validate_ForestName(ad_disc_t ctx)
1463 1472 {
1464 1473 ad_item_t *domain_controller_item;
1465 1474
1466 1475 if (is_fixed(&ctx->forest_name))
1467 1476 return (&ctx->forest_name);
1468 1477
1469 1478 domain_controller_item = validate_DomainController(ctx, AD_DISC_GLOBAL);
1470 1479 if (domain_controller_item == NULL)
1471 1480 return (NULL);
1472 1481
1473 1482 if (!is_valid(&ctx->forest_name))
1474 1483 return (NULL);
1475 1484
1476 1485 return (&ctx->forest_name);
1477 1486 }
1478 1487
1479 1488
1480 1489 char *
1481 1490 ad_disc_get_ForestName(ad_disc_t ctx, boolean_t *auto_discovered)
1482 1491 {
1483 1492 ad_item_t *forest_name_item;
1484 1493 char *forest_name = NULL;
1485 1494
1486 1495 forest_name_item = validate_ForestName(ctx);
1487 1496
1488 1497 if (forest_name_item != NULL) {
1489 1498 forest_name = strdup(forest_name_item->value);
1490 1499 if (auto_discovered != NULL)
1491 1500 *auto_discovered =
1492 1501 (forest_name_item->state == AD_STATE_AUTO);
1493 1502 } else if (auto_discovered != NULL)
1494 1503 *auto_discovered = B_FALSE;
1495 1504
1496 1505 return (forest_name);
1497 1506 }
1498 1507
1499 1508
1500 1509 /* Discover global catalog servers */
1501 1510 static ad_item_t *
1502 1511 validate_GlobalCatalog(ad_disc_t ctx, enum ad_disc_req req)
1503 1512 {
1504 1513 ad_disc_ds_t *gc = NULL;
1505 1514 ad_disc_cds_t *cgc = NULL;
1506 1515 boolean_t validate_global = B_FALSE;
1507 1516 boolean_t validate_site = B_FALSE;
1508 1517 ad_item_t *dc_item;
|
↓ open down ↓ |
151 lines elided |
↑ open up ↑ |
1509 1518 ad_item_t *forest_name_item;
1510 1519 ad_item_t *site_name_item;
1511 1520 char *forest_name;
1512 1521 char *site_name;
1513 1522
1514 1523 /* If the values is fixed there will not be a site specific version */
1515 1524 if (is_fixed(&ctx->global_catalog))
1516 1525 return (&ctx->global_catalog);
1517 1526
1518 1527 forest_name_item = validate_ForestName(ctx);
1519 - if (forest_name_item == NULL)
1528 + if (forest_name_item == NULL) {
1529 + DEBUG1STATUS(ctx, "(no forrest name)");
1520 1530 return (NULL);
1531 + }
1521 1532 forest_name = (char *)forest_name_item->value;
1522 1533
1523 1534 if (req == AD_DISC_GLOBAL)
1524 1535 validate_global = B_TRUE;
1525 1536 else {
1526 1537 if (is_fixed(&ctx->site_name))
1527 1538 validate_site = B_TRUE;
1528 - else if (req == AD_DISC_PREFER_SITE)
1539 + if (req == AD_DISC_PREFER_SITE)
1529 1540 validate_global = B_TRUE;
1530 1541 }
1531 1542
1532 - if (validate_global) {
1533 - if (!is_valid(&ctx->global_catalog) ||
1534 - is_changed(&ctx->global_catalog, PARAM1,
1535 - forest_name_item)) {
1543 + /*
1544 + * If we're trying both site-specific and global,
1545 + * try the site-specific first, then fall-back.
1546 + */
1547 + if (validate_site) {
1548 + site_name_item = &ctx->site_name;
1549 + site_name = (char *)site_name_item->value;
1536 1550
1551 + if (!is_valid(&ctx->site_global_catalog) ||
1552 + is_changed(&ctx->site_global_catalog, PARAM1,
1553 + forest_name_item) ||
1554 + is_changed(&ctx->site_global_catalog, PARAM2,
1555 + site_name_item)) {
1556 + char rr_name[DNS_MAX_NAME];
1557 +
1537 1558 /*
1538 1559 * See if our DC is also a GC.
1539 1560 */
1540 1561 dc_item = validate_DomainController(ctx, req);
1541 1562 if (dc_item != NULL) {
1542 1563 ad_disc_ds_t *ds = dc_item->value;
1543 1564 if ((ds->flags & DS_GC_FLAG) != 0) {
1544 1565 DEBUG1STATUS(ctx,
1545 - "DC is also a GC for %s",
1546 - forest_name);
1566 + "DC is also a GC for %s in %s",
1567 + forest_name, site_name);
1547 1568 gc = ds_dup(ds);
1548 1569 if (gc != NULL) {
1549 1570 gc->port = GC_PORT;
1550 - goto update_global;
1571 + goto update_site;
1551 1572 }
1552 1573 }
1553 1574 }
1554 1575
1555 1576 /*
1556 1577 * Lookup DNS SRV RR named:
1557 - * _ldap._tcp.gc._msdcs.<ForestName>
1578 + * _ldap._tcp.<siteName>._sites.gc.
1579 + * _msdcs.<ForestName>
1558 1580 */
1559 - DEBUG1STATUS(ctx, "DNS SRV query, forest=%s",
1560 - forest_name);
1581 + DEBUG1STATUS(ctx, "DNS SRV query, forest=%s, site=%s",
1582 + forest_name, site_name);
1583 + (void) snprintf(rr_name, sizeof (rr_name),
1584 + LDAP_SRV_HEAD SITE_SRV_MIDDLE GC_SRV_TAIL,
1585 + site_name);
1561 1586 DO_RES_NINIT(ctx);
1562 - cgc = srv_query(&ctx->res_state,
1563 - LDAP_SRV_HEAD GC_SRV_TAIL,
1587 + cgc = srv_query(&ctx->res_state, rr_name,
1564 1588 forest_name, NULL);
1565 1589
1566 1590 if (cgc == NULL) {
1567 1591 DEBUG1STATUS(ctx, "(no DNS response)");
1568 - return (NULL);
1592 + goto try_global;
1569 1593 }
1570 1594 log_cds(ctx, cgc);
1571 1595
1572 1596 /*
1573 1597 * Filter out unresponsive servers, and
1574 1598 * save the domain info we get back.
1575 1599 */
1576 1600 gc = ldap_ping(
1577 1601 NULL,
1578 1602 cgc,
1579 1603 forest_name,
1580 1604 DS_GC_FLAG);
1581 1605 srv_free(cgc);
1582 1606 cgc = NULL;
1583 1607
1584 1608 if (gc == NULL) {
1585 1609 DEBUG1STATUS(ctx, "(no LDAP response)");
1586 - return (NULL);
1610 + goto try_global;
1587 1611 }
1588 1612 log_ds(ctx, gc);
1589 1613
1590 - update_global:
1591 - update_item(&ctx->global_catalog, gc,
1614 + update_site:
1615 + update_item(&ctx->site_global_catalog, gc,
1592 1616 AD_STATE_AUTO, gc->ttl);
1593 - update_version(&ctx->global_catalog, PARAM1,
1617 + update_version(&ctx->site_global_catalog, PARAM1,
1594 1618 forest_name_item);
1619 + update_version(&ctx->site_global_catalog, PARAM2,
1620 + site_name_item);
1595 1621 }
1596 - return (&ctx->global_catalog);
1622 + return (&ctx->site_global_catalog);
1597 1623 }
1598 1624
1599 - if (validate_site) {
1600 - site_name_item = &ctx->site_name;
1601 - site_name = (char *)site_name_item->value;
1625 +try_global:
1602 1626
1603 - if (!is_valid(&ctx->site_global_catalog) ||
1604 - is_changed(&ctx->site_global_catalog, PARAM1,
1605 - forest_name_item) ||
1606 - is_changed(&ctx->site_global_catalog, PARAM2,
1607 - site_name_item)) {
1608 - char rr_name[DNS_MAX_NAME];
1627 + if (validate_global) {
1628 + if (!is_valid(&ctx->global_catalog) ||
1629 + is_changed(&ctx->global_catalog, PARAM1,
1630 + forest_name_item)) {
1609 1631
1610 1632 /*
1611 1633 * See if our DC is also a GC.
1612 1634 */
1613 1635 dc_item = validate_DomainController(ctx, req);
1614 1636 if (dc_item != NULL) {
1615 1637 ad_disc_ds_t *ds = dc_item->value;
1616 1638 if ((ds->flags & DS_GC_FLAG) != 0) {
1617 1639 DEBUG1STATUS(ctx,
1618 - "DC is also a GC for %s in %s",
1619 - forest_name, site_name);
1640 + "DC is also a GC for %s",
1641 + forest_name);
1620 1642 gc = ds_dup(ds);
1621 1643 if (gc != NULL) {
1622 1644 gc->port = GC_PORT;
1623 - goto update_site;
1645 + goto update_global;
1624 1646 }
1625 1647 }
1626 1648 }
1627 1649
1628 1650 /*
1629 1651 * Lookup DNS SRV RR named:
1630 - * _ldap._tcp.<siteName>._sites.gc.
1631 - * _msdcs.<ForestName>
1652 + * _ldap._tcp.gc._msdcs.<ForestName>
1632 1653 */
1633 - DEBUG1STATUS(ctx, "DNS SRV query, forest=%s, site=%s",
1634 - forest_name, site_name);
1635 - (void) snprintf(rr_name, sizeof (rr_name),
1636 - LDAP_SRV_HEAD SITE_SRV_MIDDLE GC_SRV_TAIL,
1637 - site_name);
1654 + DEBUG1STATUS(ctx, "DNS SRV query, forest=%s",
1655 + forest_name);
1638 1656 DO_RES_NINIT(ctx);
1639 - cgc = srv_query(&ctx->res_state, rr_name,
1657 + cgc = srv_query(&ctx->res_state,
1658 + LDAP_SRV_HEAD GC_SRV_TAIL,
1640 1659 forest_name, NULL);
1641 1660
1642 1661 if (cgc == NULL) {
1643 1662 DEBUG1STATUS(ctx, "(no DNS response)");
1644 1663 return (NULL);
1645 1664 }
1646 1665 log_cds(ctx, cgc);
1647 1666
1648 1667 /*
1649 1668 * Filter out unresponsive servers, and
1650 1669 * save the domain info we get back.
1651 1670 */
1652 1671 gc = ldap_ping(
1653 1672 NULL,
1654 1673 cgc,
1655 1674 forest_name,
|
↓ open down ↓ |
6 lines elided |
↑ open up ↑ |
1656 1675 DS_GC_FLAG);
1657 1676 srv_free(cgc);
1658 1677 cgc = NULL;
1659 1678
1660 1679 if (gc == NULL) {
1661 1680 DEBUG1STATUS(ctx, "(no LDAP response)");
1662 1681 return (NULL);
1663 1682 }
1664 1683 log_ds(ctx, gc);
1665 1684
1666 - update_site:
1667 - update_item(&ctx->site_global_catalog, gc,
1685 + update_global:
1686 + update_item(&ctx->global_catalog, gc,
1668 1687 AD_STATE_AUTO, gc->ttl);
1669 - update_version(&ctx->site_global_catalog, PARAM1,
1688 + update_version(&ctx->global_catalog, PARAM1,
1670 1689 forest_name_item);
1671 - update_version(&ctx->site_global_catalog, PARAM2,
1672 - site_name_item);
1673 1690 }
1674 - return (&ctx->site_global_catalog);
1691 + return (&ctx->global_catalog);
1675 1692 }
1676 1693 return (NULL);
1677 1694 }
1678 1695
1679 1696
1680 1697 ad_disc_ds_t *
1681 1698 ad_disc_get_GlobalCatalog(ad_disc_t ctx, enum ad_disc_req req,
1682 1699 boolean_t *auto_discovered)
1683 1700 {
1684 1701 ad_disc_ds_t *global_catalog = NULL;
1685 1702 ad_item_t *global_catalog_item;
1686 1703
1687 1704 global_catalog_item = validate_GlobalCatalog(ctx, req);
1688 1705
1689 1706 if (global_catalog_item != NULL) {
1690 1707 global_catalog = ds_dup(global_catalog_item->value);
1691 1708 if (auto_discovered != NULL)
1692 1709 *auto_discovered =
1693 1710 (global_catalog_item->state == AD_STATE_AUTO);
1694 1711 } else if (auto_discovered != NULL)
1695 1712 *auto_discovered = B_FALSE;
1696 1713
1697 1714 return (global_catalog);
1698 1715 }
1699 1716
1700 1717
1701 1718 static ad_item_t *
1702 1719 validate_TrustedDomains(ad_disc_t ctx)
1703 1720 {
1704 1721 LDAP *ld = NULL;
1705 1722 ad_item_t *global_catalog_item;
1706 1723 ad_item_t *forest_name_item;
1707 1724 ad_disc_trusteddomains_t *trusted_domains;
1708 1725 char *dn = NULL;
1709 1726 char *forest_name_dn;
1710 1727 int len;
1711 1728 int num_parts;
1712 1729
1713 1730 if (is_fixed(&ctx->trusted_domains))
1714 1731 return (&ctx->trusted_domains);
1715 1732
1716 1733 global_catalog_item = validate_GlobalCatalog(ctx, AD_DISC_GLOBAL);
1717 1734 if (global_catalog_item == NULL)
1718 1735 return (NULL);
1719 1736
1720 1737 forest_name_item = validate_ForestName(ctx);
1721 1738 if (forest_name_item == NULL)
1722 1739 return (NULL);
1723 1740
1724 1741 if (!is_valid(&ctx->trusted_domains) ||
1725 1742 is_changed(&ctx->trusted_domains, PARAM1, global_catalog_item) ||
1726 1743 is_changed(&ctx->trusted_domains, PARAM2, forest_name_item)) {
1727 1744
1728 1745 forest_name_dn = ldap_dns_to_dn(forest_name_item->value,
1729 1746 &num_parts);
1730 1747 if (forest_name_dn == NULL)
1731 1748 return (NULL);
1732 1749
1733 1750 len = snprintf(NULL, 0, "CN=System,%s", forest_name_dn) + 1;
1734 1751 dn = malloc(len);
1735 1752 if (dn == NULL) {
1736 1753 free(forest_name_dn);
1737 1754 return (NULL);
1738 1755 }
1739 1756 (void) snprintf(dn, len, "CN=System,%s", forest_name_dn);
1740 1757 free(forest_name_dn);
1741 1758
1742 1759 trusted_domains = ldap_lookup_trusted_domains(
1743 1760 &ld, global_catalog_item->value, dn);
1744 1761
1745 1762 if (ld != NULL)
1746 1763 (void) ldap_unbind(ld);
1747 1764 free(dn);
1748 1765
1749 1766 if (trusted_domains == NULL)
1750 1767 return (NULL);
1751 1768
1752 1769 update_item(&ctx->trusted_domains, trusted_domains,
1753 1770 AD_STATE_AUTO, 0);
1754 1771 update_version(&ctx->trusted_domains, PARAM1,
1755 1772 global_catalog_item);
1756 1773 update_version(&ctx->trusted_domains, PARAM2,
1757 1774 forest_name_item);
1758 1775 }
1759 1776
1760 1777 return (&ctx->trusted_domains);
1761 1778 }
1762 1779
1763 1780
1764 1781 ad_disc_trusteddomains_t *
1765 1782 ad_disc_get_TrustedDomains(ad_disc_t ctx, boolean_t *auto_discovered)
1766 1783 {
1767 1784 ad_disc_trusteddomains_t *trusted_domains = NULL;
1768 1785 ad_item_t *trusted_domains_item;
1769 1786
1770 1787 trusted_domains_item = validate_TrustedDomains(ctx);
1771 1788
1772 1789 if (trusted_domains_item != NULL) {
1773 1790 trusted_domains = td_dup(trusted_domains_item->value);
1774 1791 if (auto_discovered != NULL)
1775 1792 *auto_discovered =
1776 1793 (trusted_domains_item->state == AD_STATE_AUTO);
1777 1794 } else if (auto_discovered != NULL)
1778 1795 *auto_discovered = B_FALSE;
1779 1796
1780 1797 return (trusted_domains);
1781 1798 }
1782 1799
1783 1800
1784 1801 static ad_item_t *
1785 1802 validate_DomainsInForest(ad_disc_t ctx)
1786 1803 {
1787 1804 ad_item_t *global_catalog_item;
1788 1805 LDAP *ld = NULL;
1789 1806 ad_disc_domainsinforest_t *domains_in_forest;
1790 1807
1791 1808 if (is_fixed(&ctx->domains_in_forest))
1792 1809 return (&ctx->domains_in_forest);
1793 1810
1794 1811 global_catalog_item = validate_GlobalCatalog(ctx, AD_DISC_GLOBAL);
1795 1812 if (global_catalog_item == NULL)
1796 1813 return (NULL);
1797 1814
1798 1815 if (!is_valid(&ctx->domains_in_forest) ||
1799 1816 is_changed(&ctx->domains_in_forest, PARAM1, global_catalog_item)) {
1800 1817
1801 1818 domains_in_forest = ldap_lookup_domains_in_forest(
1802 1819 &ld, global_catalog_item->value);
1803 1820
1804 1821 if (ld != NULL)
1805 1822 (void) ldap_unbind(ld);
1806 1823
1807 1824 if (domains_in_forest == NULL)
1808 1825 return (NULL);
1809 1826
1810 1827 update_item(&ctx->domains_in_forest, domains_in_forest,
1811 1828 AD_STATE_AUTO, 0);
1812 1829 update_version(&ctx->domains_in_forest, PARAM1,
1813 1830 global_catalog_item);
1814 1831 }
1815 1832 return (&ctx->domains_in_forest);
1816 1833 }
1817 1834
1818 1835
1819 1836 ad_disc_domainsinforest_t *
1820 1837 ad_disc_get_DomainsInForest(ad_disc_t ctx, boolean_t *auto_discovered)
1821 1838 {
1822 1839 ad_disc_domainsinforest_t *domains_in_forest = NULL;
1823 1840 ad_item_t *domains_in_forest_item;
1824 1841
1825 1842 domains_in_forest_item = validate_DomainsInForest(ctx);
1826 1843
1827 1844 if (domains_in_forest_item != NULL) {
1828 1845 domains_in_forest = df_dup(domains_in_forest_item->value);
1829 1846 if (auto_discovered != NULL)
1830 1847 *auto_discovered =
1831 1848 (domains_in_forest_item->state == AD_STATE_AUTO);
1832 1849 } else if (auto_discovered != NULL)
1833 1850 *auto_discovered = B_FALSE;
1834 1851
1835 1852 return (domains_in_forest);
1836 1853 }
1837 1854
1838 1855 static ad_item_t *
1839 1856 validate_PreferredDC(ad_disc_t ctx)
1840 1857 {
1841 1858 if (is_valid(&ctx->preferred_dc))
1842 1859 return (&ctx->preferred_dc);
1843 1860
1844 1861 return (NULL);
1845 1862 }
1846 1863
1847 1864 ad_disc_ds_t *
1848 1865 ad_disc_get_PreferredDC(ad_disc_t ctx, boolean_t *auto_discovered)
1849 1866 {
1850 1867 ad_disc_ds_t *preferred_dc = NULL;
1851 1868 ad_item_t *preferred_dc_item;
1852 1869
1853 1870 preferred_dc_item = validate_PreferredDC(ctx);
1854 1871
1855 1872 if (preferred_dc_item != NULL) {
1856 1873 preferred_dc = ds_dup(preferred_dc_item->value);
1857 1874 if (auto_discovered != NULL)
1858 1875 *auto_discovered =
1859 1876 (preferred_dc_item->state == AD_STATE_AUTO);
1860 1877 } else if (auto_discovered != NULL)
1861 1878 *auto_discovered = B_FALSE;
1862 1879
1863 1880 return (preferred_dc);
1864 1881 }
1865 1882
1866 1883
1867 1884
1868 1885 int
1869 1886 ad_disc_set_DomainName(ad_disc_t ctx, const char *domainName)
1870 1887 {
1871 1888 char *domain_name = NULL;
1872 1889 if (domainName != NULL) {
1873 1890 domain_name = strdup(domainName);
1874 1891 if (domain_name == NULL)
1875 1892 return (-1);
1876 1893 update_item(&ctx->domain_name, domain_name,
1877 1894 AD_STATE_FIXED, 0);
1878 1895 } else if (ctx->domain_name.state == AD_STATE_FIXED)
1879 1896 ctx->domain_name.state = AD_STATE_INVALID;
1880 1897 return (0);
1881 1898 }
1882 1899
1883 1900 int
1884 1901 ad_disc_set_DomainGUID(ad_disc_t ctx, uchar_t *u)
1885 1902 {
1886 1903 char *domain_guid = NULL;
1887 1904 if (u != NULL) {
1888 1905 domain_guid = uuid_dup(u);
1889 1906 if (domain_guid == NULL)
1890 1907 return (-1);
1891 1908 update_item(&ctx->domain_guid, domain_guid,
1892 1909 AD_STATE_FIXED, 0);
1893 1910 } else if (ctx->domain_guid.state == AD_STATE_FIXED)
1894 1911 ctx->domain_guid.state = AD_STATE_INVALID;
1895 1912 return (0);
1896 1913 }
1897 1914
1898 1915 void
1899 1916 auto_set_DomainGUID(ad_disc_t ctx, uchar_t *u)
1900 1917 {
1901 1918 char *domain_guid = NULL;
1902 1919
1903 1920 if (is_fixed(&ctx->domain_guid))
1904 1921 return;
1905 1922
1906 1923 domain_guid = uuid_dup(u);
1907 1924 if (domain_guid == NULL)
1908 1925 return;
1909 1926 update_item(&ctx->domain_guid, domain_guid, AD_STATE_AUTO, 0);
1910 1927 }
1911 1928
1912 1929 int
1913 1930 ad_disc_set_DomainController(ad_disc_t ctx,
1914 1931 const ad_disc_ds_t *domainController)
1915 1932 {
1916 1933 ad_disc_ds_t *domain_controller = NULL;
1917 1934 if (domainController != NULL) {
1918 1935 domain_controller = ds_dup(domainController);
1919 1936 if (domain_controller == NULL)
1920 1937 return (-1);
1921 1938 update_item(&ctx->domain_controller, domain_controller,
1922 1939 AD_STATE_FIXED, 0);
1923 1940 } else if (ctx->domain_controller.state == AD_STATE_FIXED)
1924 1941 ctx->domain_controller.state = AD_STATE_INVALID;
1925 1942 return (0);
1926 1943 }
1927 1944
1928 1945 int
1929 1946 ad_disc_set_SiteName(ad_disc_t ctx, const char *siteName)
1930 1947 {
1931 1948 char *site_name = NULL;
1932 1949 if (siteName != NULL) {
1933 1950 site_name = strdup(siteName);
1934 1951 if (site_name == NULL)
1935 1952 return (-1);
1936 1953 update_item(&ctx->site_name, site_name, AD_STATE_FIXED, 0);
1937 1954 } else if (ctx->site_name.state == AD_STATE_FIXED)
1938 1955 ctx->site_name.state = AD_STATE_INVALID;
1939 1956 return (0);
1940 1957 }
1941 1958
1942 1959 void
1943 1960 auto_set_SiteName(ad_disc_t ctx, char *siteName)
1944 1961 {
1945 1962 char *site_name = NULL;
1946 1963
1947 1964 if (is_fixed(&ctx->site_name))
1948 1965 return;
1949 1966
1950 1967 site_name = strdup(siteName);
1951 1968 if (site_name == NULL)
1952 1969 return;
1953 1970 update_item(&ctx->site_name, site_name, AD_STATE_AUTO, 0);
1954 1971 }
1955 1972
1956 1973 int
1957 1974 ad_disc_set_ForestName(ad_disc_t ctx, const char *forestName)
1958 1975 {
1959 1976 char *forest_name = NULL;
1960 1977 if (forestName != NULL) {
1961 1978 forest_name = strdup(forestName);
1962 1979 if (forest_name == NULL)
1963 1980 return (-1);
1964 1981 update_item(&ctx->forest_name, forest_name,
1965 1982 AD_STATE_FIXED, 0);
1966 1983 } else if (ctx->forest_name.state == AD_STATE_FIXED)
1967 1984 ctx->forest_name.state = AD_STATE_INVALID;
1968 1985 return (0);
1969 1986 }
1970 1987
1971 1988 void
1972 1989 auto_set_ForestName(ad_disc_t ctx, char *forestName)
1973 1990 {
1974 1991 char *forest_name = NULL;
1975 1992
1976 1993 if (is_fixed(&ctx->forest_name))
1977 1994 return;
1978 1995
1979 1996 forest_name = strdup(forestName);
1980 1997 if (forest_name == NULL)
1981 1998 return;
1982 1999 update_item(&ctx->forest_name, forest_name, AD_STATE_AUTO, 0);
1983 2000 }
1984 2001
1985 2002 int
1986 2003 ad_disc_set_GlobalCatalog(ad_disc_t ctx,
1987 2004 const ad_disc_ds_t *globalCatalog)
1988 2005 {
1989 2006 ad_disc_ds_t *global_catalog = NULL;
1990 2007 if (globalCatalog != NULL) {
1991 2008 global_catalog = ds_dup(globalCatalog);
1992 2009 if (global_catalog == NULL)
1993 2010 return (-1);
1994 2011 update_item(&ctx->global_catalog, global_catalog,
1995 2012 AD_STATE_FIXED, 0);
1996 2013 } else if (ctx->global_catalog.state == AD_STATE_FIXED)
1997 2014 ctx->global_catalog.state = AD_STATE_INVALID;
1998 2015 return (0);
1999 2016 }
2000 2017
2001 2018 int
2002 2019 ad_disc_set_PreferredDC(ad_disc_t ctx, const ad_disc_ds_t *pref_dc)
2003 2020 {
2004 2021 ad_disc_ds_t *new_pref_dc = NULL;
2005 2022 if (pref_dc != NULL) {
2006 2023 new_pref_dc = ds_dup(pref_dc);
2007 2024 if (new_pref_dc == NULL)
2008 2025 return (-1);
2009 2026 update_item(&ctx->preferred_dc, new_pref_dc,
2010 2027 AD_STATE_FIXED, 0);
2011 2028 } else if (ctx->preferred_dc.state == AD_STATE_FIXED)
2012 2029 ctx->preferred_dc.state = AD_STATE_INVALID;
2013 2030 return (0);
2014 2031 }
2015 2032
2016 2033 void
2017 2034 ad_disc_set_StatusFP(ad_disc_t ctx, struct __FILE_TAG *fp)
2018 2035 {
2019 2036 ctx->status_fp = fp;
2020 2037 }
2021 2038
2022 2039
2023 2040 int
2024 2041 ad_disc_unset(ad_disc_t ctx)
2025 2042 {
2026 2043 if (ctx->domain_name.state == AD_STATE_FIXED)
2027 2044 ctx->domain_name.state = AD_STATE_INVALID;
2028 2045
2029 2046 if (ctx->domain_controller.state == AD_STATE_FIXED)
2030 2047 ctx->domain_controller.state = AD_STATE_INVALID;
2031 2048
2032 2049 if (ctx->preferred_dc.state == AD_STATE_FIXED)
2033 2050 ctx->preferred_dc.state = AD_STATE_INVALID;
2034 2051
2035 2052 if (ctx->site_name.state == AD_STATE_FIXED)
2036 2053 ctx->site_name.state = AD_STATE_INVALID;
2037 2054
2038 2055 if (ctx->forest_name.state == AD_STATE_FIXED)
2039 2056 ctx->forest_name.state = AD_STATE_INVALID;
2040 2057
2041 2058 if (ctx->global_catalog.state == AD_STATE_FIXED)
2042 2059 ctx->global_catalog.state = AD_STATE_INVALID;
2043 2060
2044 2061 return (0);
2045 2062 }
2046 2063
2047 2064 /*
2048 2065 * ad_disc_get_TTL
2049 2066 *
2050 2067 * This routines the time to live for AD
2051 2068 * auto discovered items.
2052 2069 *
2053 2070 * Returns:
2054 2071 * -1 if there are no TTL items
2055 2072 * 0 if there are expired items
2056 2073 * else the number of seconds
2057 2074 *
2058 2075 * The MIN_GT_ZERO(x, y) macro return the lesser of x and y, provided it
2059 2076 * is positive -- min() greater than zero.
2060 2077 */
2061 2078 #define MIN_GT_ZERO(x, y) (((x) <= 0) ? (((y) <= 0) ? \
2062 2079 (-1) : (y)) : (((y) <= 0) ? (x) : (((x) > (y)) ? (y) : (x))))
2063 2080 int
2064 2081 ad_disc_get_TTL(ad_disc_t ctx)
2065 2082 {
2066 2083 time_t expires;
2067 2084 int ttl;
2068 2085
2069 2086 expires = MIN_GT_ZERO(ctx->domain_controller.expires,
2070 2087 ctx->global_catalog.expires);
2071 2088 expires = MIN_GT_ZERO(expires, ctx->site_domain_controller.expires);
2072 2089 expires = MIN_GT_ZERO(expires, ctx->site_global_catalog.expires);
2073 2090
2074 2091 if (expires == -1) {
2075 2092 return (-1);
2076 2093 }
2077 2094
2078 2095 if (ctx->expires_not_before != 0 &&
2079 2096 expires < ctx->expires_not_before) {
2080 2097 expires = ctx->expires_not_before;
2081 2098 }
2082 2099
2083 2100 if (ctx->expires_not_after != 0 &&
2084 2101 expires > ctx->expires_not_after) {
2085 2102 expires = ctx->expires_not_after;
2086 2103 }
2087 2104
2088 2105 ttl = expires - time(NULL);
2089 2106
2090 2107 if (ttl < 0) {
2091 2108 return (0);
2092 2109 }
2093 2110 return (ttl);
2094 2111 }
2095 2112
2096 2113 boolean_t
2097 2114 ad_disc_SubnetChanged(ad_disc_t ctx)
2098 2115 {
2099 2116 ad_subnet_t *subnets;
2100 2117
2101 2118 if (ctx->subnets_changed || ctx->subnets == NULL)
2102 2119 return (B_TRUE);
2103 2120
2104 2121 if ((subnets = find_subnets()) != NULL) {
2105 2122 if (cmpsubnets(subnets, ctx->subnets) != 0)
2106 2123 ctx->subnets_changed = B_TRUE;
2107 2124 free(subnets);
2108 2125 }
2109 2126
2110 2127 return (ctx->subnets_changed);
2111 2128 }
|
↓ open down ↓ |
427 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX