3  *
   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  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 
  26 
  27 /*
  28  * Config routines common to idmap(1M) and idmapd(1M)
  29  */
  30 
  31 #include <stdlib.h>
  32 #include <strings.h>
  33 #include <libintl.h>
  34 #include <ctype.h>
  35 #include <errno.h>
  36 #include <stdio.h>
  37 #include <stdarg.h>
  38 #include <uuid/uuid.h>
  39 #include <pthread.h>
  40 #include <port.h>
  41 #include <sys/socket.h>
  42 #include <net/route.h>
  43 #include <sys/u8_textprep.h>
  44 #include <netinet/in.h>
  45 #include <arpa/inet.h>
  46 #include <netdb.h>
  47 #include <note.h>
  48 #include "idmapd.h"
  49 #include "addisc.h"
  50 
  51 #define MACHINE_SID_LEN         (9 + 3 * 11)
  52 #define FMRI_BASE               "svc:/system/idmap"
  53 #define CONFIG_PG               "config"
  54 #define DEBUG_PG                "debug"
  55 #define RECONFIGURE             1
  56 #define POKE_AUTO_DISCOVERY     2
  57 #define KICK_AUTO_DISCOVERY     3
  58 
  59 /*
  60  * Default cache timeouts.  Can override via svccfg
  61  * config/id_cache_timeout = count: seconds
  62  * config/name_cache_timeout = count: seconds
  63  */
  64 #define ID_CACHE_TMO_DEFAULT    86400
  65 #define NAME_CACHE_TMO_DEFAULT  604800
  66 
  67 /*
  68  * Default maximum time between rediscovery runs.
  69  * config/rediscovery_interval = count: seconds
  70  */
  71 #define REDISCOVERY_INTERVAL_DEFAULT    3600
  72 
  73 /*
  74  * Mininum time between rediscovery runs, in case adutils gives us a
  75  * really short TTL (which it never should, but be defensive)
  76  * (not configurable) seconds.
  77  */
  78 #define MIN_REDISCOVERY_INTERVAL        60
  79 
  80 enum event_type {
  81         EVENT_NOTHING,  /* Woke up for no good reason */
  82         EVENT_TIMEOUT,  /* Timeout expired */
  83         EVENT_ROUTING,  /* An interesting routing event happened */
  84         EVENT_POKED,    /* Requested from degrade_svc() */
  85         EVENT_KICKED,   /* Force rediscovery, i.e. DC failed. */
  86         EVENT_REFRESH,  /* SMF refresh */
  87 };
  88 
  89 
  90 static void idmapd_set_krb5_realm(char *);
  91 
  92 static pthread_t update_thread_handle = 0;
  93 
  94 static int idmapd_ev_port = -1;
  95 static int rt_sock = -1;
  96 
  97 struct enum_lookup_map directory_mapping_map[] = {
  98         { DIRECTORY_MAPPING_NONE, "none" },
  99         { DIRECTORY_MAPPING_NAME, "name" },
 
1584         else if (s == NULL || strcasecmp(s, "none") == 0)
1585                 pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NONE;
1586         else if (strcasecmp(s, "name") == 0)
1587                 pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NAME;
1588         else if (strcasecmp(s, "idmu") == 0)
1589                 pgcfg->directory_based_mapping = DIRECTORY_MAPPING_IDMU;
1590         else {
1591                 pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NONE;
1592                 idmapdlog(LOG_ERR,
1593                 "config/directory_based_mapping:  invalid value \"%s\" ignored",
1594                     s);
1595                 (*errors)++;
1596         }
1597         free(s);
1598 
1599         rc = get_val_int(handles, "list_size_limit",
1600             &pgcfg->list_size_limit, SCF_TYPE_COUNT);
1601         if (rc != 0)
1602                 (*errors)++;
1603 
1604         rc = get_val_int(handles, "id_cache_timeout",
1605             &pgcfg->id_cache_timeout, SCF_TYPE_COUNT);
1606         if (rc != 0)
1607                 (*errors)++;
1608         if (pgcfg->id_cache_timeout == 0)
1609                 pgcfg->id_cache_timeout = ID_CACHE_TMO_DEFAULT;
1610 
1611         rc = get_val_int(handles, "name_cache_timeout",
1612             &pgcfg->name_cache_timeout, SCF_TYPE_COUNT);
1613         if (rc != 0)
1614                 (*errors)++;
1615         if (pgcfg->name_cache_timeout == 0)
1616                 pgcfg->name_cache_timeout = NAME_CACHE_TMO_DEFAULT;
1617 
1618         rc = get_val_int(handles, "rediscovery_interval",
1619             &pgcfg->rediscovery_interval, SCF_TYPE_COUNT);
1620         if (rc != 0)
1621                 (*errors)++;
1622         if (pgcfg->rediscovery_interval == 0)
1623                 pgcfg->rediscovery_interval = REDISCOVERY_INTERVAL_DEFAULT;
1624 
1625         rc = get_val_astring(handles, "domain_name",
1626             &pgcfg->domain_name);
1627         if (rc != 0)
1628                 (*errors)++;
1629         else {
1630                 if (pgcfg->domain_name != NULL &&
1631                     pgcfg->domain_name[0] == '\0') {
1632                         free(pgcfg->domain_name);
1633                         pgcfg->domain_name = NULL;
1634                 }
1635                 (void) ad_disc_set_DomainName(handles->ad_ctx,
1636                     pgcfg->domain_name);
1637                 pgcfg->domain_name_auto_disc = B_FALSE;
1638         }
1639 
1640         rc = get_val_astring(handles, "default_domain",
1641             &pgcfg->default_domain);
1642         if (rc != 0) {
1643                 /*
1644                  * SCF failures fetching config/default_domain we treat
1645                  * as fatal as they may leave ID mapping rules that
1646                  * match unqualified winnames flapping in the wind.
1647                  */
1648                 return (-2);
1649         }
1650 
1651         if (pgcfg->default_domain == NULL && pgcfg->domain_name != NULL) {
1652                 pgcfg->default_domain = strdup(pgcfg->domain_name);
1653         }
1654 
1655         rc = get_val_astring(handles, "domain_guid", &s);
1656         if (rc != 0) {
1657                 (*errors)++;
 
1710         else {
1711                 (void) ad_disc_set_DomainController(handles->ad_ctx,
1712                     pgcfg->domain_controller);
1713                 pgcfg->domain_controller_auto_disc = B_FALSE;
1714         }
1715 
1716         rc = get_val_ds(handles, "preferred_dc", 389,
1717             &pgcfg->preferred_dc);
1718         if (rc != 0)
1719                 (*errors)++;
1720         else {
1721                 (void) ad_disc_set_PreferredDC(handles->ad_ctx,
1722                     pgcfg->preferred_dc);
1723                 pgcfg->preferred_dc_auto_disc = B_FALSE;
1724         }
1725 
1726         rc = get_val_astring(handles, "forest_name", &pgcfg->forest_name);
1727         if (rc != 0)
1728                 (*errors)++;
1729         else {
1730                 (void) ad_disc_set_ForestName(handles->ad_ctx,
1731                     pgcfg->forest_name);
1732                 pgcfg->forest_name_auto_disc = B_FALSE;
1733         }
1734 
1735         rc = get_val_astring(handles, "site_name", &pgcfg->site_name);
1736         if (rc != 0)
1737                 (*errors)++;
1738         else
1739                 (void) ad_disc_set_SiteName(handles->ad_ctx, pgcfg->site_name);
1740 
1741         rc = get_val_ds(handles, "global_catalog", 3268,
1742             &pgcfg->global_catalog);
1743         if (rc != 0)
1744                 (*errors)++;
1745         else {
1746                 (void) ad_disc_set_GlobalCatalog(handles->ad_ctx,
1747                     pgcfg->global_catalog);
1748                 pgcfg->global_catalog_auto_disc = B_FALSE;
1749         }
1750 
1751         /* Unless we're doing directory-based name mapping, we're done. */
1752         if (pgcfg->directory_based_mapping != DIRECTORY_MAPPING_NAME)
1753                 return (0);
1754 
1755         rc = get_val_astring(handles, "ad_unixuser_attr",
1756             &pgcfg->ad_unixuser_attr);
1757         if (rc != 0)
1758                 return (-2);
1759         if (pgcfg->ad_unixuser_attr != NULL &&
 
2181                 (void) mutex_lock(&_idmapdstate.addisc_lk);
2182                 _idmapdstate.addisc_st |= ADDISC_ST_RUNNING;
2183                 (void) mutex_unlock(&_idmapdstate.addisc_lk);
2184 
2185                 idmap_cfg_discover1(&cfg->handles, &new_pgcfg);
2186 
2187                 WRLOCK_CONFIG();
2188                 (void) mutex_lock(&_idmapdstate.addisc_lk);
2189                 _idmapdstate.addisc_st = 0;
2190                 (void) cond_broadcast(&_idmapdstate.addisc_cv);
2191                 (void) mutex_unlock(&_idmapdstate.addisc_lk);
2192         } else {
2193                 WRLOCK_CONFIG();
2194         }
2195 
2196         /* Non-discoverable props updated here */
2197 
2198         changed += update_uint64(&live_pgcfg->list_size_limit,
2199             &new_pgcfg.list_size_limit, "list_size_limit");
2200 
2201         changed += update_uint64(&live_pgcfg->id_cache_timeout,
2202             &new_pgcfg.id_cache_timeout, "id_cache_timeout");
2203 
2204         changed += update_uint64(&live_pgcfg->name_cache_timeout,
2205             &new_pgcfg.name_cache_timeout, "name_cache_timeout");
2206 
2207         changed += update_uint64(&live_pgcfg->rediscovery_interval,
2208             &new_pgcfg.rediscovery_interval, "rediscovery_interval");
2209 
2210         changed += update_string(&live_pgcfg->machine_sid,
2211             &new_pgcfg.machine_sid, "machine_sid");
2212 
2213         changed += update_bool(&live_pgcfg->eph_map_unres_sids,
2214             &new_pgcfg.eph_map_unres_sids, "unresolvable_sid_mapping");
2215 
2216         changed += update_bool(&live_pgcfg->use_ads,
2217             &new_pgcfg.use_ads, "use_ads");
2218 
2219         changed += update_bool(&live_pgcfg->use_lsa,
2220             &new_pgcfg.use_lsa, "use_lsa");
 
 | 
 
 
   3  *
   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  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2019 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 
  26 
  27 /*
  28  * Config routines common to idmap(1M) and idmapd(1M)
  29  */
  30 
  31 #include <stdlib.h>
  32 #include <strings.h>
  33 #include <libintl.h>
  34 #include <ctype.h>
  35 #include <errno.h>
  36 #include <stdio.h>
  37 #include <stdarg.h>
  38 #include <uuid/uuid.h>
  39 #include <pthread.h>
  40 #include <port.h>
  41 #include <sys/socket.h>
  42 #include <net/route.h>
  43 #include <sys/u8_textprep.h>
  44 #include <netinet/in.h>
  45 #include <arpa/inet.h>
  46 #include <netdb.h>
  47 #include <note.h>
  48 #include <limits.h>
  49 #include "idmapd.h"
  50 #include "addisc.h"
  51 
  52 #define MACHINE_SID_LEN         (9 + 3 * 11)
  53 #define FMRI_BASE               "svc:/system/idmap"
  54 #define CONFIG_PG               "config"
  55 #define DEBUG_PG                "debug"
  56 #define RECONFIGURE             1
  57 #define POKE_AUTO_DISCOVERY     2
  58 #define KICK_AUTO_DISCOVERY     3
  59 
  60 /*
  61  * Default cache timeouts.  Can override via svccfg
  62  * config/id_cache_timeout = count: seconds
  63  * config/name_cache_timeout = count: seconds
  64  */
  65 #define ID_CACHE_TMO_DEFAULT    86400
  66 #define NAME_CACHE_TMO_DEFAULT  604800
  67 
  68 /*
  69  * Default maximum time between rediscovery runs.
  70  * config/rediscovery_interval = count: seconds
  71  */
  72 #define REDISCOVERY_INTERVAL_DEFAULT    3600
  73 
  74 /*
  75  * Mininum time between rediscovery runs, in case adutils gives us a
  76  * really short TTL (which it never should, but be defensive)
  77  * (not configurable) seconds.
  78  */
  79 #define MIN_REDISCOVERY_INTERVAL        60
  80 
  81 /*
  82  * Max number of concurrent door calls
  83  */
  84 #define MAX_THREADS_DEFAULT     40
  85 
  86 enum event_type {
  87         EVENT_NOTHING,  /* Woke up for no good reason */
  88         EVENT_TIMEOUT,  /* Timeout expired */
  89         EVENT_ROUTING,  /* An interesting routing event happened */
  90         EVENT_POKED,    /* Requested from degrade_svc() */
  91         EVENT_KICKED,   /* Force rediscovery, i.e. DC failed. */
  92         EVENT_REFRESH,  /* SMF refresh */
  93 };
  94 
  95 
  96 static void idmapd_set_krb5_realm(char *);
  97 
  98 static pthread_t update_thread_handle = 0;
  99 
 100 static int idmapd_ev_port = -1;
 101 static int rt_sock = -1;
 102 
 103 struct enum_lookup_map directory_mapping_map[] = {
 104         { DIRECTORY_MAPPING_NONE, "none" },
 105         { DIRECTORY_MAPPING_NAME, "name" },
 
1590         else if (s == NULL || strcasecmp(s, "none") == 0)
1591                 pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NONE;
1592         else if (strcasecmp(s, "name") == 0)
1593                 pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NAME;
1594         else if (strcasecmp(s, "idmu") == 0)
1595                 pgcfg->directory_based_mapping = DIRECTORY_MAPPING_IDMU;
1596         else {
1597                 pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NONE;
1598                 idmapdlog(LOG_ERR,
1599                 "config/directory_based_mapping:  invalid value \"%s\" ignored",
1600                     s);
1601                 (*errors)++;
1602         }
1603         free(s);
1604 
1605         rc = get_val_int(handles, "list_size_limit",
1606             &pgcfg->list_size_limit, SCF_TYPE_COUNT);
1607         if (rc != 0)
1608                 (*errors)++;
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 
1619         rc = get_val_int(handles, "id_cache_timeout",
1620             &pgcfg->id_cache_timeout, SCF_TYPE_COUNT);
1621         if (rc != 0)
1622                 (*errors)++;
1623         if (pgcfg->id_cache_timeout == 0)
1624                 pgcfg->id_cache_timeout = ID_CACHE_TMO_DEFAULT;
1625 
1626         rc = get_val_int(handles, "name_cache_timeout",
1627             &pgcfg->name_cache_timeout, SCF_TYPE_COUNT);
1628         if (rc != 0)
1629                 (*errors)++;
1630         if (pgcfg->name_cache_timeout == 0)
1631                 pgcfg->name_cache_timeout = NAME_CACHE_TMO_DEFAULT;
1632 
1633         rc = get_val_int(handles, "rediscovery_interval",
1634             &pgcfg->rediscovery_interval, SCF_TYPE_COUNT);
1635         if (rc != 0)
1636                 (*errors)++;
1637         if (pgcfg->rediscovery_interval == 0)
1638                 pgcfg->rediscovery_interval = REDISCOVERY_INTERVAL_DEFAULT;
1639 
1640         rc = get_val_astring(handles, "domain_name",
1641             &pgcfg->domain_name);
1642         if (rc != 0)
1643                 (*errors)++;
1644         else {
1645                 if (pgcfg->domain_name != NULL &&
1646                     pgcfg->domain_name[0] == '\0') {
1647                         free(pgcfg->domain_name);
1648                         pgcfg->domain_name = NULL;
1649                 } else {
1650                         pgcfg->domain_name_auto_disc = B_FALSE;
1651                 }
1652                 (void) ad_disc_set_DomainName(handles->ad_ctx,
1653                     pgcfg->domain_name);
1654         }
1655 
1656         rc = get_val_astring(handles, "default_domain",
1657             &pgcfg->default_domain);
1658         if (rc != 0) {
1659                 /*
1660                  * SCF failures fetching config/default_domain we treat
1661                  * as fatal as they may leave ID mapping rules that
1662                  * match unqualified winnames flapping in the wind.
1663                  */
1664                 return (-2);
1665         }
1666 
1667         if (pgcfg->default_domain == NULL && pgcfg->domain_name != NULL) {
1668                 pgcfg->default_domain = strdup(pgcfg->domain_name);
1669         }
1670 
1671         rc = get_val_astring(handles, "domain_guid", &s);
1672         if (rc != 0) {
1673                 (*errors)++;
 
1726         else {
1727                 (void) ad_disc_set_DomainController(handles->ad_ctx,
1728                     pgcfg->domain_controller);
1729                 pgcfg->domain_controller_auto_disc = B_FALSE;
1730         }
1731 
1732         rc = get_val_ds(handles, "preferred_dc", 389,
1733             &pgcfg->preferred_dc);
1734         if (rc != 0)
1735                 (*errors)++;
1736         else {
1737                 (void) ad_disc_set_PreferredDC(handles->ad_ctx,
1738                     pgcfg->preferred_dc);
1739                 pgcfg->preferred_dc_auto_disc = B_FALSE;
1740         }
1741 
1742         rc = get_val_astring(handles, "forest_name", &pgcfg->forest_name);
1743         if (rc != 0)
1744                 (*errors)++;
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                 }
1753                 (void) ad_disc_set_ForestName(handles->ad_ctx,
1754                     pgcfg->forest_name);
1755         }
1756 
1757         rc = get_val_astring(handles, "site_name", &pgcfg->site_name);
1758         if (rc != 0)
1759                 (*errors)++;
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                 }
1768                 (void) ad_disc_set_SiteName(handles->ad_ctx, pgcfg->site_name);
1769         }
1770 
1771         rc = get_val_ds(handles, "global_catalog", 3268,
1772             &pgcfg->global_catalog);
1773         if (rc != 0)
1774                 (*errors)++;
1775         else {
1776                 (void) ad_disc_set_GlobalCatalog(handles->ad_ctx,
1777                     pgcfg->global_catalog);
1778                 pgcfg->global_catalog_auto_disc = B_FALSE;
1779         }
1780 
1781         /* Unless we're doing directory-based name mapping, we're done. */
1782         if (pgcfg->directory_based_mapping != DIRECTORY_MAPPING_NAME)
1783                 return (0);
1784 
1785         rc = get_val_astring(handles, "ad_unixuser_attr",
1786             &pgcfg->ad_unixuser_attr);
1787         if (rc != 0)
1788                 return (-2);
1789         if (pgcfg->ad_unixuser_attr != NULL &&
 
2211                 (void) mutex_lock(&_idmapdstate.addisc_lk);
2212                 _idmapdstate.addisc_st |= ADDISC_ST_RUNNING;
2213                 (void) mutex_unlock(&_idmapdstate.addisc_lk);
2214 
2215                 idmap_cfg_discover1(&cfg->handles, &new_pgcfg);
2216 
2217                 WRLOCK_CONFIG();
2218                 (void) mutex_lock(&_idmapdstate.addisc_lk);
2219                 _idmapdstate.addisc_st = 0;
2220                 (void) cond_broadcast(&_idmapdstate.addisc_cv);
2221                 (void) mutex_unlock(&_idmapdstate.addisc_lk);
2222         } else {
2223                 WRLOCK_CONFIG();
2224         }
2225 
2226         /* Non-discoverable props updated here */
2227 
2228         changed += update_uint64(&live_pgcfg->list_size_limit,
2229             &new_pgcfg.list_size_limit, "list_size_limit");
2230 
2231         changed += update_uint64(&live_pgcfg->max_threads,
2232             &new_pgcfg.max_threads, "max_threads");
2233 
2234         changed += update_uint64(&live_pgcfg->id_cache_timeout,
2235             &new_pgcfg.id_cache_timeout, "id_cache_timeout");
2236 
2237         changed += update_uint64(&live_pgcfg->name_cache_timeout,
2238             &new_pgcfg.name_cache_timeout, "name_cache_timeout");
2239 
2240         changed += update_uint64(&live_pgcfg->rediscovery_interval,
2241             &new_pgcfg.rediscovery_interval, "rediscovery_interval");
2242 
2243         changed += update_string(&live_pgcfg->machine_sid,
2244             &new_pgcfg.machine_sid, "machine_sid");
2245 
2246         changed += update_bool(&live_pgcfg->eph_map_unres_sids,
2247             &new_pgcfg.eph_map_unres_sids, "unresolvable_sid_mapping");
2248 
2249         changed += update_bool(&live_pgcfg->use_ads,
2250             &new_pgcfg.use_ads, "use_ads");
2251 
2252         changed += update_bool(&live_pgcfg->use_lsa,
2253             &new_pgcfg.use_lsa, "use_lsa");
 
 |