Print this page
NEX-20555 idmap fall-back to DC discovery is broken
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-3155 idmap in a loop spamming its svc log
Reviewed by: Bayard Bell <bayard.bell@nexenta.com>
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Tony Nguyen <tony.nguyen@nexenta.com>
NEX-2892 NexentaStor losing connectivity to multihomed AD servers
Reviewed by: Bayard Bell <bayard.bell@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-2225 Unable to join NexentaStor to 2008 AD
NEX-1638 Updated DC Locator
 Includes work by: matt.barden@nexenta.com, kevin.crowe@nexenta.com

Split Close
Expand all
Collapse all
          --- old/usr/src/lib/libadutils/common/addisc.c
          +++ new/usr/src/lib/libadutils/common/addisc.c
↓ open down ↓ 13 lines elided ↑ open up ↑
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  24      - * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
       24 + * Copyright 2019 Nexenta Systems, Inc.  All rights reserved.
  25   25   */
  26   26  
  27   27  /*
  28   28   * Active Directory Auto-Discovery.
  29   29   *
  30   30   * This [project private] API allows the caller to provide whatever
  31   31   * details it knows a priori (i.e., provided via configuration so as to
  32   32   * override auto-discovery) and in any order.  Then the caller can ask
  33   33   * for any of the auto-discoverable parameters in any order.
  34   34   *
↓ open down ↓ 1180 lines elided ↑ open up ↑
1215 1215          ad_item_t *site_name_item = NULL;
1216 1216          char *site_name;
1217 1217          ad_item_t *prefer_dc_item;
1218 1218          ad_disc_ds_t *prefer_dc = NULL;
1219 1219  
1220 1220          /* If the values is fixed there will not be a site specific version */
1221 1221          if (is_fixed(&ctx->domain_controller))
1222 1222                  return (&ctx->domain_controller);
1223 1223  
1224 1224          domain_name_item = validate_DomainName(ctx);
1225      -        if (domain_name_item == NULL)
     1225 +        if (domain_name_item == NULL) {
     1226 +                DEBUG1STATUS(ctx, "(no domain name)");
1226 1227                  return (NULL);
     1228 +        }
1227 1229          domain_name = (char *)domain_name_item->value;
1228 1230  
1229 1231          /* Get (optional) preferred DC. */
1230 1232          prefer_dc_item = validate_PreferredDC(ctx);
1231 1233          if (prefer_dc_item != NULL)
1232 1234                  prefer_dc = prefer_dc_item->value;
1233 1235  
1234 1236          if (req == AD_DISC_GLOBAL)
1235 1237                  validate_global = B_TRUE;
1236 1238          else {
1237 1239                  if (is_fixed(&ctx->site_name))
1238 1240                          validate_site = B_TRUE;
1239      -                else if (req == AD_DISC_PREFER_SITE)
     1241 +                if (req == AD_DISC_PREFER_SITE)
1240 1242                          validate_global = B_TRUE;
1241 1243          }
1242 1244  
1243      -        if (validate_global) {
1244      -                if (!is_valid(&ctx->domain_controller) ||
1245      -                    is_changed(&ctx->domain_controller, PARAM1,
1246      -                    domain_name_item)) {
     1245 +        /*
     1246 +         * If we're trying both site-specific and global,
     1247 +         * try the site-specific first, then fall-back.
     1248 +         */
     1249 +        if (validate_site) {
     1250 +                site_name_item = &ctx->site_name;
     1251 +                site_name = (char *)site_name_item->value;
1247 1252  
     1253 +                if (!is_valid(&ctx->site_domain_controller) ||
     1254 +                    is_changed(&ctx->site_domain_controller, PARAM1,
     1255 +                    domain_name_item) ||
     1256 +                    is_changed(&ctx->site_domain_controller, PARAM2,
     1257 +                    site_name_item)) {
     1258 +                        char rr_name[DNS_MAX_NAME];
     1259 +
1248 1260                          /*
1249 1261                           * Lookup DNS SRV RR named
1250      -                         * _ldap._tcp.dc._msdcs.<DomainName>
     1262 +                         * _ldap._tcp.<SiteName>._sites.dc._msdcs.<DomainName>
1251 1263                           */
1252      -                        DEBUG1STATUS(ctx, "DNS SRV query, dom=%s",
1253      -                            domain_name);
     1264 +                        DEBUG1STATUS(ctx, "DNS SRV query, dom=%s, site=%s",
     1265 +                            domain_name, site_name);
     1266 +                        (void) snprintf(rr_name, sizeof (rr_name),
     1267 +                            LDAP_SRV_HEAD SITE_SRV_MIDDLE DC_SRV_TAIL,
     1268 +                            site_name);
1254 1269                          DO_RES_NINIT(ctx);
1255      -                        cdc = srv_query(&ctx->res_state,
1256      -                            LDAP_SRV_HEAD DC_SRV_TAIL,
     1270 +                        cdc = srv_query(&ctx->res_state, rr_name,
1257 1271                              domain_name, prefer_dc);
1258 1272  
1259 1273                          if (cdc == NULL) {
1260 1274                                  DEBUG1STATUS(ctx, "(no DNS response)");
1261      -                                return (NULL);
     1275 +                                goto try_global;
1262 1276                          }
1263 1277                          log_cds(ctx, cdc);
1264 1278  
1265 1279                          /*
1266 1280                           * Filter out unresponsive servers, and
1267 1281                           * save the domain info we get back.
1268 1282                           */
1269 1283                          dc = ldap_ping(
1270 1284                              ctx,
1271 1285                              cdc,
1272 1286                              domain_name,
1273 1287                              DS_DS_FLAG);
1274 1288                          srv_free(cdc);
1275 1289                          cdc = NULL;
1276 1290  
1277 1291                          if (dc == NULL) {
1278 1292                                  DEBUG1STATUS(ctx, "(no LDAP response)");
1279      -                                return (NULL);
     1293 +                                goto try_global;
1280 1294                          }
1281 1295                          log_ds(ctx, dc);
1282 1296  
1283      -                        update_item(&ctx->domain_controller, dc,
     1297 +                        update_item(&ctx->site_domain_controller, dc,
1284 1298                              AD_STATE_AUTO, dc->ttl);
1285      -                        update_version(&ctx->domain_controller, PARAM1,
     1299 +                        update_version(&ctx->site_domain_controller, PARAM1,
1286 1300                              domain_name_item);
     1301 +                        update_version(&ctx->site_domain_controller, PARAM2,
     1302 +                            site_name_item);
1287 1303                  }
1288      -                return (&ctx->domain_controller);
     1304 +                return (&ctx->site_domain_controller);
1289 1305          }
1290 1306  
1291      -        if (validate_site) {
1292      -                site_name_item = &ctx->site_name;
1293      -                site_name = (char *)site_name_item->value;
     1307 +try_global:
1294 1308  
1295      -                if (!is_valid(&ctx->site_domain_controller) ||
1296      -                    is_changed(&ctx->site_domain_controller, PARAM1,
1297      -                    domain_name_item) ||
1298      -                    is_changed(&ctx->site_domain_controller, PARAM2,
1299      -                    site_name_item)) {
1300      -                        char rr_name[DNS_MAX_NAME];
     1309 +        if (validate_global) {
     1310 +                if (!is_valid(&ctx->domain_controller) ||
     1311 +                    is_changed(&ctx->domain_controller, PARAM1,
     1312 +                    domain_name_item)) {
1301 1313  
1302 1314                          /*
1303 1315                           * Lookup DNS SRV RR named
1304      -                         * _ldap._tcp.<SiteName>._sites.dc._msdcs.<DomainName>
     1316 +                         * _ldap._tcp.dc._msdcs.<DomainName>
1305 1317                           */
1306      -                        DEBUG1STATUS(ctx, "DNS SRV query, dom=%s, site=%s",
1307      -                            domain_name, site_name);
1308      -                        (void) snprintf(rr_name, sizeof (rr_name),
1309      -                            LDAP_SRV_HEAD SITE_SRV_MIDDLE DC_SRV_TAIL,
1310      -                            site_name);
     1318 +                        DEBUG1STATUS(ctx, "DNS SRV query, dom=%s",
     1319 +                            domain_name);
1311 1320                          DO_RES_NINIT(ctx);
1312      -                        cdc = srv_query(&ctx->res_state, rr_name,
     1321 +                        cdc = srv_query(&ctx->res_state,
     1322 +                            LDAP_SRV_HEAD DC_SRV_TAIL,
1313 1323                              domain_name, prefer_dc);
1314 1324  
1315 1325                          if (cdc == NULL) {
1316 1326                                  DEBUG1STATUS(ctx, "(no DNS response)");
1317 1327                                  return (NULL);
1318 1328                          }
1319 1329                          log_cds(ctx, cdc);
1320 1330  
1321 1331                          /*
1322 1332                           * Filter out unresponsive servers, and
↓ open down ↓ 6 lines elided ↑ open up ↑
1329 1339                              DS_DS_FLAG);
1330 1340                          srv_free(cdc);
1331 1341                          cdc = NULL;
1332 1342  
1333 1343                          if (dc == NULL) {
1334 1344                                  DEBUG1STATUS(ctx, "(no LDAP response)");
1335 1345                                  return (NULL);
1336 1346                          }
1337 1347                          log_ds(ctx, dc);
1338 1348  
1339      -                        update_item(&ctx->site_domain_controller, dc,
     1349 +                        update_item(&ctx->domain_controller, dc,
1340 1350                              AD_STATE_AUTO, dc->ttl);
1341      -                        update_version(&ctx->site_domain_controller, PARAM1,
     1351 +                        update_version(&ctx->domain_controller, PARAM1,
1342 1352                              domain_name_item);
1343      -                        update_version(&ctx->site_domain_controller, PARAM2,
1344      -                            site_name_item);
1345 1353                  }
1346      -                return (&ctx->site_domain_controller);
     1354 +                return (&ctx->domain_controller);
1347 1355          }
     1356 +
1348 1357          return (NULL);
1349 1358  }
1350 1359  
1351 1360  ad_disc_ds_t *
1352 1361  ad_disc_get_DomainController(ad_disc_t ctx, enum ad_disc_req req,
1353 1362      boolean_t *auto_discovered)
1354 1363  {
1355 1364          ad_item_t *domain_controller_item;
1356 1365          ad_disc_ds_t *domain_controller = NULL;
1357 1366  
↓ open down ↓ 151 lines elided ↑ open up ↑
1509 1518          ad_item_t *forest_name_item;
1510 1519          ad_item_t *site_name_item;
1511 1520          char *forest_name;
1512 1521          char *site_name;
1513 1522  
1514 1523          /* If the values is fixed there will not be a site specific version */
1515 1524          if (is_fixed(&ctx->global_catalog))
1516 1525                  return (&ctx->global_catalog);
1517 1526  
1518 1527          forest_name_item = validate_ForestName(ctx);
1519      -        if (forest_name_item == NULL)
     1528 +        if (forest_name_item == NULL) {
     1529 +                DEBUG1STATUS(ctx, "(no forrest name)");
1520 1530                  return (NULL);
     1531 +        }
1521 1532          forest_name = (char *)forest_name_item->value;
1522 1533  
1523 1534          if (req == AD_DISC_GLOBAL)
1524 1535                  validate_global = B_TRUE;
1525 1536          else {
1526 1537                  if (is_fixed(&ctx->site_name))
1527 1538                          validate_site = B_TRUE;
1528      -                else if (req == AD_DISC_PREFER_SITE)
     1539 +                if (req == AD_DISC_PREFER_SITE)
1529 1540                          validate_global = B_TRUE;
1530 1541          }
1531 1542  
1532      -        if (validate_global) {
1533      -                if (!is_valid(&ctx->global_catalog) ||
1534      -                    is_changed(&ctx->global_catalog, PARAM1,
1535      -                    forest_name_item)) {
     1543 +        /*
     1544 +         * If we're trying both site-specific and global,
     1545 +         * try the site-specific first, then fall-back.
     1546 +         */
     1547 +        if (validate_site) {
     1548 +                site_name_item = &ctx->site_name;
     1549 +                site_name = (char *)site_name_item->value;
1536 1550  
     1551 +                if (!is_valid(&ctx->site_global_catalog) ||
     1552 +                    is_changed(&ctx->site_global_catalog, PARAM1,
     1553 +                    forest_name_item) ||
     1554 +                    is_changed(&ctx->site_global_catalog, PARAM2,
     1555 +                    site_name_item)) {
     1556 +                        char rr_name[DNS_MAX_NAME];
     1557 +
1537 1558                          /*
1538 1559                           * See if our DC is also a GC.
1539 1560                           */
1540 1561                          dc_item = validate_DomainController(ctx, req);
1541 1562                          if (dc_item != NULL) {
1542 1563                                  ad_disc_ds_t *ds = dc_item->value;
1543 1564                                  if ((ds->flags & DS_GC_FLAG) != 0) {
1544 1565                                          DEBUG1STATUS(ctx,
1545      -                                            "DC is also a GC for %s",
1546      -                                            forest_name);
     1566 +                                            "DC is also a GC for %s in %s",
     1567 +                                            forest_name, site_name);
1547 1568                                          gc = ds_dup(ds);
1548 1569                                          if (gc != NULL) {
1549 1570                                                  gc->port = GC_PORT;
1550      -                                                goto update_global;
     1571 +                                                goto update_site;
1551 1572                                          }
1552 1573                                  }
1553 1574                          }
1554 1575  
1555 1576                          /*
1556 1577                           * Lookup DNS SRV RR named:
1557      -                         * _ldap._tcp.gc._msdcs.<ForestName>
     1578 +                         * _ldap._tcp.<siteName>._sites.gc.
     1579 +                         *      _msdcs.<ForestName>
1558 1580                           */
1559      -                        DEBUG1STATUS(ctx, "DNS SRV query, forest=%s",
1560      -                            forest_name);
     1581 +                        DEBUG1STATUS(ctx, "DNS SRV query, forest=%s, site=%s",
     1582 +                            forest_name, site_name);
     1583 +                        (void) snprintf(rr_name, sizeof (rr_name),
     1584 +                            LDAP_SRV_HEAD SITE_SRV_MIDDLE GC_SRV_TAIL,
     1585 +                            site_name);
1561 1586                          DO_RES_NINIT(ctx);
1562      -                        cgc = srv_query(&ctx->res_state,
1563      -                            LDAP_SRV_HEAD GC_SRV_TAIL,
     1587 +                        cgc = srv_query(&ctx->res_state, rr_name,
1564 1588                              forest_name, NULL);
1565 1589  
1566 1590                          if (cgc == NULL) {
1567 1591                                  DEBUG1STATUS(ctx, "(no DNS response)");
1568      -                                return (NULL);
     1592 +                                goto try_global;
1569 1593                          }
1570 1594                          log_cds(ctx, cgc);
1571 1595  
1572 1596                          /*
1573 1597                           * Filter out unresponsive servers, and
1574 1598                           * save the domain info we get back.
1575 1599                           */
1576 1600                          gc = ldap_ping(
1577 1601                              NULL,
1578 1602                              cgc,
1579 1603                              forest_name,
1580 1604                              DS_GC_FLAG);
1581 1605                          srv_free(cgc);
1582 1606                          cgc = NULL;
1583 1607  
1584 1608                          if (gc == NULL) {
1585 1609                                  DEBUG1STATUS(ctx, "(no LDAP response)");
1586      -                                return (NULL);
     1610 +                                goto try_global;
1587 1611                          }
1588 1612                          log_ds(ctx, gc);
1589 1613  
1590      -                update_global:
1591      -                        update_item(&ctx->global_catalog, gc,
     1614 +                update_site:
     1615 +                        update_item(&ctx->site_global_catalog, gc,
1592 1616                              AD_STATE_AUTO, gc->ttl);
1593      -                        update_version(&ctx->global_catalog, PARAM1,
     1617 +                        update_version(&ctx->site_global_catalog, PARAM1,
1594 1618                              forest_name_item);
     1619 +                        update_version(&ctx->site_global_catalog, PARAM2,
     1620 +                            site_name_item);
1595 1621                  }
1596      -                return (&ctx->global_catalog);
     1622 +                return (&ctx->site_global_catalog);
1597 1623          }
1598 1624  
1599      -        if (validate_site) {
1600      -                site_name_item = &ctx->site_name;
1601      -                site_name = (char *)site_name_item->value;
     1625 +try_global:
1602 1626  
1603      -                if (!is_valid(&ctx->site_global_catalog) ||
1604      -                    is_changed(&ctx->site_global_catalog, PARAM1,
1605      -                    forest_name_item) ||
1606      -                    is_changed(&ctx->site_global_catalog, PARAM2,
1607      -                    site_name_item)) {
1608      -                        char rr_name[DNS_MAX_NAME];
     1627 +        if (validate_global) {
     1628 +                if (!is_valid(&ctx->global_catalog) ||
     1629 +                    is_changed(&ctx->global_catalog, PARAM1,
     1630 +                    forest_name_item)) {
1609 1631  
1610 1632                          /*
1611 1633                           * See if our DC is also a GC.
1612 1634                           */
1613 1635                          dc_item = validate_DomainController(ctx, req);
1614 1636                          if (dc_item != NULL) {
1615 1637                                  ad_disc_ds_t *ds = dc_item->value;
1616 1638                                  if ((ds->flags & DS_GC_FLAG) != 0) {
1617 1639                                          DEBUG1STATUS(ctx,
1618      -                                            "DC is also a GC for %s in %s",
1619      -                                            forest_name, site_name);
     1640 +                                            "DC is also a GC for %s",
     1641 +                                            forest_name);
1620 1642                                          gc = ds_dup(ds);
1621 1643                                          if (gc != NULL) {
1622 1644                                                  gc->port = GC_PORT;
1623      -                                                goto update_site;
     1645 +                                                goto update_global;
1624 1646                                          }
1625 1647                                  }
1626 1648                          }
1627 1649  
1628 1650                          /*
1629 1651                           * Lookup DNS SRV RR named:
1630      -                         * _ldap._tcp.<siteName>._sites.gc.
1631      -                         *      _msdcs.<ForestName>
     1652 +                         * _ldap._tcp.gc._msdcs.<ForestName>
1632 1653                           */
1633      -                        DEBUG1STATUS(ctx, "DNS SRV query, forest=%s, site=%s",
1634      -                            forest_name, site_name);
1635      -                        (void) snprintf(rr_name, sizeof (rr_name),
1636      -                            LDAP_SRV_HEAD SITE_SRV_MIDDLE GC_SRV_TAIL,
1637      -                            site_name);
     1654 +                        DEBUG1STATUS(ctx, "DNS SRV query, forest=%s",
     1655 +                            forest_name);
1638 1656                          DO_RES_NINIT(ctx);
1639      -                        cgc = srv_query(&ctx->res_state, rr_name,
     1657 +                        cgc = srv_query(&ctx->res_state,
     1658 +                            LDAP_SRV_HEAD GC_SRV_TAIL,
1640 1659                              forest_name, NULL);
1641 1660  
1642 1661                          if (cgc == NULL) {
1643 1662                                  DEBUG1STATUS(ctx, "(no DNS response)");
1644 1663                                  return (NULL);
1645 1664                          }
1646 1665                          log_cds(ctx, cgc);
1647 1666  
1648 1667                          /*
1649 1668                           * Filter out unresponsive servers, and
↓ open down ↓ 6 lines elided ↑ open up ↑
1656 1675                              DS_GC_FLAG);
1657 1676                          srv_free(cgc);
1658 1677                          cgc = NULL;
1659 1678  
1660 1679                          if (gc == NULL) {
1661 1680                                  DEBUG1STATUS(ctx, "(no LDAP response)");
1662 1681                                  return (NULL);
1663 1682                          }
1664 1683                          log_ds(ctx, gc);
1665 1684  
1666      -                update_site:
1667      -                        update_item(&ctx->site_global_catalog, gc,
     1685 +                update_global:
     1686 +                        update_item(&ctx->global_catalog, gc,
1668 1687                              AD_STATE_AUTO, gc->ttl);
1669      -                        update_version(&ctx->site_global_catalog, PARAM1,
     1688 +                        update_version(&ctx->global_catalog, PARAM1,
1670 1689                              forest_name_item);
1671      -                        update_version(&ctx->site_global_catalog, PARAM2,
1672      -                            site_name_item);
1673 1690                  }
1674      -                return (&ctx->site_global_catalog);
     1691 +                return (&ctx->global_catalog);
1675 1692          }
1676 1693          return (NULL);
1677 1694  }
1678 1695  
1679 1696  
1680 1697  ad_disc_ds_t *
1681 1698  ad_disc_get_GlobalCatalog(ad_disc_t ctx, enum ad_disc_req req,
1682 1699                          boolean_t *auto_discovered)
1683 1700  {
1684 1701          ad_disc_ds_t *global_catalog = NULL;
↓ open down ↓ 427 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX