Print this page
NEX-20549 smb AD join broken if no site name
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-19665 Several door servers don't properly handle exiting threads
Review by: Gordon Ross <gordon.ross@nexenta.com>
Review by: Evan Layton <evan.layton@nexenta.com>
Merge with illumos-gate 8dcafc606a22eddb15cded4783cf27221c4404b3 (htable whitespace)
NEX-2750 idmapd spams console with "ignoring preferred_dc value"
NEX-2225 Unable to join NexentaStor to 2008 AD
NEX-2302 Need a way to control the idmap rediscovery interval
NEX-1810 extended security Kerberos (inbound)
NEX-1852 re-enable Kerberos-style AD join
NEX-1638 Updated DC Locator
Includes work by: matt.barden@nexenta.com, kevin.crowe@nexenta.com
SMB-56 extended security NTLMSSP, inbound (lint)
SMB-56 extended security NTLMSSP, inbound
OS-7 Add cache timeout settings to idmapd manifest, increase defaults
re #13190 rb4312 idmapd error -9961 (No AD servers)
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/cmd/idmap/idmapd/idmap_config.c
+++ new/usr/src/cmd/idmap/idmapd/idmap_config.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 *
|
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
13 13 * When distributing Covered Code, include this CDDL HEADER in each
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 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23 - * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
23 + * Copyright 2019 Nexenta Systems, Inc. All rights reserved.
24 24 */
25 25
26 26
27 27 /*
28 28 * Config routines common to idmap(1M) and idmapd(1M)
29 29 */
30 30
31 31 #include <stdlib.h>
32 32 #include <strings.h>
33 33 #include <libintl.h>
34 34 #include <ctype.h>
35 35 #include <errno.h>
36 36 #include <stdio.h>
37 37 #include <stdarg.h>
|
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
38 38 #include <uuid/uuid.h>
39 39 #include <pthread.h>
40 40 #include <port.h>
41 41 #include <sys/socket.h>
42 42 #include <net/route.h>
43 43 #include <sys/u8_textprep.h>
44 44 #include <netinet/in.h>
45 45 #include <arpa/inet.h>
46 46 #include <netdb.h>
47 47 #include <note.h>
48 +#include <limits.h>
48 49 #include "idmapd.h"
49 50 #include "addisc.h"
50 51
51 52 #define MACHINE_SID_LEN (9 + 3 * 11)
52 53 #define FMRI_BASE "svc:/system/idmap"
53 54 #define CONFIG_PG "config"
54 55 #define DEBUG_PG "debug"
55 56 #define RECONFIGURE 1
56 57 #define POKE_AUTO_DISCOVERY 2
57 58 #define KICK_AUTO_DISCOVERY 3
58 59
59 60 /*
60 61 * Default cache timeouts. Can override via svccfg
61 62 * config/id_cache_timeout = count: seconds
62 63 * config/name_cache_timeout = count: seconds
63 64 */
64 65 #define ID_CACHE_TMO_DEFAULT 86400
65 66 #define NAME_CACHE_TMO_DEFAULT 604800
66 67
67 68 /*
68 69 * Default maximum time between rediscovery runs.
69 70 * config/rediscovery_interval = count: seconds
|
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
70 71 */
71 72 #define REDISCOVERY_INTERVAL_DEFAULT 3600
72 73
73 74 /*
74 75 * Mininum time between rediscovery runs, in case adutils gives us a
75 76 * really short TTL (which it never should, but be defensive)
76 77 * (not configurable) seconds.
77 78 */
78 79 #define MIN_REDISCOVERY_INTERVAL 60
79 80
81 +/*
82 + * Max number of concurrent door calls
83 + */
84 +#define MAX_THREADS_DEFAULT 40
85 +
80 86 enum event_type {
81 87 EVENT_NOTHING, /* Woke up for no good reason */
82 88 EVENT_TIMEOUT, /* Timeout expired */
83 89 EVENT_ROUTING, /* An interesting routing event happened */
84 90 EVENT_POKED, /* Requested from degrade_svc() */
85 91 EVENT_KICKED, /* Force rediscovery, i.e. DC failed. */
86 92 EVENT_REFRESH, /* SMF refresh */
87 93 };
88 94
89 95
90 96 static void idmapd_set_krb5_realm(char *);
91 97
92 98 static pthread_t update_thread_handle = 0;
93 99
94 100 static int idmapd_ev_port = -1;
95 101 static int rt_sock = -1;
96 102
97 103 struct enum_lookup_map directory_mapping_map[] = {
98 104 { DIRECTORY_MAPPING_NONE, "none" },
99 105 { DIRECTORY_MAPPING_NAME, "name" },
100 106 { DIRECTORY_MAPPING_IDMU, "idmu" },
101 107 { 0, NULL },
102 108 };
103 109
104 110 struct enum_lookup_map trust_dir_map[] = {
105 111 { 1, "they trust us" },
106 112 { 2, "we trust them" },
107 113 { 3, "we trust each other" },
108 114 { 0, NULL },
109 115 };
110 116
111 117 static int
112 118 generate_machine_uuid(char **machine_uuid)
113 119 {
114 120 uuid_t uu;
115 121
116 122 *machine_uuid = calloc(1, UUID_PRINTABLE_STRING_LENGTH + 1);
117 123 if (*machine_uuid == NULL) {
118 124 idmapdlog(LOG_ERR, "Out of memory");
119 125 return (-1);
120 126 }
121 127
122 128 uuid_clear(uu);
123 129 uuid_generate_time(uu);
124 130 uuid_unparse(uu, *machine_uuid);
125 131
126 132 return (0);
127 133 }
128 134
129 135 static int
130 136 generate_machine_sid(char **machine_sid, char *machine_uuid)
131 137 {
132 138 union {
133 139 uuid_t uu;
134 140 uint32_t v[4];
135 141 } uv;
136 142 int len;
137 143
138 144 /*
139 145 * Split the 128-bit machine UUID into three 32-bit values
140 146 * we'll use as the "sub-authorities" of the machine SID.
141 147 * The machine_sid will have the form S-1-5-21-J-K-L
142 148 * (that's four sub-authorities altogether) where:
143 149 * J = last 4 bytes of node_addr,
144 150 * K = time_mid, time_hi_and_version
145 151 * L = time_low
146 152 * (see struct uuid)
147 153 */
148 154
149 155 (void) memset(&uv, 0, sizeof (uv));
150 156 (void) uuid_parse(machine_uuid, uv.uu);
151 157
152 158 len = asprintf(machine_sid, "S-1-5-21-%u-%u-%u",
153 159 uv.v[3], uv.v[0], uv.v[1]);
154 160
155 161 if (len == -1 || *machine_sid == NULL) {
156 162 idmapdlog(LOG_ERR, "Out of memory");
157 163 return (-1);
158 164 }
159 165
160 166 return (0);
161 167 }
162 168
163 169
164 170 /* In the case of error, exists is set to FALSE anyway */
165 171 static int
166 172 prop_exists(idmap_cfg_handles_t *handles, const char *name, boolean_t *exists)
167 173 {
168 174
169 175 scf_property_t *scf_prop;
170 176
171 177 *exists = B_FALSE;
172 178
173 179 scf_prop = scf_property_create(handles->main);
174 180 if (scf_prop == NULL) {
175 181 idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
176 182 scf_strerror(scf_error()));
177 183 return (-1);
178 184 }
179 185
180 186 if (scf_pg_get_property(handles->config_pg, name, scf_prop) == 0)
181 187 *exists = B_TRUE;
182 188
183 189 scf_property_destroy(scf_prop);
184 190
185 191 return (0);
186 192 }
187 193
188 194 static int
189 195 get_debug(idmap_cfg_handles_t *handles, const char *name)
190 196 {
191 197 int64_t i64 = 0;
192 198
193 199 scf_property_t *scf_prop;
194 200 scf_value_t *value;
195 201
196 202 scf_prop = scf_property_create(handles->main);
197 203 if (scf_prop == NULL) {
198 204 idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
199 205 scf_strerror(scf_error()));
200 206 abort();
201 207 }
202 208 value = scf_value_create(handles->main);
203 209 if (value == NULL) {
204 210 idmapdlog(LOG_ERR, "scf_value_create() failed: %s",
205 211 scf_strerror(scf_error()));
206 212 abort();
207 213 }
208 214
209 215 if (scf_pg_get_property(handles->debug_pg, name, scf_prop) < 0) {
210 216 /* this is OK: the property is just undefined */
211 217 goto destruction;
212 218 }
213 219
214 220
215 221 if (scf_property_get_value(scf_prop, value) < 0) {
216 222 /* It is still OK when a property doesn't have any value */
217 223 goto destruction;
218 224 }
219 225
220 226 if (scf_value_get_integer(value, &i64) != 0) {
221 227 idmapdlog(LOG_ERR, "Can not retrieve %s/%s: %s",
222 228 DEBUG_PG, name, scf_strerror(scf_error()));
223 229 abort();
224 230 }
225 231
226 232 destruction:
227 233 scf_value_destroy(value);
228 234 scf_property_destroy(scf_prop);
229 235
230 236 return ((int)i64);
231 237 }
232 238
233 239 static int
234 240 get_val_bool(idmap_cfg_handles_t *handles, const char *name,
235 241 boolean_t *val, boolean_t default_val)
236 242 {
237 243 int rc = 0;
238 244
239 245 scf_property_t *scf_prop;
240 246 scf_value_t *value;
241 247
242 248 *val = default_val;
243 249
244 250 scf_prop = scf_property_create(handles->main);
245 251 if (scf_prop == NULL) {
246 252 idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
247 253 scf_strerror(scf_error()));
248 254 return (-1);
249 255 }
250 256 value = scf_value_create(handles->main);
251 257 if (value == NULL) {
252 258 idmapdlog(LOG_ERR, "scf_value_create() failed: %s",
253 259 scf_strerror(scf_error()));
254 260 scf_property_destroy(scf_prop);
255 261 return (-1);
256 262 }
257 263
258 264 /* It is OK if the property is undefined */
259 265 if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0)
260 266 goto destruction;
261 267
262 268
263 269 /* It is still OK when a property doesn't have any value */
264 270 if (scf_property_get_value(scf_prop, value) < 0)
265 271 goto destruction;
266 272
267 273 uint8_t b;
268 274 rc = scf_value_get_boolean(value, &b);
269 275
270 276 if (rc == 0)
271 277 *val = (boolean_t)b;
272 278
273 279 destruction:
274 280 scf_value_destroy(value);
275 281 scf_property_destroy(scf_prop);
276 282
277 283 return (rc);
278 284 }
279 285
280 286 static int
281 287 get_val_int(idmap_cfg_handles_t *handles, const char *name,
282 288 void *val, scf_type_t type)
283 289 {
284 290 int rc = 0;
285 291
286 292 scf_property_t *scf_prop;
287 293 scf_value_t *value;
288 294
289 295 switch (type) {
290 296 case SCF_TYPE_COUNT:
291 297 *(uint64_t *)val = 0;
292 298 break;
293 299 case SCF_TYPE_INTEGER:
294 300 *(int64_t *)val = 0;
295 301 break;
296 302 default:
297 303 idmapdlog(LOG_ERR, "Invalid scf integer type (%d)",
298 304 type);
299 305 abort();
300 306 }
301 307
302 308 scf_prop = scf_property_create(handles->main);
303 309 if (scf_prop == NULL) {
304 310 idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
305 311 scf_strerror(scf_error()));
306 312 return (-1);
307 313 }
308 314 value = scf_value_create(handles->main);
309 315 if (value == NULL) {
310 316 idmapdlog(LOG_ERR, "scf_value_create() failed: %s",
311 317 scf_strerror(scf_error()));
312 318 scf_property_destroy(scf_prop);
313 319 return (-1);
314 320 }
315 321
316 322 if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0)
317 323 /* this is OK: the property is just undefined */
318 324 goto destruction;
319 325
320 326
321 327 if (scf_property_get_value(scf_prop, value) < 0)
322 328 /* It is still OK when a property doesn't have any value */
323 329 goto destruction;
324 330
325 331 switch (type) {
326 332 case SCF_TYPE_COUNT:
327 333 rc = scf_value_get_count(value, val);
328 334 break;
329 335 case SCF_TYPE_INTEGER:
330 336 rc = scf_value_get_integer(value, val);
331 337 break;
332 338 default:
333 339 abort(); /* tested above */
334 340 /* NOTREACHED */
335 341 }
336 342
337 343 if (rc != 0) {
338 344 idmapdlog(LOG_ERR, "Can not retrieve config/%s: %s",
339 345 name, scf_strerror(scf_error()));
340 346 }
341 347
342 348 destruction:
343 349 scf_value_destroy(value);
344 350 scf_property_destroy(scf_prop);
345 351
346 352 return (rc);
347 353 }
348 354
349 355 static char *
350 356 scf_value2string(const char *name, scf_value_t *value)
351 357 {
352 358 static size_t max_val = 0;
353 359
354 360 if (max_val == 0)
355 361 max_val = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
356 362
357 363 char buf[max_val + 1];
358 364 if (scf_value_get_astring(value, buf, max_val + 1) < 0) {
359 365 idmapdlog(LOG_ERR, "Can not retrieve config/%s: %s",
360 366 name, scf_strerror(scf_error()));
361 367 return (NULL);
362 368 }
363 369
364 370 char *s = strdup(buf);
365 371 if (s == NULL)
366 372 idmapdlog(LOG_ERR, "Out of memory");
367 373
368 374 return (s);
369 375 }
370 376
371 377 static int
372 378 get_val_ds(idmap_cfg_handles_t *handles, const char *name, int defport,
373 379 ad_disc_ds_t **val)
374 380 {
375 381 char port_str[8];
376 382 struct addrinfo hints;
377 383 struct addrinfo *ai;
378 384 ad_disc_ds_t *servers = NULL;
379 385 scf_property_t *scf_prop;
380 386 scf_value_t *value;
381 387 scf_iter_t *iter;
382 388 char *host, *portstr;
383 389 int err, len, i;
384 390 int count = 0;
385 391 int rc = -1;
386 392
387 393 *val = NULL;
388 394
389 395 restart:
390 396 scf_prop = scf_property_create(handles->main);
391 397 if (scf_prop == NULL) {
392 398 idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
393 399 scf_strerror(scf_error()));
394 400 return (-1);
395 401 }
396 402
397 403 value = scf_value_create(handles->main);
398 404 if (value == NULL) {
399 405 idmapdlog(LOG_ERR, "scf_value_create() failed: %s",
400 406 scf_strerror(scf_error()));
401 407 scf_property_destroy(scf_prop);
402 408 return (-1);
403 409 }
404 410
405 411 iter = scf_iter_create(handles->main);
406 412 if (iter == NULL) {
407 413 idmapdlog(LOG_ERR, "scf_iter_create() failed: %s",
408 414 scf_strerror(scf_error()));
409 415 scf_value_destroy(value);
410 416 scf_property_destroy(scf_prop);
411 417 return (-1);
412 418 }
413 419
414 420 if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0) {
415 421 /* this is OK: the property is just undefined */
416 422 rc = 0;
417 423 goto destruction;
418 424 }
419 425
420 426 if (scf_iter_property_values(iter, scf_prop) < 0) {
421 427 idmapdlog(LOG_ERR,
422 428 "scf_iter_property_values(%s) failed: %s",
423 429 name, scf_strerror(scf_error()));
424 430 goto destruction;
425 431 }
426 432
427 433 /* Workaround scf bugs -- can't reset an iteration */
428 434 if (count == 0) {
429 435 while (scf_iter_next_value(iter, value) > 0)
430 436 count++;
431 437
432 438 if (count == 0) {
433 439 /* no values */
434 440 rc = 0;
435 441 goto destruction;
436 442 }
437 443
438 444 scf_value_destroy(value);
439 445 scf_iter_destroy(iter);
440 446 scf_property_destroy(scf_prop);
441 447 goto restart;
442 448 }
443 449
444 450 if ((servers = calloc(count + 1, sizeof (*servers))) == NULL) {
445 451 idmapdlog(LOG_ERR, "Out of memory");
446 452 goto destruction;
447 453 }
448 454
449 455 (void) memset(&hints, 0, sizeof (hints));
450 456 hints.ai_protocol = IPPROTO_TCP;
451 457 hints.ai_socktype = SOCK_STREAM;
452 458 host = NULL;
453 459
454 460 i = 0;
455 461 while (i < count && scf_iter_next_value(iter, value) > 0) {
456 462 if (host) {
457 463 free(host);
458 464 host = NULL;
459 465 }
460 466 servers[i].priority = 0;
461 467 servers[i].weight = 100;
462 468 servers[i].port = defport;
463 469 if ((host = scf_value2string(name, value)) == NULL)
464 470 continue;
465 471 if ((portstr = strchr(host, ':')) != NULL) {
466 472 *portstr++ = '\0';
467 473 servers[i].port = strtol(portstr,
468 474 (char **)NULL, 10);
469 475 if (servers[i].port == 0)
470 476 servers[i].port = defport;
471 477 }
472 478
473 479 /*
474 480 * Ignore this server if the hostname is too long
475 481 * or empty (continue without i++)
476 482 */
477 483 len = strlen(host);
478 484 if (len == 0) {
479 485 if (DBG(CONFIG, 1)) {
480 486 idmapdlog(LOG_INFO, "%s host=\"\"", name);
481 487 }
482 488 continue;
483 489 }
484 490 if (len >= sizeof (servers->host)) {
485 491 idmapdlog(LOG_ERR, "Host name too long: %s", host);
486 492 idmapdlog(LOG_ERR, "ignoring %s value", name);
487 493 continue;
488 494 }
489 495
490 496 /*
491 497 * Get the host address too. If we can't, then
492 498 * log an error and skip this host.
493 499 */
494 500 (void) snprintf(port_str, sizeof (port_str),
495 501 "%d", servers[i].port);
496 502 ai = NULL;
497 503 err = getaddrinfo(host, port_str, &hints, &ai);
498 504 if (err != 0) {
499 505 idmapdlog(LOG_ERR, "No address for host: %s (%s)",
500 506 host, gai_strerror(err));
501 507 idmapdlog(LOG_ERR, "ignoring %s value", name);
502 508 continue;
503 509 }
504 510
505 511 (void) strlcpy(servers[i].host, host,
506 512 sizeof (servers->host));
507 513 (void) memcpy(&servers[i].addr, ai->ai_addr, ai->ai_addrlen);
508 514 freeaddrinfo(ai);
509 515
510 516 /* Added a DS to the array. */
511 517 i++;
512 518 }
513 519 free(host);
514 520
515 521 if (i == 0) {
516 522 if (DBG(CONFIG, 1)) {
517 523 idmapdlog(LOG_INFO, "%s is empty", name);
518 524 }
519 525 free(servers);
520 526 servers = NULL;
521 527 }
522 528 *val = servers;
523 529
524 530 rc = 0;
525 531
526 532 destruction:
527 533 scf_value_destroy(value);
528 534 scf_iter_destroy(iter);
529 535 scf_property_destroy(scf_prop);
530 536
531 537 if (rc < 0) {
532 538 if (servers)
533 539 free(servers);
534 540 *val = NULL;
535 541 }
536 542
537 543 return (rc);
538 544 }
539 545
540 546 static int
541 547 get_val_astring(idmap_cfg_handles_t *handles, const char *name, char **val)
542 548 {
543 549 int rc = 0;
544 550
545 551 scf_property_t *scf_prop;
546 552 scf_value_t *value;
547 553
548 554 scf_prop = scf_property_create(handles->main);
549 555 if (scf_prop == NULL) {
550 556 idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
551 557 scf_strerror(scf_error()));
552 558 return (-1);
553 559 }
554 560 value = scf_value_create(handles->main);
555 561 if (value == NULL) {
556 562 idmapdlog(LOG_ERR, "scf_value_create() failed: %s",
557 563 scf_strerror(scf_error()));
558 564 scf_property_destroy(scf_prop);
559 565 return (-1);
560 566 }
561 567
562 568 *val = NULL;
563 569
564 570 if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0)
565 571 /* this is OK: the property is just undefined */
566 572 goto destruction;
567 573
568 574 if (scf_property_get_value(scf_prop, value) < 0) {
569 575 idmapdlog(LOG_ERR,
570 576 "scf_property_get_value(%s) failed: %s",
571 577 name, scf_strerror(scf_error()));
572 578 rc = -1;
573 579 goto destruction;
574 580 }
575 581
576 582 *val = scf_value2string(name, value);
577 583 if (*val == NULL)
578 584 rc = -1;
579 585
580 586 destruction:
581 587 scf_value_destroy(value);
582 588 scf_property_destroy(scf_prop);
583 589
584 590 if (rc < 0) {
585 591 if (*val)
586 592 free(*val);
587 593 *val = NULL;
588 594 }
589 595
590 596 return (rc);
591 597 }
592 598
593 599
594 600 static int
595 601 del_val(
596 602 idmap_cfg_handles_t *handles,
597 603 scf_propertygroup_t *pg,
598 604 const char *name)
599 605 {
600 606 int rc = -1;
601 607 int ret;
602 608 scf_transaction_t *tx = NULL;
603 609 scf_transaction_entry_t *ent = NULL;
604 610
605 611 if ((tx = scf_transaction_create(handles->main)) == NULL) {
606 612 idmapdlog(LOG_ERR,
607 613 "scf_transaction_create() failed: %s",
608 614 scf_strerror(scf_error()));
609 615 goto destruction;
610 616 }
611 617 if ((ent = scf_entry_create(handles->main)) == NULL) {
612 618 idmapdlog(LOG_ERR,
613 619 "scf_entry_create() failed: %s",
614 620 scf_strerror(scf_error()));
615 621 goto destruction;
616 622 }
617 623
618 624 do {
619 625 if (scf_pg_update(pg) == -1) {
620 626 idmapdlog(LOG_ERR,
621 627 "scf_pg_update(%s) failed: %s",
622 628 name, scf_strerror(scf_error()));
623 629 goto destruction;
624 630 }
625 631 if (scf_transaction_start(tx, pg) != 0) {
626 632 idmapdlog(LOG_ERR,
627 633 "scf_transaction_start(%s) failed: %s",
628 634 name, scf_strerror(scf_error()));
629 635 goto destruction;
630 636 }
631 637
632 638 if (scf_transaction_property_delete(tx, ent, name) != 0) {
633 639 /* Don't complain if it already doesn't exist. */
634 640 if (scf_error() != SCF_ERROR_NOT_FOUND) {
635 641 idmapdlog(LOG_ERR,
636 642 "scf_transaction_property_delete() failed:"
637 643 " %s",
638 644 scf_strerror(scf_error()));
639 645 }
640 646 goto destruction;
641 647 }
642 648
643 649 ret = scf_transaction_commit(tx);
644 650
645 651 if (ret == 0)
646 652 scf_transaction_reset(tx);
647 653 } while (ret == 0);
648 654
649 655 if (ret == -1) {
650 656 idmapdlog(LOG_ERR,
651 657 "scf_transaction_commit(%s) failed: %s",
652 658 name, scf_strerror(scf_error()));
653 659 goto destruction;
654 660 }
655 661
656 662 rc = 0;
657 663
658 664 destruction:
659 665 if (ent != NULL)
660 666 scf_entry_destroy(ent);
661 667 if (tx != NULL)
662 668 scf_transaction_destroy(tx);
663 669 return (rc);
664 670 }
665 671
666 672
667 673 static int
668 674 set_val(
669 675 idmap_cfg_handles_t *handles,
670 676 scf_propertygroup_t *pg,
671 677 const char *name,
672 678 scf_value_t *value)
673 679 {
674 680 int rc = -1;
675 681 int i;
676 682 scf_property_t *prop = NULL;
677 683 scf_transaction_t *tx = NULL;
678 684 scf_transaction_entry_t *ent = NULL;
679 685
680 686 if ((prop = scf_property_create(handles->main)) == NULL ||
681 687 (tx = scf_transaction_create(handles->main)) == NULL ||
682 688 (ent = scf_entry_create(handles->main)) == NULL) {
683 689 idmapdlog(LOG_ERR, "Unable to set property %s",
684 690 name, scf_strerror(scf_error()));
685 691 goto destruction;
686 692 }
687 693
688 694 for (i = 0; i < MAX_TRIES; i++) {
689 695 int ret;
690 696
691 697 if (scf_pg_update(pg) == -1) {
692 698 idmapdlog(LOG_ERR,
693 699 "scf_pg_update() failed: %s",
694 700 scf_strerror(scf_error()));
695 701 goto destruction;
696 702 }
697 703
698 704 if (scf_transaction_start(tx, pg) == -1) {
699 705 idmapdlog(LOG_ERR,
700 706 "scf_transaction_start(%s) failed: %s",
701 707 name, scf_strerror(scf_error()));
702 708 goto destruction;
703 709 }
704 710
705 711 ret = scf_pg_get_property(pg, name, prop);
706 712 if (ret == SCF_SUCCESS) {
707 713 if (scf_transaction_property_change_type(tx, ent, name,
708 714 scf_value_type(value)) < 0) {
709 715 idmapdlog(LOG_ERR,
710 716 "scf_transaction_property_change_type(%s)"
711 717 " failed: %s",
712 718 name, scf_strerror(scf_error()));
713 719 goto destruction;
714 720 }
715 721 } else if (scf_error() == SCF_ERROR_NOT_FOUND) {
716 722 if (scf_transaction_property_new(tx, ent, name,
717 723 scf_value_type(value)) < 0) {
718 724 idmapdlog(LOG_ERR,
719 725 "scf_transaction_property_new() failed: %s",
720 726 scf_strerror(scf_error()));
721 727 goto destruction;
722 728 }
723 729 } else {
724 730 idmapdlog(LOG_ERR,
725 731 "scf_pg_get_property(%s) failed: %s",
726 732 name, scf_strerror(scf_error()));
727 733 goto destruction;
728 734 }
729 735
730 736 if (scf_entry_add_value(ent, value) == -1) {
731 737 idmapdlog(LOG_ERR,
732 738 "scf_entry_add_value() failed: %s",
733 739 scf_strerror(scf_error()));
734 740 goto destruction;
735 741 }
736 742
737 743 ret = scf_transaction_commit(tx);
738 744 if (ret == 0) {
739 745 /*
740 746 * Property group set in scf_transaction_start()
741 747 * is not the most recent. Update pg, reset tx and
742 748 * retry tx.
743 749 */
744 750 idmapdlog(LOG_WARNING,
745 751 "scf_transaction_commit(%s) failed: %s",
746 752 name, scf_strerror(scf_error()));
747 753 scf_transaction_reset(tx);
748 754 continue;
749 755 }
750 756 if (ret != 1) {
751 757 idmapdlog(LOG_ERR,
752 758 "scf_transaction_commit(%s) failed: %s",
753 759 name, scf_strerror(scf_error()));
754 760 goto destruction;
755 761 }
756 762 /* Success! */
757 763 rc = 0;
758 764 break;
759 765 }
760 766
761 767 destruction:
762 768 scf_entry_destroy(ent);
763 769 scf_transaction_destroy(tx);
764 770 scf_property_destroy(prop);
765 771 return (rc);
766 772 }
767 773
768 774 static int
769 775 set_val_integer(
770 776 idmap_cfg_handles_t *handles,
771 777 scf_propertygroup_t *pg,
772 778 const char *name,
773 779 int64_t val)
774 780 {
775 781 scf_value_t *value = NULL;
776 782 int rc;
777 783
778 784 if ((value = scf_value_create(handles->main)) == NULL) {
779 785 idmapdlog(LOG_ERR, "Unable to set property %s",
780 786 name, scf_strerror(scf_error()));
781 787 return (-1);
782 788 }
783 789
784 790 scf_value_set_integer(value, val);
785 791
786 792 rc = set_val(handles, pg, name, value);
787 793
788 794 scf_value_destroy(value);
789 795
790 796 return (rc);
791 797 }
792 798
793 799
794 800 static int
795 801 set_val_astring(
796 802 idmap_cfg_handles_t *handles,
797 803 scf_propertygroup_t *pg,
798 804 const char *name,
799 805 const char *val)
800 806 {
801 807 scf_value_t *value = NULL;
802 808 int rc = -1;
803 809
804 810 if ((value = scf_value_create(handles->main)) == NULL) {
805 811 idmapdlog(LOG_ERR, "Unable to set property %s",
806 812 name, scf_strerror(scf_error()));
807 813 goto out;
808 814 }
809 815
810 816 if (scf_value_set_astring(value, val) == -1) {
811 817 idmapdlog(LOG_ERR,
812 818 "scf_value_set_astring() failed: %s",
813 819 scf_strerror(scf_error()));
814 820 goto out;
815 821 }
816 822
817 823 rc = set_val(handles, pg, name, value);
818 824
819 825 out:
820 826 scf_value_destroy(value);
821 827 return (rc);
822 828 }
823 829
824 830
825 831
826 832 /*
827 833 * This function updates a boolean value.
828 834 * If nothing has changed it returns 0 else 1
829 835 */
830 836 static int
831 837 update_bool(boolean_t *value, boolean_t *new, char *name)
832 838 {
833 839 if (*value == *new)
834 840 return (0);
835 841
836 842 if (DBG(CONFIG, 1)) {
837 843 idmapdlog(LOG_INFO, "change %s=%s", name,
838 844 *new ? "true" : "false");
839 845 }
840 846
841 847 *value = *new;
842 848 return (1);
843 849 }
844 850
845 851 /*
846 852 * This function updates a uint64_t value.
847 853 * If nothing has changed it returns 0 else 1
848 854 */
849 855 static int
850 856 update_uint64(uint64_t *value, uint64_t *new, char *name)
851 857 {
852 858 if (*value == *new)
853 859 return (0);
854 860
855 861 if (DBG(CONFIG, 1))
856 862 idmapdlog(LOG_INFO, "change %s=%llu", name, *new);
857 863
858 864 *value = *new;
859 865 return (1);
860 866 }
861 867
862 868 /*
863 869 * This function updates a string value.
864 870 * If nothing has changed it returns 0 else 1
865 871 */
866 872 static int
867 873 update_string(char **value, char **new, char *name)
868 874 {
869 875 int changed;
870 876
871 877 if (*new == NULL && *value != NULL)
872 878 changed = 1;
873 879 else if (*new != NULL && *value == NULL)
874 880 changed = 1;
875 881 else if (*new != NULL && *value != NULL && strcmp(*new, *value) != 0)
876 882 changed = 1;
877 883 else
878 884 changed = 0;
879 885
880 886 /*
881 887 * Note that even if unchanged we can't just return; we must free one
882 888 * of the values.
883 889 */
884 890
885 891 if (DBG(CONFIG, 1) && changed)
886 892 idmapdlog(LOG_INFO, "change %s=%s", name, CHECK_NULL(*new));
887 893
888 894 free(*value);
889 895 *value = *new;
890 896 *new = NULL;
891 897 return (changed);
892 898 }
893 899
894 900 static int
895 901 update_enum(int *value, int *new, char *name, struct enum_lookup_map *map)
896 902 {
897 903 if (*value == *new)
898 904 return (0);
899 905
900 906 if (DBG(CONFIG, 1)) {
901 907 idmapdlog(LOG_INFO, "change %s=%s", name,
902 908 enum_lookup(*new, map));
903 909 }
904 910
905 911 *value = *new;
906 912
907 913 return (1);
908 914 }
909 915
910 916 /*
911 917 * This function updates a directory service structure.
912 918 * If nothing has changed it returns 0 else 1
913 919 */
914 920 static int
915 921 update_dirs(ad_disc_ds_t **value, ad_disc_ds_t **new, char *name)
916 922 {
917 923
918 924 if (*value == *new)
919 925 /* Nothing to do */
920 926 return (0);
921 927
922 928 if (*value != NULL && *new != NULL &&
923 929 ad_disc_compare_ds(*value, *new) == 0) {
924 930 free(*new);
925 931 *new = NULL;
926 932 return (0);
927 933 }
928 934
929 935 if (*value != NULL)
930 936 free(*value);
931 937
932 938 *value = *new;
933 939 *new = NULL;
934 940
935 941 if (*value == NULL) {
936 942 /* We're unsetting this DS property */
937 943 if (DBG(CONFIG, 1))
938 944 idmapdlog(LOG_INFO, "change %s=<none>", name);
939 945 return (1);
940 946 }
941 947
942 948 if (DBG(CONFIG, 1)) {
943 949 /* List all the new DSs */
944 950 char buf[64];
945 951 ad_disc_ds_t *ds;
946 952 for (ds = *value; ds->host[0] != '\0'; ds++) {
947 953 if (ad_disc_getnameinfo(buf, sizeof (buf), &ds->addr))
948 954 (void) strlcpy(buf, "?", sizeof (buf));
949 955 idmapdlog(LOG_INFO, "change %s=%s addr=%s port=%d",
950 956 name, ds->host, buf, ds->port);
951 957 }
952 958 }
953 959 return (1);
954 960 }
955 961
956 962 /*
957 963 * This function updates a trusted domains structure.
958 964 * If nothing has changed it returns 0 else 1
959 965 */
960 966 static int
961 967 update_trusted_domains(ad_disc_trusteddomains_t **value,
962 968 ad_disc_trusteddomains_t **new, char *name)
963 969 {
964 970 int i;
965 971
966 972 if (*value == *new)
967 973 /* Nothing to do */
968 974 return (0);
969 975
970 976 if (*value != NULL && *new != NULL &&
971 977 ad_disc_compare_trusteddomains(*value, *new) == 0) {
972 978 free(*new);
973 979 *new = NULL;
974 980 return (0);
975 981 }
976 982
977 983 if (*value != NULL)
978 984 free(*value);
979 985
980 986 *value = *new;
981 987 *new = NULL;
982 988
983 989 if (*value == NULL) {
984 990 /* We're unsetting this DS property */
985 991 if (DBG(CONFIG, 1))
986 992 idmapdlog(LOG_INFO, "change %s=<none>", name);
987 993 return (1);
988 994 }
989 995
990 996 if (DBG(CONFIG, 1)) {
991 997 /* List all the new domains */
992 998 for (i = 0; (*value)[i].domain[0] != '\0'; i++) {
993 999 idmapdlog(LOG_INFO, "change %s=%s direction=%s", name,
994 1000 (*value)[i].domain,
995 1001 enum_lookup((*value)[i].direction, trust_dir_map));
996 1002 }
997 1003 }
998 1004 return (1);
999 1005 }
1000 1006
1001 1007
1002 1008 /*
1003 1009 * This function updates a domains in a forest structure.
1004 1010 * If nothing has changed it returns 0 else 1
1005 1011 */
1006 1012 static int
1007 1013 update_domains_in_forest(ad_disc_domainsinforest_t **value,
1008 1014 ad_disc_domainsinforest_t **new, char *name)
1009 1015 {
1010 1016 int i;
1011 1017
1012 1018 if (*value == *new)
1013 1019 /* Nothing to do */
1014 1020 return (0);
1015 1021
1016 1022 if (*value != NULL && *new != NULL &&
1017 1023 ad_disc_compare_domainsinforest(*value, *new) == 0) {
1018 1024 free(*new);
1019 1025 *new = NULL;
1020 1026 return (0);
1021 1027 }
1022 1028
1023 1029 if (*value != NULL)
1024 1030 free(*value);
1025 1031
1026 1032 *value = *new;
1027 1033 *new = NULL;
1028 1034
1029 1035 if (*value == NULL) {
1030 1036 /* We're unsetting this DS property */
1031 1037 if (DBG(CONFIG, 1))
1032 1038 idmapdlog(LOG_INFO, "change %s=<none>", name);
1033 1039 return (1);
1034 1040 }
1035 1041
1036 1042 if (DBG(CONFIG, 1)) {
1037 1043 /* List all the new domains */
1038 1044 for (i = 0; (*value)[i].domain[0] != '\0'; i++) {
1039 1045 idmapdlog(LOG_INFO, "change %s=%s", name,
1040 1046 (*value)[i].domain);
1041 1047 }
1042 1048 }
1043 1049 return (1);
1044 1050 }
1045 1051
1046 1052
1047 1053 static void
1048 1054 free_trusted_forests(idmap_trustedforest_t **value, int *num_values)
1049 1055 {
1050 1056 int i;
1051 1057
1052 1058 for (i = 0; i < *num_values; i++) {
1053 1059 free((*value)[i].forest_name);
1054 1060 free((*value)[i].global_catalog);
1055 1061 free((*value)[i].domains_in_forest);
1056 1062 }
1057 1063 free(*value);
1058 1064 *value = NULL;
1059 1065 *num_values = 0;
1060 1066 }
1061 1067
1062 1068
1063 1069 static int
1064 1070 compare_trusteddomainsinforest(ad_disc_domainsinforest_t *df1,
1065 1071 ad_disc_domainsinforest_t *df2)
1066 1072 {
1067 1073 int i, j;
1068 1074 int num_df1 = 0;
1069 1075 int num_df2 = 0;
1070 1076 boolean_t match;
1071 1077
1072 1078 for (i = 0; df1[i].domain[0] != '\0'; i++)
1073 1079 if (df1[i].trusted)
1074 1080 num_df1++;
1075 1081
1076 1082 for (j = 0; df2[j].domain[0] != '\0'; j++)
1077 1083 if (df2[j].trusted)
1078 1084 num_df2++;
1079 1085
1080 1086 if (num_df1 != num_df2)
1081 1087 return (1);
1082 1088
1083 1089 for (i = 0; df1[i].domain[0] != '\0'; i++) {
1084 1090 if (df1[i].trusted) {
1085 1091 match = B_FALSE;
1086 1092 for (j = 0; df2[j].domain[0] != '\0'; j++) {
1087 1093 if (df2[j].trusted &&
1088 1094 domain_eq(df1[i].domain, df2[j].domain) &&
1089 1095 strcmp(df1[i].sid, df2[j].sid) == 0) {
1090 1096 match = B_TRUE;
1091 1097 break;
1092 1098 }
1093 1099 }
1094 1100 if (!match)
1095 1101 return (1);
1096 1102 }
1097 1103 }
1098 1104 return (0);
1099 1105 }
1100 1106
1101 1107
1102 1108
1103 1109 /*
1104 1110 * This function updates trusted forest structure.
1105 1111 * If nothing has changed it returns 0 else 1
1106 1112 */
1107 1113 static int
1108 1114 update_trusted_forest(idmap_trustedforest_t **value, int *num_value,
1109 1115 idmap_trustedforest_t **new, int *num_new, char *name)
1110 1116 {
1111 1117 int i, j;
1112 1118 boolean_t match;
1113 1119
1114 1120 if (*value == *new)
1115 1121 /* Nothing to do */
1116 1122 return (0);
1117 1123
1118 1124 if (*value != NULL && *new != NULL) {
1119 1125 if (*num_value != *num_new)
1120 1126 goto not_equal;
1121 1127 for (i = 0; i < *num_value; i++) {
1122 1128 match = B_FALSE;
1123 1129 for (j = 0; j < *num_new; j++) {
1124 1130 if (strcmp((*value)[i].forest_name,
1125 1131 (*new)[j].forest_name) == 0 &&
1126 1132 ad_disc_compare_ds(
1127 1133 (*value)[i].global_catalog,
1128 1134 (*new)[j].global_catalog) == 0 &&
1129 1135 compare_trusteddomainsinforest(
1130 1136 (*value)[i].domains_in_forest,
1131 1137 (*new)[j].domains_in_forest) == 0) {
1132 1138 match = B_TRUE;
1133 1139 break;
1134 1140 }
1135 1141 }
1136 1142 if (!match)
1137 1143 goto not_equal;
1138 1144 }
1139 1145 free_trusted_forests(new, num_new);
1140 1146 return (0);
1141 1147 }
1142 1148 not_equal:
1143 1149 if (*value != NULL)
1144 1150 free_trusted_forests(value, num_value);
1145 1151 *value = *new;
1146 1152 *num_value = *num_new;
1147 1153 *new = NULL;
1148 1154 *num_new = 0;
1149 1155
1150 1156 if (*value == NULL) {
1151 1157 /* We're unsetting this DS property */
1152 1158 if (DBG(CONFIG, 1))
1153 1159 idmapdlog(LOG_INFO, "change %s=<none>", name);
1154 1160 return (1);
1155 1161 }
1156 1162
1157 1163 if (DBG(CONFIG, 1)) {
1158 1164 /* List all the trusted forests */
1159 1165 for (i = 0; i < *num_value; i++) {
1160 1166 idmap_trustedforest_t *f = &(*value)[i];
1161 1167 for (j = 0;
1162 1168 f->domains_in_forest[j].domain[0] != '\0';
1163 1169 j++) {
1164 1170 /* List trusted Domains in the forest. */
1165 1171 if (f->domains_in_forest[j].trusted)
1166 1172 idmapdlog(LOG_INFO,
1167 1173 "change %s=%s domain=%s",
1168 1174 name, f->forest_name,
1169 1175 f->domains_in_forest[j].domain);
1170 1176 }
1171 1177 /* List the hosts */
1172 1178 for (j = 0;
1173 1179 f->global_catalog[j].host[0] != '\0';
1174 1180 j++) {
1175 1181 idmapdlog(LOG_INFO,
1176 1182 "change %s=%s host=%s port=%d",
1177 1183 name, f->forest_name,
1178 1184 f->global_catalog[j].host,
1179 1185 f->global_catalog[j].port);
1180 1186 }
1181 1187 }
1182 1188 }
1183 1189 return (1);
1184 1190 }
1185 1191
1186 1192 const char *
1187 1193 enum_lookup(int value, struct enum_lookup_map *map)
1188 1194 {
1189 1195 for (; map->string != NULL; map++) {
1190 1196 if (value == map->value) {
1191 1197 return (map->string);
1192 1198 }
1193 1199 }
1194 1200 return ("(invalid)");
1195 1201 }
1196 1202
1197 1203 /*
1198 1204 * Returns 1 if the PF_ROUTE socket event indicates that we should rescan the
1199 1205 * interfaces.
1200 1206 *
1201 1207 * Shamelessly based on smb_nics_changed() and other PF_ROUTE uses in ON.
1202 1208 */
1203 1209 static
1204 1210 boolean_t
1205 1211 pfroute_event_is_interesting(int rt_sock)
1206 1212 {
1207 1213 int nbytes;
1208 1214 int64_t msg[2048 / 8];
1209 1215 struct rt_msghdr *rtm;
1210 1216 boolean_t is_interesting = B_FALSE;
1211 1217
1212 1218 for (;;) {
1213 1219 if ((nbytes = read(rt_sock, msg, sizeof (msg))) <= 0)
1214 1220 break;
1215 1221 rtm = (struct rt_msghdr *)msg;
1216 1222 if (rtm->rtm_version != RTM_VERSION)
1217 1223 continue;
1218 1224 if (nbytes < rtm->rtm_msglen)
1219 1225 continue;
1220 1226 switch (rtm->rtm_type) {
1221 1227 case RTM_NEWADDR:
1222 1228 case RTM_DELADDR:
1223 1229 case RTM_IFINFO:
1224 1230 is_interesting = B_TRUE;
1225 1231 break;
1226 1232 default:
1227 1233 break;
1228 1234 }
1229 1235 }
1230 1236 return (is_interesting);
1231 1237 }
1232 1238
1233 1239 /*
1234 1240 * Wait for an event, and report what kind of event occurred.
1235 1241 *
1236 1242 * Note that there are cases where we are awoken but don't care about
1237 1243 * the lower-level event. We can't just loop here because we can't
1238 1244 * readily calculate how long to sleep the next time. We return
1239 1245 * EVENT_NOTHING and let the caller loop.
1240 1246 */
1241 1247 static
1242 1248 enum event_type
1243 1249 wait_for_event(struct timespec *timeoutp)
1244 1250 {
1245 1251 port_event_t pe;
1246 1252
1247 1253 (void) memset(&pe, 0, sizeof (pe));
1248 1254 if (port_get(idmapd_ev_port, &pe, timeoutp) != 0) {
1249 1255 switch (errno) {
1250 1256 case EINTR:
1251 1257 return (EVENT_NOTHING);
1252 1258 case ETIME:
1253 1259 /* Timeout */
1254 1260 return (EVENT_TIMEOUT);
1255 1261 default:
1256 1262 /* EBADF, EBADFD, EFAULT, EINVAL (end of time?)? */
1257 1263 idmapdlog(LOG_ERR, "Event port failed: %s",
1258 1264 strerror(errno));
1259 1265 exit(1);
1260 1266 /* NOTREACHED */
1261 1267 }
1262 1268 }
1263 1269
1264 1270
1265 1271 switch (pe.portev_source) {
1266 1272 case 0:
1267 1273 /*
1268 1274 * This isn't documented, but seems to be what you get if
1269 1275 * the timeout is zero seconds and there are no events
1270 1276 * pending.
1271 1277 */
1272 1278 return (EVENT_TIMEOUT);
1273 1279
1274 1280 case PORT_SOURCE_USER:
1275 1281 switch (pe.portev_events) {
1276 1282 case RECONFIGURE:
1277 1283 return (EVENT_REFRESH);
1278 1284 case POKE_AUTO_DISCOVERY:
1279 1285 return (EVENT_POKED);
1280 1286 case KICK_AUTO_DISCOVERY:
1281 1287 return (EVENT_KICKED);
1282 1288 }
1283 1289 return (EVENT_NOTHING);
1284 1290
1285 1291 case PORT_SOURCE_FD:
1286 1292 if (pe.portev_object == rt_sock) {
1287 1293 /*
1288 1294 * PF_ROUTE socket read event:
1289 1295 * re-associate fd
1290 1296 * handle event
1291 1297 */
1292 1298 if (port_associate(idmapd_ev_port, PORT_SOURCE_FD,
1293 1299 rt_sock, POLLIN, NULL) != 0) {
1294 1300 idmapdlog(LOG_ERR, "Failed to re-associate the "
1295 1301 "routing socket with the event port: %s",
1296 1302 strerror(errno));
1297 1303 abort();
1298 1304 }
1299 1305 /*
1300 1306 * The network configuration may still be in flux.
1301 1307 * No matter, the resolver will re-transmit and
1302 1308 * timeout if need be.
1303 1309 */
1304 1310 if (pfroute_event_is_interesting(rt_sock)) {
1305 1311 if (DBG(CONFIG, 1)) {
1306 1312 idmapdlog(LOG_DEBUG,
1307 1313 "Interesting routing event");
1308 1314 }
1309 1315 return (EVENT_ROUTING);
1310 1316 } else {
1311 1317 if (DBG(CONFIG, 2)) {
1312 1318 idmapdlog(LOG_DEBUG,
1313 1319 "Boring routing event");
1314 1320 }
1315 1321 return (EVENT_NOTHING);
1316 1322 }
1317 1323 }
1318 1324 /* Event on an FD other than the routing FD? Ignore it. */
1319 1325 break;
1320 1326 }
1321 1327
1322 1328 return (EVENT_NOTHING);
1323 1329 }
1324 1330
1325 1331 void *
1326 1332 idmap_cfg_update_thread(void *arg)
1327 1333 {
1328 1334 NOTE(ARGUNUSED(arg))
1329 1335 idmap_pg_config_t *pgcfg = &_idmapdstate.cfg->pgcfg;
1330 1336 const ad_disc_t ad_ctx = _idmapdstate.cfg->handles.ad_ctx;
1331 1337 int flags = CFG_DISCOVER;
1332 1338
1333 1339 for (;;) {
1334 1340 struct timespec timeout;
1335 1341 struct timespec *timeoutp;
1336 1342 int rc;
1337 1343 int ttl, max_ttl;
1338 1344
1339 1345 (void) ad_disc_SubnetChanged(ad_ctx);
1340 1346
1341 1347 rc = idmap_cfg_load(_idmapdstate.cfg, flags);
1342 1348 if (rc < -1) {
1343 1349 idmapdlog(LOG_ERR, "Fatal errors while reading "
1344 1350 "SMF properties");
1345 1351 exit(1);
1346 1352 } else if (rc == -1) {
1347 1353 idmapdlog(LOG_WARNING,
1348 1354 "Errors re-loading configuration may cause AD "
1349 1355 "lookups to fail");
1350 1356 }
1351 1357
1352 1358 /*
1353 1359 * Wait for an interesting event. Note that we might get
1354 1360 * boring events between interesting events. If so, we loop.
1355 1361 */
1356 1362 flags = CFG_DISCOVER;
1357 1363 for (;;) {
1358 1364 /*
1359 1365 * If we don't know our domain name, don't bother
1360 1366 * with rediscovery until the next config change.
1361 1367 * Avoids hourly noise in workgroup mode.
1362 1368 */
1363 1369 if (pgcfg->domain_name == NULL)
1364 1370 ttl = -1;
1365 1371 else
1366 1372 ttl = ad_disc_get_TTL(ad_ctx);
1367 1373 if (ttl < 0) {
1368 1374 timeoutp = NULL;
1369 1375 } else {
1370 1376 max_ttl = (int)pgcfg->rediscovery_interval;
1371 1377 if (ttl > max_ttl)
1372 1378 ttl = max_ttl;
1373 1379 if (ttl < MIN_REDISCOVERY_INTERVAL)
1374 1380 ttl = MIN_REDISCOVERY_INTERVAL;
1375 1381 timeout.tv_sec = ttl;
1376 1382 timeout.tv_nsec = 0;
1377 1383 timeoutp = &timeout;
1378 1384 }
1379 1385
1380 1386 if (DBG(CONFIG, 1))
1381 1387 idmapdlog(LOG_DEBUG,
1382 1388 "_cfg_update_thread waiting");
1383 1389
1384 1390 switch (wait_for_event(timeoutp)) {
1385 1391 case EVENT_NOTHING:
1386 1392 if (DBG(CONFIG, 2))
1387 1393 idmapdlog(LOG_DEBUG, "Boring event.");
1388 1394 continue;
1389 1395 case EVENT_REFRESH:
1390 1396 if (DBG(CONFIG, 1))
1391 1397 idmapdlog(LOG_INFO, "SMF refresh");
1392 1398 /*
1393 1399 * Forget any DC we had previously.
1394 1400 */
1395 1401 flags |= CFG_FORGET_DC;
1396 1402
1397 1403 /*
1398 1404 * Blow away the ccache, we might have
1399 1405 * re-joined the domain or joined a new one
1400 1406 */
1401 1407 (void) unlink(IDMAP_CACHEDIR "/ccache");
1402 1408 break;
1403 1409 case EVENT_POKED:
1404 1410 if (DBG(CONFIG, 1))
1405 1411 idmapdlog(LOG_DEBUG, "poked");
1406 1412 break;
1407 1413 case EVENT_KICKED:
1408 1414 if (DBG(CONFIG, 1))
1409 1415 idmapdlog(LOG_DEBUG, "kicked");
1410 1416 flags |= CFG_FORGET_DC;
1411 1417 break;
1412 1418 case EVENT_TIMEOUT:
1413 1419 if (DBG(CONFIG, 1))
1414 1420 idmapdlog(LOG_DEBUG, "TTL expired");
1415 1421 break;
1416 1422 case EVENT_ROUTING:
1417 1423 /* Already logged to DEBUG */
1418 1424 break;
1419 1425 }
1420 1426 /* An interesting event! */
1421 1427 break;
1422 1428 }
1423 1429 }
1424 1430 /*
1425 1431 * Lint isn't happy with the concept of a function declared to
1426 1432 * return something, that doesn't return. Of course, merely adding
1427 1433 * the return isn't enough, because it's never reached...
1428 1434 */
1429 1435 /*NOTREACHED*/
1430 1436 return (NULL);
1431 1437 }
1432 1438
1433 1439 int
1434 1440 idmap_cfg_start_updates(void)
1435 1441 {
1436 1442 if ((idmapd_ev_port = port_create()) < 0) {
1437 1443 idmapdlog(LOG_ERR, "Failed to create event port: %s",
1438 1444 strerror(errno));
1439 1445 return (-1);
1440 1446 }
1441 1447
1442 1448 if ((rt_sock = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) {
1443 1449 idmapdlog(LOG_ERR, "Failed to open routing socket: %s",
1444 1450 strerror(errno));
1445 1451 (void) close(idmapd_ev_port);
1446 1452 return (-1);
1447 1453 }
1448 1454
1449 1455 if (fcntl(rt_sock, F_SETFL, O_NDELAY|O_NONBLOCK) < 0) {
1450 1456 idmapdlog(LOG_ERR, "Failed to set routing socket flags: %s",
1451 1457 strerror(errno));
1452 1458 (void) close(rt_sock);
1453 1459 (void) close(idmapd_ev_port);
1454 1460 return (-1);
1455 1461 }
1456 1462
1457 1463 if (port_associate(idmapd_ev_port, PORT_SOURCE_FD,
1458 1464 rt_sock, POLLIN, NULL) != 0) {
1459 1465 idmapdlog(LOG_ERR, "Failed to associate the routing "
1460 1466 "socket with the event port: %s", strerror(errno));
1461 1467 (void) close(rt_sock);
1462 1468 (void) close(idmapd_ev_port);
1463 1469 return (-1);
1464 1470 }
1465 1471
1466 1472 if ((errno = pthread_create(&update_thread_handle, NULL,
1467 1473 idmap_cfg_update_thread, NULL)) != 0) {
1468 1474 idmapdlog(LOG_ERR, "Failed to start update thread: %s",
1469 1475 strerror(errno));
1470 1476 (void) port_dissociate(idmapd_ev_port, PORT_SOURCE_FD, rt_sock);
1471 1477 (void) close(rt_sock);
1472 1478 (void) close(idmapd_ev_port);
1473 1479 return (-1);
1474 1480 }
1475 1481
1476 1482 return (0);
1477 1483 }
1478 1484
1479 1485 /*
1480 1486 * Reject attribute names with invalid characters.
1481 1487 */
1482 1488 static
1483 1489 int
1484 1490 valid_ldap_attr(const char *attr) {
1485 1491 for (; *attr; attr++) {
1486 1492 if (!isalnum(*attr) && *attr != '-' &&
1487 1493 *attr != '_' && *attr != '.' && *attr != ';')
1488 1494 return (0);
1489 1495 }
1490 1496 return (1);
1491 1497 }
1492 1498
1493 1499 static
1494 1500 void
1495 1501 idmapd_set_debug(
1496 1502 idmap_cfg_handles_t *handles,
1497 1503 enum idmapd_debug item,
1498 1504 const char *name)
1499 1505 {
1500 1506 int val;
1501 1507
1502 1508 if (item < 0 || item > IDMAPD_DEBUG_MAX)
1503 1509 return;
1504 1510
1505 1511 val = get_debug(handles, name);
1506 1512
1507 1513 if (val != _idmapdstate.debug[item])
1508 1514 idmapdlog(LOG_DEBUG, "%s/%s = %d", DEBUG_PG, name, val);
1509 1515
1510 1516 _idmapdstate.debug[item] = val;
1511 1517 }
1512 1518
1513 1519 static
1514 1520 void
1515 1521 check_smf_debug_mode(idmap_cfg_handles_t *handles)
1516 1522 {
1517 1523 idmapd_set_debug(handles, IDMAPD_DEBUG_ALL, "all");
1518 1524 idmapd_set_debug(handles, IDMAPD_DEBUG_CONFIG, "config");
1519 1525 idmapd_set_debug(handles, IDMAPD_DEBUG_MAPPING, "mapping");
1520 1526 idmapd_set_debug(handles, IDMAPD_DEBUG_DISC, "discovery");
1521 1527 idmapd_set_debug(handles, IDMAPD_DEBUG_DNS, "dns");
1522 1528 idmapd_set_debug(handles, IDMAPD_DEBUG_LDAP, "ldap");
1523 1529
1524 1530 adutils_set_debug(AD_DEBUG_ALL, _idmapdstate.debug[IDMAPD_DEBUG_ALL]);
1525 1531 adutils_set_debug(AD_DEBUG_DISC, _idmapdstate.debug[IDMAPD_DEBUG_DISC]);
1526 1532 adutils_set_debug(AD_DEBUG_DNS, _idmapdstate.debug[IDMAPD_DEBUG_DNS]);
1527 1533 adutils_set_debug(AD_DEBUG_LDAP, _idmapdstate.debug[IDMAPD_DEBUG_LDAP]);
1528 1534 }
1529 1535
1530 1536 /*
1531 1537 * This is the half of idmap_cfg_load() that loads property values from
1532 1538 * SMF (using the config/ property group of the idmap FMRI).
1533 1539 *
1534 1540 * Return values: 0 -> success, -1 -> failure, -2 -> hard failures
1535 1541 * -3 -> hard smf config failures
1536 1542 * reading from SMF.
1537 1543 */
1538 1544 static int
1539 1545 idmap_cfg_load_smf(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg,
1540 1546 int * const errors)
1541 1547 {
1542 1548 int rc;
1543 1549 char *s;
1544 1550
1545 1551 *errors = 0;
1546 1552
1547 1553 if (scf_pg_update(handles->config_pg) < 0) {
1548 1554 idmapdlog(LOG_ERR, "scf_pg_update() failed: %s",
1549 1555 scf_strerror(scf_error()));
1550 1556 return (-2);
1551 1557 }
1552 1558
1553 1559 if (scf_pg_update(handles->debug_pg) < 0) {
1554 1560 idmapdlog(LOG_ERR, "scf_pg_update() failed: %s",
1555 1561 scf_strerror(scf_error()));
1556 1562 return (-2);
1557 1563 }
1558 1564
1559 1565 check_smf_debug_mode(handles);
1560 1566
1561 1567 rc = get_val_bool(handles, "unresolvable_sid_mapping",
1562 1568 &pgcfg->eph_map_unres_sids, B_TRUE);
1563 1569 if (rc != 0)
1564 1570 (*errors)++;
1565 1571
1566 1572 rc = get_val_bool(handles, "use_ads",
1567 1573 &pgcfg->use_ads, B_TRUE);
1568 1574 if (rc != 0)
1569 1575 (*errors)++;
1570 1576
1571 1577 rc = get_val_bool(handles, "use_lsa",
1572 1578 &pgcfg->use_lsa, B_TRUE);
1573 1579 if (rc != 0)
1574 1580 (*errors)++;
1575 1581
1576 1582 rc = get_val_bool(handles, "disable_cross_forest_trusts",
1577 1583 &pgcfg->disable_cross_forest_trusts, B_TRUE);
1578 1584 if (rc != 0)
1579 1585 (*errors)++;
1580 1586
1581 1587 rc = get_val_astring(handles, "directory_based_mapping", &s);
1582 1588 if (rc != 0)
1583 1589 (*errors)++;
1584 1590 else if (s == NULL || strcasecmp(s, "none") == 0)
1585 1591 pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NONE;
1586 1592 else if (strcasecmp(s, "name") == 0)
1587 1593 pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NAME;
1588 1594 else if (strcasecmp(s, "idmu") == 0)
1589 1595 pgcfg->directory_based_mapping = DIRECTORY_MAPPING_IDMU;
1590 1596 else {
1591 1597 pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NONE;
1592 1598 idmapdlog(LOG_ERR,
1593 1599 "config/directory_based_mapping: invalid value \"%s\" ignored",
|
↓ open down ↓ |
1504 lines elided |
↑ open up ↑ |
1594 1600 s);
1595 1601 (*errors)++;
1596 1602 }
1597 1603 free(s);
1598 1604
1599 1605 rc = get_val_int(handles, "list_size_limit",
1600 1606 &pgcfg->list_size_limit, SCF_TYPE_COUNT);
1601 1607 if (rc != 0)
1602 1608 (*errors)++;
1603 1609
1610 + rc = get_val_int(handles, "max_threads",
1611 + &pgcfg->max_threads, SCF_TYPE_COUNT);
1612 + if (rc != 0)
1613 + (*errors)++;
1614 + if (pgcfg->max_threads == 0)
1615 + pgcfg->max_threads = MAX_THREADS_DEFAULT;
1616 + if (pgcfg->max_threads > UINT_MAX)
1617 + pgcfg->max_threads = UINT_MAX;
1618 +
1604 1619 rc = get_val_int(handles, "id_cache_timeout",
1605 1620 &pgcfg->id_cache_timeout, SCF_TYPE_COUNT);
1606 1621 if (rc != 0)
1607 1622 (*errors)++;
1608 1623 if (pgcfg->id_cache_timeout == 0)
1609 1624 pgcfg->id_cache_timeout = ID_CACHE_TMO_DEFAULT;
1610 1625
1611 1626 rc = get_val_int(handles, "name_cache_timeout",
1612 1627 &pgcfg->name_cache_timeout, SCF_TYPE_COUNT);
1613 1628 if (rc != 0)
1614 1629 (*errors)++;
1615 1630 if (pgcfg->name_cache_timeout == 0)
1616 1631 pgcfg->name_cache_timeout = NAME_CACHE_TMO_DEFAULT;
1617 1632
1618 1633 rc = get_val_int(handles, "rediscovery_interval",
1619 1634 &pgcfg->rediscovery_interval, SCF_TYPE_COUNT);
1620 1635 if (rc != 0)
1621 1636 (*errors)++;
1622 1637 if (pgcfg->rediscovery_interval == 0)
1623 1638 pgcfg->rediscovery_interval = REDISCOVERY_INTERVAL_DEFAULT;
|
↓ open down ↓ |
10 lines elided |
↑ open up ↑ |
1624 1639
1625 1640 rc = get_val_astring(handles, "domain_name",
1626 1641 &pgcfg->domain_name);
1627 1642 if (rc != 0)
1628 1643 (*errors)++;
1629 1644 else {
1630 1645 if (pgcfg->domain_name != NULL &&
1631 1646 pgcfg->domain_name[0] == '\0') {
1632 1647 free(pgcfg->domain_name);
1633 1648 pgcfg->domain_name = NULL;
1649 + } else {
1650 + pgcfg->domain_name_auto_disc = B_FALSE;
1634 1651 }
1635 1652 (void) ad_disc_set_DomainName(handles->ad_ctx,
1636 1653 pgcfg->domain_name);
1637 - pgcfg->domain_name_auto_disc = B_FALSE;
1638 1654 }
1639 1655
1640 1656 rc = get_val_astring(handles, "default_domain",
1641 1657 &pgcfg->default_domain);
1642 1658 if (rc != 0) {
1643 1659 /*
1644 1660 * SCF failures fetching config/default_domain we treat
1645 1661 * as fatal as they may leave ID mapping rules that
1646 1662 * match unqualified winnames flapping in the wind.
1647 1663 */
1648 1664 return (-2);
1649 1665 }
1650 1666
1651 1667 if (pgcfg->default_domain == NULL && pgcfg->domain_name != NULL) {
1652 1668 pgcfg->default_domain = strdup(pgcfg->domain_name);
1653 1669 }
1654 1670
1655 1671 rc = get_val_astring(handles, "domain_guid", &s);
1656 1672 if (rc != 0) {
1657 1673 (*errors)++;
1658 1674 } else if (s == NULL || s[0] == '\0') {
1659 1675 /* OK, not set. */
1660 1676 free(s);
1661 1677 } else {
1662 1678 uuid_t u;
1663 1679
1664 1680 if (uuid_parse(s, u) != 0) {
1665 1681 idmapdlog(LOG_ERR,
1666 1682 "config/domain_guid: invalid value \"%s\" ignored", s);
1667 1683 free(s);
1668 1684 (*errors)++;
1669 1685 } else {
1670 1686 pgcfg->domain_guid = s;
1671 1687 pgcfg->domain_guid_auto_disc = B_FALSE;
1672 1688 (void) ad_disc_set_DomainGUID(handles->ad_ctx, u);
1673 1689 }
1674 1690 }
1675 1691
1676 1692 rc = get_val_astring(handles, "machine_uuid", &pgcfg->machine_uuid);
1677 1693 if (rc != 0)
1678 1694 (*errors)++;
1679 1695 if (pgcfg->machine_uuid == NULL) {
1680 1696 /* If machine_uuid not configured, generate one */
1681 1697 if (generate_machine_uuid(&pgcfg->machine_uuid) < 0)
1682 1698 return (-2);
1683 1699 rc = set_val_astring(handles, handles->config_pg,
1684 1700 "machine_uuid", pgcfg->machine_uuid);
1685 1701 if (rc != 0)
1686 1702 (*errors)++;
1687 1703 }
1688 1704
1689 1705 rc = get_val_astring(handles, "machine_sid", &pgcfg->machine_sid);
1690 1706 if (rc != 0)
1691 1707 (*errors)++;
1692 1708 if (pgcfg->machine_sid == NULL) {
1693 1709 /*
1694 1710 * If machine_sid not configured, generate one
1695 1711 * from the machine UUID.
1696 1712 */
1697 1713 if (generate_machine_sid(&pgcfg->machine_sid,
1698 1714 pgcfg->machine_uuid) < 0)
1699 1715 return (-2);
1700 1716 rc = set_val_astring(handles, handles->config_pg,
1701 1717 "machine_sid", pgcfg->machine_sid);
1702 1718 if (rc != 0)
1703 1719 (*errors)++;
1704 1720 }
1705 1721
1706 1722 rc = get_val_ds(handles, "domain_controller", 389,
1707 1723 &pgcfg->domain_controller);
1708 1724 if (rc != 0)
1709 1725 (*errors)++;
1710 1726 else {
1711 1727 (void) ad_disc_set_DomainController(handles->ad_ctx,
1712 1728 pgcfg->domain_controller);
1713 1729 pgcfg->domain_controller_auto_disc = B_FALSE;
1714 1730 }
1715 1731
1716 1732 rc = get_val_ds(handles, "preferred_dc", 389,
1717 1733 &pgcfg->preferred_dc);
1718 1734 if (rc != 0)
1719 1735 (*errors)++;
|
↓ open down ↓ |
72 lines elided |
↑ open up ↑ |
1720 1736 else {
1721 1737 (void) ad_disc_set_PreferredDC(handles->ad_ctx,
1722 1738 pgcfg->preferred_dc);
1723 1739 pgcfg->preferred_dc_auto_disc = B_FALSE;
1724 1740 }
1725 1741
1726 1742 rc = get_val_astring(handles, "forest_name", &pgcfg->forest_name);
1727 1743 if (rc != 0)
1728 1744 (*errors)++;
1729 1745 else {
1746 + if (pgcfg->forest_name != NULL &&
1747 + pgcfg->forest_name[0] == '\0') {
1748 + free(pgcfg->forest_name);
1749 + pgcfg->forest_name = NULL;
1750 + } else {
1751 + pgcfg->forest_name_auto_disc = B_FALSE;
1752 + }
1730 1753 (void) ad_disc_set_ForestName(handles->ad_ctx,
1731 1754 pgcfg->forest_name);
1732 - pgcfg->forest_name_auto_disc = B_FALSE;
1733 1755 }
1734 1756
1735 1757 rc = get_val_astring(handles, "site_name", &pgcfg->site_name);
1736 1758 if (rc != 0)
1737 1759 (*errors)++;
1738 - else
1760 + else {
1761 + if (pgcfg->site_name != NULL &&
1762 + pgcfg->site_name[0] == '\0') {
1763 + free(pgcfg->site_name);
1764 + pgcfg->site_name = NULL;
1765 + } else {
1766 + pgcfg->site_name_auto_disc = B_FALSE;
1767 + }
1739 1768 (void) ad_disc_set_SiteName(handles->ad_ctx, pgcfg->site_name);
1769 + }
1740 1770
1741 1771 rc = get_val_ds(handles, "global_catalog", 3268,
1742 1772 &pgcfg->global_catalog);
1743 1773 if (rc != 0)
1744 1774 (*errors)++;
1745 1775 else {
1746 1776 (void) ad_disc_set_GlobalCatalog(handles->ad_ctx,
1747 1777 pgcfg->global_catalog);
1748 1778 pgcfg->global_catalog_auto_disc = B_FALSE;
1749 1779 }
1750 1780
1751 1781 /* Unless we're doing directory-based name mapping, we're done. */
1752 1782 if (pgcfg->directory_based_mapping != DIRECTORY_MAPPING_NAME)
1753 1783 return (0);
1754 1784
1755 1785 rc = get_val_astring(handles, "ad_unixuser_attr",
1756 1786 &pgcfg->ad_unixuser_attr);
1757 1787 if (rc != 0)
1758 1788 return (-2);
1759 1789 if (pgcfg->ad_unixuser_attr != NULL &&
1760 1790 !valid_ldap_attr(pgcfg->ad_unixuser_attr)) {
1761 1791 idmapdlog(LOG_ERR, "config/ad_unixuser_attr=%s is not a "
1762 1792 "valid LDAP attribute name", pgcfg->ad_unixuser_attr);
1763 1793 return (-3);
1764 1794 }
1765 1795
1766 1796 rc = get_val_astring(handles, "ad_unixgroup_attr",
1767 1797 &pgcfg->ad_unixgroup_attr);
1768 1798 if (rc != 0)
1769 1799 return (-2);
1770 1800 if (pgcfg->ad_unixgroup_attr != NULL &&
1771 1801 !valid_ldap_attr(pgcfg->ad_unixgroup_attr)) {
1772 1802 idmapdlog(LOG_ERR, "config/ad_unixgroup_attr=%s is not a "
1773 1803 "valid LDAP attribute name", pgcfg->ad_unixgroup_attr);
1774 1804 return (-3);
1775 1805 }
1776 1806
1777 1807 rc = get_val_astring(handles, "nldap_winname_attr",
1778 1808 &pgcfg->nldap_winname_attr);
1779 1809 if (rc != 0)
1780 1810 return (-2);
1781 1811 if (pgcfg->nldap_winname_attr != NULL &&
1782 1812 !valid_ldap_attr(pgcfg->nldap_winname_attr)) {
1783 1813 idmapdlog(LOG_ERR, "config/nldap_winname_attr=%s is not a "
1784 1814 "valid LDAP attribute name", pgcfg->nldap_winname_attr);
1785 1815 return (-3);
1786 1816 }
1787 1817 if (pgcfg->ad_unixuser_attr == NULL &&
1788 1818 pgcfg->ad_unixgroup_attr == NULL &&
1789 1819 pgcfg->nldap_winname_attr == NULL) {
1790 1820 idmapdlog(LOG_ERR,
1791 1821 "If config/directory_based_mapping property is set to "
1792 1822 "\"name\" then at least one of the following name mapping "
1793 1823 "attributes must be specified. (config/ad_unixuser_attr OR "
1794 1824 "config/ad_unixgroup_attr OR config/nldap_winname_attr)");
1795 1825 return (-3);
1796 1826 }
1797 1827
1798 1828 return (rc);
1799 1829 }
1800 1830
1801 1831 static
1802 1832 void
1803 1833 log_if_unable(const void *val, const char *what)
1804 1834 {
1805 1835 if (val == NULL) {
1806 1836 idmapdlog(LOG_DEBUG, "unable to discover %s", what);
1807 1837 }
1808 1838 }
1809 1839
1810 1840 static
1811 1841 void
1812 1842 discover_trusted_domains(idmap_pg_config_t *pgcfg, ad_disc_t ad_ctx)
1813 1843 {
1814 1844 ad_disc_t trusted_ctx;
1815 1845 int i, j, k, l;
1816 1846 char *forestname;
1817 1847 int num_trusteddomains;
1818 1848 boolean_t new_forest;
1819 1849 char *trusteddomain;
1820 1850 ad_disc_ds_t *globalcatalog;
1821 1851 idmap_trustedforest_t *trustedforests;
1822 1852 ad_disc_domainsinforest_t *domainsinforest;
1823 1853
1824 1854 pgcfg->trusted_domains =
1825 1855 ad_disc_get_TrustedDomains(ad_ctx, NULL);
1826 1856
1827 1857 if (pgcfg->forest_name != NULL && pgcfg->trusted_domains != NULL &&
1828 1858 pgcfg->trusted_domains[0].domain[0] != '\0') {
1829 1859 /*
1830 1860 * We have trusted domains. We need to go through every
1831 1861 * one and find its forest. If it is a new forest we then need
1832 1862 * to find its Global Catalog and the domains in the forest
1833 1863 */
1834 1864 for (i = 0; pgcfg->trusted_domains[i].domain[0] != '\0'; i++)
1835 1865 continue;
1836 1866 num_trusteddomains = i;
1837 1867
1838 1868 trustedforests = calloc(num_trusteddomains,
1839 1869 sizeof (idmap_trustedforest_t));
1840 1870 j = 0;
1841 1871 for (i = 0; pgcfg->trusted_domains[i].domain[0] != '\0'; i++) {
1842 1872 trusteddomain = pgcfg->trusted_domains[i].domain;
1843 1873 trusted_ctx = ad_disc_init();
1844 1874 (void) ad_disc_set_DomainName(trusted_ctx,
1845 1875 trusteddomain);
1846 1876 forestname =
1847 1877 ad_disc_get_ForestName(trusted_ctx, NULL);
1848 1878 if (forestname == NULL) {
1849 1879 if (DBG(CONFIG, 1)) {
1850 1880 idmapdlog(LOG_DEBUG,
1851 1881 "unable to discover Forest Name"
1852 1882 " for the trusted domain %s",
1853 1883 trusteddomain);
1854 1884 }
1855 1885 ad_disc_fini(trusted_ctx);
1856 1886 continue;
1857 1887 }
1858 1888
1859 1889 if (strcasecmp(forestname, pgcfg->forest_name) == 0) {
1860 1890 /*
1861 1891 * Ignore the domain as it is part of
1862 1892 * the primary forest
1863 1893 */
1864 1894 free(forestname);
1865 1895 ad_disc_fini(trusted_ctx);
1866 1896 continue;
1867 1897 }
1868 1898
1869 1899 /* Is this a new forest? */
1870 1900 new_forest = B_TRUE;
1871 1901 for (k = 0; k < j; k++) {
1872 1902 if (strcasecmp(forestname,
1873 1903 trustedforests[k].forest_name) == 0) {
1874 1904 new_forest = B_FALSE;
1875 1905 domainsinforest =
1876 1906 trustedforests[k].domains_in_forest;
1877 1907 break;
1878 1908 }
1879 1909 }
1880 1910 if (!new_forest) {
1881 1911 /* Mark the domain as trusted */
1882 1912 for (l = 0;
1883 1913 domainsinforest[l].domain[0] != '\0'; l++) {
1884 1914 if (domain_eq(trusteddomain,
1885 1915 domainsinforest[l].domain)) {
1886 1916 domainsinforest[l].trusted =
1887 1917 TRUE;
1888 1918 break;
1889 1919 }
1890 1920 }
1891 1921 free(forestname);
1892 1922 ad_disc_fini(trusted_ctx);
1893 1923 continue;
1894 1924 }
1895 1925
1896 1926 /*
1897 1927 * Get the Global Catalog and the domains in
1898 1928 * this new forest.
1899 1929 */
1900 1930 globalcatalog =
1901 1931 ad_disc_get_GlobalCatalog(trusted_ctx,
1902 1932 AD_DISC_PREFER_SITE, NULL);
1903 1933 if (globalcatalog == NULL) {
1904 1934 if (DBG(CONFIG, 1)) {
1905 1935 idmapdlog(LOG_DEBUG,
1906 1936 "unable to discover Global Catalog"
1907 1937 " for the trusted domain %s",
1908 1938 trusteddomain);
1909 1939 }
1910 1940 free(forestname);
1911 1941 ad_disc_fini(trusted_ctx);
1912 1942 continue;
1913 1943 }
1914 1944 domainsinforest =
1915 1945 ad_disc_get_DomainsInForest(trusted_ctx, NULL);
1916 1946 if (domainsinforest == NULL) {
1917 1947 if (DBG(CONFIG, 1)) {
1918 1948 idmapdlog(LOG_DEBUG,
1919 1949 "unable to discover Domains in the"
1920 1950 " Forest for the trusted domain %s",
1921 1951 trusteddomain);
1922 1952 }
1923 1953 free(globalcatalog);
1924 1954 free(forestname);
1925 1955 ad_disc_fini(trusted_ctx);
1926 1956 continue;
1927 1957 }
1928 1958
1929 1959 trustedforests[j].forest_name = forestname;
1930 1960 trustedforests[j].global_catalog = globalcatalog;
1931 1961 trustedforests[j].domains_in_forest = domainsinforest;
1932 1962 j++;
1933 1963 /* Mark the domain as trusted */
1934 1964 for (l = 0; domainsinforest[l].domain[0] != '\0';
1935 1965 l++) {
1936 1966 if (domain_eq(trusteddomain,
1937 1967 domainsinforest[l].domain)) {
1938 1968 domainsinforest[l].trusted = TRUE;
1939 1969 break;
1940 1970 }
1941 1971 }
1942 1972 ad_disc_fini(trusted_ctx);
1943 1973 }
1944 1974 if (j > 0) {
1945 1975 pgcfg->num_trusted_forests = j;
1946 1976 pgcfg->trusted_forests = trustedforests;
1947 1977 } else {
1948 1978 free(trustedforests);
1949 1979 }
1950 1980 }
1951 1981 }
1952 1982
1953 1983 /*
1954 1984 * This is the half of idmap_cfg_load() that auto-discovers values of
1955 1985 * discoverable properties that weren't already set via SMF properties.
1956 1986 *
1957 1987 * idmap_cfg_discover() is called *after* idmap_cfg_load_smf(), so it
1958 1988 * needs to be careful not to overwrite any properties set in SMF.
1959 1989 */
1960 1990 static void
1961 1991 idmap_cfg_discover1(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg)
1962 1992 {
1963 1993 ad_disc_t ad_ctx = handles->ad_ctx;
1964 1994 FILE *status_fp = NULL;
1965 1995 time_t t0, t1;
1966 1996
1967 1997 t0 = time(NULL);
1968 1998 if (DBG(CONFIG, 1))
1969 1999 idmapdlog(LOG_DEBUG, "Running domain discovery.");
1970 2000
1971 2001 (void) unlink(IDMAP_CACHEDIR "/discovery.log");
1972 2002 status_fp = fopen(IDMAP_CACHEDIR "/discovery.log", "w");
1973 2003 if (status_fp) {
1974 2004 (void) fchmod(fileno(status_fp), 0644);
1975 2005 ad_disc_set_StatusFP(ad_ctx, status_fp);
1976 2006 }
1977 2007
1978 2008 if (pgcfg->domain_name == NULL) {
1979 2009 idmapdlog(LOG_DEBUG, "No domain name specified.");
1980 2010 if (status_fp)
1981 2011 (void) fprintf(status_fp, "(no domain name)\n");
1982 2012 goto out;
1983 2013 }
1984 2014
1985 2015 if (pgcfg->domain_controller == NULL)
1986 2016 pgcfg->domain_controller =
1987 2017 ad_disc_get_DomainController(ad_ctx,
1988 2018 AD_DISC_PREFER_SITE,
1989 2019 &pgcfg->domain_controller_auto_disc);
1990 2020
1991 2021 if (pgcfg->domain_guid == NULL) {
1992 2022 char buf[UUID_PRINTABLE_STRING_LENGTH];
1993 2023 uchar_t *u = ad_disc_get_DomainGUID(ad_ctx,
1994 2024 &pgcfg->domain_guid_auto_disc);
1995 2025 (void) memset(buf, 0, sizeof (buf));
1996 2026 if (u != NULL) {
1997 2027 uuid_unparse(u, buf);
1998 2028 pgcfg->domain_guid = strdup(buf);
1999 2029 }
2000 2030 }
2001 2031
2002 2032 if (pgcfg->forest_name == NULL)
2003 2033 pgcfg->forest_name = ad_disc_get_ForestName(ad_ctx,
2004 2034 &pgcfg->forest_name_auto_disc);
2005 2035
2006 2036 if (pgcfg->site_name == NULL)
2007 2037 pgcfg->site_name = ad_disc_get_SiteName(ad_ctx,
2008 2038 &pgcfg->site_name_auto_disc);
2009 2039
2010 2040 if (DBG(CONFIG, 1)) {
2011 2041 log_if_unable(pgcfg->domain_name, "Domain Name");
2012 2042 log_if_unable(pgcfg->domain_controller,
2013 2043 "Domain Controller");
2014 2044 log_if_unable(pgcfg->domain_guid, "Domain GUID");
2015 2045 log_if_unable(pgcfg->forest_name, "Forest Name");
2016 2046 log_if_unable(pgcfg->site_name, "Site Name");
2017 2047 }
2018 2048
2019 2049 out:
2020 2050 if (status_fp) {
2021 2051 ad_disc_set_StatusFP(ad_ctx, NULL);
2022 2052 (void) fclose(status_fp);
2023 2053 status_fp = NULL;
2024 2054 }
2025 2055
2026 2056 if (DBG(CONFIG, 1))
2027 2057 idmapdlog(LOG_DEBUG, "Domain discovery done.");
2028 2058
2029 2059 /*
2030 2060 * Log when this took more than 15 sec.
2031 2061 */
2032 2062 t1 = time(NULL);
2033 2063 if (t1 > (t0 + 15)) {
2034 2064 idmapdlog(LOG_NOTICE, "Domain discovery took %d sec.",
2035 2065 (int)(t1 - t0));
2036 2066 idmapdlog(LOG_NOTICE, "Check the DNS configuration.");
2037 2067 }
2038 2068 }
2039 2069
2040 2070 /*
2041 2071 * This is the second part of discovery, which can take a while.
2042 2072 * We don't want to hold up parties who just want to know what
2043 2073 * domain controller we're using (like smbd), so this part runs
2044 2074 * after we've updated that info in the "live" config and told
2045 2075 * such consumers to go ahead.
2046 2076 *
2047 2077 * This is a lot like idmap_cfg_discover(), but used LDAP queries
2048 2078 * get the forest information from the global catalog servers.
2049 2079 *
2050 2080 * Note: the previous update_* calls have usually nuked any
2051 2081 * useful information from pgcfg before we get here, so we
2052 2082 * can only use it store discovery results, not to read.
2053 2083 */
2054 2084 static void
2055 2085 idmap_cfg_discover2(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg)
2056 2086 {
2057 2087 ad_disc_t ad_ctx = handles->ad_ctx;
2058 2088 FILE *status_fp = NULL;
2059 2089 time_t t0, t1;
2060 2090
2061 2091 t0 = time(NULL);
2062 2092 if (DBG(CONFIG, 1))
2063 2093 idmapdlog(LOG_DEBUG, "Running forest discovery.");
2064 2094
2065 2095 status_fp = fopen(IDMAP_CACHEDIR "/discovery.log", "a");
2066 2096 if (status_fp)
2067 2097 ad_disc_set_StatusFP(ad_ctx, status_fp);
2068 2098
2069 2099 if (pgcfg->global_catalog == NULL)
2070 2100 pgcfg->global_catalog =
2071 2101 ad_disc_get_GlobalCatalog(ad_ctx,
2072 2102 AD_DISC_PREFER_SITE,
2073 2103 &pgcfg->global_catalog_auto_disc);
2074 2104
2075 2105 if (pgcfg->global_catalog != NULL) {
2076 2106 pgcfg->domains_in_forest =
2077 2107 ad_disc_get_DomainsInForest(ad_ctx, NULL);
2078 2108
2079 2109 if (!pgcfg->disable_cross_forest_trusts)
2080 2110 discover_trusted_domains(pgcfg, ad_ctx);
2081 2111 }
2082 2112
2083 2113 if (DBG(CONFIG, 1)) {
2084 2114 log_if_unable(pgcfg->global_catalog, "Global Catalog");
2085 2115 log_if_unable(pgcfg->domains_in_forest,
2086 2116 "Domains in the Forest");
2087 2117 /* Empty trusted domains list is OK. */
2088 2118 }
2089 2119
2090 2120 if (status_fp) {
2091 2121 ad_disc_set_StatusFP(ad_ctx, NULL);
2092 2122 (void) fclose(status_fp);
2093 2123 status_fp = NULL;
2094 2124 }
2095 2125
2096 2126 if (DBG(CONFIG, 1))
2097 2127 idmapdlog(LOG_DEBUG, "Forest discovery done.");
2098 2128
2099 2129 /*
2100 2130 * Log when this took more than 30 sec.
2101 2131 */
2102 2132 t1 = time(NULL);
2103 2133 if (t1 > (t0 + 30)) {
2104 2134 idmapdlog(LOG_NOTICE, "Forest discovery took %d sec.",
2105 2135 (int)(t1 - t0));
2106 2136 idmapdlog(LOG_NOTICE, "Check AD join status.");
2107 2137 }
2108 2138 }
2109 2139
2110 2140
2111 2141 /*
2112 2142 * idmap_cfg_load() is called at startup, and periodically via the
2113 2143 * update thread when the auto-discovery TTLs expire, as well as part of
2114 2144 * the refresh method, to update the current configuration. It always
2115 2145 * reads from SMF, but you still have to refresh the service after
2116 2146 * changing the config pg in order for the changes to take effect.
2117 2147 *
2118 2148 * There is one flag:
2119 2149 *
2120 2150 * - CFG_DISCOVER
2121 2151 *
2122 2152 * If CFG_DISCOVER is set then idmap_cfg_load() calls
2123 2153 * idmap_cfg_discover() to discover, via DNS and LDAP lookups, property
2124 2154 * values that weren't set in SMF.
2125 2155 *
2126 2156 * idmap_cfg_load() will log (to LOG_NOTICE) whether the configuration
2127 2157 * changed.
2128 2158 *
2129 2159 * Return values: 0 -> success, -1 -> failure, -2 -> hard failures
2130 2160 * reading from SMF.
2131 2161 */
2132 2162 int
2133 2163 idmap_cfg_load(idmap_cfg_t *cfg, int flags)
2134 2164 {
2135 2165 const ad_disc_t ad_ctx = cfg->handles.ad_ctx;
2136 2166 int rc = 0;
2137 2167 int errors;
2138 2168 int changed = 0;
2139 2169 int dc_changed = 0;
2140 2170 int ad_reload_required = 0;
2141 2171 idmap_pg_config_t new_pgcfg, *live_pgcfg;
2142 2172
2143 2173 if (DBG(CONFIG, 1))
2144 2174 idmapdlog(LOG_DEBUG, "Loading configuration.");
2145 2175
2146 2176 live_pgcfg = &cfg->pgcfg;
2147 2177 (void) memset(&new_pgcfg, 0, sizeof (new_pgcfg));
2148 2178
2149 2179 (void) pthread_mutex_lock(&cfg->handles.mutex);
2150 2180
2151 2181 if ((rc = idmap_cfg_load_smf(&cfg->handles, &new_pgcfg, &errors)) < -1)
2152 2182 goto err;
2153 2183
2154 2184 if (flags & CFG_DISCOVER) {
2155 2185
2156 2186 ad_disc_refresh(ad_ctx);
2157 2187
2158 2188 /*
2159 2189 * Unless we've been asked to forget the current DC,
2160 2190 * give preference (in order) to the preferred DC if
2161 2191 * configured, or the current DC. These preferences
2162 2192 * reduce undesirable DC changes.
2163 2193 */
2164 2194 if (flags & CFG_FORGET_DC) {
2165 2195 (void) ad_disc_set_PreferredDC(ad_ctx, NULL);
2166 2196 } else if (new_pgcfg.preferred_dc != NULL) {
2167 2197 (void) ad_disc_set_PreferredDC(ad_ctx,
2168 2198 new_pgcfg.preferred_dc);
2169 2199 } else if (live_pgcfg->domain_controller != NULL) {
2170 2200 (void) ad_disc_set_PreferredDC(ad_ctx,
2171 2201 live_pgcfg->domain_controller);
2172 2202 } else {
2173 2203 (void) ad_disc_set_PreferredDC(ad_ctx, NULL);
2174 2204 }
2175 2205
2176 2206 /*
2177 2207 * We want a way to tell adspriv_getdcname_1_svc()
2178 2208 * (and others) that discovery is running and therefore
2179 2209 * they may want to wait a bit or return an error...
2180 2210 */
2181 2211 (void) mutex_lock(&_idmapdstate.addisc_lk);
2182 2212 _idmapdstate.addisc_st |= ADDISC_ST_RUNNING;
2183 2213 (void) mutex_unlock(&_idmapdstate.addisc_lk);
2184 2214
2185 2215 idmap_cfg_discover1(&cfg->handles, &new_pgcfg);
2186 2216
2187 2217 WRLOCK_CONFIG();
2188 2218 (void) mutex_lock(&_idmapdstate.addisc_lk);
2189 2219 _idmapdstate.addisc_st = 0;
2190 2220 (void) cond_broadcast(&_idmapdstate.addisc_cv);
|
↓ open down ↓ |
441 lines elided |
↑ open up ↑ |
2191 2221 (void) mutex_unlock(&_idmapdstate.addisc_lk);
2192 2222 } else {
2193 2223 WRLOCK_CONFIG();
2194 2224 }
2195 2225
2196 2226 /* Non-discoverable props updated here */
2197 2227
2198 2228 changed += update_uint64(&live_pgcfg->list_size_limit,
2199 2229 &new_pgcfg.list_size_limit, "list_size_limit");
2200 2230
2231 + changed += update_uint64(&live_pgcfg->max_threads,
2232 + &new_pgcfg.max_threads, "max_threads");
2233 +
2201 2234 changed += update_uint64(&live_pgcfg->id_cache_timeout,
2202 2235 &new_pgcfg.id_cache_timeout, "id_cache_timeout");
2203 2236
2204 2237 changed += update_uint64(&live_pgcfg->name_cache_timeout,
2205 2238 &new_pgcfg.name_cache_timeout, "name_cache_timeout");
2206 2239
2207 2240 changed += update_uint64(&live_pgcfg->rediscovery_interval,
2208 2241 &new_pgcfg.rediscovery_interval, "rediscovery_interval");
2209 2242
2210 2243 changed += update_string(&live_pgcfg->machine_sid,
2211 2244 &new_pgcfg.machine_sid, "machine_sid");
2212 2245
2213 2246 changed += update_bool(&live_pgcfg->eph_map_unres_sids,
2214 2247 &new_pgcfg.eph_map_unres_sids, "unresolvable_sid_mapping");
2215 2248
2216 2249 changed += update_bool(&live_pgcfg->use_ads,
2217 2250 &new_pgcfg.use_ads, "use_ads");
2218 2251
2219 2252 changed += update_bool(&live_pgcfg->use_lsa,
2220 2253 &new_pgcfg.use_lsa, "use_lsa");
2221 2254
2222 2255 changed += update_bool(&live_pgcfg->disable_cross_forest_trusts,
2223 2256 &new_pgcfg.disable_cross_forest_trusts,
2224 2257 "disable_cross_forest_trusts");
2225 2258
2226 2259 changed += update_enum(&live_pgcfg->directory_based_mapping,
2227 2260 &new_pgcfg.directory_based_mapping, "directory_based_mapping",
2228 2261 directory_mapping_map);
2229 2262
2230 2263 changed += update_string(&live_pgcfg->ad_unixuser_attr,
2231 2264 &new_pgcfg.ad_unixuser_attr, "ad_unixuser_attr");
2232 2265
2233 2266 changed += update_string(&live_pgcfg->ad_unixgroup_attr,
2234 2267 &new_pgcfg.ad_unixgroup_attr, "ad_unixgroup_attr");
2235 2268
2236 2269 changed += update_string(&live_pgcfg->nldap_winname_attr,
2237 2270 &new_pgcfg.nldap_winname_attr, "nldap_winname_attr");
2238 2271
2239 2272 changed += update_string(&live_pgcfg->default_domain,
2240 2273 &new_pgcfg.default_domain, "default_domain");
2241 2274
2242 2275 changed += update_dirs(&live_pgcfg->preferred_dc,
2243 2276 &new_pgcfg.preferred_dc, "preferred_dc");
2244 2277
2245 2278 /* Props that can be discovered or set in SMF updated here */
2246 2279
2247 2280 if (update_string(&live_pgcfg->domain_name,
2248 2281 &new_pgcfg.domain_name, "domain_name")) {
2249 2282 changed++;
2250 2283 ad_reload_required = TRUE;
2251 2284 idmapd_set_krb5_realm(live_pgcfg->domain_name);
2252 2285 }
2253 2286 live_pgcfg->domain_name_auto_disc = new_pgcfg.domain_name_auto_disc;
2254 2287
2255 2288 changed += update_string(&live_pgcfg->domain_guid,
2256 2289 &new_pgcfg.domain_guid, "domain_guid");
2257 2290 live_pgcfg->domain_guid_auto_disc = new_pgcfg.domain_guid_auto_disc;
2258 2291
2259 2292 dc_changed = update_dirs(&live_pgcfg->domain_controller,
2260 2293 &new_pgcfg.domain_controller, "domain_controller");
2261 2294 changed += dc_changed;
2262 2295 live_pgcfg->domain_controller_auto_disc =
2263 2296 new_pgcfg.domain_controller_auto_disc;
2264 2297
2265 2298 changed += update_string(&live_pgcfg->forest_name,
2266 2299 &new_pgcfg.forest_name, "forest_name");
2267 2300 live_pgcfg->forest_name_auto_disc = new_pgcfg.forest_name_auto_disc;
2268 2301
2269 2302 changed += update_string(&live_pgcfg->site_name,
2270 2303 &new_pgcfg.site_name, "site_name");
2271 2304 live_pgcfg->site_name_auto_disc = new_pgcfg.site_name_auto_disc;
2272 2305
2273 2306 if (DBG(CONFIG, 1)) {
2274 2307 if (changed)
2275 2308 idmapdlog(LOG_NOTICE, "Configuration changed");
2276 2309 else
2277 2310 idmapdlog(LOG_NOTICE, "Configuration unchanged");
2278 2311 }
2279 2312
2280 2313 UNLOCK_CONFIG();
2281 2314
2282 2315 if (dc_changed != 0) {
2283 2316 notify_dc_changed();
2284 2317 }
2285 2318
2286 2319 /*
2287 2320 * Discovery2 can take a while.
2288 2321 */
2289 2322 if (flags & CFG_DISCOVER) {
2290 2323 if (live_pgcfg->domain_name != NULL &&
2291 2324 live_pgcfg->forest_name != NULL)
2292 2325 idmap_cfg_discover2(&cfg->handles, &new_pgcfg);
2293 2326 ad_disc_done(ad_ctx);
2294 2327 }
2295 2328
2296 2329 WRLOCK_CONFIG();
2297 2330
2298 2331 /* More props that can be discovered or set in SMF */
2299 2332
2300 2333 changed += update_dirs(&live_pgcfg->global_catalog,
2301 2334 &new_pgcfg.global_catalog, "global_catalog");
2302 2335 live_pgcfg->global_catalog_auto_disc =
2303 2336 new_pgcfg.global_catalog_auto_disc;
2304 2337
2305 2338 /* Props that are only discovered (never in SMF) */
2306 2339
2307 2340 if (update_domains_in_forest(&live_pgcfg->domains_in_forest,
2308 2341 &new_pgcfg.domains_in_forest, "domains_in_forest")) {
2309 2342 changed++;
2310 2343 ad_reload_required = TRUE;
2311 2344 }
2312 2345
2313 2346 if (update_trusted_domains(&live_pgcfg->trusted_domains,
2314 2347 &new_pgcfg.trusted_domains, "trusted_domains")) {
2315 2348 changed++;
2316 2349 if (live_pgcfg->trusted_domains != NULL &&
2317 2350 live_pgcfg->trusted_domains[0].domain[0] != '\0')
2318 2351 ad_reload_required = TRUE;
2319 2352 }
2320 2353
2321 2354 if (update_trusted_forest(&live_pgcfg->trusted_forests,
2322 2355 &live_pgcfg->num_trusted_forests, &new_pgcfg.trusted_forests,
2323 2356 &new_pgcfg.num_trusted_forests, "trusted_forest")) {
2324 2357 changed++;
2325 2358 if (live_pgcfg->trusted_forests != NULL)
2326 2359 ad_reload_required = TRUE;
2327 2360 }
2328 2361
2329 2362 if (DBG(CONFIG, 1)) {
2330 2363 if (changed)
2331 2364 idmapdlog(LOG_NOTICE, "Configuration changed");
2332 2365 else
2333 2366 idmapdlog(LOG_NOTICE, "Configuration unchanged");
2334 2367 }
2335 2368
2336 2369 UNLOCK_CONFIG();
2337 2370
2338 2371 if (ad_reload_required)
2339 2372 reload_ad();
2340 2373
2341 2374 idmap_cfg_unload(&new_pgcfg);
2342 2375
2343 2376 err:
2344 2377 (void) pthread_mutex_unlock(&cfg->handles.mutex);
2345 2378
2346 2379 if (rc < -1)
2347 2380 return (rc);
2348 2381
2349 2382 return ((errors == 0) ? 0 : -1);
2350 2383 }
2351 2384
2352 2385 /*
2353 2386 * Initialize 'cfg'.
2354 2387 */
2355 2388 idmap_cfg_t *
2356 2389 idmap_cfg_init()
2357 2390 {
2358 2391 idmap_cfg_handles_t *handles;
2359 2392
2360 2393 /* First the smf repository handles: */
2361 2394 idmap_cfg_t *cfg = calloc(1, sizeof (idmap_cfg_t));
2362 2395 if (!cfg) {
2363 2396 idmapdlog(LOG_ERR, "Out of memory");
2364 2397 return (NULL);
2365 2398 }
2366 2399 handles = &cfg->handles;
2367 2400
2368 2401 (void) pthread_mutex_init(&handles->mutex, NULL);
2369 2402
2370 2403 if (!(handles->main = scf_handle_create(SCF_VERSION))) {
2371 2404 idmapdlog(LOG_ERR, "scf_handle_create() failed: %s",
2372 2405 scf_strerror(scf_error()));
2373 2406 goto error;
2374 2407 }
2375 2408
2376 2409 if (scf_handle_bind(handles->main) < 0) {
2377 2410 idmapdlog(LOG_ERR, "scf_handle_bind() failed: %s",
2378 2411 scf_strerror(scf_error()));
2379 2412 goto error;
2380 2413 }
2381 2414
2382 2415 if (!(handles->service = scf_service_create(handles->main)) ||
2383 2416 !(handles->instance = scf_instance_create(handles->main)) ||
2384 2417 !(handles->config_pg = scf_pg_create(handles->main)) ||
2385 2418 !(handles->debug_pg = scf_pg_create(handles->main))) {
2386 2419 idmapdlog(LOG_ERR, "scf handle creation failed: %s",
2387 2420 scf_strerror(scf_error()));
2388 2421 goto error;
2389 2422 }
2390 2423
2391 2424 if (scf_handle_decode_fmri(handles->main,
2392 2425 FMRI_BASE "/:properties/" CONFIG_PG,
2393 2426 NULL, /* scope */
2394 2427 handles->service, /* service */
2395 2428 handles->instance, /* instance */
2396 2429 handles->config_pg, /* pg */
2397 2430 NULL, /* prop */
2398 2431 SCF_DECODE_FMRI_EXACT) < 0) {
2399 2432 idmapdlog(LOG_ERR, "scf_handle_decode_fmri() failed: %s",
2400 2433 scf_strerror(scf_error()));
2401 2434 goto error;
2402 2435 }
2403 2436
2404 2437 if (scf_service_get_pg(handles->service,
2405 2438 DEBUG_PG, handles->debug_pg) < 0) {
2406 2439 idmapdlog(LOG_ERR, "Property group \"%s\": %s",
2407 2440 DEBUG_PG, scf_strerror(scf_error()));
2408 2441 goto error;
2409 2442 }
2410 2443
2411 2444 check_smf_debug_mode(handles);
2412 2445
2413 2446 /* Initialize AD Auto Discovery context */
2414 2447 handles->ad_ctx = ad_disc_init();
2415 2448 if (handles->ad_ctx == NULL)
2416 2449 goto error;
2417 2450
2418 2451 return (cfg);
2419 2452
2420 2453 error:
2421 2454 (void) idmap_cfg_fini(cfg);
2422 2455 return (NULL);
2423 2456 }
2424 2457
2425 2458 void
2426 2459 idmap_cfg_unload(idmap_pg_config_t *pgcfg)
2427 2460 {
2428 2461
2429 2462 if (pgcfg->default_domain) {
2430 2463 free(pgcfg->default_domain);
2431 2464 pgcfg->default_domain = NULL;
2432 2465 }
2433 2466 if (pgcfg->domain_name) {
2434 2467 free(pgcfg->domain_name);
2435 2468 pgcfg->domain_name = NULL;
2436 2469 }
2437 2470 if (pgcfg->domain_guid) {
2438 2471 free(pgcfg->domain_guid);
2439 2472 pgcfg->domain_guid = NULL;
2440 2473 }
2441 2474 if (pgcfg->machine_sid) {
2442 2475 free(pgcfg->machine_sid);
2443 2476 pgcfg->machine_sid = NULL;
2444 2477 }
2445 2478 if (pgcfg->domain_controller) {
2446 2479 free(pgcfg->domain_controller);
2447 2480 pgcfg->domain_controller = NULL;
2448 2481 }
2449 2482 if (pgcfg->forest_name) {
2450 2483 free(pgcfg->forest_name);
2451 2484 pgcfg->forest_name = NULL;
2452 2485 }
2453 2486 if (pgcfg->site_name) {
2454 2487 free(pgcfg->site_name);
2455 2488 pgcfg->site_name = NULL;
2456 2489 }
2457 2490 if (pgcfg->global_catalog) {
2458 2491 free(pgcfg->global_catalog);
2459 2492 pgcfg->global_catalog = NULL;
2460 2493 }
2461 2494 if (pgcfg->trusted_domains) {
2462 2495 free(pgcfg->trusted_domains);
2463 2496 pgcfg->trusted_domains = NULL;
2464 2497 }
2465 2498 if (pgcfg->trusted_forests)
2466 2499 free_trusted_forests(&pgcfg->trusted_forests,
2467 2500 &pgcfg->num_trusted_forests);
2468 2501
2469 2502 if (pgcfg->ad_unixuser_attr) {
2470 2503 free(pgcfg->ad_unixuser_attr);
2471 2504 pgcfg->ad_unixuser_attr = NULL;
2472 2505 }
2473 2506 if (pgcfg->ad_unixgroup_attr) {
2474 2507 free(pgcfg->ad_unixgroup_attr);
2475 2508 pgcfg->ad_unixgroup_attr = NULL;
2476 2509 }
2477 2510 if (pgcfg->nldap_winname_attr) {
2478 2511 free(pgcfg->nldap_winname_attr);
2479 2512 pgcfg->nldap_winname_attr = NULL;
2480 2513 }
2481 2514 }
2482 2515
2483 2516 int
2484 2517 idmap_cfg_fini(idmap_cfg_t *cfg)
2485 2518 {
2486 2519 idmap_cfg_handles_t *handles = &cfg->handles;
2487 2520 idmap_cfg_unload(&cfg->pgcfg);
2488 2521
2489 2522 (void) pthread_mutex_destroy(&handles->mutex);
2490 2523 scf_pg_destroy(handles->config_pg);
2491 2524 if (handles->debug_pg != NULL)
2492 2525 scf_pg_destroy(handles->debug_pg);
2493 2526 scf_instance_destroy(handles->instance);
2494 2527 scf_service_destroy(handles->service);
2495 2528 scf_handle_destroy(handles->main);
2496 2529 if (handles->ad_ctx != NULL)
2497 2530 ad_disc_fini(handles->ad_ctx);
2498 2531 free(cfg);
2499 2532
2500 2533 return (0);
2501 2534 }
2502 2535
2503 2536 void
2504 2537 idmap_cfg_poke_updates(void)
2505 2538 {
2506 2539 int prev_st;
2507 2540
2508 2541 if (DBG(CONFIG, 1)) {
2509 2542 idmapdlog(LOG_INFO, "idmap_cfg_poke_updates");
2510 2543 }
2511 2544
2512 2545 (void) mutex_lock(&_idmapdstate.addisc_lk);
2513 2546 prev_st = _idmapdstate.addisc_st;
2514 2547 _idmapdstate.addisc_st |= ADDISC_ST_REQUESTED;
2515 2548 (void) mutex_unlock(&_idmapdstate.addisc_lk);
2516 2549
2517 2550 if (prev_st & ADDISC_ST_REQUESTED) {
2518 2551 idmapdlog(LOG_DEBUG, "already poked");
2519 2552 } else {
2520 2553 idmapdlog(LOG_DEBUG, "port send poke");
2521 2554 (void) port_send(idmapd_ev_port, POKE_AUTO_DISCOVERY, NULL);
2522 2555 }
2523 2556 }
2524 2557
2525 2558 void
2526 2559 idmap_cfg_force_rediscovery(void)
2527 2560 {
2528 2561 int prev_st;
2529 2562
2530 2563 if (DBG(CONFIG, 1)) {
2531 2564 idmapdlog(LOG_INFO, "idmap_cfg_force_rediscovery");
2532 2565 }
2533 2566
2534 2567 (void) mutex_lock(&_idmapdstate.addisc_lk);
2535 2568 prev_st = _idmapdstate.addisc_st;
2536 2569 _idmapdstate.addisc_st |= ADDISC_ST_REQUESTED;
2537 2570 (void) mutex_unlock(&_idmapdstate.addisc_lk);
2538 2571
2539 2572 if (prev_st & ADDISC_ST_REQUESTED) {
2540 2573 idmapdlog(LOG_DEBUG, "already kicked");
2541 2574 } else {
2542 2575 idmapdlog(LOG_DEBUG, "port send kick");
2543 2576 (void) port_send(idmapd_ev_port, KICK_AUTO_DISCOVERY, NULL);
2544 2577 }
2545 2578 }
2546 2579
2547 2580 /*ARGSUSED*/
2548 2581 void
2549 2582 idmap_cfg_hup_handler(int sig)
2550 2583 {
2551 2584 if (idmapd_ev_port >= 0)
2552 2585 (void) port_send(idmapd_ev_port, RECONFIGURE, NULL);
2553 2586 }
2554 2587
2555 2588 /*
2556 2589 * Upgrade the debug flags.
2557 2590 *
2558 2591 * We're replacing a single debug flag with a fine-grained mechanism that
2559 2592 * is also capable of considerably more verbosity. We'll take a stab at
2560 2593 * producing roughly the same level of output.
2561 2594 */
2562 2595 static
2563 2596 int
2564 2597 upgrade_debug(idmap_cfg_handles_t *handles)
2565 2598 {
2566 2599 boolean_t debug_present;
2567 2600 const char DEBUG_PROP[] = "debug";
2568 2601 int rc;
2569 2602
2570 2603 rc = prop_exists(handles, DEBUG_PROP, &debug_present);
2571 2604
2572 2605 if (rc != 0)
2573 2606 return (rc);
2574 2607
2575 2608 if (!debug_present)
2576 2609 return (0);
2577 2610
2578 2611 idmapdlog(LOG_INFO,
2579 2612 "Upgrading old %s/%s setting to %s/* settings.",
2580 2613 CONFIG_PG, DEBUG_PROP, DEBUG_PG);
2581 2614
2582 2615 rc = set_val_integer(handles, handles->debug_pg, "config", 1);
2583 2616 if (rc != 0)
2584 2617 return (rc);
2585 2618 rc = set_val_integer(handles, handles->debug_pg, "discovery", 1);
2586 2619 if (rc != 0)
2587 2620 return (rc);
2588 2621
2589 2622 rc = del_val(handles, handles->config_pg, DEBUG_PROP);
2590 2623 if (rc != 0)
2591 2624 return (rc);
2592 2625
2593 2626 return (0);
2594 2627 }
2595 2628
2596 2629 /*
2597 2630 * Upgrade the DS mapping flags.
2598 2631 *
2599 2632 * If the old ds_name_mapping_enabled flag is present, then
2600 2633 * if the new directory_based_mapping value is present, then
2601 2634 * if the two are compatible, delete the old and note it
2602 2635 * else delete the old and warn
2603 2636 * else
2604 2637 * set the new based on the old, and note it
2605 2638 * delete the old
2606 2639 */
2607 2640 static
2608 2641 int
2609 2642 upgrade_directory_mapping(idmap_cfg_handles_t *handles)
2610 2643 {
2611 2644 boolean_t legacy_ds_name_mapping_present;
2612 2645 const char DS_NAME_MAPPING_ENABLED[] = "ds_name_mapping_enabled";
2613 2646 const char DIRECTORY_BASED_MAPPING[] = "directory_based_mapping";
2614 2647 int rc;
2615 2648
2616 2649 rc = prop_exists(handles, DS_NAME_MAPPING_ENABLED,
2617 2650 &legacy_ds_name_mapping_present);
2618 2651
2619 2652 if (rc != 0)
2620 2653 return (rc);
2621 2654
2622 2655 if (!legacy_ds_name_mapping_present)
2623 2656 return (0);
2624 2657
2625 2658 boolean_t legacy_ds_name_mapping_enabled;
2626 2659 rc = get_val_bool(handles, DS_NAME_MAPPING_ENABLED,
2627 2660 &legacy_ds_name_mapping_enabled, B_FALSE);
2628 2661 if (rc != 0)
2629 2662 return (rc);
2630 2663
2631 2664 char *legacy_mode;
2632 2665 char *legacy_bool_string;
2633 2666 if (legacy_ds_name_mapping_enabled) {
2634 2667 legacy_mode = "name";
2635 2668 legacy_bool_string = "true";
2636 2669 } else {
2637 2670 legacy_mode = "none";
2638 2671 legacy_bool_string = "false";
2639 2672 }
2640 2673
2641 2674 char *directory_based_mapping;
2642 2675 rc = get_val_astring(handles, DIRECTORY_BASED_MAPPING,
2643 2676 &directory_based_mapping);
2644 2677 if (rc != 0)
2645 2678 return (rc);
2646 2679
2647 2680 if (directory_based_mapping == NULL) {
2648 2681 idmapdlog(LOG_INFO,
2649 2682 "Upgrading old %s=%s setting\n"
2650 2683 "to %s=%s.",
2651 2684 DS_NAME_MAPPING_ENABLED, legacy_bool_string,
2652 2685 DIRECTORY_BASED_MAPPING, legacy_mode);
2653 2686 rc = set_val_astring(handles, handles->config_pg,
2654 2687 DIRECTORY_BASED_MAPPING, legacy_mode);
2655 2688 if (rc != 0)
2656 2689 return (rc);
2657 2690 } else {
2658 2691 boolean_t new_name_mapping;
2659 2692 if (strcasecmp(directory_based_mapping, "name") == 0)
2660 2693 new_name_mapping = B_TRUE;
2661 2694 else
2662 2695 new_name_mapping = B_FALSE;
2663 2696
2664 2697 if (legacy_ds_name_mapping_enabled == new_name_mapping) {
2665 2698 idmapdlog(LOG_INFO,
2666 2699 "Automatically removing old %s=%s setting\n"
2667 2700 "in favor of %s=%s.",
2668 2701 DS_NAME_MAPPING_ENABLED, legacy_bool_string,
2669 2702 DIRECTORY_BASED_MAPPING, directory_based_mapping);
2670 2703 } else {
2671 2704 idmapdlog(LOG_WARNING,
2672 2705 "Removing conflicting %s=%s setting\n"
2673 2706 "in favor of %s=%s.",
2674 2707 DS_NAME_MAPPING_ENABLED, legacy_bool_string,
2675 2708 DIRECTORY_BASED_MAPPING, directory_based_mapping);
2676 2709 }
2677 2710 free(directory_based_mapping);
2678 2711 }
2679 2712
2680 2713 rc = del_val(handles, handles->config_pg, DS_NAME_MAPPING_ENABLED);
2681 2714 if (rc != 0)
2682 2715 return (rc);
2683 2716
2684 2717 return (0);
2685 2718 }
2686 2719
2687 2720 /*
2688 2721 * Do whatever is necessary to upgrade idmap's configuration before
2689 2722 * we load it.
2690 2723 */
2691 2724 int
2692 2725 idmap_cfg_upgrade(idmap_cfg_t *cfg)
2693 2726 {
2694 2727 int rc;
2695 2728
2696 2729 rc = upgrade_directory_mapping(&cfg->handles);
2697 2730 if (rc != 0)
2698 2731 return (rc);
2699 2732
2700 2733 rc = upgrade_debug(&cfg->handles);
2701 2734 if (rc != 0)
2702 2735 return (rc);
2703 2736
2704 2737 return (0);
2705 2738 }
2706 2739
2707 2740 /*
2708 2741 * The LDAP code passes principal names lacking any
2709 2742 * realm information, which causes mech_krb5 to do
2710 2743 * awful things trying to figure out the realm.
2711 2744 * Avoid that by making sure it has a default,
2712 2745 * even when krb5.conf is not configured.
2713 2746 */
2714 2747 static void
2715 2748 idmapd_set_krb5_realm(char *domain)
2716 2749 {
2717 2750 static char realm[MAXHOSTNAMELEN];
2718 2751 size_t ilen, olen;
2719 2752 int err;
2720 2753
2721 2754 if (domain == NULL) {
2722 2755 (void) unsetenv("KRB5_DEFAULT_REALM");
2723 2756 return;
2724 2757 }
2725 2758
2726 2759 /* Convert to upper case, in place. */
2727 2760 (void) strlcpy(realm, domain, sizeof (realm));
2728 2761 olen = ilen = strlen(realm);
2729 2762 (void) u8_textprep_str(realm, &ilen, realm, &olen,
2730 2763 U8_TEXTPREP_TOUPPER, U8_UNICODE_LATEST, &err);
2731 2764
2732 2765 (void) setenv("KRB5_DEFAULT_REALM", realm, 1);
2733 2766 }
|
↓ open down ↓ |
523 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX