18671SJulian.Pullen@Sun.COM /*
28671SJulian.Pullen@Sun.COM * CDDL HEADER START
38671SJulian.Pullen@Sun.COM *
48671SJulian.Pullen@Sun.COM * The contents of this file are subject to the terms of the
58671SJulian.Pullen@Sun.COM * Common Development and Distribution License (the "License").
68671SJulian.Pullen@Sun.COM * You may not use this file except in compliance with the License.
78671SJulian.Pullen@Sun.COM *
88671SJulian.Pullen@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
98671SJulian.Pullen@Sun.COM * or http://www.opensolaris.org/os/licensing.
108671SJulian.Pullen@Sun.COM * See the License for the specific language governing permissions
118671SJulian.Pullen@Sun.COM * and limitations under the License.
128671SJulian.Pullen@Sun.COM *
138671SJulian.Pullen@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
148671SJulian.Pullen@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
158671SJulian.Pullen@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
168671SJulian.Pullen@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
178671SJulian.Pullen@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
188671SJulian.Pullen@Sun.COM *
198671SJulian.Pullen@Sun.COM * CDDL HEADER END
208671SJulian.Pullen@Sun.COM */
218671SJulian.Pullen@Sun.COM
228671SJulian.Pullen@Sun.COM /*
23*12508Samw@Sun.COM * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
248671SJulian.Pullen@Sun.COM */
258671SJulian.Pullen@Sun.COM
268671SJulian.Pullen@Sun.COM /*
278671SJulian.Pullen@Sun.COM * Active Directory Auto-Discovery.
288671SJulian.Pullen@Sun.COM *
298671SJulian.Pullen@Sun.COM * This [project private] API allows the caller to provide whatever
308671SJulian.Pullen@Sun.COM * details it knows a priori (i.e., provided via configuration so as to
318671SJulian.Pullen@Sun.COM * override auto-discovery) and in any order. Then the caller can ask
328671SJulian.Pullen@Sun.COM * for any of the auto-discoverable parameters in any order.
338671SJulian.Pullen@Sun.COM *
348671SJulian.Pullen@Sun.COM * But there is an actual order in which discovery must be done. Given
358671SJulian.Pullen@Sun.COM * the discovery mechanism implemented here, that order is:
368671SJulian.Pullen@Sun.COM *
378671SJulian.Pullen@Sun.COM * - the domain name joined must be discovered first
388671SJulian.Pullen@Sun.COM * - then the domain controllers
398671SJulian.Pullen@Sun.COM * - then the forest name and site name
408671SJulian.Pullen@Sun.COM * - then the global catalog servers, and site-specific domain
418671SJulian.Pullen@Sun.COM * controllers and global catalog servers.
428671SJulian.Pullen@Sun.COM *
438671SJulian.Pullen@Sun.COM * The API does not require it be called in the same order because there
448671SJulian.Pullen@Sun.COM * may be other discovery mechanisms in the future, and exposing
458671SJulian.Pullen@Sun.COM * ordering requirements of the current mechanism now can create trouble
468671SJulian.Pullen@Sun.COM * down the line. Also, this makes the API easier to use now, which
478671SJulian.Pullen@Sun.COM * means less work to do some day when we make this a public API.
488671SJulian.Pullen@Sun.COM *
498671SJulian.Pullen@Sun.COM * Domain discovery is done by res_nsearch() of the DNS SRV RR name for
508671SJulian.Pullen@Sun.COM * domain controllers. As long as the joined domain appears in the DNS
518671SJulian.Pullen@Sun.COM * resolver's search list then we'll find it.
528671SJulian.Pullen@Sun.COM *
538671SJulian.Pullen@Sun.COM * Domain controller discovery is a matter of formatting the DNS SRV RR
548671SJulian.Pullen@Sun.COM * FQDN for domain controllers and doing a lookup for them. Knowledge
558671SJulian.Pullen@Sun.COM * of the domain name is not fundamentally required, but we separate the
568671SJulian.Pullen@Sun.COM * two processes, which in practice can lead to one more DNS lookup than
578671SJulian.Pullen@Sun.COM * is strictly required.
588671SJulian.Pullen@Sun.COM *
598671SJulian.Pullen@Sun.COM * Forest and site name discovery require an LDAP search of the AD
608671SJulian.Pullen@Sun.COM * "configuration partition" at a domain controller for the joined
618671SJulian.Pullen@Sun.COM * domain. Forest and site name discovery depend on knowing the joined
628671SJulian.Pullen@Sun.COM * domain name and domain controllers for that domain.
638671SJulian.Pullen@Sun.COM *
648671SJulian.Pullen@Sun.COM * Global catalog server discovery requires knowledge of the forest
658671SJulian.Pullen@Sun.COM * name in order to format the DNS SRV RR FQDN to lookup. Site-specific
668671SJulian.Pullen@Sun.COM * domain controller discovery depends on knowing the site name (and,
678671SJulian.Pullen@Sun.COM * therefore, joined domain, ...). Site-specific global catalog server
688671SJulian.Pullen@Sun.COM * discovery depends on knowledge of the forest and site names, which
698671SJulian.Pullen@Sun.COM * depend on...
708671SJulian.Pullen@Sun.COM *
718671SJulian.Pullen@Sun.COM * All the work of discovering particular items is done by functions
728671SJulian.Pullen@Sun.COM * named validate_<item>(). Each such function calls validate_<item>()
738671SJulian.Pullen@Sun.COM * for any items that it depends on.
748671SJulian.Pullen@Sun.COM *
758671SJulian.Pullen@Sun.COM * This API is not thread-safe.
768671SJulian.Pullen@Sun.COM */
778671SJulian.Pullen@Sun.COM
788671SJulian.Pullen@Sun.COM
798671SJulian.Pullen@Sun.COM #include <stdio.h>
808671SJulian.Pullen@Sun.COM #include <string.h>
818671SJulian.Pullen@Sun.COM #include <strings.h>
828671SJulian.Pullen@Sun.COM #include <unistd.h>
838671SJulian.Pullen@Sun.COM #include <assert.h>
848671SJulian.Pullen@Sun.COM #include <stdlib.h>
858671SJulian.Pullen@Sun.COM #include <net/if.h>
868671SJulian.Pullen@Sun.COM #include <net/if.h>
878671SJulian.Pullen@Sun.COM #include <sys/types.h>
888671SJulian.Pullen@Sun.COM #include <sys/socket.h>
898671SJulian.Pullen@Sun.COM #include <sys/sockio.h>
908671SJulian.Pullen@Sun.COM #include <netinet/in.h>
918671SJulian.Pullen@Sun.COM #include <netinet/in.h>
928671SJulian.Pullen@Sun.COM #include <arpa/inet.h>
938671SJulian.Pullen@Sun.COM #include <arpa/nameser.h>
948671SJulian.Pullen@Sun.COM #include <resolv.h>
958671SJulian.Pullen@Sun.COM #include <netdb.h>
968671SJulian.Pullen@Sun.COM #include <ctype.h>
978671SJulian.Pullen@Sun.COM #include <errno.h>
988671SJulian.Pullen@Sun.COM #include <ldap.h>
998671SJulian.Pullen@Sun.COM #include <sasl/sasl.h>
1008671SJulian.Pullen@Sun.COM #include <sys/u8_textprep.h>
1018671SJulian.Pullen@Sun.COM #include <syslog.h>
1028671SJulian.Pullen@Sun.COM #include "adutils_impl.h"
1038671SJulian.Pullen@Sun.COM #include "addisc.h"
1048671SJulian.Pullen@Sun.COM
10512065SKeyur.Desai@Sun.COM /*
10612065SKeyur.Desai@Sun.COM * These set some sanity policies for discovery. After a discovery
10712065SKeyur.Desai@Sun.COM * cycle, we will consider the results (successful or unsuccessful)
10812065SKeyur.Desai@Sun.COM * to be valid for at least MINIMUM_TTL seconds, and for at most
10912065SKeyur.Desai@Sun.COM * MAXIMUM_TTL seconds. Note that the caller is free to request
11012065SKeyur.Desai@Sun.COM * discovery cycles sooner than MINIMUM_TTL if it has reason to believe
11112065SKeyur.Desai@Sun.COM * that the situation has changed.
11212065SKeyur.Desai@Sun.COM */
11312065SKeyur.Desai@Sun.COM #define MINIMUM_TTL (5 * 60)
11412065SKeyur.Desai@Sun.COM #define MAXIMUM_TTL (20 * 60)
1158671SJulian.Pullen@Sun.COM
1168671SJulian.Pullen@Sun.COM enum ad_item_state {
1178671SJulian.Pullen@Sun.COM AD_STATE_INVALID = 0, /* The value is not valid */
1188671SJulian.Pullen@Sun.COM AD_STATE_FIXED, /* The value was fixed by caller */
1198671SJulian.Pullen@Sun.COM AD_STATE_AUTO /* The value is auto discovered */
1208671SJulian.Pullen@Sun.COM };
1218671SJulian.Pullen@Sun.COM
1228671SJulian.Pullen@Sun.COM enum ad_data_type {
1238671SJulian.Pullen@Sun.COM AD_STRING = 123,
1248671SJulian.Pullen@Sun.COM AD_DIRECTORY,
1258671SJulian.Pullen@Sun.COM AD_DOMAINS_IN_FOREST,
1268671SJulian.Pullen@Sun.COM AD_TRUSTED_DOMAINS
1278671SJulian.Pullen@Sun.COM };
1288671SJulian.Pullen@Sun.COM
1298671SJulian.Pullen@Sun.COM
1308671SJulian.Pullen@Sun.COM typedef struct ad_subnet {
1318671SJulian.Pullen@Sun.COM char subnet[24];
1328671SJulian.Pullen@Sun.COM } ad_subnet_t;
1338671SJulian.Pullen@Sun.COM
1348671SJulian.Pullen@Sun.COM
1358671SJulian.Pullen@Sun.COM typedef struct ad_item {
1368671SJulian.Pullen@Sun.COM enum ad_item_state state;
1378671SJulian.Pullen@Sun.COM enum ad_data_type type;
1388671SJulian.Pullen@Sun.COM void *value;
13912065SKeyur.Desai@Sun.COM time_t expires;
1408671SJulian.Pullen@Sun.COM unsigned int version; /* Version is only changed */
1418671SJulian.Pullen@Sun.COM /* if the value changes */
1428671SJulian.Pullen@Sun.COM #define PARAM1 0
1438671SJulian.Pullen@Sun.COM #define PARAM2 1
1448671SJulian.Pullen@Sun.COM int param_version[2];
1458671SJulian.Pullen@Sun.COM /* These holds the version of */
1468671SJulian.Pullen@Sun.COM /* dependents so that a dependent */
1478671SJulian.Pullen@Sun.COM /* change can be detected */
1488671SJulian.Pullen@Sun.COM } ad_item_t;
1498671SJulian.Pullen@Sun.COM
1508671SJulian.Pullen@Sun.COM typedef struct ad_disc {
1518671SJulian.Pullen@Sun.COM struct __res_state res_state;
1528671SJulian.Pullen@Sun.COM int res_ninitted;
1538671SJulian.Pullen@Sun.COM ad_subnet_t *subnets;
1548671SJulian.Pullen@Sun.COM boolean_t subnets_changed;
1558671SJulian.Pullen@Sun.COM time_t subnets_last_check;
15612065SKeyur.Desai@Sun.COM time_t expires_not_before;
15712065SKeyur.Desai@Sun.COM time_t expires_not_after;
1588671SJulian.Pullen@Sun.COM ad_item_t domain_name; /* DNS hostname string */
1598671SJulian.Pullen@Sun.COM ad_item_t domain_controller; /* Directory hostname and */
1608671SJulian.Pullen@Sun.COM /* port array */
1618671SJulian.Pullen@Sun.COM ad_item_t site_name; /* String */
1628671SJulian.Pullen@Sun.COM ad_item_t forest_name; /* DNS forestname string */
1638671SJulian.Pullen@Sun.COM ad_item_t global_catalog; /* Directory hostname and */
1648671SJulian.Pullen@Sun.COM /* port array */
1658671SJulian.Pullen@Sun.COM ad_item_t domains_in_forest; /* DNS domainname and SID */
1668671SJulian.Pullen@Sun.COM /* array */
1678671SJulian.Pullen@Sun.COM ad_item_t trusted_domains; /* DNS domainname and trust */
1688671SJulian.Pullen@Sun.COM /* direction array */
1698671SJulian.Pullen@Sun.COM /* Site specfic versions */
1708671SJulian.Pullen@Sun.COM ad_item_t site_domain_controller; /* Directory hostname and */
1718671SJulian.Pullen@Sun.COM /* port array */
1728671SJulian.Pullen@Sun.COM ad_item_t site_global_catalog; /* Directory hostname and */
1738671SJulian.Pullen@Sun.COM /* port array */
174*12508Samw@Sun.COM int debug[AD_DEBUG_MAX+1]; /* Debug levels */
1758671SJulian.Pullen@Sun.COM } ad_disc;
1768671SJulian.Pullen@Sun.COM
1778671SJulian.Pullen@Sun.COM
1788671SJulian.Pullen@Sun.COM #define DNS_MAX_NAME NS_MAXDNAME
1798671SJulian.Pullen@Sun.COM
1808671SJulian.Pullen@Sun.COM
1818671SJulian.Pullen@Sun.COM /* SRV RR names for various queries */
1828671SJulian.Pullen@Sun.COM #define LDAP_SRV_HEAD "_ldap._tcp."
1838671SJulian.Pullen@Sun.COM #define SITE_SRV_MIDDLE "%s._sites."
1848671SJulian.Pullen@Sun.COM #define GC_SRV_TAIL "gc._msdcs"
1858671SJulian.Pullen@Sun.COM #define DC_SRV_TAIL "dc._msdcs"
1868671SJulian.Pullen@Sun.COM #define ALL_GC_SRV_TAIL "_gc._tcp"
1878671SJulian.Pullen@Sun.COM #define PDC_SRV "_ldap._tcp.pdc._msdcs.%s"
1888671SJulian.Pullen@Sun.COM
1898671SJulian.Pullen@Sun.COM /* A RR name for all GCs -- last resort this works */
1908671SJulian.Pullen@Sun.COM #define GC_ALL_A_NAME_FSTR "gc._msdcs.%s."
1918671SJulian.Pullen@Sun.COM
1928671SJulian.Pullen@Sun.COM
1938671SJulian.Pullen@Sun.COM /*
1948671SJulian.Pullen@Sun.COM * We try res_ninit() whenever we don't have one. res_ninit() fails if
1958671SJulian.Pullen@Sun.COM * idmapd is running before the network is up!
1968671SJulian.Pullen@Sun.COM */
1978671SJulian.Pullen@Sun.COM #define DO_RES_NINIT(ctx) if (!(ctx)->res_ninitted) \
1988671SJulian.Pullen@Sun.COM (ctx)->res_ninitted = (res_ninit(&ctx->res_state) != -1)
1998671SJulian.Pullen@Sun.COM
2008671SJulian.Pullen@Sun.COM #define is_fixed(item) \
2018671SJulian.Pullen@Sun.COM ((item)->state == AD_STATE_FIXED)
2028671SJulian.Pullen@Sun.COM
2038671SJulian.Pullen@Sun.COM #define is_changed(item, num, param) \
2048671SJulian.Pullen@Sun.COM ((item)->param_version[num] != (param)->version)
2058671SJulian.Pullen@Sun.COM
2068671SJulian.Pullen@Sun.COM /*
2078671SJulian.Pullen@Sun.COM * Function definitions
2088671SJulian.Pullen@Sun.COM */
2098671SJulian.Pullen@Sun.COM static ad_item_t *
2108671SJulian.Pullen@Sun.COM validate_SiteName(ad_disc_t ctx);
2118671SJulian.Pullen@Sun.COM
2128671SJulian.Pullen@Sun.COM
2138671SJulian.Pullen@Sun.COM
2148671SJulian.Pullen@Sun.COM static void
update_version(ad_item_t * item,int num,ad_item_t * param)2158671SJulian.Pullen@Sun.COM update_version(ad_item_t *item, int num, ad_item_t *param)
2168671SJulian.Pullen@Sun.COM {
2178671SJulian.Pullen@Sun.COM item->param_version[num] = param->version;
2188671SJulian.Pullen@Sun.COM }
2198671SJulian.Pullen@Sun.COM
2208671SJulian.Pullen@Sun.COM
2218671SJulian.Pullen@Sun.COM
2228671SJulian.Pullen@Sun.COM static boolean_t
is_valid(ad_item_t * item)2238671SJulian.Pullen@Sun.COM is_valid(ad_item_t *item)
2248671SJulian.Pullen@Sun.COM {
2258671SJulian.Pullen@Sun.COM if (item->value != NULL) {
2268671SJulian.Pullen@Sun.COM if (item->state == AD_STATE_FIXED)
2278671SJulian.Pullen@Sun.COM return (B_TRUE);
2288671SJulian.Pullen@Sun.COM if (item->state == AD_STATE_AUTO &&
22912065SKeyur.Desai@Sun.COM (item->expires == 0 || item->expires > time(NULL)))
2308671SJulian.Pullen@Sun.COM return (B_TRUE);
2318671SJulian.Pullen@Sun.COM }
2328671SJulian.Pullen@Sun.COM return (B_FALSE);
2338671SJulian.Pullen@Sun.COM }
2348671SJulian.Pullen@Sun.COM
2358671SJulian.Pullen@Sun.COM
2368671SJulian.Pullen@Sun.COM static void
update_item(ad_item_t * item,void * value,enum ad_item_state state,uint32_t ttl)2378671SJulian.Pullen@Sun.COM update_item(ad_item_t *item, void *value, enum ad_item_state state,
2388671SJulian.Pullen@Sun.COM uint32_t ttl)
2398671SJulian.Pullen@Sun.COM {
2408671SJulian.Pullen@Sun.COM if (item->value != NULL && value != NULL) {
2418671SJulian.Pullen@Sun.COM if ((item->type == AD_STRING &&
2428671SJulian.Pullen@Sun.COM strcmp(item->value, value) != 0) ||
2438671SJulian.Pullen@Sun.COM (item->type == AD_DIRECTORY &&
2448671SJulian.Pullen@Sun.COM ad_disc_compare_ds(item->value, value) != 0)||
2458671SJulian.Pullen@Sun.COM (item->type == AD_DOMAINS_IN_FOREST &&
2468671SJulian.Pullen@Sun.COM ad_disc_compare_domainsinforest(item->value, value) != 0) ||
2478671SJulian.Pullen@Sun.COM (item->type == AD_TRUSTED_DOMAINS &&
2488671SJulian.Pullen@Sun.COM ad_disc_compare_trusteddomains(item->value, value) != 0))
2498671SJulian.Pullen@Sun.COM item->version++;
2508671SJulian.Pullen@Sun.COM } else if (item->value != value)
2518671SJulian.Pullen@Sun.COM item->version++;
2528671SJulian.Pullen@Sun.COM
2538671SJulian.Pullen@Sun.COM if (item->value != NULL)
2548671SJulian.Pullen@Sun.COM free(item->value);
2558671SJulian.Pullen@Sun.COM
2568671SJulian.Pullen@Sun.COM item->value = value;
2578671SJulian.Pullen@Sun.COM item->state = state;
2588671SJulian.Pullen@Sun.COM
2598671SJulian.Pullen@Sun.COM if (ttl == 0)
26012065SKeyur.Desai@Sun.COM item->expires = 0;
2618671SJulian.Pullen@Sun.COM else
26212065SKeyur.Desai@Sun.COM item->expires = time(NULL) + ttl;
2638671SJulian.Pullen@Sun.COM }
2648671SJulian.Pullen@Sun.COM
2658671SJulian.Pullen@Sun.COM
2668671SJulian.Pullen@Sun.COM /* Compare DS lists */
2678671SJulian.Pullen@Sun.COM int
ad_disc_compare_ds(idmap_ad_disc_ds_t * ds1,idmap_ad_disc_ds_t * ds2)2688671SJulian.Pullen@Sun.COM ad_disc_compare_ds(idmap_ad_disc_ds_t *ds1, idmap_ad_disc_ds_t *ds2)
2698671SJulian.Pullen@Sun.COM {
2708671SJulian.Pullen@Sun.COM int i, j;
2718671SJulian.Pullen@Sun.COM int num_ds1;
2728671SJulian.Pullen@Sun.COM int num_ds2;
2738671SJulian.Pullen@Sun.COM boolean_t match;
2748671SJulian.Pullen@Sun.COM
2758671SJulian.Pullen@Sun.COM for (i = 0; ds1[i].host[0] != '\0'; i++)
2768671SJulian.Pullen@Sun.COM continue;
2778671SJulian.Pullen@Sun.COM num_ds1 = i;
2788671SJulian.Pullen@Sun.COM for (j = 0; ds2[j].host[0] != '\0'; j++)
2798671SJulian.Pullen@Sun.COM continue;
2808671SJulian.Pullen@Sun.COM num_ds2 = j;
2818671SJulian.Pullen@Sun.COM if (num_ds1 != num_ds2)
2828671SJulian.Pullen@Sun.COM return (1);
2838671SJulian.Pullen@Sun.COM
2848671SJulian.Pullen@Sun.COM for (i = 0; i < num_ds1; i++) {
2858671SJulian.Pullen@Sun.COM match = B_FALSE;
2868671SJulian.Pullen@Sun.COM for (j = 0; j < num_ds2; j++) {
2879744SJordan.Brown@Sun.COM if (strcmp(ds1[i].host, ds2[j].host) == 0 &&
2889744SJordan.Brown@Sun.COM ds1[i].port == ds2[j].port) {
2898671SJulian.Pullen@Sun.COM match = B_TRUE;
2908671SJulian.Pullen@Sun.COM break;
2918671SJulian.Pullen@Sun.COM }
2928671SJulian.Pullen@Sun.COM }
2938671SJulian.Pullen@Sun.COM if (!match)
2948671SJulian.Pullen@Sun.COM return (1);
2958671SJulian.Pullen@Sun.COM }
2968671SJulian.Pullen@Sun.COM return (0);
2978671SJulian.Pullen@Sun.COM }
2988671SJulian.Pullen@Sun.COM
2998671SJulian.Pullen@Sun.COM
3008671SJulian.Pullen@Sun.COM /* Copy a list of DSs */
3018671SJulian.Pullen@Sun.COM static idmap_ad_disc_ds_t *
ds_dup(const idmap_ad_disc_ds_t * srv)3028671SJulian.Pullen@Sun.COM ds_dup(const idmap_ad_disc_ds_t *srv)
3038671SJulian.Pullen@Sun.COM {
3048671SJulian.Pullen@Sun.COM int i;
3058671SJulian.Pullen@Sun.COM int size;
3068671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t *new = NULL;
3078671SJulian.Pullen@Sun.COM
3088671SJulian.Pullen@Sun.COM for (i = 0; srv[i].host[0] != '\0'; i++)
3098671SJulian.Pullen@Sun.COM continue;
3108671SJulian.Pullen@Sun.COM
3118671SJulian.Pullen@Sun.COM size = (i + 1) * sizeof (idmap_ad_disc_ds_t);
3128671SJulian.Pullen@Sun.COM new = malloc(size);
3138671SJulian.Pullen@Sun.COM if (new != NULL)
314*12508Samw@Sun.COM (void) memcpy(new, srv, size);
3158671SJulian.Pullen@Sun.COM return (new);
3168671SJulian.Pullen@Sun.COM }
3178671SJulian.Pullen@Sun.COM
3188671SJulian.Pullen@Sun.COM
3198671SJulian.Pullen@Sun.COM int
ad_disc_compare_trusteddomains(ad_disc_trusteddomains_t * td1,ad_disc_trusteddomains_t * td2)3208671SJulian.Pullen@Sun.COM ad_disc_compare_trusteddomains(ad_disc_trusteddomains_t *td1,
3218671SJulian.Pullen@Sun.COM ad_disc_trusteddomains_t *td2)
3228671SJulian.Pullen@Sun.COM {
3238671SJulian.Pullen@Sun.COM int i, j;
3248671SJulian.Pullen@Sun.COM int num_td1;
3258671SJulian.Pullen@Sun.COM int num_td2;
3268671SJulian.Pullen@Sun.COM boolean_t match;
3278671SJulian.Pullen@Sun.COM
3288671SJulian.Pullen@Sun.COM for (i = 0; td1[i].domain[0] != '\0'; i++)
3298671SJulian.Pullen@Sun.COM continue;
3308671SJulian.Pullen@Sun.COM num_td1 = i;
3318671SJulian.Pullen@Sun.COM
3328671SJulian.Pullen@Sun.COM for (j = 0; td2[j].domain[0] != '\0'; j++)
3338671SJulian.Pullen@Sun.COM continue;
3348671SJulian.Pullen@Sun.COM num_td2 = j;
3358671SJulian.Pullen@Sun.COM
3368671SJulian.Pullen@Sun.COM if (num_td1 != num_td2)
3378671SJulian.Pullen@Sun.COM return (1);
3388671SJulian.Pullen@Sun.COM
3398671SJulian.Pullen@Sun.COM for (i = 0; i < num_td1; i++) {
3408671SJulian.Pullen@Sun.COM match = B_FALSE;
3418671SJulian.Pullen@Sun.COM for (j = 0; j < num_td2; j++) {
34210122SJordan.Brown@Sun.COM if (domain_eq(td1[i].domain, td2[j].domain)) {
3438671SJulian.Pullen@Sun.COM match = B_TRUE;
3448671SJulian.Pullen@Sun.COM break;
3458671SJulian.Pullen@Sun.COM }
3468671SJulian.Pullen@Sun.COM }
3478671SJulian.Pullen@Sun.COM if (!match)
3488671SJulian.Pullen@Sun.COM return (1);
3498671SJulian.Pullen@Sun.COM }
3508671SJulian.Pullen@Sun.COM return (0);
3518671SJulian.Pullen@Sun.COM }
3528671SJulian.Pullen@Sun.COM
3538671SJulian.Pullen@Sun.COM
3548671SJulian.Pullen@Sun.COM
3558671SJulian.Pullen@Sun.COM /* Copy a list of Trusted Domains */
3568671SJulian.Pullen@Sun.COM static ad_disc_trusteddomains_t *
td_dup(const ad_disc_trusteddomains_t * td)3578671SJulian.Pullen@Sun.COM td_dup(const ad_disc_trusteddomains_t *td)
3588671SJulian.Pullen@Sun.COM {
3598671SJulian.Pullen@Sun.COM int i;
3608671SJulian.Pullen@Sun.COM int size;
3618671SJulian.Pullen@Sun.COM ad_disc_trusteddomains_t *new = NULL;
3628671SJulian.Pullen@Sun.COM
3638671SJulian.Pullen@Sun.COM for (i = 0; td[i].domain[0] != '\0'; i++)
3648671SJulian.Pullen@Sun.COM continue;
3658671SJulian.Pullen@Sun.COM
3668671SJulian.Pullen@Sun.COM size = (i + 1) * sizeof (ad_disc_trusteddomains_t);
3678671SJulian.Pullen@Sun.COM new = malloc(size);
3688671SJulian.Pullen@Sun.COM if (new != NULL)
369*12508Samw@Sun.COM (void) memcpy(new, td, size);
3708671SJulian.Pullen@Sun.COM return (new);
3718671SJulian.Pullen@Sun.COM }
3728671SJulian.Pullen@Sun.COM
3738671SJulian.Pullen@Sun.COM
3748671SJulian.Pullen@Sun.COM
3758671SJulian.Pullen@Sun.COM int
ad_disc_compare_domainsinforest(ad_disc_domainsinforest_t * df1,ad_disc_domainsinforest_t * df2)3768671SJulian.Pullen@Sun.COM ad_disc_compare_domainsinforest(ad_disc_domainsinforest_t *df1,
3778671SJulian.Pullen@Sun.COM ad_disc_domainsinforest_t *df2)
3788671SJulian.Pullen@Sun.COM {
3798671SJulian.Pullen@Sun.COM int i, j;
3808671SJulian.Pullen@Sun.COM int num_df1;
3818671SJulian.Pullen@Sun.COM int num_df2;
3828671SJulian.Pullen@Sun.COM boolean_t match;
3838671SJulian.Pullen@Sun.COM
3848671SJulian.Pullen@Sun.COM for (i = 0; df1[i].domain[0] != '\0'; i++)
3858671SJulian.Pullen@Sun.COM continue;
3868671SJulian.Pullen@Sun.COM num_df1 = i;
3878671SJulian.Pullen@Sun.COM
3888671SJulian.Pullen@Sun.COM for (j = 0; df2[j].domain[0] != '\0'; j++)
3898671SJulian.Pullen@Sun.COM continue;
3908671SJulian.Pullen@Sun.COM num_df2 = j;
3918671SJulian.Pullen@Sun.COM
3928671SJulian.Pullen@Sun.COM if (num_df1 != num_df2)
3938671SJulian.Pullen@Sun.COM return (1);
3948671SJulian.Pullen@Sun.COM
3958671SJulian.Pullen@Sun.COM for (i = 0; i < num_df1; i++) {
3968671SJulian.Pullen@Sun.COM match = B_FALSE;
3978671SJulian.Pullen@Sun.COM for (j = 0; j < num_df2; j++) {
39810122SJordan.Brown@Sun.COM if (domain_eq(df1[i].domain, df2[j].domain) &&
3999744SJordan.Brown@Sun.COM strcmp(df1[i].sid, df2[j].sid) == 0) {
4008671SJulian.Pullen@Sun.COM match = B_TRUE;
4018671SJulian.Pullen@Sun.COM break;
4028671SJulian.Pullen@Sun.COM }
4038671SJulian.Pullen@Sun.COM }
4048671SJulian.Pullen@Sun.COM if (!match)
4058671SJulian.Pullen@Sun.COM return (1);
4068671SJulian.Pullen@Sun.COM }
4078671SJulian.Pullen@Sun.COM return (0);
4088671SJulian.Pullen@Sun.COM }
4098671SJulian.Pullen@Sun.COM
4108671SJulian.Pullen@Sun.COM
4118671SJulian.Pullen@Sun.COM
4128671SJulian.Pullen@Sun.COM /* Copy a list of Trusted Domains */
4138671SJulian.Pullen@Sun.COM static ad_disc_domainsinforest_t *
df_dup(const ad_disc_domainsinforest_t * df)4148671SJulian.Pullen@Sun.COM df_dup(const ad_disc_domainsinforest_t *df)
4158671SJulian.Pullen@Sun.COM {
4168671SJulian.Pullen@Sun.COM int i;
4178671SJulian.Pullen@Sun.COM int size;
4188671SJulian.Pullen@Sun.COM ad_disc_domainsinforest_t *new = NULL;
4198671SJulian.Pullen@Sun.COM
4208671SJulian.Pullen@Sun.COM for (i = 0; df[i].domain[0] != '\0'; i++)
4218671SJulian.Pullen@Sun.COM continue;
4228671SJulian.Pullen@Sun.COM
4238671SJulian.Pullen@Sun.COM size = (i + 1) * sizeof (ad_disc_domainsinforest_t);
4248671SJulian.Pullen@Sun.COM new = malloc(size);
4258671SJulian.Pullen@Sun.COM if (new != NULL)
426*12508Samw@Sun.COM (void) memcpy(new, df, size);
4278671SJulian.Pullen@Sun.COM return (new);
4288671SJulian.Pullen@Sun.COM }
4298671SJulian.Pullen@Sun.COM
4308671SJulian.Pullen@Sun.COM
4318671SJulian.Pullen@Sun.COM
4328671SJulian.Pullen@Sun.COM
4338671SJulian.Pullen@Sun.COM
4348671SJulian.Pullen@Sun.COM /*
4358671SJulian.Pullen@Sun.COM * Returns an array of IPv4 address/prefix length
4368671SJulian.Pullen@Sun.COM * The last subnet is NULL
4378671SJulian.Pullen@Sun.COM */
4388671SJulian.Pullen@Sun.COM static ad_subnet_t *
find_subnets()4398671SJulian.Pullen@Sun.COM find_subnets()
4408671SJulian.Pullen@Sun.COM {
4418671SJulian.Pullen@Sun.COM int sock, n, i;
4428671SJulian.Pullen@Sun.COM struct lifconf lifc;
4438671SJulian.Pullen@Sun.COM struct lifreq lifr, *lifrp;
4448671SJulian.Pullen@Sun.COM struct lifnum lifn;
4458671SJulian.Pullen@Sun.COM uint32_t prefix_len;
4468671SJulian.Pullen@Sun.COM char *s;
4478671SJulian.Pullen@Sun.COM ad_subnet_t *results;
4488671SJulian.Pullen@Sun.COM
4498671SJulian.Pullen@Sun.COM lifrp = &lifr;
4508671SJulian.Pullen@Sun.COM
4518671SJulian.Pullen@Sun.COM if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
4528671SJulian.Pullen@Sun.COM logger(LOG_ERR, "Failed to open IPv4 socket for "
4538671SJulian.Pullen@Sun.COM "listing network interfaces (%s)", strerror(errno));
4548671SJulian.Pullen@Sun.COM return (NULL);
4558671SJulian.Pullen@Sun.COM }
4568671SJulian.Pullen@Sun.COM
4578671SJulian.Pullen@Sun.COM lifn.lifn_family = AF_INET;
4588671SJulian.Pullen@Sun.COM lifn.lifn_flags = 0;
4598671SJulian.Pullen@Sun.COM if (ioctl(sock, SIOCGLIFNUM, (char *)&lifn) < 0) {
4608671SJulian.Pullen@Sun.COM logger(LOG_ERR,
4618671SJulian.Pullen@Sun.COM "Failed to find the number of network interfaces (%s)",
4628671SJulian.Pullen@Sun.COM strerror(errno));
463*12508Samw@Sun.COM (void) close(sock);
4648671SJulian.Pullen@Sun.COM return (NULL);
4658671SJulian.Pullen@Sun.COM }
4668671SJulian.Pullen@Sun.COM
4678671SJulian.Pullen@Sun.COM if (lifn.lifn_count < 1) {
4688671SJulian.Pullen@Sun.COM logger(LOG_ERR, "No IPv4 network interfaces found");
469*12508Samw@Sun.COM (void) close(sock);
4708671SJulian.Pullen@Sun.COM return (NULL);
4718671SJulian.Pullen@Sun.COM }
4728671SJulian.Pullen@Sun.COM
4738671SJulian.Pullen@Sun.COM lifc.lifc_family = AF_INET;
4748671SJulian.Pullen@Sun.COM lifc.lifc_flags = 0;
4758671SJulian.Pullen@Sun.COM lifc.lifc_len = lifn.lifn_count * sizeof (struct lifreq);
4768671SJulian.Pullen@Sun.COM lifc.lifc_buf = malloc(lifc.lifc_len);
4778671SJulian.Pullen@Sun.COM
4788671SJulian.Pullen@Sun.COM if (lifc.lifc_buf == NULL) {
4798671SJulian.Pullen@Sun.COM logger(LOG_ERR, "Out of memory");
480*12508Samw@Sun.COM (void) close(sock);
4818671SJulian.Pullen@Sun.COM return (NULL);
4828671SJulian.Pullen@Sun.COM }
4838671SJulian.Pullen@Sun.COM
4848671SJulian.Pullen@Sun.COM if (ioctl(sock, SIOCGLIFCONF, (char *)&lifc) < 0) {
4858671SJulian.Pullen@Sun.COM logger(LOG_ERR, "Failed to list network interfaces (%s)",
4868671SJulian.Pullen@Sun.COM strerror(errno));
4878671SJulian.Pullen@Sun.COM free(lifc.lifc_buf);
488*12508Samw@Sun.COM (void) close(sock);
4898671SJulian.Pullen@Sun.COM return (NULL);
4908671SJulian.Pullen@Sun.COM }
4918671SJulian.Pullen@Sun.COM
4928671SJulian.Pullen@Sun.COM n = lifc.lifc_len / (int)sizeof (struct lifreq);
4938671SJulian.Pullen@Sun.COM
4948671SJulian.Pullen@Sun.COM if ((results = calloc(n + 1, sizeof (ad_subnet_t))) == NULL) {
4958671SJulian.Pullen@Sun.COM free(lifc.lifc_buf);
496*12508Samw@Sun.COM (void) close(sock);
4978671SJulian.Pullen@Sun.COM return (NULL);
4988671SJulian.Pullen@Sun.COM }
4998671SJulian.Pullen@Sun.COM
5008671SJulian.Pullen@Sun.COM for (i = 0, lifrp = lifc.lifc_req; i < n; i++, lifrp++) {
5018671SJulian.Pullen@Sun.COM if (ioctl(sock, SIOCGLIFFLAGS, lifrp) < 0)
5028671SJulian.Pullen@Sun.COM continue;
5038671SJulian.Pullen@Sun.COM
5048671SJulian.Pullen@Sun.COM if ((lifrp->lifr_flags & IFF_UP) == 0)
5058671SJulian.Pullen@Sun.COM continue;
5068671SJulian.Pullen@Sun.COM
5078671SJulian.Pullen@Sun.COM if (ioctl(sock, SIOCGLIFSUBNET, lifrp) < 0)
5088671SJulian.Pullen@Sun.COM continue;
5098671SJulian.Pullen@Sun.COM
5108671SJulian.Pullen@Sun.COM prefix_len = lifrp->lifr_addrlen;
5118671SJulian.Pullen@Sun.COM
5128671SJulian.Pullen@Sun.COM s = inet_ntoa(((struct sockaddr_in *)
5138671SJulian.Pullen@Sun.COM &lifrp->lifr_addr)->sin_addr);
5148671SJulian.Pullen@Sun.COM
5158671SJulian.Pullen@Sun.COM (void) snprintf(results[i].subnet, sizeof (ad_subnet_t),
5168671SJulian.Pullen@Sun.COM "%s/%d", s, prefix_len);
5178671SJulian.Pullen@Sun.COM }
5188671SJulian.Pullen@Sun.COM
5198671SJulian.Pullen@Sun.COM free(lifc.lifc_buf);
520*12508Samw@Sun.COM (void) close(sock);
5218671SJulian.Pullen@Sun.COM
5228671SJulian.Pullen@Sun.COM return (results);
5238671SJulian.Pullen@Sun.COM }
5248671SJulian.Pullen@Sun.COM
5258671SJulian.Pullen@Sun.COM static int
cmpsubnets(ad_subnet_t * subnets1,ad_subnet_t * subnets2)5268671SJulian.Pullen@Sun.COM cmpsubnets(ad_subnet_t *subnets1, ad_subnet_t *subnets2)
5278671SJulian.Pullen@Sun.COM {
5288671SJulian.Pullen@Sun.COM int num_subnets1;
5298671SJulian.Pullen@Sun.COM int num_subnets2;
5308671SJulian.Pullen@Sun.COM boolean_t matched;
5318671SJulian.Pullen@Sun.COM int i, j;
5328671SJulian.Pullen@Sun.COM
5338671SJulian.Pullen@Sun.COM for (i = 0; subnets1[i].subnet[0] != '\0'; i++)
5348671SJulian.Pullen@Sun.COM continue;
5358671SJulian.Pullen@Sun.COM num_subnets1 = i;
5368671SJulian.Pullen@Sun.COM
5378671SJulian.Pullen@Sun.COM for (i = 0; subnets2[i].subnet[0] != '\0'; i++)
5388671SJulian.Pullen@Sun.COM continue;
5398671SJulian.Pullen@Sun.COM num_subnets2 = i;
5408671SJulian.Pullen@Sun.COM
5418671SJulian.Pullen@Sun.COM if (num_subnets1 != num_subnets2)
5428671SJulian.Pullen@Sun.COM return (1);
5438671SJulian.Pullen@Sun.COM
5448671SJulian.Pullen@Sun.COM for (i = 0; i < num_subnets1; i++) {
5458671SJulian.Pullen@Sun.COM matched = B_FALSE;
5468671SJulian.Pullen@Sun.COM for (j = 0; j < num_subnets2; j++) {
5478671SJulian.Pullen@Sun.COM if (strcmp(subnets1[i].subnet,
5488671SJulian.Pullen@Sun.COM subnets2[j].subnet) == 0) {
5498671SJulian.Pullen@Sun.COM matched = B_TRUE;
5508671SJulian.Pullen@Sun.COM break;
5518671SJulian.Pullen@Sun.COM }
5528671SJulian.Pullen@Sun.COM }
5538671SJulian.Pullen@Sun.COM if (!matched)
5548671SJulian.Pullen@Sun.COM return (1);
5558671SJulian.Pullen@Sun.COM }
5568671SJulian.Pullen@Sun.COM return (0);
5578671SJulian.Pullen@Sun.COM }
5588671SJulian.Pullen@Sun.COM
5598671SJulian.Pullen@Sun.COM
5608671SJulian.Pullen@Sun.COM
5618671SJulian.Pullen@Sun.COM
5628671SJulian.Pullen@Sun.COM /* Convert a DN's DC components into a DNS domainname */
5638671SJulian.Pullen@Sun.COM char *
DN_to_DNS(const char * dn_name)5648671SJulian.Pullen@Sun.COM DN_to_DNS(const char *dn_name)
5658671SJulian.Pullen@Sun.COM {
5668671SJulian.Pullen@Sun.COM char dns[DNS_MAX_NAME];
5678671SJulian.Pullen@Sun.COM char *dns_name;
5688671SJulian.Pullen@Sun.COM int i, j;
5698671SJulian.Pullen@Sun.COM int num = 0;
5708671SJulian.Pullen@Sun.COM
5718671SJulian.Pullen@Sun.COM j = 0;
5728671SJulian.Pullen@Sun.COM i = 0;
5738671SJulian.Pullen@Sun.COM
5748671SJulian.Pullen@Sun.COM if (dn_name == NULL)
5758671SJulian.Pullen@Sun.COM return (NULL);
5768671SJulian.Pullen@Sun.COM /*
5778671SJulian.Pullen@Sun.COM * Find all DC=<value> and form DNS name of the
5788671SJulian.Pullen@Sun.COM * form <value1>.<value2>...
5798671SJulian.Pullen@Sun.COM */
5808671SJulian.Pullen@Sun.COM while (dn_name[i] != '\0') {
5818671SJulian.Pullen@Sun.COM if (strncasecmp(&dn_name[i], "DC=", 3) == 0) {
5828671SJulian.Pullen@Sun.COM i += 3;
5838671SJulian.Pullen@Sun.COM if (dn_name[i] != '\0' && num > 0)
5848671SJulian.Pullen@Sun.COM dns[j++] = '.';
5858671SJulian.Pullen@Sun.COM while (dn_name[i] != '\0' &&
5868671SJulian.Pullen@Sun.COM dn_name[i] != ',' && dn_name[i] != '+')
5878671SJulian.Pullen@Sun.COM dns[j++] = dn_name[i++];
5888671SJulian.Pullen@Sun.COM num++;
5898671SJulian.Pullen@Sun.COM } else {
5908671SJulian.Pullen@Sun.COM /* Skip attr=value as it is not DC= */
5918671SJulian.Pullen@Sun.COM while (dn_name[i] != '\0' &&
5928671SJulian.Pullen@Sun.COM dn_name[i] != ',' && dn_name[i] != '+')
5938671SJulian.Pullen@Sun.COM i++;
5948671SJulian.Pullen@Sun.COM }
5958671SJulian.Pullen@Sun.COM /* Skip over separator ',' or '+' */
5968671SJulian.Pullen@Sun.COM if (dn_name[i] != '\0') i++;
5978671SJulian.Pullen@Sun.COM }
5988671SJulian.Pullen@Sun.COM dns[j] = '\0';
5998671SJulian.Pullen@Sun.COM dns_name = malloc(j + 1);
6008671SJulian.Pullen@Sun.COM if (dns_name != NULL)
6018671SJulian.Pullen@Sun.COM (void) strlcpy(dns_name, dns, j + 1);
6028671SJulian.Pullen@Sun.COM return (dns_name);
6038671SJulian.Pullen@Sun.COM }
6048671SJulian.Pullen@Sun.COM
6058671SJulian.Pullen@Sun.COM
6068671SJulian.Pullen@Sun.COM /* Make a list of subnet object DNs from a list of subnets */
6078671SJulian.Pullen@Sun.COM static char **
subnets_to_DNs(ad_subnet_t * subnets,const char * base_dn)6088671SJulian.Pullen@Sun.COM subnets_to_DNs(ad_subnet_t *subnets, const char *base_dn)
6098671SJulian.Pullen@Sun.COM {
6108671SJulian.Pullen@Sun.COM char **results;
6118671SJulian.Pullen@Sun.COM int i, j;
6128671SJulian.Pullen@Sun.COM
6138671SJulian.Pullen@Sun.COM for (i = 0; subnets[i].subnet[0] != '\0'; i++)
6148671SJulian.Pullen@Sun.COM continue;
6158671SJulian.Pullen@Sun.COM
6168671SJulian.Pullen@Sun.COM results = calloc(i + 1, sizeof (char *));
6178671SJulian.Pullen@Sun.COM if (results == NULL)
6188671SJulian.Pullen@Sun.COM return (NULL);
6198671SJulian.Pullen@Sun.COM
6208671SJulian.Pullen@Sun.COM for (i = 0; subnets[i].subnet[0] != '\0'; i++) {
62112065SKeyur.Desai@Sun.COM (void) asprintf(&results[i], "CN=%s,CN=Subnets,CN=Sites,%s",
62212065SKeyur.Desai@Sun.COM subnets[i].subnet, base_dn);
62312065SKeyur.Desai@Sun.COM if (results[i] == NULL) {
6248671SJulian.Pullen@Sun.COM for (j = 0; j < i; j++)
6258671SJulian.Pullen@Sun.COM free(results[j]);
6268671SJulian.Pullen@Sun.COM free(results);
6278671SJulian.Pullen@Sun.COM return (NULL);
6288671SJulian.Pullen@Sun.COM }
6298671SJulian.Pullen@Sun.COM }
6308671SJulian.Pullen@Sun.COM
6318671SJulian.Pullen@Sun.COM return (results);
6328671SJulian.Pullen@Sun.COM }
6338671SJulian.Pullen@Sun.COM
6348671SJulian.Pullen@Sun.COM
6358671SJulian.Pullen@Sun.COM /* Compare SRC RRs; used with qsort() */
6368671SJulian.Pullen@Sun.COM static int
srvcmp(idmap_ad_disc_ds_t * s1,idmap_ad_disc_ds_t * s2)6378671SJulian.Pullen@Sun.COM srvcmp(idmap_ad_disc_ds_t *s1, idmap_ad_disc_ds_t *s2)
6388671SJulian.Pullen@Sun.COM {
6398671SJulian.Pullen@Sun.COM if (s1->priority < s2->priority)
6408671SJulian.Pullen@Sun.COM return (1);
6418671SJulian.Pullen@Sun.COM else if (s1->priority > s2->priority)
6428671SJulian.Pullen@Sun.COM return (-1);
6438671SJulian.Pullen@Sun.COM
6448671SJulian.Pullen@Sun.COM if (s1->weight < s2->weight)
6458671SJulian.Pullen@Sun.COM return (1);
6468671SJulian.Pullen@Sun.COM else if (s1->weight > s2->weight)
6478671SJulian.Pullen@Sun.COM return (-1);
6488671SJulian.Pullen@Sun.COM
6498671SJulian.Pullen@Sun.COM return (0);
6508671SJulian.Pullen@Sun.COM }
6518671SJulian.Pullen@Sun.COM
6528671SJulian.Pullen@Sun.COM
6538671SJulian.Pullen@Sun.COM /*
6548671SJulian.Pullen@Sun.COM * Query or search the SRV RRs for a given name.
6558671SJulian.Pullen@Sun.COM *
6568671SJulian.Pullen@Sun.COM * If name == NULL then search (as in res_nsearch(3RESOLV), honoring any
6578671SJulian.Pullen@Sun.COM * search list/option), else query (as in res_nquery(3RESOLV)).
6588671SJulian.Pullen@Sun.COM *
6598671SJulian.Pullen@Sun.COM * The output TTL will be the one of the SRV RR with the lowest TTL.
6608671SJulian.Pullen@Sun.COM */
6618671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t *
srv_query(res_state state,const char * svc_name,const char * dname,char ** rrname,uint32_t * ttl)6628671SJulian.Pullen@Sun.COM srv_query(res_state state, const char *svc_name, const char *dname,
6638671SJulian.Pullen@Sun.COM char **rrname, uint32_t *ttl)
6648671SJulian.Pullen@Sun.COM {
6658671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t *srv;
66610966SJordan.Brown@Sun.COM idmap_ad_disc_ds_t *srv_res = NULL;
6678671SJulian.Pullen@Sun.COM union {
6688671SJulian.Pullen@Sun.COM HEADER hdr;
6698671SJulian.Pullen@Sun.COM uchar_t buf[NS_MAXMSG];
6708671SJulian.Pullen@Sun.COM } msg;
6718671SJulian.Pullen@Sun.COM int len, cnt, qdcount, ancount;
6728671SJulian.Pullen@Sun.COM uchar_t *ptr, *eom;
6738671SJulian.Pullen@Sun.COM uchar_t *end;
6748671SJulian.Pullen@Sun.COM uint16_t type;
6758671SJulian.Pullen@Sun.COM /* LINTED E_FUNC_SET_NOT_USED */
6768671SJulian.Pullen@Sun.COM uint16_t class;
6778671SJulian.Pullen@Sun.COM uint32_t rttl;
6788671SJulian.Pullen@Sun.COM uint16_t size;
6798671SJulian.Pullen@Sun.COM char namebuf[NS_MAXDNAME];
6808671SJulian.Pullen@Sun.COM
6818671SJulian.Pullen@Sun.COM if (state == NULL)
6828671SJulian.Pullen@Sun.COM return (NULL);
6838671SJulian.Pullen@Sun.COM
6848671SJulian.Pullen@Sun.COM /* Set negative result TTL */
6858671SJulian.Pullen@Sun.COM *ttl = 5 * 60;
6868671SJulian.Pullen@Sun.COM
6878671SJulian.Pullen@Sun.COM /* 1. query necessary resource records */
6888671SJulian.Pullen@Sun.COM
6898671SJulian.Pullen@Sun.COM /* Search, querydomain or query */
6908671SJulian.Pullen@Sun.COM if (rrname != NULL) {
6918671SJulian.Pullen@Sun.COM *rrname = NULL;
692*12508Samw@Sun.COM if (DBG(DNS, 1)) {
693*12508Samw@Sun.COM logger(LOG_DEBUG, "Looking for SRV RRs '%s.*'",
694*12508Samw@Sun.COM svc_name);
695*12508Samw@Sun.COM }
6968671SJulian.Pullen@Sun.COM len = res_nsearch(state, svc_name, C_IN, T_SRV,
6978671SJulian.Pullen@Sun.COM msg.buf, sizeof (msg.buf));
6988671SJulian.Pullen@Sun.COM if (len < 0) {
699*12508Samw@Sun.COM if (DBG(DNS, 0)) {
700*12508Samw@Sun.COM logger(LOG_DEBUG,
701*12508Samw@Sun.COM "DNS search for '%s' failed (%s)",
702*12508Samw@Sun.COM svc_name, hstrerror(state->res_h_errno));
703*12508Samw@Sun.COM }
7048671SJulian.Pullen@Sun.COM return (NULL);
7058671SJulian.Pullen@Sun.COM }
7068671SJulian.Pullen@Sun.COM } else if (dname != NULL) {
707*12508Samw@Sun.COM if (DBG(DNS, 1)) {
708*12508Samw@Sun.COM logger(LOG_DEBUG, "Looking for SRV RRs '%s.%s' ",
709*12508Samw@Sun.COM svc_name, dname);
710*12508Samw@Sun.COM }
7118671SJulian.Pullen@Sun.COM
71210504SKeyur.Desai@Sun.COM len = res_nquerydomain(state, svc_name, dname, C_IN, T_SRV,
71310504SKeyur.Desai@Sun.COM msg.buf, sizeof (msg.buf));
71410504SKeyur.Desai@Sun.COM
7158671SJulian.Pullen@Sun.COM if (len < 0) {
716*12508Samw@Sun.COM if (DBG(DNS, 0)) {
717*12508Samw@Sun.COM logger(LOG_DEBUG, "DNS: %s.%s: %s",
718*12508Samw@Sun.COM svc_name, dname,
719*12508Samw@Sun.COM hstrerror(state->res_h_errno));
720*12508Samw@Sun.COM }
7218671SJulian.Pullen@Sun.COM return (NULL);
7228671SJulian.Pullen@Sun.COM }
7238671SJulian.Pullen@Sun.COM }
7248671SJulian.Pullen@Sun.COM
7258671SJulian.Pullen@Sun.COM if (len > sizeof (msg.buf)) {
726*12508Samw@Sun.COM logger(LOG_ERR,
727*12508Samw@Sun.COM "DNS query %ib message doesn't fit into %ib buffer",
7288671SJulian.Pullen@Sun.COM len, sizeof (msg.buf));
7298671SJulian.Pullen@Sun.COM return (NULL);
7308671SJulian.Pullen@Sun.COM }
7318671SJulian.Pullen@Sun.COM
7328671SJulian.Pullen@Sun.COM /* 2. parse the reply, skip header and question sections */
7338671SJulian.Pullen@Sun.COM
7348671SJulian.Pullen@Sun.COM ptr = msg.buf + sizeof (msg.hdr);
7358671SJulian.Pullen@Sun.COM eom = msg.buf + len;
7368671SJulian.Pullen@Sun.COM qdcount = ntohs(msg.hdr.qdcount);
7378671SJulian.Pullen@Sun.COM ancount = ntohs(msg.hdr.ancount);
7388671SJulian.Pullen@Sun.COM
7398671SJulian.Pullen@Sun.COM for (cnt = qdcount; cnt > 0; --cnt) {
7408671SJulian.Pullen@Sun.COM if ((len = dn_skipname(ptr, eom)) < 0) {
7418671SJulian.Pullen@Sun.COM logger(LOG_ERR, "DNS query invalid message format");
7428671SJulian.Pullen@Sun.COM return (NULL);
7438671SJulian.Pullen@Sun.COM }
7448671SJulian.Pullen@Sun.COM ptr += len + QFIXEDSZ;
7458671SJulian.Pullen@Sun.COM }
7468671SJulian.Pullen@Sun.COM
7478671SJulian.Pullen@Sun.COM /* 3. walk through the answer section */
7488671SJulian.Pullen@Sun.COM
7498671SJulian.Pullen@Sun.COM srv_res = calloc(ancount + 1, sizeof (idmap_ad_disc_ds_t));
75010966SJordan.Brown@Sun.COM if (srv_res == NULL) {
75110966SJordan.Brown@Sun.COM logger(LOG_ERR, "Out of memory");
75210966SJordan.Brown@Sun.COM return (NULL);
75310966SJordan.Brown@Sun.COM }
75410966SJordan.Brown@Sun.COM
7558671SJulian.Pullen@Sun.COM *ttl = (uint32_t)-1;
7568671SJulian.Pullen@Sun.COM
7578671SJulian.Pullen@Sun.COM for (srv = srv_res, cnt = ancount;
7588671SJulian.Pullen@Sun.COM cnt > 0; --cnt, srv++) {
7598671SJulian.Pullen@Sun.COM
7608671SJulian.Pullen@Sun.COM len = dn_expand(msg.buf, eom, ptr, namebuf,
7618671SJulian.Pullen@Sun.COM sizeof (namebuf));
7628671SJulian.Pullen@Sun.COM if (len < 0) {
7638671SJulian.Pullen@Sun.COM logger(LOG_ERR, "DNS query invalid message format");
76410966SJordan.Brown@Sun.COM goto err;
7658671SJulian.Pullen@Sun.COM }
76610966SJordan.Brown@Sun.COM if (rrname != NULL && *rrname == NULL) {
7678671SJulian.Pullen@Sun.COM *rrname = strdup(namebuf);
76810966SJordan.Brown@Sun.COM if (*rrname == NULL) {
76910966SJordan.Brown@Sun.COM logger(LOG_ERR, "Out of memory");
77010966SJordan.Brown@Sun.COM goto err;
77110966SJordan.Brown@Sun.COM }
77210966SJordan.Brown@Sun.COM }
7738671SJulian.Pullen@Sun.COM ptr += len;
7748671SJulian.Pullen@Sun.COM NS_GET16(type, ptr);
7758671SJulian.Pullen@Sun.COM NS_GET16(class, ptr);
7768671SJulian.Pullen@Sun.COM NS_GET32(rttl, ptr);
7778671SJulian.Pullen@Sun.COM NS_GET16(size, ptr);
7788671SJulian.Pullen@Sun.COM if ((end = ptr + size) > eom) {
7798671SJulian.Pullen@Sun.COM logger(LOG_ERR, "DNS query invalid message format");
78010966SJordan.Brown@Sun.COM goto err;
7818671SJulian.Pullen@Sun.COM }
7828671SJulian.Pullen@Sun.COM
7838671SJulian.Pullen@Sun.COM if (type != T_SRV) {
7848671SJulian.Pullen@Sun.COM ptr = end;
7858671SJulian.Pullen@Sun.COM continue;
7868671SJulian.Pullen@Sun.COM }
7878671SJulian.Pullen@Sun.COM
7888671SJulian.Pullen@Sun.COM NS_GET16(srv->priority, ptr);
7898671SJulian.Pullen@Sun.COM NS_GET16(srv->weight, ptr);
7908671SJulian.Pullen@Sun.COM NS_GET16(srv->port, ptr);
7918671SJulian.Pullen@Sun.COM len = dn_expand(msg.buf, eom, ptr, srv->host,
7928671SJulian.Pullen@Sun.COM sizeof (srv->host));
7938671SJulian.Pullen@Sun.COM if (len < 0) {
7948671SJulian.Pullen@Sun.COM logger(LOG_ERR, "DNS query invalid SRV record");
79510966SJordan.Brown@Sun.COM goto err;
7968671SJulian.Pullen@Sun.COM }
7978671SJulian.Pullen@Sun.COM
7988671SJulian.Pullen@Sun.COM if (rttl < *ttl)
7998671SJulian.Pullen@Sun.COM *ttl = rttl;
8008671SJulian.Pullen@Sun.COM
801*12508Samw@Sun.COM if (DBG(DNS, 1)) {
802*12508Samw@Sun.COM logger(LOG_DEBUG, " %s", namebuf);
803*12508Samw@Sun.COM logger(LOG_DEBUG,
804*12508Samw@Sun.COM " ttl=%d pri=%d weight=%d %s:%d",
805*12508Samw@Sun.COM rttl, srv->priority, srv->weight,
806*12508Samw@Sun.COM srv->host, srv->port);
807*12508Samw@Sun.COM }
8088671SJulian.Pullen@Sun.COM
8098671SJulian.Pullen@Sun.COM /* 3. move ptr to the end of current record */
8108671SJulian.Pullen@Sun.COM
8118671SJulian.Pullen@Sun.COM ptr = end;
8128671SJulian.Pullen@Sun.COM }
8138671SJulian.Pullen@Sun.COM
8148671SJulian.Pullen@Sun.COM if (ancount > 1)
8158671SJulian.Pullen@Sun.COM qsort(srv_res, ancount, sizeof (*srv_res),
8168671SJulian.Pullen@Sun.COM (int (*)(const void *, const void *))srvcmp);
8178671SJulian.Pullen@Sun.COM
8188671SJulian.Pullen@Sun.COM return (srv_res);
81910966SJordan.Brown@Sun.COM
82010966SJordan.Brown@Sun.COM err:
82110966SJordan.Brown@Sun.COM free(srv_res);
82210966SJordan.Brown@Sun.COM if (rrname != NULL) {
82310966SJordan.Brown@Sun.COM free(*rrname);
82410966SJordan.Brown@Sun.COM *rrname = NULL;
82510966SJordan.Brown@Sun.COM }
82610966SJordan.Brown@Sun.COM return (NULL);
8278671SJulian.Pullen@Sun.COM }
8288671SJulian.Pullen@Sun.COM
8298671SJulian.Pullen@Sun.COM
8308671SJulian.Pullen@Sun.COM /*
8318671SJulian.Pullen@Sun.COM * A utility function to bind to a Directory server
8328671SJulian.Pullen@Sun.COM */
8338671SJulian.Pullen@Sun.COM
83412065SKeyur.Desai@Sun.COM static
83512065SKeyur.Desai@Sun.COM LDAP *
ldap_lookup_init(idmap_ad_disc_ds_t * ds)8368671SJulian.Pullen@Sun.COM ldap_lookup_init(idmap_ad_disc_ds_t *ds)
8378671SJulian.Pullen@Sun.COM {
8388671SJulian.Pullen@Sun.COM int i;
8398671SJulian.Pullen@Sun.COM int rc, ldversion;
8408671SJulian.Pullen@Sun.COM int zero = 0;
8418671SJulian.Pullen@Sun.COM int timeoutms = 5 * 1000;
8428671SJulian.Pullen@Sun.COM char *saslmech = "GSSAPI";
8438671SJulian.Pullen@Sun.COM uint32_t saslflags = LDAP_SASL_INTERACTIVE;
8448671SJulian.Pullen@Sun.COM LDAP *ld = NULL;
8458671SJulian.Pullen@Sun.COM
8468671SJulian.Pullen@Sun.COM for (i = 0; ds[i].host[0] != '\0'; i++) {
8478671SJulian.Pullen@Sun.COM ld = ldap_init(ds[i].host, ds[i].port);
8488671SJulian.Pullen@Sun.COM if (ld == NULL) {
849*12508Samw@Sun.COM if (DBG(LDAP, 1)) {
850*12508Samw@Sun.COM logger(LOG_DEBUG,
851*12508Samw@Sun.COM "Couldn't connect to AD DC %s:%d (%s)",
852*12508Samw@Sun.COM ds[i].host, ds[i].port,
853*12508Samw@Sun.COM strerror(errno));
854*12508Samw@Sun.COM }
8558671SJulian.Pullen@Sun.COM continue;
8568671SJulian.Pullen@Sun.COM }
8578671SJulian.Pullen@Sun.COM
8588671SJulian.Pullen@Sun.COM ldversion = LDAP_VERSION3;
8598671SJulian.Pullen@Sun.COM (void) ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION,
8608671SJulian.Pullen@Sun.COM &ldversion);
8618671SJulian.Pullen@Sun.COM (void) ldap_set_option(ld, LDAP_OPT_REFERRALS,
8628671SJulian.Pullen@Sun.COM LDAP_OPT_OFF);
8638671SJulian.Pullen@Sun.COM (void) ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &zero);
8648671SJulian.Pullen@Sun.COM (void) ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &zero);
8658671SJulian.Pullen@Sun.COM /* setup TCP/IP connect timeout */
8668671SJulian.Pullen@Sun.COM (void) ldap_set_option(ld, LDAP_X_OPT_CONNECT_TIMEOUT,
8678671SJulian.Pullen@Sun.COM &timeoutms);
8688671SJulian.Pullen@Sun.COM (void) ldap_set_option(ld, LDAP_OPT_RESTART,
8698671SJulian.Pullen@Sun.COM LDAP_OPT_ON);
8708671SJulian.Pullen@Sun.COM
87110706SJulian.Pullen@Sun.COM rc = adutils_set_thread_functions(ld);
87210706SJulian.Pullen@Sun.COM if (rc != LDAP_SUCCESS) {
87310706SJulian.Pullen@Sun.COM /* Error has already been logged */
87410706SJulian.Pullen@Sun.COM (void) ldap_unbind(ld);
87510706SJulian.Pullen@Sun.COM ld = NULL;
87610706SJulian.Pullen@Sun.COM continue;
87710706SJulian.Pullen@Sun.COM }
87810706SJulian.Pullen@Sun.COM
8798671SJulian.Pullen@Sun.COM rc = ldap_sasl_interactive_bind_s(ld, "" /* binddn */,
8808671SJulian.Pullen@Sun.COM saslmech, NULL, NULL, saslflags, &saslcallback,
8818671SJulian.Pullen@Sun.COM NULL /* defaults */);
8828671SJulian.Pullen@Sun.COM if (rc == LDAP_SUCCESS)
8838671SJulian.Pullen@Sun.COM break;
8848671SJulian.Pullen@Sun.COM
885*12508Samw@Sun.COM if (DBG(LDAP, 0)) {
886*12508Samw@Sun.COM logger(LOG_INFO, "LDAP: %s:%d: %s",
887*12508Samw@Sun.COM ds[i].host, ds[i].port, ldap_err2string(rc));
888*12508Samw@Sun.COM ldap_perror(ld, ds[i].host);
889*12508Samw@Sun.COM }
8908671SJulian.Pullen@Sun.COM (void) ldap_unbind(ld);
8918671SJulian.Pullen@Sun.COM ld = NULL;
8928671SJulian.Pullen@Sun.COM }
8938671SJulian.Pullen@Sun.COM return (ld);
8948671SJulian.Pullen@Sun.COM }
8958671SJulian.Pullen@Sun.COM
8968671SJulian.Pullen@Sun.COM
8978671SJulian.Pullen@Sun.COM
8988671SJulian.Pullen@Sun.COM /*
8998671SJulian.Pullen@Sun.COM * A utility function to get the value of some attribute of one of one
9008671SJulian.Pullen@Sun.COM * or more AD LDAP objects named by the dn_list; first found one wins.
9018671SJulian.Pullen@Sun.COM */
9028671SJulian.Pullen@Sun.COM static char *
ldap_lookup_entry_attr(LDAP ** ld,idmap_ad_disc_ds_t * domainControllers,char ** dn_list,char * attr)9038671SJulian.Pullen@Sun.COM ldap_lookup_entry_attr(LDAP **ld, idmap_ad_disc_ds_t *domainControllers,
9048671SJulian.Pullen@Sun.COM char **dn_list, char *attr)
9058671SJulian.Pullen@Sun.COM {
9068671SJulian.Pullen@Sun.COM int i;
9078671SJulian.Pullen@Sun.COM int rc;
9088671SJulian.Pullen@Sun.COM int scope = LDAP_SCOPE_BASE;
9098671SJulian.Pullen@Sun.COM char *attrs[2];
9108671SJulian.Pullen@Sun.COM LDAPMessage *results = NULL;
9118671SJulian.Pullen@Sun.COM LDAPMessage *entry;
9128671SJulian.Pullen@Sun.COM char **values = NULL;
9138671SJulian.Pullen@Sun.COM char *val = NULL;
9148671SJulian.Pullen@Sun.COM
9158671SJulian.Pullen@Sun.COM attrs[0] = attr;
9168671SJulian.Pullen@Sun.COM attrs[1] = NULL;
9178671SJulian.Pullen@Sun.COM
9188671SJulian.Pullen@Sun.COM if (*ld == NULL)
9198671SJulian.Pullen@Sun.COM *ld = ldap_lookup_init(domainControllers);
9208671SJulian.Pullen@Sun.COM
9218671SJulian.Pullen@Sun.COM if (*ld == NULL)
9228671SJulian.Pullen@Sun.COM return (NULL);
9238671SJulian.Pullen@Sun.COM
9248671SJulian.Pullen@Sun.COM for (i = 0; dn_list[i] != NULL; i++) {
9258671SJulian.Pullen@Sun.COM rc = ldap_search_s(*ld, dn_list[i], scope,
9268671SJulian.Pullen@Sun.COM "(objectclass=*)", attrs, 0, &results);
9278671SJulian.Pullen@Sun.COM if (rc == LDAP_SUCCESS) {
9288671SJulian.Pullen@Sun.COM for (entry = ldap_first_entry(*ld, results);
9298671SJulian.Pullen@Sun.COM entry != NULL && values == NULL;
9308671SJulian.Pullen@Sun.COM entry = ldap_next_entry(*ld, entry)) {
9318671SJulian.Pullen@Sun.COM values = ldap_get_values(
9328671SJulian.Pullen@Sun.COM *ld, entry, attr);
9338671SJulian.Pullen@Sun.COM }
9348671SJulian.Pullen@Sun.COM
9358671SJulian.Pullen@Sun.COM if (values != NULL) {
9368671SJulian.Pullen@Sun.COM (void) ldap_msgfree(results);
9378671SJulian.Pullen@Sun.COM val = strdup(values[0]);
9388671SJulian.Pullen@Sun.COM ldap_value_free(values);
9398671SJulian.Pullen@Sun.COM return (val);
9408671SJulian.Pullen@Sun.COM }
9418671SJulian.Pullen@Sun.COM }
9428671SJulian.Pullen@Sun.COM if (results != NULL) {
9438671SJulian.Pullen@Sun.COM (void) ldap_msgfree(results);
9448671SJulian.Pullen@Sun.COM results = NULL;
9458671SJulian.Pullen@Sun.COM }
9468671SJulian.Pullen@Sun.COM }
9478671SJulian.Pullen@Sun.COM
9488671SJulian.Pullen@Sun.COM return (NULL);
9498671SJulian.Pullen@Sun.COM }
9508671SJulian.Pullen@Sun.COM
9518671SJulian.Pullen@Sun.COM
9528671SJulian.Pullen@Sun.COM /*
9538671SJulian.Pullen@Sun.COM * Lookup the trusted domains in the global catalog.
9548671SJulian.Pullen@Sun.COM *
9558671SJulian.Pullen@Sun.COM * Returns:
9568671SJulian.Pullen@Sun.COM * array of trusted domains which is terminated by
9578671SJulian.Pullen@Sun.COM * an empty trusted domain.
9588671SJulian.Pullen@Sun.COM * NULL an error occured
9598671SJulian.Pullen@Sun.COM */
9608671SJulian.Pullen@Sun.COM ad_disc_trusteddomains_t *
ldap_lookup_trusted_domains(LDAP ** ld,idmap_ad_disc_ds_t * globalCatalog,char * base_dn)9618671SJulian.Pullen@Sun.COM ldap_lookup_trusted_domains(LDAP **ld, idmap_ad_disc_ds_t *globalCatalog,
9628671SJulian.Pullen@Sun.COM char *base_dn)
9638671SJulian.Pullen@Sun.COM {
9648671SJulian.Pullen@Sun.COM int scope = LDAP_SCOPE_SUBTREE;
9658671SJulian.Pullen@Sun.COM char *attrs[3];
9668671SJulian.Pullen@Sun.COM int rc;
9678671SJulian.Pullen@Sun.COM LDAPMessage *results = NULL;
9688671SJulian.Pullen@Sun.COM LDAPMessage *entry;
9698671SJulian.Pullen@Sun.COM char *filter;
9708671SJulian.Pullen@Sun.COM char **partner = NULL;
9718671SJulian.Pullen@Sun.COM char **direction = NULL;
9728671SJulian.Pullen@Sun.COM int num = 0;
9738671SJulian.Pullen@Sun.COM ad_disc_trusteddomains_t *trusted_domains = NULL;
9748671SJulian.Pullen@Sun.COM
975*12508Samw@Sun.COM if (DBG(DISC, 1))
976*12508Samw@Sun.COM logger(LOG_DEBUG, "Looking for trusted domains...");
9778671SJulian.Pullen@Sun.COM
9788671SJulian.Pullen@Sun.COM if (*ld == NULL)
9798671SJulian.Pullen@Sun.COM *ld = ldap_lookup_init(globalCatalog);
9808671SJulian.Pullen@Sun.COM
9818671SJulian.Pullen@Sun.COM if (*ld == NULL)
9828671SJulian.Pullen@Sun.COM return (NULL);
9838671SJulian.Pullen@Sun.COM
9848671SJulian.Pullen@Sun.COM attrs[0] = "trustPartner";
9858671SJulian.Pullen@Sun.COM attrs[1] = "trustDirection";
9868671SJulian.Pullen@Sun.COM attrs[2] = NULL;
9878671SJulian.Pullen@Sun.COM
988*12508Samw@Sun.COM /*
989*12508Samw@Sun.COM * Trust direction values:
990*12508Samw@Sun.COM * 1 - inbound (they trust us)
991*12508Samw@Sun.COM * 2 - outbound (we trust them)
992*12508Samw@Sun.COM * 3 - bidirectional (we trust each other)
993*12508Samw@Sun.COM */
9948671SJulian.Pullen@Sun.COM filter = "(&(objectclass=trustedDomain)"
995*12508Samw@Sun.COM "(|(trustDirection=3)(trustDirection=2)))";
9968671SJulian.Pullen@Sun.COM
9978671SJulian.Pullen@Sun.COM rc = ldap_search_s(*ld, base_dn, scope, filter, attrs, 0, &results);
998*12508Samw@Sun.COM if (DBG(DISC, 1))
999*12508Samw@Sun.COM logger(LOG_DEBUG, "Trusted domains:");
10008671SJulian.Pullen@Sun.COM if (rc == LDAP_SUCCESS) {
10018671SJulian.Pullen@Sun.COM for (entry = ldap_first_entry(*ld, results);
10028671SJulian.Pullen@Sun.COM entry != NULL; entry = ldap_next_entry(*ld, entry)) {
10038671SJulian.Pullen@Sun.COM partner = ldap_get_values(*ld, entry, "trustPartner");
10048671SJulian.Pullen@Sun.COM direction = ldap_get_values(
10058671SJulian.Pullen@Sun.COM *ld, entry, "trustDirection");
10068671SJulian.Pullen@Sun.COM
10078671SJulian.Pullen@Sun.COM if (partner != NULL && direction != NULL) {
1008*12508Samw@Sun.COM if (DBG(DISC, 1)) {
1009*12508Samw@Sun.COM logger(LOG_DEBUG, " %s (%s)",
1010*12508Samw@Sun.COM partner[0], direction[0]);
1011*12508Samw@Sun.COM }
10128671SJulian.Pullen@Sun.COM num++;
101312065SKeyur.Desai@Sun.COM void *tmp = realloc(trusted_domains,
10148671SJulian.Pullen@Sun.COM (num + 1) *
10158671SJulian.Pullen@Sun.COM sizeof (ad_disc_trusteddomains_t));
101612065SKeyur.Desai@Sun.COM if (tmp == NULL) {
101712065SKeyur.Desai@Sun.COM free(trusted_domains);
10188671SJulian.Pullen@Sun.COM ldap_value_free(partner);
10198671SJulian.Pullen@Sun.COM ldap_value_free(direction);
1020*12508Samw@Sun.COM (void) ldap_msgfree(results);
10218671SJulian.Pullen@Sun.COM return (NULL);
10228671SJulian.Pullen@Sun.COM }
102312065SKeyur.Desai@Sun.COM trusted_domains = tmp;
10248671SJulian.Pullen@Sun.COM /* Last element should be zero */
1025*12508Samw@Sun.COM (void) memset(&trusted_domains[num], 0,
10268671SJulian.Pullen@Sun.COM sizeof (ad_disc_trusteddomains_t));
1027*12508Samw@Sun.COM (void) strcpy(trusted_domains[num - 1].domain,
10288671SJulian.Pullen@Sun.COM partner[0]);
10298671SJulian.Pullen@Sun.COM trusted_domains[num - 1].direction =
10308671SJulian.Pullen@Sun.COM atoi(direction[0]);
10318671SJulian.Pullen@Sun.COM }
10328671SJulian.Pullen@Sun.COM if (partner != NULL)
10338671SJulian.Pullen@Sun.COM ldap_value_free(partner);
10348671SJulian.Pullen@Sun.COM if (direction != NULL)
10358671SJulian.Pullen@Sun.COM ldap_value_free(direction);
10368671SJulian.Pullen@Sun.COM }
10378671SJulian.Pullen@Sun.COM } else if (rc == LDAP_NO_RESULTS_RETURNED) {
10388671SJulian.Pullen@Sun.COM /* This is not an error - return empty trusted domain */
10398671SJulian.Pullen@Sun.COM trusted_domains = calloc(1, sizeof (ad_disc_trusteddomains_t));
1040*12508Samw@Sun.COM if (DBG(DISC, 1))
1041*12508Samw@Sun.COM logger(LOG_DEBUG, " not found");
10428671SJulian.Pullen@Sun.COM }
10438671SJulian.Pullen@Sun.COM if (results != NULL)
1044*12508Samw@Sun.COM (void) ldap_msgfree(results);
10458671SJulian.Pullen@Sun.COM
10468671SJulian.Pullen@Sun.COM return (trusted_domains);
10478671SJulian.Pullen@Sun.COM }
10488671SJulian.Pullen@Sun.COM
10498671SJulian.Pullen@Sun.COM
10508671SJulian.Pullen@Sun.COM /*
10518671SJulian.Pullen@Sun.COM * This functions finds all the domains in a forest.
10528671SJulian.Pullen@Sun.COM */
10538671SJulian.Pullen@Sun.COM ad_disc_domainsinforest_t *
ldap_lookup_domains_in_forest(LDAP ** ld,idmap_ad_disc_ds_t * globalCatalogs)10548671SJulian.Pullen@Sun.COM ldap_lookup_domains_in_forest(LDAP **ld, idmap_ad_disc_ds_t *globalCatalogs)
10558671SJulian.Pullen@Sun.COM {
10569744SJordan.Brown@Sun.COM static char *attrs[] = {
10579744SJordan.Brown@Sun.COM "objectSid",
10589744SJordan.Brown@Sun.COM NULL,
10599744SJordan.Brown@Sun.COM };
10608671SJulian.Pullen@Sun.COM int rc;
10618671SJulian.Pullen@Sun.COM LDAPMessage *result = NULL;
10628671SJulian.Pullen@Sun.COM LDAPMessage *entry;
10639744SJordan.Brown@Sun.COM int ndomains = 0;
10649744SJordan.Brown@Sun.COM int nresults;
10658671SJulian.Pullen@Sun.COM ad_disc_domainsinforest_t *domains = NULL;
10668671SJulian.Pullen@Sun.COM
1067*12508Samw@Sun.COM if (DBG(DISC, 2))
1068*12508Samw@Sun.COM logger(LOG_DEBUG, "Looking for domains in forest...");
1069*12508Samw@Sun.COM
10708671SJulian.Pullen@Sun.COM if (*ld == NULL)
10718671SJulian.Pullen@Sun.COM *ld = ldap_lookup_init(globalCatalogs);
10728671SJulian.Pullen@Sun.COM
10738671SJulian.Pullen@Sun.COM if (*ld == NULL)
10748671SJulian.Pullen@Sun.COM return (NULL);
10758671SJulian.Pullen@Sun.COM
10769744SJordan.Brown@Sun.COM /* Find domains */
10779744SJordan.Brown@Sun.COM rc = ldap_search_s(*ld, "", LDAP_SCOPE_SUBTREE,
10789744SJordan.Brown@Sun.COM "(objectClass=Domain)", attrs, 0, &result);
1079*12508Samw@Sun.COM if (DBG(DISC, 1))
1080*12508Samw@Sun.COM logger(LOG_DEBUG, "Domains in forest:");
10819744SJordan.Brown@Sun.COM if (rc != LDAP_SUCCESS)
10829744SJordan.Brown@Sun.COM goto err;
10839744SJordan.Brown@Sun.COM
10849744SJordan.Brown@Sun.COM nresults = ldap_count_entries(*ld, result);
10859744SJordan.Brown@Sun.COM domains = calloc(nresults + 1, sizeof (*domains));
10869744SJordan.Brown@Sun.COM if (domains == NULL)
10879744SJordan.Brown@Sun.COM goto err;
10888671SJulian.Pullen@Sun.COM
10899744SJordan.Brown@Sun.COM for (entry = ldap_first_entry(*ld, result);
10909744SJordan.Brown@Sun.COM entry != NULL;
10919744SJordan.Brown@Sun.COM entry = ldap_next_entry(*ld, entry)) {
10929744SJordan.Brown@Sun.COM struct berval **sid_ber;
10939744SJordan.Brown@Sun.COM adutils_sid_t sid;
10949744SJordan.Brown@Sun.COM char *sid_str;
10959744SJordan.Brown@Sun.COM char *name;
109610966SJordan.Brown@Sun.COM char *dn;
10978671SJulian.Pullen@Sun.COM
10989744SJordan.Brown@Sun.COM sid_ber = ldap_get_values_len(*ld, entry,
10999744SJordan.Brown@Sun.COM "objectSid");
11009744SJordan.Brown@Sun.COM if (sid_ber == NULL)
11019744SJordan.Brown@Sun.COM continue;
11029744SJordan.Brown@Sun.COM
11039744SJordan.Brown@Sun.COM rc = adutils_getsid(sid_ber[0], &sid);
11049744SJordan.Brown@Sun.COM ldap_value_free_len(sid_ber);
11059744SJordan.Brown@Sun.COM if (rc < 0)
11069744SJordan.Brown@Sun.COM goto err;
11078671SJulian.Pullen@Sun.COM
11089744SJordan.Brown@Sun.COM if ((sid_str = adutils_sid2txt(&sid)) == NULL)
11099744SJordan.Brown@Sun.COM goto err;
11109744SJordan.Brown@Sun.COM
1111*12508Samw@Sun.COM (void) strcpy(domains[ndomains].sid, sid_str);
11129744SJordan.Brown@Sun.COM free(sid_str);
11139744SJordan.Brown@Sun.COM
111410966SJordan.Brown@Sun.COM dn = ldap_get_dn(*ld, entry);
111510966SJordan.Brown@Sun.COM name = DN_to_DNS(dn);
111610966SJordan.Brown@Sun.COM free(dn);
11179744SJordan.Brown@Sun.COM if (name == NULL)
11189744SJordan.Brown@Sun.COM goto err;
11199744SJordan.Brown@Sun.COM
1120*12508Samw@Sun.COM (void) strcpy(domains[ndomains].domain, name);
11219744SJordan.Brown@Sun.COM free(name);
11229744SJordan.Brown@Sun.COM
1123*12508Samw@Sun.COM if (DBG(DISC, 1))
1124*12508Samw@Sun.COM logger(LOG_DEBUG, " %s", domains[ndomains].domain);
11259744SJordan.Brown@Sun.COM
11269744SJordan.Brown@Sun.COM ndomains++;
11278671SJulian.Pullen@Sun.COM }
11289744SJordan.Brown@Sun.COM
1129*12508Samw@Sun.COM if (ndomains == 0) {
1130*12508Samw@Sun.COM if (DBG(DISC, 1))
1131*12508Samw@Sun.COM logger(LOG_DEBUG, " not found");
11329744SJordan.Brown@Sun.COM goto err;
1133*12508Samw@Sun.COM }
11349744SJordan.Brown@Sun.COM
11359744SJordan.Brown@Sun.COM if (ndomains < nresults) {
11369744SJordan.Brown@Sun.COM ad_disc_domainsinforest_t *tmp;
113710122SJordan.Brown@Sun.COM tmp = realloc(domains, (ndomains + 1) * sizeof (*domains));
11389744SJordan.Brown@Sun.COM if (tmp == NULL)
11399744SJordan.Brown@Sun.COM goto err;
11409744SJordan.Brown@Sun.COM domains = tmp;
11419744SJordan.Brown@Sun.COM }
11429744SJordan.Brown@Sun.COM
11438671SJulian.Pullen@Sun.COM if (result != NULL)
1144*12508Samw@Sun.COM (void) ldap_msgfree(result);
11458671SJulian.Pullen@Sun.COM
11468671SJulian.Pullen@Sun.COM return (domains);
11479744SJordan.Brown@Sun.COM
11489744SJordan.Brown@Sun.COM err:
11499744SJordan.Brown@Sun.COM free(domains);
11509744SJordan.Brown@Sun.COM if (result != NULL)
1151*12508Samw@Sun.COM (void) ldap_msgfree(result);
11529744SJordan.Brown@Sun.COM return (NULL);
11538671SJulian.Pullen@Sun.COM }
11548671SJulian.Pullen@Sun.COM
11558671SJulian.Pullen@Sun.COM
11568671SJulian.Pullen@Sun.COM ad_disc_t
ad_disc_init(void)11578671SJulian.Pullen@Sun.COM ad_disc_init(void)
11588671SJulian.Pullen@Sun.COM {
11598671SJulian.Pullen@Sun.COM struct ad_disc *ctx;
11608671SJulian.Pullen@Sun.COM ctx = calloc(1, sizeof (struct ad_disc));
11618671SJulian.Pullen@Sun.COM if (ctx != NULL)
11628671SJulian.Pullen@Sun.COM DO_RES_NINIT(ctx);
11638671SJulian.Pullen@Sun.COM
11648671SJulian.Pullen@Sun.COM ctx->domain_name.type = AD_STRING;
11658671SJulian.Pullen@Sun.COM ctx->domain_controller.type = AD_DIRECTORY;
11668671SJulian.Pullen@Sun.COM ctx->site_name.type = AD_STRING;
11678671SJulian.Pullen@Sun.COM ctx->forest_name.type = AD_STRING;
11688671SJulian.Pullen@Sun.COM ctx->global_catalog.type = AD_DIRECTORY;
11698671SJulian.Pullen@Sun.COM ctx->domains_in_forest.type = AD_DOMAINS_IN_FOREST;
11708671SJulian.Pullen@Sun.COM ctx->trusted_domains.type = AD_TRUSTED_DOMAINS;
11718671SJulian.Pullen@Sun.COM /* Site specific versions */
11728671SJulian.Pullen@Sun.COM ctx->site_domain_controller.type = AD_DIRECTORY;
11738671SJulian.Pullen@Sun.COM ctx->site_global_catalog.type = AD_DIRECTORY;
11748671SJulian.Pullen@Sun.COM return (ctx);
11758671SJulian.Pullen@Sun.COM }
11768671SJulian.Pullen@Sun.COM
11778671SJulian.Pullen@Sun.COM void
ad_disc_fini(ad_disc_t ctx)11788671SJulian.Pullen@Sun.COM ad_disc_fini(ad_disc_t ctx)
11798671SJulian.Pullen@Sun.COM {
11808671SJulian.Pullen@Sun.COM if (ctx == NULL)
11818671SJulian.Pullen@Sun.COM return;
11828671SJulian.Pullen@Sun.COM
11838671SJulian.Pullen@Sun.COM if (ctx->res_ninitted)
11848671SJulian.Pullen@Sun.COM res_ndestroy(&ctx->res_state);
11858671SJulian.Pullen@Sun.COM
11868671SJulian.Pullen@Sun.COM if (ctx->subnets != NULL)
11878671SJulian.Pullen@Sun.COM free(ctx->subnets);
11888671SJulian.Pullen@Sun.COM
11898671SJulian.Pullen@Sun.COM if (ctx->domain_name.value != NULL)
11908671SJulian.Pullen@Sun.COM free(ctx->domain_name.value);
11918671SJulian.Pullen@Sun.COM
11928671SJulian.Pullen@Sun.COM if (ctx->domain_controller.value != NULL)
11938671SJulian.Pullen@Sun.COM free(ctx->domain_controller.value);
11948671SJulian.Pullen@Sun.COM
11958671SJulian.Pullen@Sun.COM if (ctx->site_name.value != NULL)
11968671SJulian.Pullen@Sun.COM free(ctx->site_name.value);
11978671SJulian.Pullen@Sun.COM
11988671SJulian.Pullen@Sun.COM if (ctx->forest_name.value != NULL)
11998671SJulian.Pullen@Sun.COM free(ctx->forest_name.value);
12008671SJulian.Pullen@Sun.COM
12018671SJulian.Pullen@Sun.COM if (ctx->global_catalog.value != NULL)
12028671SJulian.Pullen@Sun.COM free(ctx->global_catalog.value);
12038671SJulian.Pullen@Sun.COM
12048671SJulian.Pullen@Sun.COM if (ctx->domains_in_forest.value != NULL)
12058671SJulian.Pullen@Sun.COM free(ctx->domains_in_forest.value);
12068671SJulian.Pullen@Sun.COM
12078671SJulian.Pullen@Sun.COM if (ctx->trusted_domains.value != NULL)
12088671SJulian.Pullen@Sun.COM free(ctx->trusted_domains.value);
12098671SJulian.Pullen@Sun.COM
12108671SJulian.Pullen@Sun.COM /* Site specific versions */
12118671SJulian.Pullen@Sun.COM if (ctx->site_domain_controller.value != NULL)
12128671SJulian.Pullen@Sun.COM free(ctx->site_domain_controller.value);
12138671SJulian.Pullen@Sun.COM
12148671SJulian.Pullen@Sun.COM if (ctx->site_global_catalog.value != NULL)
12158671SJulian.Pullen@Sun.COM free(ctx->site_global_catalog.value);
12168671SJulian.Pullen@Sun.COM
12178671SJulian.Pullen@Sun.COM free(ctx);
12188671SJulian.Pullen@Sun.COM }
12198671SJulian.Pullen@Sun.COM
12208671SJulian.Pullen@Sun.COM void
ad_disc_refresh(ad_disc_t ctx)12218671SJulian.Pullen@Sun.COM ad_disc_refresh(ad_disc_t ctx)
12228671SJulian.Pullen@Sun.COM {
12238671SJulian.Pullen@Sun.COM if (ctx->res_ninitted)
12248671SJulian.Pullen@Sun.COM res_ndestroy(&ctx->res_state);
12258671SJulian.Pullen@Sun.COM (void) memset(&ctx->res_state, 0, sizeof (ctx->res_state));
12268671SJulian.Pullen@Sun.COM ctx->res_ninitted = res_ninit(&ctx->res_state) != -1;
12278671SJulian.Pullen@Sun.COM
12288671SJulian.Pullen@Sun.COM if (ctx->domain_name.state == AD_STATE_AUTO)
12298671SJulian.Pullen@Sun.COM ctx->domain_name.state = AD_STATE_INVALID;
12308671SJulian.Pullen@Sun.COM
12318671SJulian.Pullen@Sun.COM if (ctx->domain_controller.state == AD_STATE_AUTO)
12328671SJulian.Pullen@Sun.COM ctx->domain_controller.state = AD_STATE_INVALID;
12338671SJulian.Pullen@Sun.COM
12348671SJulian.Pullen@Sun.COM if (ctx->site_name.state == AD_STATE_AUTO)
12358671SJulian.Pullen@Sun.COM ctx->site_name.state = AD_STATE_INVALID;
12368671SJulian.Pullen@Sun.COM
12378671SJulian.Pullen@Sun.COM if (ctx->forest_name.state == AD_STATE_AUTO)
12388671SJulian.Pullen@Sun.COM ctx->forest_name.state = AD_STATE_INVALID;
12398671SJulian.Pullen@Sun.COM
12408671SJulian.Pullen@Sun.COM if (ctx->global_catalog.state == AD_STATE_AUTO)
12418671SJulian.Pullen@Sun.COM ctx->global_catalog.state = AD_STATE_INVALID;
12428671SJulian.Pullen@Sun.COM
12438671SJulian.Pullen@Sun.COM if (ctx->domains_in_forest.state == AD_STATE_AUTO)
12448671SJulian.Pullen@Sun.COM ctx->domains_in_forest.state = AD_STATE_INVALID;
12458671SJulian.Pullen@Sun.COM
12468671SJulian.Pullen@Sun.COM if (ctx->trusted_domains.state == AD_STATE_AUTO)
12478671SJulian.Pullen@Sun.COM ctx->trusted_domains.state = AD_STATE_INVALID;
12488671SJulian.Pullen@Sun.COM
12498671SJulian.Pullen@Sun.COM if (ctx->site_domain_controller.state == AD_STATE_AUTO)
12508671SJulian.Pullen@Sun.COM ctx->site_domain_controller.state = AD_STATE_INVALID;
12518671SJulian.Pullen@Sun.COM
12528671SJulian.Pullen@Sun.COM if (ctx->site_global_catalog.state == AD_STATE_AUTO)
12538671SJulian.Pullen@Sun.COM ctx->site_global_catalog.state = AD_STATE_INVALID;
12548671SJulian.Pullen@Sun.COM }
12558671SJulian.Pullen@Sun.COM
12568671SJulian.Pullen@Sun.COM
125712065SKeyur.Desai@Sun.COM /*
125812065SKeyur.Desai@Sun.COM * Called when the discovery cycle is done. Sets a master TTL
125912065SKeyur.Desai@Sun.COM * that will avoid doing new time-based discoveries too soon after
126012065SKeyur.Desai@Sun.COM * the last discovery cycle. Most interesting when the discovery
126112065SKeyur.Desai@Sun.COM * cycle failed, because then the TTLs on the individual items will
126212065SKeyur.Desai@Sun.COM * not be updated and may go stale.
126312065SKeyur.Desai@Sun.COM */
126412065SKeyur.Desai@Sun.COM void
ad_disc_done(ad_disc_t ctx)126512065SKeyur.Desai@Sun.COM ad_disc_done(ad_disc_t ctx)
126612065SKeyur.Desai@Sun.COM {
126712065SKeyur.Desai@Sun.COM time_t now = time(NULL);
126812065SKeyur.Desai@Sun.COM
126912065SKeyur.Desai@Sun.COM ctx->expires_not_before = now + MINIMUM_TTL;
127012065SKeyur.Desai@Sun.COM ctx->expires_not_after = now + MAXIMUM_TTL;
127112065SKeyur.Desai@Sun.COM }
127212065SKeyur.Desai@Sun.COM
12738671SJulian.Pullen@Sun.COM
12748671SJulian.Pullen@Sun.COM /* Discover joined Active Directory domainName */
12758671SJulian.Pullen@Sun.COM static ad_item_t *
validate_DomainName(ad_disc_t ctx)12768671SJulian.Pullen@Sun.COM validate_DomainName(ad_disc_t ctx)
12778671SJulian.Pullen@Sun.COM {
12788671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t *domain_controller = NULL;
12798671SJulian.Pullen@Sun.COM char *dname, *srvname;
12808671SJulian.Pullen@Sun.COM uint32_t ttl = 0;
12819744SJordan.Brown@Sun.COM int len;
12828671SJulian.Pullen@Sun.COM
12838671SJulian.Pullen@Sun.COM if (is_valid(&ctx->domain_name))
12848671SJulian.Pullen@Sun.COM return (&ctx->domain_name);
12858671SJulian.Pullen@Sun.COM
12868671SJulian.Pullen@Sun.COM
12878671SJulian.Pullen@Sun.COM /* Try to find our domain by searching for DCs for it */
12888671SJulian.Pullen@Sun.COM DO_RES_NINIT(ctx);
1289*12508Samw@Sun.COM if (DBG(DISC, 2))
1290*12508Samw@Sun.COM logger(LOG_DEBUG, "Looking for our AD domain name...");
1291*12508Samw@Sun.COM domain_controller = srv_query(&ctx->res_state,
1292*12508Samw@Sun.COM LDAP_SRV_HEAD DC_SRV_TAIL,
1293*12508Samw@Sun.COM ctx->domain_name.value, &srvname, &ttl);
12948671SJulian.Pullen@Sun.COM
12958671SJulian.Pullen@Sun.COM /*
12968671SJulian.Pullen@Sun.COM * If we can't find DCs by via res_nsearch() then there's no
12978671SJulian.Pullen@Sun.COM * point in trying anything else to discover the AD domain name.
12988671SJulian.Pullen@Sun.COM */
1299*12508Samw@Sun.COM if (domain_controller == NULL) {
1300*12508Samw@Sun.COM if (DBG(DISC, 1))
1301*12508Samw@Sun.COM logger(LOG_DEBUG, "Can't find our domain name.");
13028671SJulian.Pullen@Sun.COM return (NULL);
1303*12508Samw@Sun.COM }
13048671SJulian.Pullen@Sun.COM
13058671SJulian.Pullen@Sun.COM free(domain_controller);
13068671SJulian.Pullen@Sun.COM /*
13078671SJulian.Pullen@Sun.COM * We have the FQDN of the SRV RR name, so now we extract the
13088671SJulian.Pullen@Sun.COM * domainname suffix from it.
13098671SJulian.Pullen@Sun.COM */
13108671SJulian.Pullen@Sun.COM dname = strdup(srvname + strlen(LDAP_SRV_HEAD DC_SRV_TAIL) +
13118671SJulian.Pullen@Sun.COM 1 /* for the dot between RR name and domainname */);
13128671SJulian.Pullen@Sun.COM
13138671SJulian.Pullen@Sun.COM free(srvname);
13148671SJulian.Pullen@Sun.COM
13158671SJulian.Pullen@Sun.COM if (dname == NULL) {
13168671SJulian.Pullen@Sun.COM logger(LOG_ERR, "Out of memory");
13178671SJulian.Pullen@Sun.COM return (NULL);
13188671SJulian.Pullen@Sun.COM }
13198671SJulian.Pullen@Sun.COM
13208671SJulian.Pullen@Sun.COM /* Eat any trailing dot */
13219744SJordan.Brown@Sun.COM len = strlen(dname);
132210122SJordan.Brown@Sun.COM if (len > 0 && dname[len - 1] == '.')
132310122SJordan.Brown@Sun.COM dname[len - 1] = '\0';
13248671SJulian.Pullen@Sun.COM
1325*12508Samw@Sun.COM if (DBG(DISC, 1))
1326*12508Samw@Sun.COM logger(LOG_DEBUG, "Our domain name: %s", dname);
13278671SJulian.Pullen@Sun.COM update_item(&ctx->domain_name, dname, AD_STATE_AUTO, ttl);
13288671SJulian.Pullen@Sun.COM
13298671SJulian.Pullen@Sun.COM return (&ctx->domain_name);
13308671SJulian.Pullen@Sun.COM }
13318671SJulian.Pullen@Sun.COM
13328671SJulian.Pullen@Sun.COM
13338671SJulian.Pullen@Sun.COM char *
ad_disc_get_DomainName(ad_disc_t ctx,boolean_t * auto_discovered)13348671SJulian.Pullen@Sun.COM ad_disc_get_DomainName(ad_disc_t ctx, boolean_t *auto_discovered)
13358671SJulian.Pullen@Sun.COM {
13368671SJulian.Pullen@Sun.COM char *domain_name = NULL;
13378671SJulian.Pullen@Sun.COM ad_item_t *domain_name_item;
13388671SJulian.Pullen@Sun.COM
13398671SJulian.Pullen@Sun.COM domain_name_item = validate_DomainName(ctx);
13408671SJulian.Pullen@Sun.COM
13418671SJulian.Pullen@Sun.COM if (domain_name_item) {
13428671SJulian.Pullen@Sun.COM domain_name = strdup(domain_name_item->value);
13438671SJulian.Pullen@Sun.COM if (auto_discovered != NULL)
13448671SJulian.Pullen@Sun.COM *auto_discovered =
13458671SJulian.Pullen@Sun.COM (domain_name_item->state == AD_STATE_AUTO);
13468671SJulian.Pullen@Sun.COM } else if (auto_discovered != NULL)
13478671SJulian.Pullen@Sun.COM *auto_discovered = B_FALSE;
13488671SJulian.Pullen@Sun.COM
13498671SJulian.Pullen@Sun.COM return (domain_name);
13508671SJulian.Pullen@Sun.COM }
13518671SJulian.Pullen@Sun.COM
13528671SJulian.Pullen@Sun.COM
13538671SJulian.Pullen@Sun.COM /* Discover domain controllers */
13548671SJulian.Pullen@Sun.COM static ad_item_t *
validate_DomainController(ad_disc_t ctx,enum ad_disc_req req)13558671SJulian.Pullen@Sun.COM validate_DomainController(ad_disc_t ctx, enum ad_disc_req req)
13568671SJulian.Pullen@Sun.COM {
13578671SJulian.Pullen@Sun.COM uint32_t ttl = 0;
13588671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t *domain_controller = NULL;
13598671SJulian.Pullen@Sun.COM boolean_t validate_global = B_FALSE;
13608671SJulian.Pullen@Sun.COM boolean_t validate_site = B_FALSE;
13618671SJulian.Pullen@Sun.COM ad_item_t *domain_name_item;
13628671SJulian.Pullen@Sun.COM ad_item_t *site_name_item = NULL;
13638671SJulian.Pullen@Sun.COM
13648671SJulian.Pullen@Sun.COM /* If the values is fixed there will not be a site specific version */
13658671SJulian.Pullen@Sun.COM if (is_fixed(&ctx->domain_controller))
13668671SJulian.Pullen@Sun.COM return (&ctx->domain_controller);
13678671SJulian.Pullen@Sun.COM
13688671SJulian.Pullen@Sun.COM domain_name_item = validate_DomainName(ctx);
13698671SJulian.Pullen@Sun.COM if (domain_name_item == NULL)
13708671SJulian.Pullen@Sun.COM return (NULL);
13718671SJulian.Pullen@Sun.COM
13728671SJulian.Pullen@Sun.COM if (req == AD_DISC_GLOBAL)
13738671SJulian.Pullen@Sun.COM validate_global = B_TRUE;
13748671SJulian.Pullen@Sun.COM else {
13758671SJulian.Pullen@Sun.COM site_name_item = validate_SiteName(ctx);
13768671SJulian.Pullen@Sun.COM if (site_name_item != NULL)
13778671SJulian.Pullen@Sun.COM validate_site = B_TRUE;
13788671SJulian.Pullen@Sun.COM else if (req == AD_DISC_PREFER_SITE)
13798671SJulian.Pullen@Sun.COM validate_global = B_TRUE;
13808671SJulian.Pullen@Sun.COM }
13818671SJulian.Pullen@Sun.COM
13828671SJulian.Pullen@Sun.COM if (validate_global) {
13838671SJulian.Pullen@Sun.COM if (!is_valid(&ctx->domain_controller) ||
13848671SJulian.Pullen@Sun.COM is_changed(&ctx->domain_controller, PARAM1,
13858671SJulian.Pullen@Sun.COM domain_name_item)) {
1386*12508Samw@Sun.COM if (DBG(DISC, 2)) {
1387*12508Samw@Sun.COM logger(LOG_DEBUG, "Looking for DCs for %s",
1388*12508Samw@Sun.COM domain_name_item->value);
1389*12508Samw@Sun.COM }
13908671SJulian.Pullen@Sun.COM /*
13918671SJulian.Pullen@Sun.COM * Lookup DNS SRV RR named
13928671SJulian.Pullen@Sun.COM * _ldap._tcp.dc._msdcs.<DomainName>
13938671SJulian.Pullen@Sun.COM */
13948671SJulian.Pullen@Sun.COM DO_RES_NINIT(ctx);
13958671SJulian.Pullen@Sun.COM domain_controller = srv_query(&ctx->res_state,
13968671SJulian.Pullen@Sun.COM LDAP_SRV_HEAD DC_SRV_TAIL,
13978671SJulian.Pullen@Sun.COM domain_name_item->value, NULL, &ttl);
13988671SJulian.Pullen@Sun.COM
1399*12508Samw@Sun.COM if (DBG(DISC, 1)) {
1400*12508Samw@Sun.COM logger(LOG_DEBUG, "DCs for %s:",
1401*12508Samw@Sun.COM domain_name_item->value);
1402*12508Samw@Sun.COM }
1403*12508Samw@Sun.COM if (domain_controller == NULL) {
1404*12508Samw@Sun.COM if (DBG(DISC, 1))
1405*12508Samw@Sun.COM logger(LOG_DEBUG, " not found");
14068671SJulian.Pullen@Sun.COM return (NULL);
1407*12508Samw@Sun.COM }
1408*12508Samw@Sun.COM
1409*12508Samw@Sun.COM if (DBG(DISC, 1)) {
1410*12508Samw@Sun.COM int i;
1411*12508Samw@Sun.COM
1412*12508Samw@Sun.COM for (i = 0;
1413*12508Samw@Sun.COM domain_controller[i].host[0] != '\0';
1414*12508Samw@Sun.COM i++) {
1415*12508Samw@Sun.COM logger(LOG_DEBUG, " %s:%d",
1416*12508Samw@Sun.COM domain_controller[i].host,
1417*12508Samw@Sun.COM domain_controller[i].port);
1418*12508Samw@Sun.COM }
1419*12508Samw@Sun.COM }
14208671SJulian.Pullen@Sun.COM
14218671SJulian.Pullen@Sun.COM update_item(&ctx->domain_controller, domain_controller,
14228671SJulian.Pullen@Sun.COM AD_STATE_AUTO, ttl);
14238671SJulian.Pullen@Sun.COM update_version(&ctx->domain_controller, PARAM1,
14248671SJulian.Pullen@Sun.COM domain_name_item);
14258671SJulian.Pullen@Sun.COM }
14268671SJulian.Pullen@Sun.COM return (&ctx->domain_controller);
14278671SJulian.Pullen@Sun.COM }
14288671SJulian.Pullen@Sun.COM
14298671SJulian.Pullen@Sun.COM if (validate_site) {
14308671SJulian.Pullen@Sun.COM if (!is_valid(&ctx->site_domain_controller) ||
14318671SJulian.Pullen@Sun.COM is_changed(&ctx->site_domain_controller, PARAM1,
14328671SJulian.Pullen@Sun.COM domain_name_item) ||
14338671SJulian.Pullen@Sun.COM is_changed(&ctx->site_domain_controller, PARAM2,
14348671SJulian.Pullen@Sun.COM site_name_item)) {
14358671SJulian.Pullen@Sun.COM char rr_name[DNS_MAX_NAME];
1436*12508Samw@Sun.COM if (DBG(DISC, 2)) {
1437*12508Samw@Sun.COM logger(LOG_DEBUG,
1438*12508Samw@Sun.COM "Looking for DCs for %s in %s",
1439*12508Samw@Sun.COM domain_name_item->value,
1440*12508Samw@Sun.COM site_name_item->value);
1441*12508Samw@Sun.COM }
14428671SJulian.Pullen@Sun.COM /*
14438671SJulian.Pullen@Sun.COM * Lookup DNS SRV RR named
14448671SJulian.Pullen@Sun.COM * _ldap._tcp.<SiteName>._sites.dc._msdcs.<DomainName>
14458671SJulian.Pullen@Sun.COM */
14468671SJulian.Pullen@Sun.COM (void) snprintf(rr_name, sizeof (rr_name),
14478671SJulian.Pullen@Sun.COM LDAP_SRV_HEAD SITE_SRV_MIDDLE DC_SRV_TAIL,
14488671SJulian.Pullen@Sun.COM site_name_item->value);
14498671SJulian.Pullen@Sun.COM DO_RES_NINIT(ctx);
14508671SJulian.Pullen@Sun.COM domain_controller = srv_query(&ctx->res_state, rr_name,
14518671SJulian.Pullen@Sun.COM domain_name_item->value, NULL, &ttl);
1452*12508Samw@Sun.COM if (DBG(DISC, 1)) {
1453*12508Samw@Sun.COM logger(LOG_DEBUG,
1454*12508Samw@Sun.COM "DCs for %s in %s",
1455*12508Samw@Sun.COM domain_name_item->value,
1456*12508Samw@Sun.COM site_name_item->value);
1457*12508Samw@Sun.COM }
1458*12508Samw@Sun.COM if (domain_controller == NULL) {
1459*12508Samw@Sun.COM if (DBG(DISC, 1))
1460*12508Samw@Sun.COM logger(LOG_DEBUG, " not found");
14618671SJulian.Pullen@Sun.COM return (NULL);
1462*12508Samw@Sun.COM }
1463*12508Samw@Sun.COM
1464*12508Samw@Sun.COM if (DBG(DISC, 1)) {
1465*12508Samw@Sun.COM int i;
1466*12508Samw@Sun.COM
1467*12508Samw@Sun.COM for (i = 0;
1468*12508Samw@Sun.COM domain_controller[i].host[0] != '\0';
1469*12508Samw@Sun.COM i++) {
1470*12508Samw@Sun.COM logger(LOG_DEBUG, " %s:%d",
1471*12508Samw@Sun.COM domain_controller[i].host,
1472*12508Samw@Sun.COM domain_controller[i].port);
1473*12508Samw@Sun.COM }
1474*12508Samw@Sun.COM }
14758671SJulian.Pullen@Sun.COM
14768671SJulian.Pullen@Sun.COM update_item(&ctx->site_domain_controller,
14778671SJulian.Pullen@Sun.COM domain_controller, AD_STATE_AUTO, ttl);
14788671SJulian.Pullen@Sun.COM update_version(&ctx->site_domain_controller, PARAM1,
14798671SJulian.Pullen@Sun.COM domain_name_item);
14808671SJulian.Pullen@Sun.COM update_version(&ctx->site_domain_controller, PARAM2,
14818671SJulian.Pullen@Sun.COM site_name_item);
14828671SJulian.Pullen@Sun.COM }
14838671SJulian.Pullen@Sun.COM return (&ctx->site_domain_controller);
14848671SJulian.Pullen@Sun.COM }
14858671SJulian.Pullen@Sun.COM return (NULL);
14868671SJulian.Pullen@Sun.COM }
14878671SJulian.Pullen@Sun.COM
14888671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t *
ad_disc_get_DomainController(ad_disc_t ctx,enum ad_disc_req req,boolean_t * auto_discovered)14898671SJulian.Pullen@Sun.COM ad_disc_get_DomainController(ad_disc_t ctx, enum ad_disc_req req,
14908671SJulian.Pullen@Sun.COM boolean_t *auto_discovered)
14918671SJulian.Pullen@Sun.COM {
14928671SJulian.Pullen@Sun.COM ad_item_t *domain_controller_item;
14938671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t *domain_controller = NULL;
14948671SJulian.Pullen@Sun.COM
14958671SJulian.Pullen@Sun.COM domain_controller_item = validate_DomainController(ctx, req);
14968671SJulian.Pullen@Sun.COM
14978671SJulian.Pullen@Sun.COM if (domain_controller_item != NULL) {
14988671SJulian.Pullen@Sun.COM domain_controller = ds_dup(domain_controller_item->value);
14998671SJulian.Pullen@Sun.COM if (auto_discovered != NULL)
15008671SJulian.Pullen@Sun.COM *auto_discovered =
15018671SJulian.Pullen@Sun.COM (domain_controller_item->state == AD_STATE_AUTO);
15028671SJulian.Pullen@Sun.COM } else if (auto_discovered != NULL)
15038671SJulian.Pullen@Sun.COM *auto_discovered = B_FALSE;
15048671SJulian.Pullen@Sun.COM
15058671SJulian.Pullen@Sun.COM return (domain_controller);
15068671SJulian.Pullen@Sun.COM }
15078671SJulian.Pullen@Sun.COM
15088671SJulian.Pullen@Sun.COM
15098671SJulian.Pullen@Sun.COM /* Discover site name (for multi-homed systems the first one found wins) */
15108671SJulian.Pullen@Sun.COM static ad_item_t *
validate_SiteName(ad_disc_t ctx)15118671SJulian.Pullen@Sun.COM validate_SiteName(ad_disc_t ctx)
15128671SJulian.Pullen@Sun.COM {
15138671SJulian.Pullen@Sun.COM LDAP *ld = NULL;
15148671SJulian.Pullen@Sun.COM ad_subnet_t *subnets = NULL;
15158671SJulian.Pullen@Sun.COM char **dn_subnets = NULL;
15168671SJulian.Pullen@Sun.COM char *dn_root[2];
15178671SJulian.Pullen@Sun.COM char *config_naming_context = NULL;
15188671SJulian.Pullen@Sun.COM char *site_object = NULL;
15198671SJulian.Pullen@Sun.COM char *site_name = NULL;
15208671SJulian.Pullen@Sun.COM char *forest_name;
15218671SJulian.Pullen@Sun.COM int len;
15228671SJulian.Pullen@Sun.COM boolean_t update_required = B_FALSE;
15238671SJulian.Pullen@Sun.COM ad_item_t *domain_controller_item;
15248671SJulian.Pullen@Sun.COM
15258671SJulian.Pullen@Sun.COM if (is_fixed(&ctx->site_name))
15268671SJulian.Pullen@Sun.COM return (&ctx->site_name);
15278671SJulian.Pullen@Sun.COM
15288671SJulian.Pullen@Sun.COM /* Can't rely on site-specific DCs */
15298671SJulian.Pullen@Sun.COM domain_controller_item = validate_DomainController(ctx, AD_DISC_GLOBAL);
15308671SJulian.Pullen@Sun.COM if (domain_controller_item == NULL)
15318671SJulian.Pullen@Sun.COM return (NULL);
15328671SJulian.Pullen@Sun.COM
15338671SJulian.Pullen@Sun.COM if (!is_valid(&ctx->site_name) ||
153412065SKeyur.Desai@Sun.COM is_changed(&ctx->site_name, PARAM1, domain_controller_item) ||
15358671SJulian.Pullen@Sun.COM ctx->subnets == NULL || ctx->subnets_changed) {
15368671SJulian.Pullen@Sun.COM subnets = find_subnets();
15378671SJulian.Pullen@Sun.COM ctx->subnets_last_check = time(NULL);
15388671SJulian.Pullen@Sun.COM update_required = B_TRUE;
15398671SJulian.Pullen@Sun.COM } else if (ctx->subnets_last_check + 60 < time(NULL)) {
154012065SKeyur.Desai@Sun.COM /* NEEDSWORK magic constant 60 above */
15418671SJulian.Pullen@Sun.COM subnets = find_subnets();
15428671SJulian.Pullen@Sun.COM ctx->subnets_last_check = time(NULL);
15438671SJulian.Pullen@Sun.COM if (cmpsubnets(ctx->subnets, subnets) != 0)
15448671SJulian.Pullen@Sun.COM update_required = B_TRUE;
15458671SJulian.Pullen@Sun.COM }
15468671SJulian.Pullen@Sun.COM
15478671SJulian.Pullen@Sun.COM if (!update_required) {
15488671SJulian.Pullen@Sun.COM free(subnets);
15498671SJulian.Pullen@Sun.COM return (&ctx->site_name);
15508671SJulian.Pullen@Sun.COM }
15518671SJulian.Pullen@Sun.COM
15528671SJulian.Pullen@Sun.COM if (subnets == NULL)
15538671SJulian.Pullen@Sun.COM return (NULL);
15548671SJulian.Pullen@Sun.COM
15558671SJulian.Pullen@Sun.COM dn_root[0] = "";
15568671SJulian.Pullen@Sun.COM dn_root[1] = NULL;
15578671SJulian.Pullen@Sun.COM
1558*12508Samw@Sun.COM if (DBG(DISC, 1))
1559*12508Samw@Sun.COM logger(LOG_DEBUG, "Getting site name");
1560*12508Samw@Sun.COM
15618671SJulian.Pullen@Sun.COM config_naming_context = ldap_lookup_entry_attr(
15628671SJulian.Pullen@Sun.COM &ld, ctx->domain_controller.value,
15638671SJulian.Pullen@Sun.COM dn_root, "configurationNamingContext");
15648671SJulian.Pullen@Sun.COM if (config_naming_context == NULL)
15658671SJulian.Pullen@Sun.COM goto out;
15668671SJulian.Pullen@Sun.COM /*
15678671SJulian.Pullen@Sun.COM * configurationNamingContext also provides the Forest
15688671SJulian.Pullen@Sun.COM * Name.
15698671SJulian.Pullen@Sun.COM */
15708671SJulian.Pullen@Sun.COM if (!is_fixed(&ctx->forest_name)) {
15718671SJulian.Pullen@Sun.COM /*
15728671SJulian.Pullen@Sun.COM * The configurationNamingContext should be of
15738671SJulian.Pullen@Sun.COM * form:
15748671SJulian.Pullen@Sun.COM * CN=Configuration,<DNforestName>
15758671SJulian.Pullen@Sun.COM * Remove the first part and convert to DNS form
15768671SJulian.Pullen@Sun.COM * (replace ",DC=" with ".")
15778671SJulian.Pullen@Sun.COM */
15788671SJulian.Pullen@Sun.COM char *str = "CN=Configuration,";
15798671SJulian.Pullen@Sun.COM int len = strlen(str);
15808671SJulian.Pullen@Sun.COM if (strncasecmp(config_naming_context, str, len) == 0) {
15818671SJulian.Pullen@Sun.COM forest_name = DN_to_DNS(config_naming_context + len);
1582*12508Samw@Sun.COM if (DBG(DISC, 1)) {
1583*12508Samw@Sun.COM logger(LOG_DEBUG, " forest: %s",
1584*12508Samw@Sun.COM forest_name);
1585*12508Samw@Sun.COM }
15868671SJulian.Pullen@Sun.COM update_item(&ctx->forest_name, forest_name,
15878671SJulian.Pullen@Sun.COM AD_STATE_AUTO, 0);
158812065SKeyur.Desai@Sun.COM update_version(&ctx->forest_name, PARAM1,
158912065SKeyur.Desai@Sun.COM domain_controller_item);
15908671SJulian.Pullen@Sun.COM }
15918671SJulian.Pullen@Sun.COM }
15928671SJulian.Pullen@Sun.COM
1593*12508Samw@Sun.COM if (DBG(DISC, 2))
1594*12508Samw@Sun.COM logger(LOG_DEBUG, " CNC: %s", config_naming_context);
1595*12508Samw@Sun.COM
1596*12508Samw@Sun.COM if (DBG(DISC, 2)) {
1597*12508Samw@Sun.COM int i;
1598*12508Samw@Sun.COM logger(LOG_DEBUG, " Looking for sites for subnets:");
1599*12508Samw@Sun.COM for (i = 0; subnets[i].subnet[0] != '\0'; i++) {
1600*12508Samw@Sun.COM logger(LOG_DEBUG, " %s", subnets[i].subnet);
1601*12508Samw@Sun.COM }
1602*12508Samw@Sun.COM }
1603*12508Samw@Sun.COM
16048671SJulian.Pullen@Sun.COM dn_subnets = subnets_to_DNs(subnets, config_naming_context);
16058671SJulian.Pullen@Sun.COM if (dn_subnets == NULL)
16068671SJulian.Pullen@Sun.COM goto out;
16078671SJulian.Pullen@Sun.COM
16088671SJulian.Pullen@Sun.COM site_object = ldap_lookup_entry_attr(
16098671SJulian.Pullen@Sun.COM &ld, domain_controller_item->value,
16108671SJulian.Pullen@Sun.COM dn_subnets, "siteobject");
16118671SJulian.Pullen@Sun.COM if (site_object != NULL) {
16128671SJulian.Pullen@Sun.COM /*
16138671SJulian.Pullen@Sun.COM * The site object should be of the form
16148671SJulian.Pullen@Sun.COM * CN=<site>,CN=Sites,CN=Configuration,
16158671SJulian.Pullen@Sun.COM * <DN Domain>
16168671SJulian.Pullen@Sun.COM */
1617*12508Samw@Sun.COM if (DBG(DISC, 2))
1618*12508Samw@Sun.COM logger(LOG_DEBUG, " Site object: %s", site_object);
16198671SJulian.Pullen@Sun.COM if (strncasecmp(site_object, "CN=", 3) == 0) {
16208671SJulian.Pullen@Sun.COM for (len = 0; site_object[len + 3] != ','; len++)
16218671SJulian.Pullen@Sun.COM ;
16228671SJulian.Pullen@Sun.COM site_name = malloc(len + 1);
16238671SJulian.Pullen@Sun.COM (void) strncpy(site_name, &site_object[3], len);
16248671SJulian.Pullen@Sun.COM site_name[len] = '\0';
1625*12508Samw@Sun.COM if (DBG(DISC, 1)) {
1626*12508Samw@Sun.COM logger(LOG_DEBUG, " Site name \"%s\"",
1627*12508Samw@Sun.COM site_name);
1628*12508Samw@Sun.COM }
16298671SJulian.Pullen@Sun.COM update_item(&ctx->site_name, site_name,
16308671SJulian.Pullen@Sun.COM AD_STATE_AUTO, 0);
163112065SKeyur.Desai@Sun.COM update_version(&ctx->site_name, PARAM1,
163212065SKeyur.Desai@Sun.COM domain_controller_item);
16338671SJulian.Pullen@Sun.COM }
16348671SJulian.Pullen@Sun.COM }
16358671SJulian.Pullen@Sun.COM
16368671SJulian.Pullen@Sun.COM if (ctx->subnets != NULL) {
16378671SJulian.Pullen@Sun.COM free(ctx->subnets);
16388671SJulian.Pullen@Sun.COM ctx->subnets = NULL;
16398671SJulian.Pullen@Sun.COM }
16408671SJulian.Pullen@Sun.COM ctx->subnets = subnets;
16418671SJulian.Pullen@Sun.COM subnets = NULL;
16428671SJulian.Pullen@Sun.COM ctx->subnets_changed = B_FALSE;
16438671SJulian.Pullen@Sun.COM
16448671SJulian.Pullen@Sun.COM out:
16458671SJulian.Pullen@Sun.COM if (ld != NULL)
16468671SJulian.Pullen@Sun.COM (void) ldap_unbind(ld);
16478671SJulian.Pullen@Sun.COM
16488671SJulian.Pullen@Sun.COM if (dn_subnets != NULL) {
1649*12508Samw@Sun.COM int i;
16508671SJulian.Pullen@Sun.COM for (i = 0; dn_subnets[i] != NULL; i++)
16518671SJulian.Pullen@Sun.COM free(dn_subnets[i]);
16528671SJulian.Pullen@Sun.COM free(dn_subnets);
16538671SJulian.Pullen@Sun.COM }
16548671SJulian.Pullen@Sun.COM if (config_naming_context != NULL)
16558671SJulian.Pullen@Sun.COM free(config_naming_context);
16568671SJulian.Pullen@Sun.COM if (site_object != NULL)
16578671SJulian.Pullen@Sun.COM free(site_object);
16588671SJulian.Pullen@Sun.COM
16598671SJulian.Pullen@Sun.COM free(subnets);
16608671SJulian.Pullen@Sun.COM if (site_name == NULL)
16618671SJulian.Pullen@Sun.COM return (NULL);
16628671SJulian.Pullen@Sun.COM return (&ctx->site_name);
16638671SJulian.Pullen@Sun.COM
16648671SJulian.Pullen@Sun.COM }
16658671SJulian.Pullen@Sun.COM
16668671SJulian.Pullen@Sun.COM
16678671SJulian.Pullen@Sun.COM char *
ad_disc_get_SiteName(ad_disc_t ctx,boolean_t * auto_discovered)16688671SJulian.Pullen@Sun.COM ad_disc_get_SiteName(ad_disc_t ctx, boolean_t *auto_discovered)
16698671SJulian.Pullen@Sun.COM {
16708671SJulian.Pullen@Sun.COM ad_item_t *site_name_item;
16718671SJulian.Pullen@Sun.COM char *site_name = NULL;
16728671SJulian.Pullen@Sun.COM
16738671SJulian.Pullen@Sun.COM site_name_item = validate_SiteName(ctx);
16748671SJulian.Pullen@Sun.COM if (site_name_item != NULL) {
16758671SJulian.Pullen@Sun.COM site_name = strdup(site_name_item->value);
16768671SJulian.Pullen@Sun.COM if (auto_discovered != NULL)
16778671SJulian.Pullen@Sun.COM *auto_discovered =
16788671SJulian.Pullen@Sun.COM (site_name_item->state == AD_STATE_AUTO);
16798671SJulian.Pullen@Sun.COM } else if (auto_discovered != NULL)
16808671SJulian.Pullen@Sun.COM *auto_discovered = B_FALSE;
16818671SJulian.Pullen@Sun.COM
16828671SJulian.Pullen@Sun.COM return (site_name);
16838671SJulian.Pullen@Sun.COM }
16848671SJulian.Pullen@Sun.COM
16858671SJulian.Pullen@Sun.COM
16868671SJulian.Pullen@Sun.COM
16878671SJulian.Pullen@Sun.COM /* Discover forest name */
16888671SJulian.Pullen@Sun.COM static ad_item_t *
validate_ForestName(ad_disc_t ctx)16898671SJulian.Pullen@Sun.COM validate_ForestName(ad_disc_t ctx)
16908671SJulian.Pullen@Sun.COM {
16918671SJulian.Pullen@Sun.COM LDAP *ld = NULL;
16928671SJulian.Pullen@Sun.COM char *config_naming_context;
16938671SJulian.Pullen@Sun.COM char *forest_name = NULL;
16948671SJulian.Pullen@Sun.COM char *dn_list[2];
16958671SJulian.Pullen@Sun.COM ad_item_t *domain_controller_item;
16968671SJulian.Pullen@Sun.COM
16978671SJulian.Pullen@Sun.COM if (is_fixed(&ctx->forest_name))
16988671SJulian.Pullen@Sun.COM return (&ctx->forest_name);
16998671SJulian.Pullen@Sun.COM /*
17008671SJulian.Pullen@Sun.COM * We may not have a site name yet, so we won't rely on
17018671SJulian.Pullen@Sun.COM * site-specific DCs. (But maybe we could replace
17028671SJulian.Pullen@Sun.COM * validate_ForestName() with validate_siteName()?)
17038671SJulian.Pullen@Sun.COM */
17048671SJulian.Pullen@Sun.COM domain_controller_item = validate_DomainController(ctx, AD_DISC_GLOBAL);
17058671SJulian.Pullen@Sun.COM if (domain_controller_item == NULL)
17068671SJulian.Pullen@Sun.COM return (NULL);
17078671SJulian.Pullen@Sun.COM
17088671SJulian.Pullen@Sun.COM if (!is_valid(&ctx->forest_name) ||
17098671SJulian.Pullen@Sun.COM is_changed(&ctx->forest_name, PARAM1, domain_controller_item)) {
17108671SJulian.Pullen@Sun.COM
17118671SJulian.Pullen@Sun.COM dn_list[0] = "";
17128671SJulian.Pullen@Sun.COM dn_list[1] = NULL;
1713*12508Samw@Sun.COM if (DBG(DISC, 1))
1714*12508Samw@Sun.COM logger(LOG_DEBUG, "Getting forest name");
17158671SJulian.Pullen@Sun.COM config_naming_context = ldap_lookup_entry_attr(
17168671SJulian.Pullen@Sun.COM &ld, ctx->domain_controller.value,
17178671SJulian.Pullen@Sun.COM dn_list, "configurationNamingContext");
17188671SJulian.Pullen@Sun.COM if (config_naming_context != NULL) {
17198671SJulian.Pullen@Sun.COM /*
17208671SJulian.Pullen@Sun.COM * The configurationNamingContext should be of
17218671SJulian.Pullen@Sun.COM * form:
17228671SJulian.Pullen@Sun.COM * CN=Configuration,<DNforestName>
17238671SJulian.Pullen@Sun.COM * Remove the first part and convert to DNS form
17248671SJulian.Pullen@Sun.COM * (replace ",DC=" with ".")
17258671SJulian.Pullen@Sun.COM */
17268671SJulian.Pullen@Sun.COM char *str = "CN=Configuration,";
17278671SJulian.Pullen@Sun.COM int len = strlen(str);
17288671SJulian.Pullen@Sun.COM if (strncasecmp(config_naming_context, str, len) == 0) {
17298671SJulian.Pullen@Sun.COM forest_name = DN_to_DNS(
17308671SJulian.Pullen@Sun.COM config_naming_context + len);
17318671SJulian.Pullen@Sun.COM }
17328671SJulian.Pullen@Sun.COM free(config_naming_context);
17338671SJulian.Pullen@Sun.COM }
17348671SJulian.Pullen@Sun.COM if (ld != NULL)
17358671SJulian.Pullen@Sun.COM (void) ldap_unbind(ld);
17368671SJulian.Pullen@Sun.COM
1737*12508Samw@Sun.COM if (forest_name == NULL) {
1738*12508Samw@Sun.COM if (DBG(DISC, 1))
1739*12508Samw@Sun.COM logger(LOG_DEBUG, " not found");
17408671SJulian.Pullen@Sun.COM return (NULL);
1741*12508Samw@Sun.COM }
1742*12508Samw@Sun.COM
1743*12508Samw@Sun.COM if (DBG(DISC, 1))
1744*12508Samw@Sun.COM logger(LOG_DEBUG, " %s", forest_name);
17458671SJulian.Pullen@Sun.COM
17468671SJulian.Pullen@Sun.COM update_item(&ctx->forest_name, forest_name, AD_STATE_AUTO, 0);
17478671SJulian.Pullen@Sun.COM update_version(&ctx->forest_name, PARAM1,
17488671SJulian.Pullen@Sun.COM domain_controller_item);
17498671SJulian.Pullen@Sun.COM }
17508671SJulian.Pullen@Sun.COM return (&ctx->forest_name);
17518671SJulian.Pullen@Sun.COM }
17528671SJulian.Pullen@Sun.COM
17538671SJulian.Pullen@Sun.COM
17548671SJulian.Pullen@Sun.COM char *
ad_disc_get_ForestName(ad_disc_t ctx,boolean_t * auto_discovered)17558671SJulian.Pullen@Sun.COM ad_disc_get_ForestName(ad_disc_t ctx, boolean_t *auto_discovered)
17568671SJulian.Pullen@Sun.COM {
17578671SJulian.Pullen@Sun.COM ad_item_t *forest_name_item;
17588671SJulian.Pullen@Sun.COM char *forest_name = NULL;
17598671SJulian.Pullen@Sun.COM
17608671SJulian.Pullen@Sun.COM forest_name_item = validate_ForestName(ctx);
17618671SJulian.Pullen@Sun.COM
17628671SJulian.Pullen@Sun.COM if (forest_name_item != NULL) {
17638671SJulian.Pullen@Sun.COM forest_name = strdup(forest_name_item->value);
17648671SJulian.Pullen@Sun.COM if (auto_discovered != NULL)
17658671SJulian.Pullen@Sun.COM *auto_discovered =
17668671SJulian.Pullen@Sun.COM (forest_name_item->state == AD_STATE_AUTO);
17678671SJulian.Pullen@Sun.COM } else if (auto_discovered != NULL)
17688671SJulian.Pullen@Sun.COM *auto_discovered = B_FALSE;
17698671SJulian.Pullen@Sun.COM
17708671SJulian.Pullen@Sun.COM return (forest_name);
17718671SJulian.Pullen@Sun.COM }
17728671SJulian.Pullen@Sun.COM
17738671SJulian.Pullen@Sun.COM
17748671SJulian.Pullen@Sun.COM /* Discover global catalog servers */
17758671SJulian.Pullen@Sun.COM static ad_item_t *
validate_GlobalCatalog(ad_disc_t ctx,enum ad_disc_req req)17768671SJulian.Pullen@Sun.COM validate_GlobalCatalog(ad_disc_t ctx, enum ad_disc_req req)
17778671SJulian.Pullen@Sun.COM {
17788671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t *global_catalog = NULL;
17798671SJulian.Pullen@Sun.COM uint32_t ttl = 0;
17808671SJulian.Pullen@Sun.COM boolean_t validate_global = B_FALSE;
17818671SJulian.Pullen@Sun.COM boolean_t validate_site = B_FALSE;
17828671SJulian.Pullen@Sun.COM ad_item_t *forest_name_item;
17838671SJulian.Pullen@Sun.COM ad_item_t *site_name_item;
17848671SJulian.Pullen@Sun.COM
17858671SJulian.Pullen@Sun.COM /* If the values is fixed there will not be a site specific version */
17868671SJulian.Pullen@Sun.COM if (is_fixed(&ctx->global_catalog))
17878671SJulian.Pullen@Sun.COM return (&ctx->global_catalog);
17888671SJulian.Pullen@Sun.COM
17898671SJulian.Pullen@Sun.COM forest_name_item = validate_ForestName(ctx);
17908671SJulian.Pullen@Sun.COM if (forest_name_item == NULL)
17918671SJulian.Pullen@Sun.COM return (NULL);
17928671SJulian.Pullen@Sun.COM
17938671SJulian.Pullen@Sun.COM if (req == AD_DISC_GLOBAL)
17948671SJulian.Pullen@Sun.COM validate_global = B_TRUE;
17958671SJulian.Pullen@Sun.COM else {
17968671SJulian.Pullen@Sun.COM site_name_item = validate_SiteName(ctx);
17978671SJulian.Pullen@Sun.COM if (site_name_item != NULL)
17988671SJulian.Pullen@Sun.COM validate_site = B_TRUE;
17998671SJulian.Pullen@Sun.COM else if (req == AD_DISC_PREFER_SITE)
18008671SJulian.Pullen@Sun.COM validate_global = B_TRUE;
18018671SJulian.Pullen@Sun.COM }
18028671SJulian.Pullen@Sun.COM
18038671SJulian.Pullen@Sun.COM if (validate_global) {
18048671SJulian.Pullen@Sun.COM if (!is_valid(&ctx->global_catalog) ||
18058671SJulian.Pullen@Sun.COM is_changed(&ctx->global_catalog, PARAM1,
18068671SJulian.Pullen@Sun.COM forest_name_item)) {
18078671SJulian.Pullen@Sun.COM /*
18088671SJulian.Pullen@Sun.COM * Lookup DNS SRV RR named
18098671SJulian.Pullen@Sun.COM * _ldap._tcp.gc._msdcs.<ForestName>
18108671SJulian.Pullen@Sun.COM */
18118671SJulian.Pullen@Sun.COM DO_RES_NINIT(ctx);
18128671SJulian.Pullen@Sun.COM global_catalog =
18138671SJulian.Pullen@Sun.COM srv_query(&ctx->res_state,
18148671SJulian.Pullen@Sun.COM LDAP_SRV_HEAD GC_SRV_TAIL,
18158671SJulian.Pullen@Sun.COM ctx->forest_name.value, NULL, &ttl);
18168671SJulian.Pullen@Sun.COM
1817*12508Samw@Sun.COM if (DBG(DISC, 1)) {
1818*12508Samw@Sun.COM logger(LOG_DEBUG,
1819*12508Samw@Sun.COM "GC servers for %s:",
1820*12508Samw@Sun.COM ctx->forest_name.value);
1821*12508Samw@Sun.COM }
1822*12508Samw@Sun.COM if (global_catalog == NULL) {
1823*12508Samw@Sun.COM if (DBG(DISC, 1))
1824*12508Samw@Sun.COM logger(LOG_DEBUG, " not found");
18258671SJulian.Pullen@Sun.COM return (NULL);
1826*12508Samw@Sun.COM }
1827*12508Samw@Sun.COM
1828*12508Samw@Sun.COM if (DBG(DISC, 1)) {
1829*12508Samw@Sun.COM int i;
1830*12508Samw@Sun.COM for (i = 0;
1831*12508Samw@Sun.COM global_catalog[i].host[0] != '\0';
1832*12508Samw@Sun.COM i++) {
1833*12508Samw@Sun.COM logger(LOG_DEBUG, " %s:%d",
1834*12508Samw@Sun.COM global_catalog[i].host,
1835*12508Samw@Sun.COM global_catalog[i].port);
1836*12508Samw@Sun.COM }
1837*12508Samw@Sun.COM }
18388671SJulian.Pullen@Sun.COM
18398671SJulian.Pullen@Sun.COM update_item(&ctx->global_catalog, global_catalog,
18408671SJulian.Pullen@Sun.COM AD_STATE_AUTO, ttl);
18418671SJulian.Pullen@Sun.COM update_version(&ctx->global_catalog, PARAM1,
18428671SJulian.Pullen@Sun.COM forest_name_item);
18438671SJulian.Pullen@Sun.COM }
18448671SJulian.Pullen@Sun.COM return (&ctx->global_catalog);
18458671SJulian.Pullen@Sun.COM }
18468671SJulian.Pullen@Sun.COM
18478671SJulian.Pullen@Sun.COM if (validate_site) {
18488671SJulian.Pullen@Sun.COM if (!is_valid(&ctx->site_global_catalog) ||
18498671SJulian.Pullen@Sun.COM is_changed(&ctx->site_global_catalog, PARAM1,
18508671SJulian.Pullen@Sun.COM forest_name_item) ||
18518671SJulian.Pullen@Sun.COM is_changed(&ctx->site_global_catalog, PARAM2,
18528671SJulian.Pullen@Sun.COM site_name_item)) {
18538671SJulian.Pullen@Sun.COM char rr_name[DNS_MAX_NAME];
18548671SJulian.Pullen@Sun.COM
18558671SJulian.Pullen@Sun.COM /*
18568671SJulian.Pullen@Sun.COM * Lookup DNS SRV RR named:
18578671SJulian.Pullen@Sun.COM * _ldap._tcp.<siteName>._sites.gc.
18588671SJulian.Pullen@Sun.COM * _msdcs.<ForestName>
18598671SJulian.Pullen@Sun.COM */
18608671SJulian.Pullen@Sun.COM (void) snprintf(rr_name,
18618671SJulian.Pullen@Sun.COM sizeof (rr_name),
18628671SJulian.Pullen@Sun.COM LDAP_SRV_HEAD SITE_SRV_MIDDLE GC_SRV_TAIL,
18638671SJulian.Pullen@Sun.COM ctx->site_name.value);
18648671SJulian.Pullen@Sun.COM DO_RES_NINIT(ctx);
18658671SJulian.Pullen@Sun.COM global_catalog = srv_query(&ctx->res_state, rr_name,
18668671SJulian.Pullen@Sun.COM ctx->forest_name.value, NULL, &ttl);
18678671SJulian.Pullen@Sun.COM
1868*12508Samw@Sun.COM if (DBG(DISC, 1)) {
1869*12508Samw@Sun.COM logger(LOG_DEBUG,
1870*12508Samw@Sun.COM "GC servers for %s in %s",
1871*12508Samw@Sun.COM ctx->forest_name.value,
1872*12508Samw@Sun.COM ctx->site_name.value);
1873*12508Samw@Sun.COM }
1874*12508Samw@Sun.COM if (global_catalog == NULL) {
1875*12508Samw@Sun.COM if (DBG(DISC, 1))
1876*12508Samw@Sun.COM logger(LOG_DEBUG, " not found");
18778671SJulian.Pullen@Sun.COM return (NULL);
1878*12508Samw@Sun.COM }
1879*12508Samw@Sun.COM
1880*12508Samw@Sun.COM if (DBG(DISC, 1)) {
1881*12508Samw@Sun.COM int i;
1882*12508Samw@Sun.COM for (i = 0;
1883*12508Samw@Sun.COM global_catalog[i].host[0] != '\0';
1884*12508Samw@Sun.COM i++) {
1885*12508Samw@Sun.COM logger(LOG_DEBUG, " %s:%d",
1886*12508Samw@Sun.COM global_catalog[i].host,
1887*12508Samw@Sun.COM global_catalog[i].port);
1888*12508Samw@Sun.COM }
1889*12508Samw@Sun.COM }
1890*12508Samw@Sun.COM
18918671SJulian.Pullen@Sun.COM update_item(&ctx->site_global_catalog, global_catalog,
18928671SJulian.Pullen@Sun.COM AD_STATE_AUTO, ttl);
18938671SJulian.Pullen@Sun.COM update_version(&ctx->site_global_catalog, PARAM1,
18948671SJulian.Pullen@Sun.COM forest_name_item);
18958671SJulian.Pullen@Sun.COM update_version(&ctx->site_global_catalog, PARAM2,
18968671SJulian.Pullen@Sun.COM site_name_item);
18978671SJulian.Pullen@Sun.COM }
18988671SJulian.Pullen@Sun.COM return (&ctx->site_global_catalog);
18998671SJulian.Pullen@Sun.COM }
19008671SJulian.Pullen@Sun.COM return (NULL);
19018671SJulian.Pullen@Sun.COM }
19028671SJulian.Pullen@Sun.COM
19038671SJulian.Pullen@Sun.COM
19048671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t *
ad_disc_get_GlobalCatalog(ad_disc_t ctx,enum ad_disc_req req,boolean_t * auto_discovered)19058671SJulian.Pullen@Sun.COM ad_disc_get_GlobalCatalog(ad_disc_t ctx, enum ad_disc_req req,
19068671SJulian.Pullen@Sun.COM boolean_t *auto_discovered)
19078671SJulian.Pullen@Sun.COM {
19088671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t *global_catalog = NULL;
19098671SJulian.Pullen@Sun.COM ad_item_t *global_catalog_item;
19108671SJulian.Pullen@Sun.COM
19118671SJulian.Pullen@Sun.COM global_catalog_item = validate_GlobalCatalog(ctx, req);
19128671SJulian.Pullen@Sun.COM
19138671SJulian.Pullen@Sun.COM if (global_catalog_item != NULL) {
19148671SJulian.Pullen@Sun.COM global_catalog = ds_dup(global_catalog_item->value);
19158671SJulian.Pullen@Sun.COM if (auto_discovered != NULL)
19168671SJulian.Pullen@Sun.COM *auto_discovered =
19178671SJulian.Pullen@Sun.COM (global_catalog_item->state == AD_STATE_AUTO);
19188671SJulian.Pullen@Sun.COM } else if (auto_discovered != NULL)
19198671SJulian.Pullen@Sun.COM *auto_discovered = B_FALSE;
19208671SJulian.Pullen@Sun.COM
19218671SJulian.Pullen@Sun.COM return (global_catalog);
19228671SJulian.Pullen@Sun.COM }
19238671SJulian.Pullen@Sun.COM
19248671SJulian.Pullen@Sun.COM
19258671SJulian.Pullen@Sun.COM static ad_item_t *
validate_TrustedDomains(ad_disc_t ctx)19268671SJulian.Pullen@Sun.COM validate_TrustedDomains(ad_disc_t ctx)
19278671SJulian.Pullen@Sun.COM {
19288671SJulian.Pullen@Sun.COM LDAP *ld = NULL;
19298671SJulian.Pullen@Sun.COM ad_item_t *global_catalog_item;
19308671SJulian.Pullen@Sun.COM ad_item_t *forest_name_item;
19318671SJulian.Pullen@Sun.COM ad_disc_trusteddomains_t *trusted_domains;
19328671SJulian.Pullen@Sun.COM char *dn = NULL;
19338671SJulian.Pullen@Sun.COM char *forest_name_dn;
19348671SJulian.Pullen@Sun.COM int len;
19358671SJulian.Pullen@Sun.COM int num_parts;
19368671SJulian.Pullen@Sun.COM
19378671SJulian.Pullen@Sun.COM if (is_fixed(&ctx->trusted_domains))
19388671SJulian.Pullen@Sun.COM return (&ctx->trusted_domains);
19398671SJulian.Pullen@Sun.COM
19408671SJulian.Pullen@Sun.COM global_catalog_item = validate_GlobalCatalog(ctx, AD_DISC_GLOBAL);
19418671SJulian.Pullen@Sun.COM if (global_catalog_item == NULL)
19428671SJulian.Pullen@Sun.COM return (NULL);
19438671SJulian.Pullen@Sun.COM
19448671SJulian.Pullen@Sun.COM forest_name_item = validate_ForestName(ctx);
19458671SJulian.Pullen@Sun.COM if (forest_name_item == NULL)
19468671SJulian.Pullen@Sun.COM return (NULL);
19478671SJulian.Pullen@Sun.COM
19488671SJulian.Pullen@Sun.COM if (!is_valid(&ctx->trusted_domains) ||
19498671SJulian.Pullen@Sun.COM is_changed(&ctx->trusted_domains, PARAM1, global_catalog_item) ||
19508671SJulian.Pullen@Sun.COM is_changed(&ctx->trusted_domains, PARAM2, forest_name_item)) {
19518671SJulian.Pullen@Sun.COM
19528671SJulian.Pullen@Sun.COM forest_name_dn = ldap_dns_to_dn(forest_name_item->value,
19538671SJulian.Pullen@Sun.COM &num_parts);
19548671SJulian.Pullen@Sun.COM if (forest_name_dn == NULL)
19558671SJulian.Pullen@Sun.COM return (NULL);
19568671SJulian.Pullen@Sun.COM
19578671SJulian.Pullen@Sun.COM len = snprintf(NULL, 0, "CN=System,%s", forest_name_dn) + 1;
19588671SJulian.Pullen@Sun.COM dn = malloc(len);
19598671SJulian.Pullen@Sun.COM if (dn == NULL) {
19608671SJulian.Pullen@Sun.COM free(forest_name_dn);
19618671SJulian.Pullen@Sun.COM return (NULL);
19628671SJulian.Pullen@Sun.COM }
19638671SJulian.Pullen@Sun.COM (void) snprintf(dn, len, "CN=System,%s", forest_name_dn);
19648671SJulian.Pullen@Sun.COM free(forest_name_dn);
19658671SJulian.Pullen@Sun.COM
19668671SJulian.Pullen@Sun.COM trusted_domains = ldap_lookup_trusted_domains(
19678671SJulian.Pullen@Sun.COM &ld, global_catalog_item->value, dn);
19688671SJulian.Pullen@Sun.COM
19698671SJulian.Pullen@Sun.COM if (ld != NULL)
19708671SJulian.Pullen@Sun.COM (void) ldap_unbind(ld);
19718671SJulian.Pullen@Sun.COM free(dn);
19728671SJulian.Pullen@Sun.COM
19738671SJulian.Pullen@Sun.COM if (trusted_domains == NULL)
19748671SJulian.Pullen@Sun.COM return (NULL);
19758671SJulian.Pullen@Sun.COM
19768671SJulian.Pullen@Sun.COM update_item(&ctx->trusted_domains, trusted_domains,
19778671SJulian.Pullen@Sun.COM AD_STATE_AUTO, 0);
19788671SJulian.Pullen@Sun.COM update_version(&ctx->trusted_domains, PARAM1,
19798671SJulian.Pullen@Sun.COM global_catalog_item);
19808671SJulian.Pullen@Sun.COM update_version(&ctx->trusted_domains, PARAM2,
19818671SJulian.Pullen@Sun.COM forest_name_item);
19828671SJulian.Pullen@Sun.COM }
19838671SJulian.Pullen@Sun.COM
19848671SJulian.Pullen@Sun.COM return (&ctx->trusted_domains);
19858671SJulian.Pullen@Sun.COM }
19868671SJulian.Pullen@Sun.COM
19878671SJulian.Pullen@Sun.COM
19888671SJulian.Pullen@Sun.COM ad_disc_trusteddomains_t *
ad_disc_get_TrustedDomains(ad_disc_t ctx,boolean_t * auto_discovered)19898671SJulian.Pullen@Sun.COM ad_disc_get_TrustedDomains(ad_disc_t ctx, boolean_t *auto_discovered)
19908671SJulian.Pullen@Sun.COM {
19918671SJulian.Pullen@Sun.COM ad_disc_trusteddomains_t *trusted_domains = NULL;
19928671SJulian.Pullen@Sun.COM ad_item_t *trusted_domains_item;
19938671SJulian.Pullen@Sun.COM
19948671SJulian.Pullen@Sun.COM trusted_domains_item = validate_TrustedDomains(ctx);
19958671SJulian.Pullen@Sun.COM
19968671SJulian.Pullen@Sun.COM if (trusted_domains_item != NULL) {
19978671SJulian.Pullen@Sun.COM trusted_domains = td_dup(trusted_domains_item->value);
19988671SJulian.Pullen@Sun.COM if (auto_discovered != NULL)
19998671SJulian.Pullen@Sun.COM *auto_discovered =
20008671SJulian.Pullen@Sun.COM (trusted_domains_item->state == AD_STATE_AUTO);
20018671SJulian.Pullen@Sun.COM } else if (auto_discovered != NULL)
20028671SJulian.Pullen@Sun.COM *auto_discovered = B_FALSE;
20038671SJulian.Pullen@Sun.COM
20048671SJulian.Pullen@Sun.COM return (trusted_domains);
20058671SJulian.Pullen@Sun.COM }
20068671SJulian.Pullen@Sun.COM
20078671SJulian.Pullen@Sun.COM
20088671SJulian.Pullen@Sun.COM static ad_item_t *
validate_DomainsInForest(ad_disc_t ctx)20098671SJulian.Pullen@Sun.COM validate_DomainsInForest(ad_disc_t ctx)
20108671SJulian.Pullen@Sun.COM {
20118671SJulian.Pullen@Sun.COM ad_item_t *global_catalog_item;
20128671SJulian.Pullen@Sun.COM LDAP *ld = NULL;
20138671SJulian.Pullen@Sun.COM ad_disc_domainsinforest_t *domains_in_forest;
20148671SJulian.Pullen@Sun.COM
20158671SJulian.Pullen@Sun.COM if (is_fixed(&ctx->domains_in_forest))
20168671SJulian.Pullen@Sun.COM return (&ctx->domains_in_forest);
20178671SJulian.Pullen@Sun.COM
20188671SJulian.Pullen@Sun.COM global_catalog_item = validate_GlobalCatalog(ctx, AD_DISC_GLOBAL);
20198671SJulian.Pullen@Sun.COM if (global_catalog_item == NULL)
20208671SJulian.Pullen@Sun.COM return (NULL);
20218671SJulian.Pullen@Sun.COM
20228671SJulian.Pullen@Sun.COM if (!is_valid(&ctx->domains_in_forest) ||
20238671SJulian.Pullen@Sun.COM is_changed(&ctx->domains_in_forest, PARAM1, global_catalog_item)) {
20248671SJulian.Pullen@Sun.COM
20258671SJulian.Pullen@Sun.COM domains_in_forest = ldap_lookup_domains_in_forest(
20268671SJulian.Pullen@Sun.COM &ld, global_catalog_item->value);
20278671SJulian.Pullen@Sun.COM
20288671SJulian.Pullen@Sun.COM if (ld != NULL)
20298671SJulian.Pullen@Sun.COM (void) ldap_unbind(ld);
20308671SJulian.Pullen@Sun.COM
20318671SJulian.Pullen@Sun.COM if (domains_in_forest == NULL)
20328671SJulian.Pullen@Sun.COM return (NULL);
20338671SJulian.Pullen@Sun.COM
20348671SJulian.Pullen@Sun.COM update_item(&ctx->domains_in_forest, domains_in_forest,
20358671SJulian.Pullen@Sun.COM AD_STATE_AUTO, 0);
20368671SJulian.Pullen@Sun.COM update_version(&ctx->domains_in_forest, PARAM1,
20378671SJulian.Pullen@Sun.COM global_catalog_item);
20388671SJulian.Pullen@Sun.COM }
20398671SJulian.Pullen@Sun.COM return (&ctx->domains_in_forest);
20408671SJulian.Pullen@Sun.COM }
20418671SJulian.Pullen@Sun.COM
20428671SJulian.Pullen@Sun.COM
20438671SJulian.Pullen@Sun.COM ad_disc_domainsinforest_t *
ad_disc_get_DomainsInForest(ad_disc_t ctx,boolean_t * auto_discovered)20448671SJulian.Pullen@Sun.COM ad_disc_get_DomainsInForest(ad_disc_t ctx, boolean_t *auto_discovered)
20458671SJulian.Pullen@Sun.COM {
20468671SJulian.Pullen@Sun.COM ad_disc_domainsinforest_t *domains_in_forest = NULL;
20478671SJulian.Pullen@Sun.COM ad_item_t *domains_in_forest_item;
20488671SJulian.Pullen@Sun.COM
20498671SJulian.Pullen@Sun.COM domains_in_forest_item = validate_DomainsInForest(ctx);
20508671SJulian.Pullen@Sun.COM
20518671SJulian.Pullen@Sun.COM if (domains_in_forest_item != NULL) {
20528671SJulian.Pullen@Sun.COM domains_in_forest = df_dup(domains_in_forest_item->value);
20538671SJulian.Pullen@Sun.COM if (auto_discovered != NULL)
20548671SJulian.Pullen@Sun.COM *auto_discovered =
20558671SJulian.Pullen@Sun.COM (domains_in_forest_item->state == AD_STATE_AUTO);
20568671SJulian.Pullen@Sun.COM } else if (auto_discovered != NULL)
20578671SJulian.Pullen@Sun.COM *auto_discovered = B_FALSE;
20588671SJulian.Pullen@Sun.COM
20598671SJulian.Pullen@Sun.COM return (domains_in_forest);
20608671SJulian.Pullen@Sun.COM }
20618671SJulian.Pullen@Sun.COM
20628671SJulian.Pullen@Sun.COM
20638671SJulian.Pullen@Sun.COM
20648671SJulian.Pullen@Sun.COM
20658671SJulian.Pullen@Sun.COM int
ad_disc_set_DomainName(ad_disc_t ctx,const char * domainName)20668671SJulian.Pullen@Sun.COM ad_disc_set_DomainName(ad_disc_t ctx, const char *domainName)
20678671SJulian.Pullen@Sun.COM {
20688671SJulian.Pullen@Sun.COM char *domain_name = NULL;
20698671SJulian.Pullen@Sun.COM if (domainName != NULL) {
20708671SJulian.Pullen@Sun.COM domain_name = strdup(domainName);
20718671SJulian.Pullen@Sun.COM if (domain_name == NULL)
20728671SJulian.Pullen@Sun.COM return (-1);
20738671SJulian.Pullen@Sun.COM update_item(&ctx->domain_name, domain_name,
20748671SJulian.Pullen@Sun.COM AD_STATE_FIXED, 0);
20758671SJulian.Pullen@Sun.COM } else if (ctx->domain_name.state == AD_STATE_FIXED)
20768671SJulian.Pullen@Sun.COM ctx->domain_name.state = AD_STATE_INVALID;
20778671SJulian.Pullen@Sun.COM return (0);
20788671SJulian.Pullen@Sun.COM }
20798671SJulian.Pullen@Sun.COM
20808671SJulian.Pullen@Sun.COM
20818671SJulian.Pullen@Sun.COM int
ad_disc_set_DomainController(ad_disc_t ctx,const idmap_ad_disc_ds_t * domainController)20828671SJulian.Pullen@Sun.COM ad_disc_set_DomainController(ad_disc_t ctx,
20838671SJulian.Pullen@Sun.COM const idmap_ad_disc_ds_t *domainController)
20848671SJulian.Pullen@Sun.COM {
20858671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t *domain_controller = NULL;
20868671SJulian.Pullen@Sun.COM if (domainController != NULL) {
20878671SJulian.Pullen@Sun.COM domain_controller = ds_dup(domainController);
20888671SJulian.Pullen@Sun.COM if (domain_controller == NULL)
20898671SJulian.Pullen@Sun.COM return (-1);
20908671SJulian.Pullen@Sun.COM update_item(&ctx->domain_controller, domain_controller,
20918671SJulian.Pullen@Sun.COM AD_STATE_FIXED, 0);
20928671SJulian.Pullen@Sun.COM } else if (ctx->domain_controller.state == AD_STATE_FIXED)
20938671SJulian.Pullen@Sun.COM ctx->domain_controller.state = AD_STATE_INVALID;
20948671SJulian.Pullen@Sun.COM return (0);
20958671SJulian.Pullen@Sun.COM }
20968671SJulian.Pullen@Sun.COM
20978671SJulian.Pullen@Sun.COM
20988671SJulian.Pullen@Sun.COM int
ad_disc_set_SiteName(ad_disc_t ctx,const char * siteName)20998671SJulian.Pullen@Sun.COM ad_disc_set_SiteName(ad_disc_t ctx, const char *siteName)
21008671SJulian.Pullen@Sun.COM {
21018671SJulian.Pullen@Sun.COM char *site_name = NULL;
21028671SJulian.Pullen@Sun.COM if (siteName != NULL) {
21038671SJulian.Pullen@Sun.COM site_name = strdup(siteName);
21048671SJulian.Pullen@Sun.COM if (site_name == NULL)
21058671SJulian.Pullen@Sun.COM return (-1);
21068671SJulian.Pullen@Sun.COM update_item(&ctx->site_name, site_name, AD_STATE_FIXED, 0);
21078671SJulian.Pullen@Sun.COM } else if (ctx->site_name.state == AD_STATE_FIXED)
21088671SJulian.Pullen@Sun.COM ctx->site_name.state = AD_STATE_INVALID;
21098671SJulian.Pullen@Sun.COM return (0);
21108671SJulian.Pullen@Sun.COM }
21118671SJulian.Pullen@Sun.COM
21128671SJulian.Pullen@Sun.COM int
ad_disc_set_ForestName(ad_disc_t ctx,const char * forestName)21138671SJulian.Pullen@Sun.COM ad_disc_set_ForestName(ad_disc_t ctx, const char *forestName)
21148671SJulian.Pullen@Sun.COM {
21158671SJulian.Pullen@Sun.COM char *forest_name = NULL;
21168671SJulian.Pullen@Sun.COM if (forestName != NULL) {
21178671SJulian.Pullen@Sun.COM forest_name = strdup(forestName);
21188671SJulian.Pullen@Sun.COM if (forest_name == NULL)
21198671SJulian.Pullen@Sun.COM return (-1);
21208671SJulian.Pullen@Sun.COM update_item(&ctx->forest_name, forest_name,
21218671SJulian.Pullen@Sun.COM AD_STATE_FIXED, 0);
21228671SJulian.Pullen@Sun.COM } else if (ctx->forest_name.state == AD_STATE_FIXED)
21238671SJulian.Pullen@Sun.COM ctx->forest_name.state = AD_STATE_INVALID;
21248671SJulian.Pullen@Sun.COM return (0);
21258671SJulian.Pullen@Sun.COM }
21268671SJulian.Pullen@Sun.COM
21278671SJulian.Pullen@Sun.COM int
ad_disc_set_GlobalCatalog(ad_disc_t ctx,const idmap_ad_disc_ds_t * globalCatalog)21288671SJulian.Pullen@Sun.COM ad_disc_set_GlobalCatalog(ad_disc_t ctx,
21298671SJulian.Pullen@Sun.COM const idmap_ad_disc_ds_t *globalCatalog)
21308671SJulian.Pullen@Sun.COM {
21318671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t *global_catalog = NULL;
21328671SJulian.Pullen@Sun.COM if (globalCatalog != NULL) {
21338671SJulian.Pullen@Sun.COM global_catalog = ds_dup(globalCatalog);
21348671SJulian.Pullen@Sun.COM if (global_catalog == NULL)
21358671SJulian.Pullen@Sun.COM return (-1);
21368671SJulian.Pullen@Sun.COM update_item(&ctx->global_catalog, global_catalog,
21378671SJulian.Pullen@Sun.COM AD_STATE_FIXED, 0);
21388671SJulian.Pullen@Sun.COM } else if (ctx->global_catalog.state == AD_STATE_FIXED)
21398671SJulian.Pullen@Sun.COM ctx->global_catalog.state = AD_STATE_INVALID;
21408671SJulian.Pullen@Sun.COM return (0);
21418671SJulian.Pullen@Sun.COM }
21428671SJulian.Pullen@Sun.COM
21438671SJulian.Pullen@Sun.COM
21448671SJulian.Pullen@Sun.COM int
ad_disc_unset(ad_disc_t ctx)21458671SJulian.Pullen@Sun.COM ad_disc_unset(ad_disc_t ctx)
21468671SJulian.Pullen@Sun.COM {
21478671SJulian.Pullen@Sun.COM if (ctx->domain_name.state == AD_STATE_FIXED)
21488671SJulian.Pullen@Sun.COM ctx->domain_name.state = AD_STATE_INVALID;
21498671SJulian.Pullen@Sun.COM
21508671SJulian.Pullen@Sun.COM if (ctx->domain_controller.state == AD_STATE_FIXED)
21518671SJulian.Pullen@Sun.COM ctx->domain_controller.state = AD_STATE_INVALID;
21528671SJulian.Pullen@Sun.COM
21538671SJulian.Pullen@Sun.COM if (ctx->site_name.state == AD_STATE_FIXED)
21548671SJulian.Pullen@Sun.COM ctx->site_name.state = AD_STATE_INVALID;
21558671SJulian.Pullen@Sun.COM
21568671SJulian.Pullen@Sun.COM if (ctx->forest_name.state == AD_STATE_FIXED)
21578671SJulian.Pullen@Sun.COM ctx->forest_name.state = AD_STATE_INVALID;
21588671SJulian.Pullen@Sun.COM
21598671SJulian.Pullen@Sun.COM if (ctx->global_catalog.state == AD_STATE_FIXED)
21608671SJulian.Pullen@Sun.COM ctx->global_catalog.state = AD_STATE_INVALID;
21618671SJulian.Pullen@Sun.COM
21628671SJulian.Pullen@Sun.COM return (0);
21638671SJulian.Pullen@Sun.COM }
21648671SJulian.Pullen@Sun.COM
21658671SJulian.Pullen@Sun.COM /*
21668671SJulian.Pullen@Sun.COM * ad_disc_get_TTL
21678671SJulian.Pullen@Sun.COM *
21688671SJulian.Pullen@Sun.COM * This routines the time to live for AD
21698671SJulian.Pullen@Sun.COM * auto discovered items.
21708671SJulian.Pullen@Sun.COM *
21718671SJulian.Pullen@Sun.COM * Returns:
21728671SJulian.Pullen@Sun.COM * -1 if there are no TTL items
21738671SJulian.Pullen@Sun.COM * 0 if there are expired items
21748671SJulian.Pullen@Sun.COM * else the number of seconds
21758671SJulian.Pullen@Sun.COM *
21768671SJulian.Pullen@Sun.COM * The MIN_GT_ZERO(x, y) macro return the lesser of x and y, provided it
21778671SJulian.Pullen@Sun.COM * is positive -- min() greater than zero.
21788671SJulian.Pullen@Sun.COM */
21798671SJulian.Pullen@Sun.COM #define MIN_GT_ZERO(x, y) (((x) <= 0) ? (((y) <= 0) ? \
21808671SJulian.Pullen@Sun.COM (-1) : (y)) : (((y) <= 0) ? (x) : (((x) > (y)) ? (y) : (x))))
21818671SJulian.Pullen@Sun.COM int
ad_disc_get_TTL(ad_disc_t ctx)21828671SJulian.Pullen@Sun.COM ad_disc_get_TTL(ad_disc_t ctx)
21838671SJulian.Pullen@Sun.COM {
218412065SKeyur.Desai@Sun.COM time_t expires;
21858671SJulian.Pullen@Sun.COM int ttl;
21868671SJulian.Pullen@Sun.COM
218712065SKeyur.Desai@Sun.COM expires = MIN_GT_ZERO(ctx->domain_controller.expires,
218812065SKeyur.Desai@Sun.COM ctx->global_catalog.expires);
218912065SKeyur.Desai@Sun.COM expires = MIN_GT_ZERO(expires, ctx->site_domain_controller.expires);
219012065SKeyur.Desai@Sun.COM expires = MIN_GT_ZERO(expires, ctx->site_global_catalog.expires);
219112065SKeyur.Desai@Sun.COM
219212065SKeyur.Desai@Sun.COM if (expires == -1) {
219312065SKeyur.Desai@Sun.COM return (-1);
219412065SKeyur.Desai@Sun.COM }
21958671SJulian.Pullen@Sun.COM
219612065SKeyur.Desai@Sun.COM if (ctx->expires_not_before != 0 &&
219712065SKeyur.Desai@Sun.COM expires < ctx->expires_not_before) {
219812065SKeyur.Desai@Sun.COM expires = ctx->expires_not_before;
219912065SKeyur.Desai@Sun.COM }
220012065SKeyur.Desai@Sun.COM
220112065SKeyur.Desai@Sun.COM if (ctx->expires_not_after != 0 &&
220212065SKeyur.Desai@Sun.COM expires > ctx->expires_not_after) {
220312065SKeyur.Desai@Sun.COM expires = ctx->expires_not_after;
220412065SKeyur.Desai@Sun.COM }
220512065SKeyur.Desai@Sun.COM
220612065SKeyur.Desai@Sun.COM ttl = expires - time(NULL);
220712065SKeyur.Desai@Sun.COM
220812065SKeyur.Desai@Sun.COM if (ttl < 0) {
22098671SJulian.Pullen@Sun.COM return (0);
221012065SKeyur.Desai@Sun.COM }
22118671SJulian.Pullen@Sun.COM return (ttl);
22128671SJulian.Pullen@Sun.COM }
22138671SJulian.Pullen@Sun.COM
22148671SJulian.Pullen@Sun.COM boolean_t
ad_disc_SubnetChanged(ad_disc_t ctx)22158671SJulian.Pullen@Sun.COM ad_disc_SubnetChanged(ad_disc_t ctx)
22168671SJulian.Pullen@Sun.COM {
22178671SJulian.Pullen@Sun.COM ad_subnet_t *subnets;
22188671SJulian.Pullen@Sun.COM
22198671SJulian.Pullen@Sun.COM if (ctx->subnets_changed || ctx->subnets == NULL)
22208671SJulian.Pullen@Sun.COM return (B_TRUE);
22218671SJulian.Pullen@Sun.COM
22228671SJulian.Pullen@Sun.COM if ((subnets = find_subnets()) != NULL) {
22238671SJulian.Pullen@Sun.COM if (cmpsubnets(subnets, ctx->subnets) != 0)
22248671SJulian.Pullen@Sun.COM ctx->subnets_changed = B_TRUE;
22258671SJulian.Pullen@Sun.COM free(subnets);
22268671SJulian.Pullen@Sun.COM }
22278671SJulian.Pullen@Sun.COM
22288671SJulian.Pullen@Sun.COM return (ctx->subnets_changed);
22298671SJulian.Pullen@Sun.COM }
2230