4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
25 */
26
27 /*
28 * Active Directory Auto-Discovery.
29 *
30 * This [project private] API allows the caller to provide whatever
31 * details it knows a priori (i.e., provided via configuration so as to
32 * override auto-discovery) and in any order. Then the caller can ask
33 * for any of the auto-discoverable parameters in any order.
34 *
35 * But there is an actual order in which discovery must be done. Given
36 * the discovery mechanism implemented here, that order is:
37 *
38 * - the domain name joined must be discovered first
39 * - then the domain controllers
40 * - then the forest name and site name
41 * - then the global catalog servers, and site-specific domain
42 * controllers and global catalog servers.
43 *
44 * The API does not require it be called in the same order because there
1205 /* Discover domain controllers */
1206 static ad_item_t *
1207 validate_DomainController(ad_disc_t ctx, enum ad_disc_req req)
1208 {
1209 ad_disc_ds_t *dc = NULL;
1210 ad_disc_cds_t *cdc = NULL;
1211 boolean_t validate_global = B_FALSE;
1212 boolean_t validate_site = B_FALSE;
1213 ad_item_t *domain_name_item;
1214 char *domain_name;
1215 ad_item_t *site_name_item = NULL;
1216 char *site_name;
1217 ad_item_t *prefer_dc_item;
1218 ad_disc_ds_t *prefer_dc = NULL;
1219
1220 /* If the values is fixed there will not be a site specific version */
1221 if (is_fixed(&ctx->domain_controller))
1222 return (&ctx->domain_controller);
1223
1224 domain_name_item = validate_DomainName(ctx);
1225 if (domain_name_item == NULL)
1226 return (NULL);
1227 domain_name = (char *)domain_name_item->value;
1228
1229 /* Get (optional) preferred DC. */
1230 prefer_dc_item = validate_PreferredDC(ctx);
1231 if (prefer_dc_item != NULL)
1232 prefer_dc = prefer_dc_item->value;
1233
1234 if (req == AD_DISC_GLOBAL)
1235 validate_global = B_TRUE;
1236 else {
1237 if (is_fixed(&ctx->site_name))
1238 validate_site = B_TRUE;
1239 else if (req == AD_DISC_PREFER_SITE)
1240 validate_global = B_TRUE;
1241 }
1242
1243 if (validate_global) {
1244 if (!is_valid(&ctx->domain_controller) ||
1245 is_changed(&ctx->domain_controller, PARAM1,
1246 domain_name_item)) {
1247
1248 /*
1249 * Lookup DNS SRV RR named
1250 * _ldap._tcp.dc._msdcs.<DomainName>
1251 */
1252 DEBUG1STATUS(ctx, "DNS SRV query, dom=%s",
1253 domain_name);
1254 DO_RES_NINIT(ctx);
1255 cdc = srv_query(&ctx->res_state,
1256 LDAP_SRV_HEAD DC_SRV_TAIL,
1257 domain_name, prefer_dc);
1258
1259 if (cdc == NULL) {
1260 DEBUG1STATUS(ctx, "(no DNS response)");
1261 return (NULL);
1262 }
1263 log_cds(ctx, cdc);
1264
1265 /*
1266 * Filter out unresponsive servers, and
1267 * save the domain info we get back.
1268 */
1269 dc = ldap_ping(
1270 ctx,
1271 cdc,
1272 domain_name,
1273 DS_DS_FLAG);
1274 srv_free(cdc);
1275 cdc = NULL;
1276
1277 if (dc == NULL) {
1278 DEBUG1STATUS(ctx, "(no LDAP response)");
1279 return (NULL);
1280 }
1281 log_ds(ctx, dc);
1282
1283 update_item(&ctx->domain_controller, dc,
1284 AD_STATE_AUTO, dc->ttl);
1285 update_version(&ctx->domain_controller, PARAM1,
1286 domain_name_item);
1287 }
1288 return (&ctx->domain_controller);
1289 }
1290
1291 if (validate_site) {
1292 site_name_item = &ctx->site_name;
1293 site_name = (char *)site_name_item->value;
1294
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];
1301
1302 /*
1303 * Lookup DNS SRV RR named
1304 * _ldap._tcp.<SiteName>._sites.dc._msdcs.<DomainName>
1305 */
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);
1311 DO_RES_NINIT(ctx);
1312 cdc = srv_query(&ctx->res_state, rr_name,
1313 domain_name, prefer_dc);
1314
1315 if (cdc == NULL) {
1316 DEBUG1STATUS(ctx, "(no DNS response)");
1317 return (NULL);
1318 }
1319 log_cds(ctx, cdc);
1320
1321 /*
1322 * Filter out unresponsive servers, and
1323 * save the domain info we get back.
1324 */
1325 dc = ldap_ping(
1326 ctx,
1327 cdc,
1328 domain_name,
1329 DS_DS_FLAG);
1330 srv_free(cdc);
1331 cdc = NULL;
1332
1333 if (dc == NULL) {
1334 DEBUG1STATUS(ctx, "(no LDAP response)");
1335 return (NULL);
1336 }
1337 log_ds(ctx, dc);
1338
1339 update_item(&ctx->site_domain_controller, dc,
1340 AD_STATE_AUTO, dc->ttl);
1341 update_version(&ctx->site_domain_controller, PARAM1,
1342 domain_name_item);
1343 update_version(&ctx->site_domain_controller, PARAM2,
1344 site_name_item);
1345 }
1346 return (&ctx->site_domain_controller);
1347 }
1348 return (NULL);
1349 }
1350
1351 ad_disc_ds_t *
1352 ad_disc_get_DomainController(ad_disc_t ctx, enum ad_disc_req req,
1353 boolean_t *auto_discovered)
1354 {
1355 ad_item_t *domain_controller_item;
1356 ad_disc_ds_t *domain_controller = NULL;
1357
1358 domain_controller_item = validate_DomainController(ctx, req);
1359
1360 if (domain_controller_item != NULL) {
1361 domain_controller = ds_dup(domain_controller_item->value);
1362 if (auto_discovered != NULL)
1363 *auto_discovered =
1364 (domain_controller_item->state == AD_STATE_AUTO);
1365 } else if (auto_discovered != NULL)
1366 *auto_discovered = B_FALSE;
1367
1499
1500 /* Discover global catalog servers */
1501 static ad_item_t *
1502 validate_GlobalCatalog(ad_disc_t ctx, enum ad_disc_req req)
1503 {
1504 ad_disc_ds_t *gc = NULL;
1505 ad_disc_cds_t *cgc = NULL;
1506 boolean_t validate_global = B_FALSE;
1507 boolean_t validate_site = B_FALSE;
1508 ad_item_t *dc_item;
1509 ad_item_t *forest_name_item;
1510 ad_item_t *site_name_item;
1511 char *forest_name;
1512 char *site_name;
1513
1514 /* If the values is fixed there will not be a site specific version */
1515 if (is_fixed(&ctx->global_catalog))
1516 return (&ctx->global_catalog);
1517
1518 forest_name_item = validate_ForestName(ctx);
1519 if (forest_name_item == NULL)
1520 return (NULL);
1521 forest_name = (char *)forest_name_item->value;
1522
1523 if (req == AD_DISC_GLOBAL)
1524 validate_global = B_TRUE;
1525 else {
1526 if (is_fixed(&ctx->site_name))
1527 validate_site = B_TRUE;
1528 else if (req == AD_DISC_PREFER_SITE)
1529 validate_global = B_TRUE;
1530 }
1531
1532 if (validate_global) {
1533 if (!is_valid(&ctx->global_catalog) ||
1534 is_changed(&ctx->global_catalog, PARAM1,
1535 forest_name_item)) {
1536
1537 /*
1538 * See if our DC is also a GC.
1539 */
1540 dc_item = validate_DomainController(ctx, req);
1541 if (dc_item != NULL) {
1542 ad_disc_ds_t *ds = dc_item->value;
1543 if ((ds->flags & DS_GC_FLAG) != 0) {
1544 DEBUG1STATUS(ctx,
1545 "DC is also a GC for %s",
1546 forest_name);
1547 gc = ds_dup(ds);
1548 if (gc != NULL) {
1549 gc->port = GC_PORT;
1550 goto update_global;
1551 }
1552 }
1553 }
1554
1555 /*
1556 * Lookup DNS SRV RR named:
1557 * _ldap._tcp.gc._msdcs.<ForestName>
1558 */
1559 DEBUG1STATUS(ctx, "DNS SRV query, forest=%s",
1560 forest_name);
1561 DO_RES_NINIT(ctx);
1562 cgc = srv_query(&ctx->res_state,
1563 LDAP_SRV_HEAD GC_SRV_TAIL,
1564 forest_name, NULL);
1565
1566 if (cgc == NULL) {
1567 DEBUG1STATUS(ctx, "(no DNS response)");
1568 return (NULL);
1569 }
1570 log_cds(ctx, cgc);
1571
1572 /*
1573 * Filter out unresponsive servers, and
1574 * save the domain info we get back.
1575 */
1576 gc = ldap_ping(
1577 NULL,
1578 cgc,
1579 forest_name,
1580 DS_GC_FLAG);
1581 srv_free(cgc);
1582 cgc = NULL;
1583
1584 if (gc == NULL) {
1585 DEBUG1STATUS(ctx, "(no LDAP response)");
1586 return (NULL);
1587 }
1588 log_ds(ctx, gc);
1589
1590 update_global:
1591 update_item(&ctx->global_catalog, gc,
1592 AD_STATE_AUTO, gc->ttl);
1593 update_version(&ctx->global_catalog, PARAM1,
1594 forest_name_item);
1595 }
1596 return (&ctx->global_catalog);
1597 }
1598
1599 if (validate_site) {
1600 site_name_item = &ctx->site_name;
1601 site_name = (char *)site_name_item->value;
1602
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];
1609
1610 /*
1611 * See if our DC is also a GC.
1612 */
1613 dc_item = validate_DomainController(ctx, req);
1614 if (dc_item != NULL) {
1615 ad_disc_ds_t *ds = dc_item->value;
1616 if ((ds->flags & DS_GC_FLAG) != 0) {
1617 DEBUG1STATUS(ctx,
1618 "DC is also a GC for %s in %s",
1619 forest_name, site_name);
1620 gc = ds_dup(ds);
1621 if (gc != NULL) {
1622 gc->port = GC_PORT;
1623 goto update_site;
1624 }
1625 }
1626 }
1627
1628 /*
1629 * Lookup DNS SRV RR named:
1630 * _ldap._tcp.<siteName>._sites.gc.
1631 * _msdcs.<ForestName>
1632 */
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);
1638 DO_RES_NINIT(ctx);
1639 cgc = srv_query(&ctx->res_state, rr_name,
1640 forest_name, NULL);
1641
1642 if (cgc == NULL) {
1643 DEBUG1STATUS(ctx, "(no DNS response)");
1644 return (NULL);
1645 }
1646 log_cds(ctx, cgc);
1647
1648 /*
1649 * Filter out unresponsive servers, and
1650 * save the domain info we get back.
1651 */
1652 gc = ldap_ping(
1653 NULL,
1654 cgc,
1655 forest_name,
1656 DS_GC_FLAG);
1657 srv_free(cgc);
1658 cgc = NULL;
1659
1660 if (gc == NULL) {
1661 DEBUG1STATUS(ctx, "(no LDAP response)");
1662 return (NULL);
1663 }
1664 log_ds(ctx, gc);
1665
1666 update_site:
1667 update_item(&ctx->site_global_catalog, gc,
1668 AD_STATE_AUTO, gc->ttl);
1669 update_version(&ctx->site_global_catalog, PARAM1,
1670 forest_name_item);
1671 update_version(&ctx->site_global_catalog, PARAM2,
1672 site_name_item);
1673 }
1674 return (&ctx->site_global_catalog);
1675 }
1676 return (NULL);
1677 }
1678
1679
1680 ad_disc_ds_t *
1681 ad_disc_get_GlobalCatalog(ad_disc_t ctx, enum ad_disc_req req,
1682 boolean_t *auto_discovered)
1683 {
1684 ad_disc_ds_t *global_catalog = NULL;
1685 ad_item_t *global_catalog_item;
1686
1687 global_catalog_item = validate_GlobalCatalog(ctx, req);
1688
1689 if (global_catalog_item != NULL) {
1690 global_catalog = ds_dup(global_catalog_item->value);
1691 if (auto_discovered != NULL)
1692 *auto_discovered =
1693 (global_catalog_item->state == AD_STATE_AUTO);
1694 } else if (auto_discovered != NULL)
|
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2019 Nexenta Systems, Inc. All rights reserved.
25 */
26
27 /*
28 * Active Directory Auto-Discovery.
29 *
30 * This [project private] API allows the caller to provide whatever
31 * details it knows a priori (i.e., provided via configuration so as to
32 * override auto-discovery) and in any order. Then the caller can ask
33 * for any of the auto-discoverable parameters in any order.
34 *
35 * But there is an actual order in which discovery must be done. Given
36 * the discovery mechanism implemented here, that order is:
37 *
38 * - the domain name joined must be discovered first
39 * - then the domain controllers
40 * - then the forest name and site name
41 * - then the global catalog servers, and site-specific domain
42 * controllers and global catalog servers.
43 *
44 * The API does not require it be called in the same order because there
1205 /* Discover domain controllers */
1206 static ad_item_t *
1207 validate_DomainController(ad_disc_t ctx, enum ad_disc_req req)
1208 {
1209 ad_disc_ds_t *dc = NULL;
1210 ad_disc_cds_t *cdc = NULL;
1211 boolean_t validate_global = B_FALSE;
1212 boolean_t validate_site = B_FALSE;
1213 ad_item_t *domain_name_item;
1214 char *domain_name;
1215 ad_item_t *site_name_item = NULL;
1216 char *site_name;
1217 ad_item_t *prefer_dc_item;
1218 ad_disc_ds_t *prefer_dc = NULL;
1219
1220 /* If the values is fixed there will not be a site specific version */
1221 if (is_fixed(&ctx->domain_controller))
1222 return (&ctx->domain_controller);
1223
1224 domain_name_item = validate_DomainName(ctx);
1225 if (domain_name_item == NULL) {
1226 DEBUG1STATUS(ctx, "(no domain name)");
1227 return (NULL);
1228 }
1229 domain_name = (char *)domain_name_item->value;
1230
1231 /* Get (optional) preferred DC. */
1232 prefer_dc_item = validate_PreferredDC(ctx);
1233 if (prefer_dc_item != NULL)
1234 prefer_dc = prefer_dc_item->value;
1235
1236 if (req == AD_DISC_GLOBAL)
1237 validate_global = B_TRUE;
1238 else {
1239 if (is_fixed(&ctx->site_name))
1240 validate_site = B_TRUE;
1241 if (req == AD_DISC_PREFER_SITE)
1242 validate_global = B_TRUE;
1243 }
1244
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;
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
1260 /*
1261 * Lookup DNS SRV RR named
1262 * _ldap._tcp.<SiteName>._sites.dc._msdcs.<DomainName>
1263 */
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);
1269 DO_RES_NINIT(ctx);
1270 cdc = srv_query(&ctx->res_state, rr_name,
1271 domain_name, prefer_dc);
1272
1273 if (cdc == NULL) {
1274 DEBUG1STATUS(ctx, "(no DNS response)");
1275 goto try_global;
1276 }
1277 log_cds(ctx, cdc);
1278
1279 /*
1280 * Filter out unresponsive servers, and
1281 * save the domain info we get back.
1282 */
1283 dc = ldap_ping(
1284 ctx,
1285 cdc,
1286 domain_name,
1287 DS_DS_FLAG);
1288 srv_free(cdc);
1289 cdc = NULL;
1290
1291 if (dc == NULL) {
1292 DEBUG1STATUS(ctx, "(no LDAP response)");
1293 goto try_global;
1294 }
1295 log_ds(ctx, dc);
1296
1297 update_item(&ctx->site_domain_controller, dc,
1298 AD_STATE_AUTO, dc->ttl);
1299 update_version(&ctx->site_domain_controller, PARAM1,
1300 domain_name_item);
1301 update_version(&ctx->site_domain_controller, PARAM2,
1302 site_name_item);
1303 }
1304 return (&ctx->site_domain_controller);
1305 }
1306
1307 try_global:
1308
1309 if (validate_global) {
1310 if (!is_valid(&ctx->domain_controller) ||
1311 is_changed(&ctx->domain_controller, PARAM1,
1312 domain_name_item)) {
1313
1314 /*
1315 * Lookup DNS SRV RR named
1316 * _ldap._tcp.dc._msdcs.<DomainName>
1317 */
1318 DEBUG1STATUS(ctx, "DNS SRV query, dom=%s",
1319 domain_name);
1320 DO_RES_NINIT(ctx);
1321 cdc = srv_query(&ctx->res_state,
1322 LDAP_SRV_HEAD DC_SRV_TAIL,
1323 domain_name, prefer_dc);
1324
1325 if (cdc == NULL) {
1326 DEBUG1STATUS(ctx, "(no DNS response)");
1327 return (NULL);
1328 }
1329 log_cds(ctx, cdc);
1330
1331 /*
1332 * Filter out unresponsive servers, and
1333 * save the domain info we get back.
1334 */
1335 dc = ldap_ping(
1336 ctx,
1337 cdc,
1338 domain_name,
1339 DS_DS_FLAG);
1340 srv_free(cdc);
1341 cdc = NULL;
1342
1343 if (dc == NULL) {
1344 DEBUG1STATUS(ctx, "(no LDAP response)");
1345 return (NULL);
1346 }
1347 log_ds(ctx, dc);
1348
1349 update_item(&ctx->domain_controller, dc,
1350 AD_STATE_AUTO, dc->ttl);
1351 update_version(&ctx->domain_controller, PARAM1,
1352 domain_name_item);
1353 }
1354 return (&ctx->domain_controller);
1355 }
1356
1357 return (NULL);
1358 }
1359
1360 ad_disc_ds_t *
1361 ad_disc_get_DomainController(ad_disc_t ctx, enum ad_disc_req req,
1362 boolean_t *auto_discovered)
1363 {
1364 ad_item_t *domain_controller_item;
1365 ad_disc_ds_t *domain_controller = NULL;
1366
1367 domain_controller_item = validate_DomainController(ctx, req);
1368
1369 if (domain_controller_item != NULL) {
1370 domain_controller = ds_dup(domain_controller_item->value);
1371 if (auto_discovered != NULL)
1372 *auto_discovered =
1373 (domain_controller_item->state == AD_STATE_AUTO);
1374 } else if (auto_discovered != NULL)
1375 *auto_discovered = B_FALSE;
1376
1508
1509 /* Discover global catalog servers */
1510 static ad_item_t *
1511 validate_GlobalCatalog(ad_disc_t ctx, enum ad_disc_req req)
1512 {
1513 ad_disc_ds_t *gc = NULL;
1514 ad_disc_cds_t *cgc = NULL;
1515 boolean_t validate_global = B_FALSE;
1516 boolean_t validate_site = B_FALSE;
1517 ad_item_t *dc_item;
1518 ad_item_t *forest_name_item;
1519 ad_item_t *site_name_item;
1520 char *forest_name;
1521 char *site_name;
1522
1523 /* If the values is fixed there will not be a site specific version */
1524 if (is_fixed(&ctx->global_catalog))
1525 return (&ctx->global_catalog);
1526
1527 forest_name_item = validate_ForestName(ctx);
1528 if (forest_name_item == NULL) {
1529 DEBUG1STATUS(ctx, "(no forrest name)");
1530 return (NULL);
1531 }
1532 forest_name = (char *)forest_name_item->value;
1533
1534 if (req == AD_DISC_GLOBAL)
1535 validate_global = B_TRUE;
1536 else {
1537 if (is_fixed(&ctx->site_name))
1538 validate_site = B_TRUE;
1539 if (req == AD_DISC_PREFER_SITE)
1540 validate_global = B_TRUE;
1541 }
1542
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;
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
1558 /*
1559 * See if our DC is also a GC.
1560 */
1561 dc_item = validate_DomainController(ctx, req);
1562 if (dc_item != NULL) {
1563 ad_disc_ds_t *ds = dc_item->value;
1564 if ((ds->flags & DS_GC_FLAG) != 0) {
1565 DEBUG1STATUS(ctx,
1566 "DC is also a GC for %s in %s",
1567 forest_name, site_name);
1568 gc = ds_dup(ds);
1569 if (gc != NULL) {
1570 gc->port = GC_PORT;
1571 goto update_site;
1572 }
1573 }
1574 }
1575
1576 /*
1577 * Lookup DNS SRV RR named:
1578 * _ldap._tcp.<siteName>._sites.gc.
1579 * _msdcs.<ForestName>
1580 */
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);
1586 DO_RES_NINIT(ctx);
1587 cgc = srv_query(&ctx->res_state, rr_name,
1588 forest_name, NULL);
1589
1590 if (cgc == NULL) {
1591 DEBUG1STATUS(ctx, "(no DNS response)");
1592 goto try_global;
1593 }
1594 log_cds(ctx, cgc);
1595
1596 /*
1597 * Filter out unresponsive servers, and
1598 * save the domain info we get back.
1599 */
1600 gc = ldap_ping(
1601 NULL,
1602 cgc,
1603 forest_name,
1604 DS_GC_FLAG);
1605 srv_free(cgc);
1606 cgc = NULL;
1607
1608 if (gc == NULL) {
1609 DEBUG1STATUS(ctx, "(no LDAP response)");
1610 goto try_global;
1611 }
1612 log_ds(ctx, gc);
1613
1614 update_site:
1615 update_item(&ctx->site_global_catalog, gc,
1616 AD_STATE_AUTO, gc->ttl);
1617 update_version(&ctx->site_global_catalog, PARAM1,
1618 forest_name_item);
1619 update_version(&ctx->site_global_catalog, PARAM2,
1620 site_name_item);
1621 }
1622 return (&ctx->site_global_catalog);
1623 }
1624
1625 try_global:
1626
1627 if (validate_global) {
1628 if (!is_valid(&ctx->global_catalog) ||
1629 is_changed(&ctx->global_catalog, PARAM1,
1630 forest_name_item)) {
1631
1632 /*
1633 * See if our DC is also a GC.
1634 */
1635 dc_item = validate_DomainController(ctx, req);
1636 if (dc_item != NULL) {
1637 ad_disc_ds_t *ds = dc_item->value;
1638 if ((ds->flags & DS_GC_FLAG) != 0) {
1639 DEBUG1STATUS(ctx,
1640 "DC is also a GC for %s",
1641 forest_name);
1642 gc = ds_dup(ds);
1643 if (gc != NULL) {
1644 gc->port = GC_PORT;
1645 goto update_global;
1646 }
1647 }
1648 }
1649
1650 /*
1651 * Lookup DNS SRV RR named:
1652 * _ldap._tcp.gc._msdcs.<ForestName>
1653 */
1654 DEBUG1STATUS(ctx, "DNS SRV query, forest=%s",
1655 forest_name);
1656 DO_RES_NINIT(ctx);
1657 cgc = srv_query(&ctx->res_state,
1658 LDAP_SRV_HEAD GC_SRV_TAIL,
1659 forest_name, NULL);
1660
1661 if (cgc == NULL) {
1662 DEBUG1STATUS(ctx, "(no DNS response)");
1663 return (NULL);
1664 }
1665 log_cds(ctx, cgc);
1666
1667 /*
1668 * Filter out unresponsive servers, and
1669 * save the domain info we get back.
1670 */
1671 gc = ldap_ping(
1672 NULL,
1673 cgc,
1674 forest_name,
1675 DS_GC_FLAG);
1676 srv_free(cgc);
1677 cgc = NULL;
1678
1679 if (gc == NULL) {
1680 DEBUG1STATUS(ctx, "(no LDAP response)");
1681 return (NULL);
1682 }
1683 log_ds(ctx, gc);
1684
1685 update_global:
1686 update_item(&ctx->global_catalog, gc,
1687 AD_STATE_AUTO, gc->ttl);
1688 update_version(&ctx->global_catalog, PARAM1,
1689 forest_name_item);
1690 }
1691 return (&ctx->global_catalog);
1692 }
1693 return (NULL);
1694 }
1695
1696
1697 ad_disc_ds_t *
1698 ad_disc_get_GlobalCatalog(ad_disc_t ctx, enum ad_disc_req req,
1699 boolean_t *auto_discovered)
1700 {
1701 ad_disc_ds_t *global_catalog = NULL;
1702 ad_item_t *global_catalog_item;
1703
1704 global_catalog_item = validate_GlobalCatalog(ctx, req);
1705
1706 if (global_catalog_item != NULL) {
1707 global_catalog = ds_dup(global_catalog_item->value);
1708 if (auto_discovered != NULL)
1709 *auto_discovered =
1710 (global_catalog_item->state == AD_STATE_AUTO);
1711 } else if (auto_discovered != NULL)
|