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");
|