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*12065SKeyur.Desai@Sun.COM * Copyright (c) 2009, 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 105*12065SKeyur.Desai@Sun.COM /* 106*12065SKeyur.Desai@Sun.COM * These set some sanity policies for discovery. After a discovery 107*12065SKeyur.Desai@Sun.COM * cycle, we will consider the results (successful or unsuccessful) 108*12065SKeyur.Desai@Sun.COM * to be valid for at least MINIMUM_TTL seconds, and for at most 109*12065SKeyur.Desai@Sun.COM * MAXIMUM_TTL seconds. Note that the caller is free to request 110*12065SKeyur.Desai@Sun.COM * discovery cycles sooner than MINIMUM_TTL if it has reason to believe 111*12065SKeyur.Desai@Sun.COM * that the situation has changed. 112*12065SKeyur.Desai@Sun.COM */ 113*12065SKeyur.Desai@Sun.COM #define MINIMUM_TTL (5 * 60) 114*12065SKeyur.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; 139*12065SKeyur.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; 156*12065SKeyur.Desai@Sun.COM time_t expires_not_before; 157*12065SKeyur.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 */ 1748671SJulian.Pullen@Sun.COM } ad_disc; 1758671SJulian.Pullen@Sun.COM 1768671SJulian.Pullen@Sun.COM 1778671SJulian.Pullen@Sun.COM #define DNS_MAX_NAME NS_MAXDNAME 1788671SJulian.Pullen@Sun.COM 1798671SJulian.Pullen@Sun.COM 1808671SJulian.Pullen@Sun.COM /* SRV RR names for various queries */ 1818671SJulian.Pullen@Sun.COM #define LDAP_SRV_HEAD "_ldap._tcp." 1828671SJulian.Pullen@Sun.COM #define SITE_SRV_MIDDLE "%s._sites." 1838671SJulian.Pullen@Sun.COM #define GC_SRV_TAIL "gc._msdcs" 1848671SJulian.Pullen@Sun.COM #define DC_SRV_TAIL "dc._msdcs" 1858671SJulian.Pullen@Sun.COM #define ALL_GC_SRV_TAIL "_gc._tcp" 1868671SJulian.Pullen@Sun.COM #define PDC_SRV "_ldap._tcp.pdc._msdcs.%s" 1878671SJulian.Pullen@Sun.COM 1888671SJulian.Pullen@Sun.COM /* A RR name for all GCs -- last resort this works */ 1898671SJulian.Pullen@Sun.COM #define GC_ALL_A_NAME_FSTR "gc._msdcs.%s." 1908671SJulian.Pullen@Sun.COM 1918671SJulian.Pullen@Sun.COM 1928671SJulian.Pullen@Sun.COM /* 1938671SJulian.Pullen@Sun.COM * We try res_ninit() whenever we don't have one. res_ninit() fails if 1948671SJulian.Pullen@Sun.COM * idmapd is running before the network is up! 1958671SJulian.Pullen@Sun.COM */ 1968671SJulian.Pullen@Sun.COM #define DO_RES_NINIT(ctx) if (!(ctx)->res_ninitted) \ 1978671SJulian.Pullen@Sun.COM (ctx)->res_ninitted = (res_ninit(&ctx->res_state) != -1) 1988671SJulian.Pullen@Sun.COM 1998671SJulian.Pullen@Sun.COM #define is_fixed(item) \ 2008671SJulian.Pullen@Sun.COM ((item)->state == AD_STATE_FIXED) 2018671SJulian.Pullen@Sun.COM 2028671SJulian.Pullen@Sun.COM #define is_changed(item, num, param) \ 2038671SJulian.Pullen@Sun.COM ((item)->param_version[num] != (param)->version) 2048671SJulian.Pullen@Sun.COM 2058671SJulian.Pullen@Sun.COM /*LINTLIBRARY*/ 2068671SJulian.Pullen@Sun.COM 2078671SJulian.Pullen@Sun.COM /* 2088671SJulian.Pullen@Sun.COM * Function definitions 2098671SJulian.Pullen@Sun.COM */ 2108671SJulian.Pullen@Sun.COM static ad_item_t * 2118671SJulian.Pullen@Sun.COM validate_SiteName(ad_disc_t ctx); 2128671SJulian.Pullen@Sun.COM 2138671SJulian.Pullen@Sun.COM 2148671SJulian.Pullen@Sun.COM 2158671SJulian.Pullen@Sun.COM static void 2168671SJulian.Pullen@Sun.COM update_version(ad_item_t *item, int num, ad_item_t *param) 2178671SJulian.Pullen@Sun.COM { 2188671SJulian.Pullen@Sun.COM item->param_version[num] = param->version; 2198671SJulian.Pullen@Sun.COM } 2208671SJulian.Pullen@Sun.COM 2218671SJulian.Pullen@Sun.COM 2228671SJulian.Pullen@Sun.COM 2238671SJulian.Pullen@Sun.COM static boolean_t 2248671SJulian.Pullen@Sun.COM is_valid(ad_item_t *item) 2258671SJulian.Pullen@Sun.COM { 2268671SJulian.Pullen@Sun.COM if (item->value != NULL) { 2278671SJulian.Pullen@Sun.COM if (item->state == AD_STATE_FIXED) 2288671SJulian.Pullen@Sun.COM return (B_TRUE); 2298671SJulian.Pullen@Sun.COM if (item->state == AD_STATE_AUTO && 230*12065SKeyur.Desai@Sun.COM (item->expires == 0 || item->expires > time(NULL))) 2318671SJulian.Pullen@Sun.COM return (B_TRUE); 2328671SJulian.Pullen@Sun.COM } 2338671SJulian.Pullen@Sun.COM return (B_FALSE); 2348671SJulian.Pullen@Sun.COM } 2358671SJulian.Pullen@Sun.COM 2368671SJulian.Pullen@Sun.COM 2378671SJulian.Pullen@Sun.COM static void 2388671SJulian.Pullen@Sun.COM update_item(ad_item_t *item, void *value, enum ad_item_state state, 2398671SJulian.Pullen@Sun.COM uint32_t ttl) 2408671SJulian.Pullen@Sun.COM { 2418671SJulian.Pullen@Sun.COM if (item->value != NULL && value != NULL) { 2428671SJulian.Pullen@Sun.COM if ((item->type == AD_STRING && 2438671SJulian.Pullen@Sun.COM strcmp(item->value, value) != 0) || 2448671SJulian.Pullen@Sun.COM (item->type == AD_DIRECTORY && 2458671SJulian.Pullen@Sun.COM ad_disc_compare_ds(item->value, value) != 0)|| 2468671SJulian.Pullen@Sun.COM (item->type == AD_DOMAINS_IN_FOREST && 2478671SJulian.Pullen@Sun.COM ad_disc_compare_domainsinforest(item->value, value) != 0) || 2488671SJulian.Pullen@Sun.COM (item->type == AD_TRUSTED_DOMAINS && 2498671SJulian.Pullen@Sun.COM ad_disc_compare_trusteddomains(item->value, value) != 0)) 2508671SJulian.Pullen@Sun.COM item->version++; 2518671SJulian.Pullen@Sun.COM } else if (item->value != value) 2528671SJulian.Pullen@Sun.COM item->version++; 2538671SJulian.Pullen@Sun.COM 2548671SJulian.Pullen@Sun.COM if (item->value != NULL) 2558671SJulian.Pullen@Sun.COM free(item->value); 2568671SJulian.Pullen@Sun.COM 2578671SJulian.Pullen@Sun.COM item->value = value; 2588671SJulian.Pullen@Sun.COM item->state = state; 2598671SJulian.Pullen@Sun.COM 2608671SJulian.Pullen@Sun.COM if (ttl == 0) 261*12065SKeyur.Desai@Sun.COM item->expires = 0; 2628671SJulian.Pullen@Sun.COM else 263*12065SKeyur.Desai@Sun.COM item->expires = time(NULL) + ttl; 2648671SJulian.Pullen@Sun.COM } 2658671SJulian.Pullen@Sun.COM 2668671SJulian.Pullen@Sun.COM 2678671SJulian.Pullen@Sun.COM /* Compare DS lists */ 2688671SJulian.Pullen@Sun.COM int 2698671SJulian.Pullen@Sun.COM ad_disc_compare_ds(idmap_ad_disc_ds_t *ds1, idmap_ad_disc_ds_t *ds2) 2708671SJulian.Pullen@Sun.COM { 2718671SJulian.Pullen@Sun.COM int i, j; 2728671SJulian.Pullen@Sun.COM int num_ds1; 2738671SJulian.Pullen@Sun.COM int num_ds2; 2748671SJulian.Pullen@Sun.COM boolean_t match; 2758671SJulian.Pullen@Sun.COM 2768671SJulian.Pullen@Sun.COM for (i = 0; ds1[i].host[0] != '\0'; i++) 2778671SJulian.Pullen@Sun.COM continue; 2788671SJulian.Pullen@Sun.COM num_ds1 = i; 2798671SJulian.Pullen@Sun.COM for (j = 0; ds2[j].host[0] != '\0'; j++) 2808671SJulian.Pullen@Sun.COM continue; 2818671SJulian.Pullen@Sun.COM num_ds2 = j; 2828671SJulian.Pullen@Sun.COM if (num_ds1 != num_ds2) 2838671SJulian.Pullen@Sun.COM return (1); 2848671SJulian.Pullen@Sun.COM 2858671SJulian.Pullen@Sun.COM for (i = 0; i < num_ds1; i++) { 2868671SJulian.Pullen@Sun.COM match = B_FALSE; 2878671SJulian.Pullen@Sun.COM for (j = 0; j < num_ds2; j++) { 2889744SJordan.Brown@Sun.COM if (strcmp(ds1[i].host, ds2[j].host) == 0 && 2899744SJordan.Brown@Sun.COM ds1[i].port == ds2[j].port) { 2908671SJulian.Pullen@Sun.COM match = B_TRUE; 2918671SJulian.Pullen@Sun.COM break; 2928671SJulian.Pullen@Sun.COM } 2938671SJulian.Pullen@Sun.COM } 2948671SJulian.Pullen@Sun.COM if (!match) 2958671SJulian.Pullen@Sun.COM return (1); 2968671SJulian.Pullen@Sun.COM } 2978671SJulian.Pullen@Sun.COM return (0); 2988671SJulian.Pullen@Sun.COM } 2998671SJulian.Pullen@Sun.COM 3008671SJulian.Pullen@Sun.COM 3018671SJulian.Pullen@Sun.COM /* Copy a list of DSs */ 3028671SJulian.Pullen@Sun.COM static idmap_ad_disc_ds_t * 3038671SJulian.Pullen@Sun.COM ds_dup(const idmap_ad_disc_ds_t *srv) 3048671SJulian.Pullen@Sun.COM { 3058671SJulian.Pullen@Sun.COM int i; 3068671SJulian.Pullen@Sun.COM int size; 3078671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t *new = NULL; 3088671SJulian.Pullen@Sun.COM 3098671SJulian.Pullen@Sun.COM for (i = 0; srv[i].host[0] != '\0'; i++) 3108671SJulian.Pullen@Sun.COM continue; 3118671SJulian.Pullen@Sun.COM 3128671SJulian.Pullen@Sun.COM size = (i + 1) * sizeof (idmap_ad_disc_ds_t); 3138671SJulian.Pullen@Sun.COM new = malloc(size); 3148671SJulian.Pullen@Sun.COM if (new != NULL) 3158671SJulian.Pullen@Sun.COM memcpy(new, srv, size); 3168671SJulian.Pullen@Sun.COM return (new); 3178671SJulian.Pullen@Sun.COM } 3188671SJulian.Pullen@Sun.COM 3198671SJulian.Pullen@Sun.COM 3208671SJulian.Pullen@Sun.COM int 3218671SJulian.Pullen@Sun.COM ad_disc_compare_trusteddomains(ad_disc_trusteddomains_t *td1, 3228671SJulian.Pullen@Sun.COM ad_disc_trusteddomains_t *td2) 3238671SJulian.Pullen@Sun.COM { 3248671SJulian.Pullen@Sun.COM int i, j; 3258671SJulian.Pullen@Sun.COM int num_td1; 3268671SJulian.Pullen@Sun.COM int num_td2; 3278671SJulian.Pullen@Sun.COM boolean_t match; 3288671SJulian.Pullen@Sun.COM 3298671SJulian.Pullen@Sun.COM for (i = 0; td1[i].domain[0] != '\0'; i++) 3308671SJulian.Pullen@Sun.COM continue; 3318671SJulian.Pullen@Sun.COM num_td1 = i; 3328671SJulian.Pullen@Sun.COM 3338671SJulian.Pullen@Sun.COM for (j = 0; td2[j].domain[0] != '\0'; j++) 3348671SJulian.Pullen@Sun.COM continue; 3358671SJulian.Pullen@Sun.COM num_td2 = j; 3368671SJulian.Pullen@Sun.COM 3378671SJulian.Pullen@Sun.COM if (num_td1 != num_td2) 3388671SJulian.Pullen@Sun.COM return (1); 3398671SJulian.Pullen@Sun.COM 3408671SJulian.Pullen@Sun.COM for (i = 0; i < num_td1; i++) { 3418671SJulian.Pullen@Sun.COM match = B_FALSE; 3428671SJulian.Pullen@Sun.COM for (j = 0; j < num_td2; j++) { 34310122SJordan.Brown@Sun.COM if (domain_eq(td1[i].domain, td2[j].domain)) { 3448671SJulian.Pullen@Sun.COM match = B_TRUE; 3458671SJulian.Pullen@Sun.COM break; 3468671SJulian.Pullen@Sun.COM } 3478671SJulian.Pullen@Sun.COM } 3488671SJulian.Pullen@Sun.COM if (!match) 3498671SJulian.Pullen@Sun.COM return (1); 3508671SJulian.Pullen@Sun.COM } 3518671SJulian.Pullen@Sun.COM return (0); 3528671SJulian.Pullen@Sun.COM } 3538671SJulian.Pullen@Sun.COM 3548671SJulian.Pullen@Sun.COM 3558671SJulian.Pullen@Sun.COM 3568671SJulian.Pullen@Sun.COM /* Copy a list of Trusted Domains */ 3578671SJulian.Pullen@Sun.COM static ad_disc_trusteddomains_t * 3588671SJulian.Pullen@Sun.COM td_dup(const ad_disc_trusteddomains_t *td) 3598671SJulian.Pullen@Sun.COM { 3608671SJulian.Pullen@Sun.COM int i; 3618671SJulian.Pullen@Sun.COM int size; 3628671SJulian.Pullen@Sun.COM ad_disc_trusteddomains_t *new = NULL; 3638671SJulian.Pullen@Sun.COM 3648671SJulian.Pullen@Sun.COM for (i = 0; td[i].domain[0] != '\0'; i++) 3658671SJulian.Pullen@Sun.COM continue; 3668671SJulian.Pullen@Sun.COM 3678671SJulian.Pullen@Sun.COM size = (i + 1) * sizeof (ad_disc_trusteddomains_t); 3688671SJulian.Pullen@Sun.COM new = malloc(size); 3698671SJulian.Pullen@Sun.COM if (new != NULL) 3708671SJulian.Pullen@Sun.COM memcpy(new, td, size); 3718671SJulian.Pullen@Sun.COM return (new); 3728671SJulian.Pullen@Sun.COM } 3738671SJulian.Pullen@Sun.COM 3748671SJulian.Pullen@Sun.COM 3758671SJulian.Pullen@Sun.COM 3768671SJulian.Pullen@Sun.COM int 3778671SJulian.Pullen@Sun.COM ad_disc_compare_domainsinforest(ad_disc_domainsinforest_t *df1, 3788671SJulian.Pullen@Sun.COM ad_disc_domainsinforest_t *df2) 3798671SJulian.Pullen@Sun.COM { 3808671SJulian.Pullen@Sun.COM int i, j; 3818671SJulian.Pullen@Sun.COM int num_df1; 3828671SJulian.Pullen@Sun.COM int num_df2; 3838671SJulian.Pullen@Sun.COM boolean_t match; 3848671SJulian.Pullen@Sun.COM 3858671SJulian.Pullen@Sun.COM for (i = 0; df1[i].domain[0] != '\0'; i++) 3868671SJulian.Pullen@Sun.COM continue; 3878671SJulian.Pullen@Sun.COM num_df1 = i; 3888671SJulian.Pullen@Sun.COM 3898671SJulian.Pullen@Sun.COM for (j = 0; df2[j].domain[0] != '\0'; j++) 3908671SJulian.Pullen@Sun.COM continue; 3918671SJulian.Pullen@Sun.COM num_df2 = j; 3928671SJulian.Pullen@Sun.COM 3938671SJulian.Pullen@Sun.COM if (num_df1 != num_df2) 3948671SJulian.Pullen@Sun.COM return (1); 3958671SJulian.Pullen@Sun.COM 3968671SJulian.Pullen@Sun.COM for (i = 0; i < num_df1; i++) { 3978671SJulian.Pullen@Sun.COM match = B_FALSE; 3988671SJulian.Pullen@Sun.COM for (j = 0; j < num_df2; j++) { 39910122SJordan.Brown@Sun.COM if (domain_eq(df1[i].domain, df2[j].domain) && 4009744SJordan.Brown@Sun.COM strcmp(df1[i].sid, df2[j].sid) == 0) { 4018671SJulian.Pullen@Sun.COM match = B_TRUE; 4028671SJulian.Pullen@Sun.COM break; 4038671SJulian.Pullen@Sun.COM } 4048671SJulian.Pullen@Sun.COM } 4058671SJulian.Pullen@Sun.COM if (!match) 4068671SJulian.Pullen@Sun.COM return (1); 4078671SJulian.Pullen@Sun.COM } 4088671SJulian.Pullen@Sun.COM return (0); 4098671SJulian.Pullen@Sun.COM } 4108671SJulian.Pullen@Sun.COM 4118671SJulian.Pullen@Sun.COM 4128671SJulian.Pullen@Sun.COM 4138671SJulian.Pullen@Sun.COM /* Copy a list of Trusted Domains */ 4148671SJulian.Pullen@Sun.COM static ad_disc_domainsinforest_t * 4158671SJulian.Pullen@Sun.COM df_dup(const ad_disc_domainsinforest_t *df) 4168671SJulian.Pullen@Sun.COM { 4178671SJulian.Pullen@Sun.COM int i; 4188671SJulian.Pullen@Sun.COM int size; 4198671SJulian.Pullen@Sun.COM ad_disc_domainsinforest_t *new = NULL; 4208671SJulian.Pullen@Sun.COM 4218671SJulian.Pullen@Sun.COM for (i = 0; df[i].domain[0] != '\0'; i++) 4228671SJulian.Pullen@Sun.COM continue; 4238671SJulian.Pullen@Sun.COM 4248671SJulian.Pullen@Sun.COM size = (i + 1) * sizeof (ad_disc_domainsinforest_t); 4258671SJulian.Pullen@Sun.COM new = malloc(size); 4268671SJulian.Pullen@Sun.COM if (new != NULL) 4278671SJulian.Pullen@Sun.COM memcpy(new, df, size); 4288671SJulian.Pullen@Sun.COM return (new); 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 /* 4368671SJulian.Pullen@Sun.COM * Returns an array of IPv4 address/prefix length 4378671SJulian.Pullen@Sun.COM * The last subnet is NULL 4388671SJulian.Pullen@Sun.COM */ 4398671SJulian.Pullen@Sun.COM static ad_subnet_t * 4408671SJulian.Pullen@Sun.COM find_subnets() 4418671SJulian.Pullen@Sun.COM { 4428671SJulian.Pullen@Sun.COM int sock, n, i; 4438671SJulian.Pullen@Sun.COM struct lifconf lifc; 4448671SJulian.Pullen@Sun.COM struct lifreq lifr, *lifrp; 4458671SJulian.Pullen@Sun.COM struct lifnum lifn; 4468671SJulian.Pullen@Sun.COM uint32_t prefix_len; 4478671SJulian.Pullen@Sun.COM char *s; 4488671SJulian.Pullen@Sun.COM ad_subnet_t *results; 4498671SJulian.Pullen@Sun.COM 4508671SJulian.Pullen@Sun.COM lifrp = &lifr; 4518671SJulian.Pullen@Sun.COM 4528671SJulian.Pullen@Sun.COM if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 4538671SJulian.Pullen@Sun.COM logger(LOG_ERR, "Failed to open IPv4 socket for " 4548671SJulian.Pullen@Sun.COM "listing network interfaces (%s)", strerror(errno)); 4558671SJulian.Pullen@Sun.COM return (NULL); 4568671SJulian.Pullen@Sun.COM } 4578671SJulian.Pullen@Sun.COM 4588671SJulian.Pullen@Sun.COM lifn.lifn_family = AF_INET; 4598671SJulian.Pullen@Sun.COM lifn.lifn_flags = 0; 4608671SJulian.Pullen@Sun.COM if (ioctl(sock, SIOCGLIFNUM, (char *)&lifn) < 0) { 4618671SJulian.Pullen@Sun.COM logger(LOG_ERR, 4628671SJulian.Pullen@Sun.COM "Failed to find the number of network interfaces (%s)", 4638671SJulian.Pullen@Sun.COM strerror(errno)); 4648671SJulian.Pullen@Sun.COM close(sock); 4658671SJulian.Pullen@Sun.COM return (NULL); 4668671SJulian.Pullen@Sun.COM } 4678671SJulian.Pullen@Sun.COM 4688671SJulian.Pullen@Sun.COM if (lifn.lifn_count < 1) { 4698671SJulian.Pullen@Sun.COM logger(LOG_ERR, "No IPv4 network interfaces found"); 4708671SJulian.Pullen@Sun.COM close(sock); 4718671SJulian.Pullen@Sun.COM return (NULL); 4728671SJulian.Pullen@Sun.COM } 4738671SJulian.Pullen@Sun.COM 4748671SJulian.Pullen@Sun.COM lifc.lifc_family = AF_INET; 4758671SJulian.Pullen@Sun.COM lifc.lifc_flags = 0; 4768671SJulian.Pullen@Sun.COM lifc.lifc_len = lifn.lifn_count * sizeof (struct lifreq); 4778671SJulian.Pullen@Sun.COM lifc.lifc_buf = malloc(lifc.lifc_len); 4788671SJulian.Pullen@Sun.COM 4798671SJulian.Pullen@Sun.COM if (lifc.lifc_buf == NULL) { 4808671SJulian.Pullen@Sun.COM logger(LOG_ERR, "Out of memory"); 4818671SJulian.Pullen@Sun.COM close(sock); 4828671SJulian.Pullen@Sun.COM return (NULL); 4838671SJulian.Pullen@Sun.COM } 4848671SJulian.Pullen@Sun.COM 4858671SJulian.Pullen@Sun.COM if (ioctl(sock, SIOCGLIFCONF, (char *)&lifc) < 0) { 4868671SJulian.Pullen@Sun.COM logger(LOG_ERR, "Failed to list network interfaces (%s)", 4878671SJulian.Pullen@Sun.COM strerror(errno)); 4888671SJulian.Pullen@Sun.COM free(lifc.lifc_buf); 4898671SJulian.Pullen@Sun.COM close(sock); 4908671SJulian.Pullen@Sun.COM return (NULL); 4918671SJulian.Pullen@Sun.COM } 4928671SJulian.Pullen@Sun.COM 4938671SJulian.Pullen@Sun.COM n = lifc.lifc_len / (int)sizeof (struct lifreq); 4948671SJulian.Pullen@Sun.COM 4958671SJulian.Pullen@Sun.COM if ((results = calloc(n + 1, sizeof (ad_subnet_t))) == NULL) { 4968671SJulian.Pullen@Sun.COM free(lifc.lifc_buf); 4978671SJulian.Pullen@Sun.COM close(sock); 4988671SJulian.Pullen@Sun.COM return (NULL); 4998671SJulian.Pullen@Sun.COM } 5008671SJulian.Pullen@Sun.COM 5018671SJulian.Pullen@Sun.COM for (i = 0, lifrp = lifc.lifc_req; i < n; i++, lifrp++) { 5028671SJulian.Pullen@Sun.COM if (ioctl(sock, SIOCGLIFFLAGS, lifrp) < 0) 5038671SJulian.Pullen@Sun.COM continue; 5048671SJulian.Pullen@Sun.COM 5058671SJulian.Pullen@Sun.COM if ((lifrp->lifr_flags & IFF_UP) == 0) 5068671SJulian.Pullen@Sun.COM continue; 5078671SJulian.Pullen@Sun.COM 5088671SJulian.Pullen@Sun.COM if (ioctl(sock, SIOCGLIFSUBNET, lifrp) < 0) 5098671SJulian.Pullen@Sun.COM continue; 5108671SJulian.Pullen@Sun.COM 5118671SJulian.Pullen@Sun.COM prefix_len = lifrp->lifr_addrlen; 5128671SJulian.Pullen@Sun.COM 5138671SJulian.Pullen@Sun.COM s = inet_ntoa(((struct sockaddr_in *) 5148671SJulian.Pullen@Sun.COM &lifrp->lifr_addr)->sin_addr); 5158671SJulian.Pullen@Sun.COM 5168671SJulian.Pullen@Sun.COM (void) snprintf(results[i].subnet, sizeof (ad_subnet_t), 5178671SJulian.Pullen@Sun.COM "%s/%d", s, prefix_len); 5188671SJulian.Pullen@Sun.COM } 5198671SJulian.Pullen@Sun.COM 5208671SJulian.Pullen@Sun.COM free(lifc.lifc_buf); 5218671SJulian.Pullen@Sun.COM close(sock); 5228671SJulian.Pullen@Sun.COM 5238671SJulian.Pullen@Sun.COM return (results); 5248671SJulian.Pullen@Sun.COM } 5258671SJulian.Pullen@Sun.COM 5268671SJulian.Pullen@Sun.COM static int 5278671SJulian.Pullen@Sun.COM cmpsubnets(ad_subnet_t *subnets1, ad_subnet_t *subnets2) 5288671SJulian.Pullen@Sun.COM { 5298671SJulian.Pullen@Sun.COM int num_subnets1; 5308671SJulian.Pullen@Sun.COM int num_subnets2; 5318671SJulian.Pullen@Sun.COM boolean_t matched; 5328671SJulian.Pullen@Sun.COM int i, j; 5338671SJulian.Pullen@Sun.COM 5348671SJulian.Pullen@Sun.COM for (i = 0; subnets1[i].subnet[0] != '\0'; i++) 5358671SJulian.Pullen@Sun.COM continue; 5368671SJulian.Pullen@Sun.COM num_subnets1 = i; 5378671SJulian.Pullen@Sun.COM 5388671SJulian.Pullen@Sun.COM for (i = 0; subnets2[i].subnet[0] != '\0'; i++) 5398671SJulian.Pullen@Sun.COM continue; 5408671SJulian.Pullen@Sun.COM num_subnets2 = i; 5418671SJulian.Pullen@Sun.COM 5428671SJulian.Pullen@Sun.COM if (num_subnets1 != num_subnets2) 5438671SJulian.Pullen@Sun.COM return (1); 5448671SJulian.Pullen@Sun.COM 5458671SJulian.Pullen@Sun.COM for (i = 0; i < num_subnets1; i++) { 5468671SJulian.Pullen@Sun.COM matched = B_FALSE; 5478671SJulian.Pullen@Sun.COM for (j = 0; j < num_subnets2; j++) { 5488671SJulian.Pullen@Sun.COM if (strcmp(subnets1[i].subnet, 5498671SJulian.Pullen@Sun.COM subnets2[j].subnet) == 0) { 5508671SJulian.Pullen@Sun.COM matched = B_TRUE; 5518671SJulian.Pullen@Sun.COM break; 5528671SJulian.Pullen@Sun.COM } 5538671SJulian.Pullen@Sun.COM } 5548671SJulian.Pullen@Sun.COM if (!matched) 5558671SJulian.Pullen@Sun.COM return (1); 5568671SJulian.Pullen@Sun.COM } 5578671SJulian.Pullen@Sun.COM return (0); 5588671SJulian.Pullen@Sun.COM } 5598671SJulian.Pullen@Sun.COM 5608671SJulian.Pullen@Sun.COM 5618671SJulian.Pullen@Sun.COM 5628671SJulian.Pullen@Sun.COM 5638671SJulian.Pullen@Sun.COM /* Convert a DN's DC components into a DNS domainname */ 5648671SJulian.Pullen@Sun.COM char * 5658671SJulian.Pullen@Sun.COM DN_to_DNS(const char *dn_name) 5668671SJulian.Pullen@Sun.COM { 5678671SJulian.Pullen@Sun.COM char dns[DNS_MAX_NAME]; 5688671SJulian.Pullen@Sun.COM char *dns_name; 5698671SJulian.Pullen@Sun.COM int i, j; 5708671SJulian.Pullen@Sun.COM int num = 0; 5718671SJulian.Pullen@Sun.COM 5728671SJulian.Pullen@Sun.COM j = 0; 5738671SJulian.Pullen@Sun.COM i = 0; 5748671SJulian.Pullen@Sun.COM 5758671SJulian.Pullen@Sun.COM if (dn_name == NULL) 5768671SJulian.Pullen@Sun.COM return (NULL); 5778671SJulian.Pullen@Sun.COM /* 5788671SJulian.Pullen@Sun.COM * Find all DC=<value> and form DNS name of the 5798671SJulian.Pullen@Sun.COM * form <value1>.<value2>... 5808671SJulian.Pullen@Sun.COM */ 5818671SJulian.Pullen@Sun.COM while (dn_name[i] != '\0') { 5828671SJulian.Pullen@Sun.COM if (strncasecmp(&dn_name[i], "DC=", 3) == 0) { 5838671SJulian.Pullen@Sun.COM i += 3; 5848671SJulian.Pullen@Sun.COM if (dn_name[i] != '\0' && num > 0) 5858671SJulian.Pullen@Sun.COM dns[j++] = '.'; 5868671SJulian.Pullen@Sun.COM while (dn_name[i] != '\0' && 5878671SJulian.Pullen@Sun.COM dn_name[i] != ',' && dn_name[i] != '+') 5888671SJulian.Pullen@Sun.COM dns[j++] = dn_name[i++]; 5898671SJulian.Pullen@Sun.COM num++; 5908671SJulian.Pullen@Sun.COM } else { 5918671SJulian.Pullen@Sun.COM /* Skip attr=value as it is not DC= */ 5928671SJulian.Pullen@Sun.COM while (dn_name[i] != '\0' && 5938671SJulian.Pullen@Sun.COM dn_name[i] != ',' && dn_name[i] != '+') 5948671SJulian.Pullen@Sun.COM i++; 5958671SJulian.Pullen@Sun.COM } 5968671SJulian.Pullen@Sun.COM /* Skip over separator ',' or '+' */ 5978671SJulian.Pullen@Sun.COM if (dn_name[i] != '\0') i++; 5988671SJulian.Pullen@Sun.COM } 5998671SJulian.Pullen@Sun.COM dns[j] = '\0'; 6008671SJulian.Pullen@Sun.COM dns_name = malloc(j + 1); 6018671SJulian.Pullen@Sun.COM if (dns_name != NULL) 6028671SJulian.Pullen@Sun.COM (void) strlcpy(dns_name, dns, j + 1); 6038671SJulian.Pullen@Sun.COM return (dns_name); 6048671SJulian.Pullen@Sun.COM } 6058671SJulian.Pullen@Sun.COM 6068671SJulian.Pullen@Sun.COM 6078671SJulian.Pullen@Sun.COM /* Make a list of subnet object DNs from a list of subnets */ 6088671SJulian.Pullen@Sun.COM static char ** 6098671SJulian.Pullen@Sun.COM subnets_to_DNs(ad_subnet_t *subnets, const char *base_dn) 6108671SJulian.Pullen@Sun.COM { 6118671SJulian.Pullen@Sun.COM char **results; 6128671SJulian.Pullen@Sun.COM int i, j; 6138671SJulian.Pullen@Sun.COM 6148671SJulian.Pullen@Sun.COM for (i = 0; subnets[i].subnet[0] != '\0'; i++) 6158671SJulian.Pullen@Sun.COM continue; 6168671SJulian.Pullen@Sun.COM 6178671SJulian.Pullen@Sun.COM results = calloc(i + 1, sizeof (char *)); 6188671SJulian.Pullen@Sun.COM if (results == NULL) 6198671SJulian.Pullen@Sun.COM return (NULL); 6208671SJulian.Pullen@Sun.COM 6218671SJulian.Pullen@Sun.COM for (i = 0; subnets[i].subnet[0] != '\0'; i++) { 622*12065SKeyur.Desai@Sun.COM (void) asprintf(&results[i], "CN=%s,CN=Subnets,CN=Sites,%s", 623*12065SKeyur.Desai@Sun.COM subnets[i].subnet, base_dn); 624*12065SKeyur.Desai@Sun.COM if (results[i] == NULL) { 6258671SJulian.Pullen@Sun.COM for (j = 0; j < i; j++) 6268671SJulian.Pullen@Sun.COM free(results[j]); 6278671SJulian.Pullen@Sun.COM free(results); 6288671SJulian.Pullen@Sun.COM return (NULL); 6298671SJulian.Pullen@Sun.COM } 6308671SJulian.Pullen@Sun.COM } 6318671SJulian.Pullen@Sun.COM 6328671SJulian.Pullen@Sun.COM return (results); 6338671SJulian.Pullen@Sun.COM } 6348671SJulian.Pullen@Sun.COM 6358671SJulian.Pullen@Sun.COM 6368671SJulian.Pullen@Sun.COM /* Compare SRC RRs; used with qsort() */ 6378671SJulian.Pullen@Sun.COM static int 6388671SJulian.Pullen@Sun.COM srvcmp(idmap_ad_disc_ds_t *s1, idmap_ad_disc_ds_t *s2) 6398671SJulian.Pullen@Sun.COM { 6408671SJulian.Pullen@Sun.COM if (s1->priority < s2->priority) 6418671SJulian.Pullen@Sun.COM return (1); 6428671SJulian.Pullen@Sun.COM else if (s1->priority > s2->priority) 6438671SJulian.Pullen@Sun.COM return (-1); 6448671SJulian.Pullen@Sun.COM 6458671SJulian.Pullen@Sun.COM if (s1->weight < s2->weight) 6468671SJulian.Pullen@Sun.COM return (1); 6478671SJulian.Pullen@Sun.COM else if (s1->weight > s2->weight) 6488671SJulian.Pullen@Sun.COM return (-1); 6498671SJulian.Pullen@Sun.COM 6508671SJulian.Pullen@Sun.COM return (0); 6518671SJulian.Pullen@Sun.COM } 6528671SJulian.Pullen@Sun.COM 6538671SJulian.Pullen@Sun.COM 6548671SJulian.Pullen@Sun.COM /* 6558671SJulian.Pullen@Sun.COM * Query or search the SRV RRs for a given name. 6568671SJulian.Pullen@Sun.COM * 6578671SJulian.Pullen@Sun.COM * If name == NULL then search (as in res_nsearch(3RESOLV), honoring any 6588671SJulian.Pullen@Sun.COM * search list/option), else query (as in res_nquery(3RESOLV)). 6598671SJulian.Pullen@Sun.COM * 6608671SJulian.Pullen@Sun.COM * The output TTL will be the one of the SRV RR with the lowest TTL. 6618671SJulian.Pullen@Sun.COM */ 6628671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t * 6638671SJulian.Pullen@Sun.COM srv_query(res_state state, const char *svc_name, const char *dname, 6648671SJulian.Pullen@Sun.COM char **rrname, uint32_t *ttl) 6658671SJulian.Pullen@Sun.COM { 6668671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t *srv; 66710966SJordan.Brown@Sun.COM idmap_ad_disc_ds_t *srv_res = NULL; 6688671SJulian.Pullen@Sun.COM union { 6698671SJulian.Pullen@Sun.COM HEADER hdr; 6708671SJulian.Pullen@Sun.COM uchar_t buf[NS_MAXMSG]; 6718671SJulian.Pullen@Sun.COM } msg; 6728671SJulian.Pullen@Sun.COM int len, cnt, qdcount, ancount; 6738671SJulian.Pullen@Sun.COM uchar_t *ptr, *eom; 6748671SJulian.Pullen@Sun.COM uchar_t *end; 6758671SJulian.Pullen@Sun.COM uint16_t type; 6768671SJulian.Pullen@Sun.COM /* LINTED E_FUNC_SET_NOT_USED */ 6778671SJulian.Pullen@Sun.COM uint16_t class; 6788671SJulian.Pullen@Sun.COM uint32_t rttl; 6798671SJulian.Pullen@Sun.COM uint16_t size; 6808671SJulian.Pullen@Sun.COM char namebuf[NS_MAXDNAME]; 6818671SJulian.Pullen@Sun.COM 6828671SJulian.Pullen@Sun.COM if (state == NULL) 6838671SJulian.Pullen@Sun.COM return (NULL); 6848671SJulian.Pullen@Sun.COM 6858671SJulian.Pullen@Sun.COM /* Set negative result TTL */ 6868671SJulian.Pullen@Sun.COM *ttl = 5 * 60; 6878671SJulian.Pullen@Sun.COM 6888671SJulian.Pullen@Sun.COM /* 1. query necessary resource records */ 6898671SJulian.Pullen@Sun.COM 6908671SJulian.Pullen@Sun.COM /* Search, querydomain or query */ 6918671SJulian.Pullen@Sun.COM if (rrname != NULL) { 6928671SJulian.Pullen@Sun.COM *rrname = NULL; 6938671SJulian.Pullen@Sun.COM len = res_nsearch(state, svc_name, C_IN, T_SRV, 6948671SJulian.Pullen@Sun.COM msg.buf, sizeof (msg.buf)); 6958671SJulian.Pullen@Sun.COM logger(LOG_DEBUG, "Searching DNS for SRV RRs named '%s'", 6968671SJulian.Pullen@Sun.COM svc_name); 6978671SJulian.Pullen@Sun.COM if (len < 0) { 6988671SJulian.Pullen@Sun.COM logger(LOG_DEBUG, "DNS search for '%s' failed (%s)", 6998671SJulian.Pullen@Sun.COM svc_name, hstrerror(state->res_h_errno)); 7008671SJulian.Pullen@Sun.COM return (NULL); 7018671SJulian.Pullen@Sun.COM } 7028671SJulian.Pullen@Sun.COM } else if (dname != NULL) { 7038671SJulian.Pullen@Sun.COM logger(LOG_DEBUG, 7048671SJulian.Pullen@Sun.COM "Querying DNS for SRV RRs named '%s' for '%s' ", 7058671SJulian.Pullen@Sun.COM svc_name, dname); 7068671SJulian.Pullen@Sun.COM 70710504SKeyur.Desai@Sun.COM len = res_nquerydomain(state, svc_name, dname, C_IN, T_SRV, 70810504SKeyur.Desai@Sun.COM msg.buf, sizeof (msg.buf)); 70910504SKeyur.Desai@Sun.COM 7108671SJulian.Pullen@Sun.COM if (len < 0) { 7118671SJulian.Pullen@Sun.COM logger(LOG_DEBUG, 7128671SJulian.Pullen@Sun.COM "DNS query for '%s' for '%s' failed (%s)", 7138671SJulian.Pullen@Sun.COM svc_name, dname, hstrerror(state->res_h_errno)); 7148671SJulian.Pullen@Sun.COM return (NULL); 7158671SJulian.Pullen@Sun.COM } 7168671SJulian.Pullen@Sun.COM } 7178671SJulian.Pullen@Sun.COM 7188671SJulian.Pullen@Sun.COM if (len > sizeof (msg.buf)) { 7198671SJulian.Pullen@Sun.COM logger(LOG_ERR, "DNS query %ib message doesn't fit" 7208671SJulian.Pullen@Sun.COM " into %ib buffer", 7218671SJulian.Pullen@Sun.COM len, sizeof (msg.buf)); 7228671SJulian.Pullen@Sun.COM return (NULL); 7238671SJulian.Pullen@Sun.COM } 7248671SJulian.Pullen@Sun.COM 7258671SJulian.Pullen@Sun.COM /* 2. parse the reply, skip header and question sections */ 7268671SJulian.Pullen@Sun.COM 7278671SJulian.Pullen@Sun.COM ptr = msg.buf + sizeof (msg.hdr); 7288671SJulian.Pullen@Sun.COM eom = msg.buf + len; 7298671SJulian.Pullen@Sun.COM qdcount = ntohs(msg.hdr.qdcount); 7308671SJulian.Pullen@Sun.COM ancount = ntohs(msg.hdr.ancount); 7318671SJulian.Pullen@Sun.COM 7328671SJulian.Pullen@Sun.COM for (cnt = qdcount; cnt > 0; --cnt) { 7338671SJulian.Pullen@Sun.COM if ((len = dn_skipname(ptr, eom)) < 0) { 7348671SJulian.Pullen@Sun.COM logger(LOG_ERR, "DNS query invalid message format"); 7358671SJulian.Pullen@Sun.COM return (NULL); 7368671SJulian.Pullen@Sun.COM } 7378671SJulian.Pullen@Sun.COM ptr += len + QFIXEDSZ; 7388671SJulian.Pullen@Sun.COM } 7398671SJulian.Pullen@Sun.COM 7408671SJulian.Pullen@Sun.COM /* 3. walk through the answer section */ 7418671SJulian.Pullen@Sun.COM 7428671SJulian.Pullen@Sun.COM srv_res = calloc(ancount + 1, sizeof (idmap_ad_disc_ds_t)); 74310966SJordan.Brown@Sun.COM if (srv_res == NULL) { 74410966SJordan.Brown@Sun.COM logger(LOG_ERR, "Out of memory"); 74510966SJordan.Brown@Sun.COM return (NULL); 74610966SJordan.Brown@Sun.COM } 74710966SJordan.Brown@Sun.COM 7488671SJulian.Pullen@Sun.COM *ttl = (uint32_t)-1; 7498671SJulian.Pullen@Sun.COM 7508671SJulian.Pullen@Sun.COM for (srv = srv_res, cnt = ancount; 7518671SJulian.Pullen@Sun.COM cnt > 0; --cnt, srv++) { 7528671SJulian.Pullen@Sun.COM 7538671SJulian.Pullen@Sun.COM len = dn_expand(msg.buf, eom, ptr, namebuf, 7548671SJulian.Pullen@Sun.COM sizeof (namebuf)); 7558671SJulian.Pullen@Sun.COM if (len < 0) { 7568671SJulian.Pullen@Sun.COM logger(LOG_ERR, "DNS query invalid message format"); 75710966SJordan.Brown@Sun.COM goto err; 7588671SJulian.Pullen@Sun.COM } 75910966SJordan.Brown@Sun.COM if (rrname != NULL && *rrname == NULL) { 7608671SJulian.Pullen@Sun.COM *rrname = strdup(namebuf); 76110966SJordan.Brown@Sun.COM if (*rrname == NULL) { 76210966SJordan.Brown@Sun.COM logger(LOG_ERR, "Out of memory"); 76310966SJordan.Brown@Sun.COM goto err; 76410966SJordan.Brown@Sun.COM } 76510966SJordan.Brown@Sun.COM } 7668671SJulian.Pullen@Sun.COM ptr += len; 7678671SJulian.Pullen@Sun.COM NS_GET16(type, ptr); 7688671SJulian.Pullen@Sun.COM NS_GET16(class, ptr); 7698671SJulian.Pullen@Sun.COM NS_GET32(rttl, ptr); 7708671SJulian.Pullen@Sun.COM NS_GET16(size, ptr); 7718671SJulian.Pullen@Sun.COM if ((end = ptr + size) > eom) { 7728671SJulian.Pullen@Sun.COM logger(LOG_ERR, "DNS query invalid message format"); 77310966SJordan.Brown@Sun.COM goto err; 7748671SJulian.Pullen@Sun.COM } 7758671SJulian.Pullen@Sun.COM 7768671SJulian.Pullen@Sun.COM if (type != T_SRV) { 7778671SJulian.Pullen@Sun.COM ptr = end; 7788671SJulian.Pullen@Sun.COM continue; 7798671SJulian.Pullen@Sun.COM } 7808671SJulian.Pullen@Sun.COM 7818671SJulian.Pullen@Sun.COM NS_GET16(srv->priority, ptr); 7828671SJulian.Pullen@Sun.COM NS_GET16(srv->weight, ptr); 7838671SJulian.Pullen@Sun.COM NS_GET16(srv->port, ptr); 7848671SJulian.Pullen@Sun.COM len = dn_expand(msg.buf, eom, ptr, srv->host, 7858671SJulian.Pullen@Sun.COM sizeof (srv->host)); 7868671SJulian.Pullen@Sun.COM if (len < 0) { 7878671SJulian.Pullen@Sun.COM logger(LOG_ERR, "DNS query invalid SRV record"); 78810966SJordan.Brown@Sun.COM goto err; 7898671SJulian.Pullen@Sun.COM } 7908671SJulian.Pullen@Sun.COM 7918671SJulian.Pullen@Sun.COM if (rttl < *ttl) 7928671SJulian.Pullen@Sun.COM *ttl = rttl; 7938671SJulian.Pullen@Sun.COM 7948671SJulian.Pullen@Sun.COM logger(LOG_DEBUG, "Found %s %d IN SRV [%d][%d] %s:%d", 7958671SJulian.Pullen@Sun.COM namebuf, rttl, srv->priority, srv->weight, srv->host, 7968671SJulian.Pullen@Sun.COM srv->port); 7978671SJulian.Pullen@Sun.COM 7988671SJulian.Pullen@Sun.COM /* 3. move ptr to the end of current record */ 7998671SJulian.Pullen@Sun.COM 8008671SJulian.Pullen@Sun.COM ptr = end; 8018671SJulian.Pullen@Sun.COM } 8028671SJulian.Pullen@Sun.COM 8038671SJulian.Pullen@Sun.COM if (ancount > 1) 8048671SJulian.Pullen@Sun.COM qsort(srv_res, ancount, sizeof (*srv_res), 8058671SJulian.Pullen@Sun.COM (int (*)(const void *, const void *))srvcmp); 8068671SJulian.Pullen@Sun.COM 8078671SJulian.Pullen@Sun.COM return (srv_res); 80810966SJordan.Brown@Sun.COM 80910966SJordan.Brown@Sun.COM err: 81010966SJordan.Brown@Sun.COM free(srv_res); 81110966SJordan.Brown@Sun.COM if (rrname != NULL) { 81210966SJordan.Brown@Sun.COM free(*rrname); 81310966SJordan.Brown@Sun.COM *rrname = NULL; 81410966SJordan.Brown@Sun.COM } 81510966SJordan.Brown@Sun.COM return (NULL); 8168671SJulian.Pullen@Sun.COM } 8178671SJulian.Pullen@Sun.COM 8188671SJulian.Pullen@Sun.COM 8198671SJulian.Pullen@Sun.COM /* 8208671SJulian.Pullen@Sun.COM * A utility function to bind to a Directory server 8218671SJulian.Pullen@Sun.COM */ 8228671SJulian.Pullen@Sun.COM 823*12065SKeyur.Desai@Sun.COM static 824*12065SKeyur.Desai@Sun.COM LDAP * 8258671SJulian.Pullen@Sun.COM ldap_lookup_init(idmap_ad_disc_ds_t *ds) 8268671SJulian.Pullen@Sun.COM { 8278671SJulian.Pullen@Sun.COM int i; 8288671SJulian.Pullen@Sun.COM int rc, ldversion; 8298671SJulian.Pullen@Sun.COM int zero = 0; 8308671SJulian.Pullen@Sun.COM int timeoutms = 5 * 1000; 8318671SJulian.Pullen@Sun.COM char *saslmech = "GSSAPI"; 8328671SJulian.Pullen@Sun.COM uint32_t saslflags = LDAP_SASL_INTERACTIVE; 8338671SJulian.Pullen@Sun.COM LDAP *ld = NULL; 8348671SJulian.Pullen@Sun.COM 8358671SJulian.Pullen@Sun.COM for (i = 0; ds[i].host[0] != '\0'; i++) { 8368671SJulian.Pullen@Sun.COM ld = ldap_init(ds[i].host, ds[i].port); 8378671SJulian.Pullen@Sun.COM if (ld == NULL) { 8388671SJulian.Pullen@Sun.COM logger(LOG_DEBUG, "Couldn't connect to " 8398671SJulian.Pullen@Sun.COM "AD DC %s:%d (%s)", 8408671SJulian.Pullen@Sun.COM ds[i].host, ds[i].port, 8418671SJulian.Pullen@Sun.COM strerror(errno)); 8428671SJulian.Pullen@Sun.COM continue; 8438671SJulian.Pullen@Sun.COM } 8448671SJulian.Pullen@Sun.COM 8458671SJulian.Pullen@Sun.COM ldversion = LDAP_VERSION3; 8468671SJulian.Pullen@Sun.COM (void) ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, 8478671SJulian.Pullen@Sun.COM &ldversion); 8488671SJulian.Pullen@Sun.COM (void) ldap_set_option(ld, LDAP_OPT_REFERRALS, 8498671SJulian.Pullen@Sun.COM LDAP_OPT_OFF); 8508671SJulian.Pullen@Sun.COM (void) ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &zero); 8518671SJulian.Pullen@Sun.COM (void) ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &zero); 8528671SJulian.Pullen@Sun.COM /* setup TCP/IP connect timeout */ 8538671SJulian.Pullen@Sun.COM (void) ldap_set_option(ld, LDAP_X_OPT_CONNECT_TIMEOUT, 8548671SJulian.Pullen@Sun.COM &timeoutms); 8558671SJulian.Pullen@Sun.COM (void) ldap_set_option(ld, LDAP_OPT_RESTART, 8568671SJulian.Pullen@Sun.COM LDAP_OPT_ON); 8578671SJulian.Pullen@Sun.COM 85810706SJulian.Pullen@Sun.COM rc = adutils_set_thread_functions(ld); 85910706SJulian.Pullen@Sun.COM if (rc != LDAP_SUCCESS) { 86010706SJulian.Pullen@Sun.COM /* Error has already been logged */ 86110706SJulian.Pullen@Sun.COM (void) ldap_unbind(ld); 86210706SJulian.Pullen@Sun.COM ld = NULL; 86310706SJulian.Pullen@Sun.COM continue; 86410706SJulian.Pullen@Sun.COM } 86510706SJulian.Pullen@Sun.COM 8668671SJulian.Pullen@Sun.COM rc = ldap_sasl_interactive_bind_s(ld, "" /* binddn */, 8678671SJulian.Pullen@Sun.COM saslmech, NULL, NULL, saslflags, &saslcallback, 8688671SJulian.Pullen@Sun.COM NULL /* defaults */); 8698671SJulian.Pullen@Sun.COM if (rc == LDAP_SUCCESS) 8708671SJulian.Pullen@Sun.COM break; 8718671SJulian.Pullen@Sun.COM 8728671SJulian.Pullen@Sun.COM logger(LOG_INFO, "LDAP SASL bind to %s:%d failed (%s)", 8738671SJulian.Pullen@Sun.COM ds[i].host, ds[i].port, ldap_err2string(rc)); 8748671SJulian.Pullen@Sun.COM (void) ldap_unbind(ld); 8758671SJulian.Pullen@Sun.COM ld = NULL; 8768671SJulian.Pullen@Sun.COM } 8778671SJulian.Pullen@Sun.COM return (ld); 8788671SJulian.Pullen@Sun.COM } 8798671SJulian.Pullen@Sun.COM 8808671SJulian.Pullen@Sun.COM 8818671SJulian.Pullen@Sun.COM 8828671SJulian.Pullen@Sun.COM /* 8838671SJulian.Pullen@Sun.COM * A utility function to get the value of some attribute of one of one 8848671SJulian.Pullen@Sun.COM * or more AD LDAP objects named by the dn_list; first found one wins. 8858671SJulian.Pullen@Sun.COM */ 8868671SJulian.Pullen@Sun.COM static char * 8878671SJulian.Pullen@Sun.COM ldap_lookup_entry_attr(LDAP **ld, idmap_ad_disc_ds_t *domainControllers, 8888671SJulian.Pullen@Sun.COM char **dn_list, char *attr) 8898671SJulian.Pullen@Sun.COM { 8908671SJulian.Pullen@Sun.COM int i; 8918671SJulian.Pullen@Sun.COM int rc; 8928671SJulian.Pullen@Sun.COM int scope = LDAP_SCOPE_BASE; 8938671SJulian.Pullen@Sun.COM char *attrs[2]; 8948671SJulian.Pullen@Sun.COM LDAPMessage *results = NULL; 8958671SJulian.Pullen@Sun.COM LDAPMessage *entry; 8968671SJulian.Pullen@Sun.COM char **values = NULL; 8978671SJulian.Pullen@Sun.COM char *val = NULL; 8988671SJulian.Pullen@Sun.COM 8998671SJulian.Pullen@Sun.COM attrs[0] = attr; 9008671SJulian.Pullen@Sun.COM attrs[1] = NULL; 9018671SJulian.Pullen@Sun.COM 9028671SJulian.Pullen@Sun.COM if (*ld == NULL) 9038671SJulian.Pullen@Sun.COM *ld = ldap_lookup_init(domainControllers); 9048671SJulian.Pullen@Sun.COM 9058671SJulian.Pullen@Sun.COM if (*ld == NULL) 9068671SJulian.Pullen@Sun.COM return (NULL); 9078671SJulian.Pullen@Sun.COM 9088671SJulian.Pullen@Sun.COM for (i = 0; dn_list[i] != NULL; i++) { 9098671SJulian.Pullen@Sun.COM rc = ldap_search_s(*ld, dn_list[i], scope, 9108671SJulian.Pullen@Sun.COM "(objectclass=*)", attrs, 0, &results); 9118671SJulian.Pullen@Sun.COM if (rc == LDAP_SUCCESS) { 9128671SJulian.Pullen@Sun.COM for (entry = ldap_first_entry(*ld, results); 9138671SJulian.Pullen@Sun.COM entry != NULL && values == NULL; 9148671SJulian.Pullen@Sun.COM entry = ldap_next_entry(*ld, entry)) { 9158671SJulian.Pullen@Sun.COM values = ldap_get_values( 9168671SJulian.Pullen@Sun.COM *ld, entry, attr); 9178671SJulian.Pullen@Sun.COM } 9188671SJulian.Pullen@Sun.COM 9198671SJulian.Pullen@Sun.COM if (values != NULL) { 9208671SJulian.Pullen@Sun.COM (void) ldap_msgfree(results); 9218671SJulian.Pullen@Sun.COM val = strdup(values[0]); 9228671SJulian.Pullen@Sun.COM ldap_value_free(values); 9238671SJulian.Pullen@Sun.COM return (val); 9248671SJulian.Pullen@Sun.COM } 9258671SJulian.Pullen@Sun.COM } 9268671SJulian.Pullen@Sun.COM if (results != NULL) { 9278671SJulian.Pullen@Sun.COM (void) ldap_msgfree(results); 9288671SJulian.Pullen@Sun.COM results = NULL; 9298671SJulian.Pullen@Sun.COM } 9308671SJulian.Pullen@Sun.COM } 9318671SJulian.Pullen@Sun.COM 9328671SJulian.Pullen@Sun.COM return (NULL); 9338671SJulian.Pullen@Sun.COM } 9348671SJulian.Pullen@Sun.COM 9358671SJulian.Pullen@Sun.COM 9368671SJulian.Pullen@Sun.COM /* 9378671SJulian.Pullen@Sun.COM * Lookup the trusted domains in the global catalog. 9388671SJulian.Pullen@Sun.COM * 9398671SJulian.Pullen@Sun.COM * Returns: 9408671SJulian.Pullen@Sun.COM * array of trusted domains which is terminated by 9418671SJulian.Pullen@Sun.COM * an empty trusted domain. 9428671SJulian.Pullen@Sun.COM * NULL an error occured 9438671SJulian.Pullen@Sun.COM */ 9448671SJulian.Pullen@Sun.COM ad_disc_trusteddomains_t * 9458671SJulian.Pullen@Sun.COM ldap_lookup_trusted_domains(LDAP **ld, idmap_ad_disc_ds_t *globalCatalog, 9468671SJulian.Pullen@Sun.COM char *base_dn) 9478671SJulian.Pullen@Sun.COM { 9488671SJulian.Pullen@Sun.COM int scope = LDAP_SCOPE_SUBTREE; 9498671SJulian.Pullen@Sun.COM char *attrs[3]; 9508671SJulian.Pullen@Sun.COM int rc; 9518671SJulian.Pullen@Sun.COM LDAPMessage *results = NULL; 9528671SJulian.Pullen@Sun.COM LDAPMessage *entry; 9538671SJulian.Pullen@Sun.COM char *filter; 9548671SJulian.Pullen@Sun.COM char **partner = NULL; 9558671SJulian.Pullen@Sun.COM char **direction = NULL; 9568671SJulian.Pullen@Sun.COM int num = 0; 9578671SJulian.Pullen@Sun.COM ad_disc_trusteddomains_t *trusted_domains = NULL; 9588671SJulian.Pullen@Sun.COM 9598671SJulian.Pullen@Sun.COM 9608671SJulian.Pullen@Sun.COM if (*ld == NULL) 9618671SJulian.Pullen@Sun.COM *ld = ldap_lookup_init(globalCatalog); 9628671SJulian.Pullen@Sun.COM 9638671SJulian.Pullen@Sun.COM if (*ld == NULL) 9648671SJulian.Pullen@Sun.COM return (NULL); 9658671SJulian.Pullen@Sun.COM 9668671SJulian.Pullen@Sun.COM attrs[0] = "trustPartner"; 9678671SJulian.Pullen@Sun.COM attrs[1] = "trustDirection"; 9688671SJulian.Pullen@Sun.COM attrs[2] = NULL; 9698671SJulian.Pullen@Sun.COM 9708671SJulian.Pullen@Sun.COM /* trustDirection values - inbound = 1 and bidirectional = 3 */ 9718671SJulian.Pullen@Sun.COM filter = "(&(objectclass=trustedDomain)" 9728671SJulian.Pullen@Sun.COM "(|(trustDirection=3)(trustDirection=1)))"; 9738671SJulian.Pullen@Sun.COM 9748671SJulian.Pullen@Sun.COM rc = ldap_search_s(*ld, base_dn, scope, filter, attrs, 0, &results); 9758671SJulian.Pullen@Sun.COM if (rc == LDAP_SUCCESS) { 9768671SJulian.Pullen@Sun.COM for (entry = ldap_first_entry(*ld, results); 9778671SJulian.Pullen@Sun.COM entry != NULL; entry = ldap_next_entry(*ld, entry)) { 9788671SJulian.Pullen@Sun.COM partner = ldap_get_values(*ld, entry, "trustPartner"); 9798671SJulian.Pullen@Sun.COM direction = ldap_get_values( 9808671SJulian.Pullen@Sun.COM *ld, entry, "trustDirection"); 9818671SJulian.Pullen@Sun.COM 9828671SJulian.Pullen@Sun.COM if (partner != NULL && direction != NULL) { 9838671SJulian.Pullen@Sun.COM num++; 984*12065SKeyur.Desai@Sun.COM void *tmp = realloc(trusted_domains, 9858671SJulian.Pullen@Sun.COM (num + 1) * 9868671SJulian.Pullen@Sun.COM sizeof (ad_disc_trusteddomains_t)); 987*12065SKeyur.Desai@Sun.COM if (tmp == NULL) { 988*12065SKeyur.Desai@Sun.COM free(trusted_domains); 9898671SJulian.Pullen@Sun.COM ldap_value_free(partner); 9908671SJulian.Pullen@Sun.COM ldap_value_free(direction); 9918671SJulian.Pullen@Sun.COM ldap_msgfree(results); 9928671SJulian.Pullen@Sun.COM return (NULL); 9938671SJulian.Pullen@Sun.COM } 994*12065SKeyur.Desai@Sun.COM trusted_domains = tmp; 9958671SJulian.Pullen@Sun.COM /* Last element should be zero */ 9968671SJulian.Pullen@Sun.COM memset(&trusted_domains[num], 0, 9978671SJulian.Pullen@Sun.COM sizeof (ad_disc_trusteddomains_t)); 9988671SJulian.Pullen@Sun.COM strcpy(trusted_domains[num - 1].domain, 9998671SJulian.Pullen@Sun.COM partner[0]); 10008671SJulian.Pullen@Sun.COM trusted_domains[num - 1].direction = 10018671SJulian.Pullen@Sun.COM atoi(direction[0]); 10028671SJulian.Pullen@Sun.COM } 10038671SJulian.Pullen@Sun.COM if (partner != NULL) 10048671SJulian.Pullen@Sun.COM ldap_value_free(partner); 10058671SJulian.Pullen@Sun.COM if (direction != NULL) 10068671SJulian.Pullen@Sun.COM ldap_value_free(direction); 10078671SJulian.Pullen@Sun.COM } 10088671SJulian.Pullen@Sun.COM } else if (rc == LDAP_NO_RESULTS_RETURNED) { 10098671SJulian.Pullen@Sun.COM /* This is not an error - return empty trusted domain */ 10108671SJulian.Pullen@Sun.COM trusted_domains = calloc(1, sizeof (ad_disc_trusteddomains_t)); 10118671SJulian.Pullen@Sun.COM } 10128671SJulian.Pullen@Sun.COM if (results != NULL) 10138671SJulian.Pullen@Sun.COM ldap_msgfree(results); 10148671SJulian.Pullen@Sun.COM 10158671SJulian.Pullen@Sun.COM return (trusted_domains); 10168671SJulian.Pullen@Sun.COM } 10178671SJulian.Pullen@Sun.COM 10188671SJulian.Pullen@Sun.COM 10198671SJulian.Pullen@Sun.COM /* 10208671SJulian.Pullen@Sun.COM * This functions finds all the domains in a forest. 10218671SJulian.Pullen@Sun.COM */ 10228671SJulian.Pullen@Sun.COM ad_disc_domainsinforest_t * 10238671SJulian.Pullen@Sun.COM ldap_lookup_domains_in_forest(LDAP **ld, idmap_ad_disc_ds_t *globalCatalogs) 10248671SJulian.Pullen@Sun.COM { 10259744SJordan.Brown@Sun.COM static char *attrs[] = { 10269744SJordan.Brown@Sun.COM "objectSid", 10279744SJordan.Brown@Sun.COM NULL, 10289744SJordan.Brown@Sun.COM }; 10298671SJulian.Pullen@Sun.COM int rc; 10308671SJulian.Pullen@Sun.COM LDAPMessage *result = NULL; 10318671SJulian.Pullen@Sun.COM LDAPMessage *entry; 10329744SJordan.Brown@Sun.COM int ndomains = 0; 10339744SJordan.Brown@Sun.COM int nresults; 10348671SJulian.Pullen@Sun.COM ad_disc_domainsinforest_t *domains = NULL; 10358671SJulian.Pullen@Sun.COM 10368671SJulian.Pullen@Sun.COM if (*ld == NULL) 10378671SJulian.Pullen@Sun.COM *ld = ldap_lookup_init(globalCatalogs); 10388671SJulian.Pullen@Sun.COM 10398671SJulian.Pullen@Sun.COM if (*ld == NULL) 10408671SJulian.Pullen@Sun.COM return (NULL); 10418671SJulian.Pullen@Sun.COM 10429744SJordan.Brown@Sun.COM logger(LOG_DEBUG, "Looking for domains in forest..."); 10439744SJordan.Brown@Sun.COM /* Find domains */ 10449744SJordan.Brown@Sun.COM rc = ldap_search_s(*ld, "", LDAP_SCOPE_SUBTREE, 10459744SJordan.Brown@Sun.COM "(objectClass=Domain)", attrs, 0, &result); 10469744SJordan.Brown@Sun.COM if (rc != LDAP_SUCCESS) 10479744SJordan.Brown@Sun.COM goto err; 10489744SJordan.Brown@Sun.COM 10499744SJordan.Brown@Sun.COM nresults = ldap_count_entries(*ld, result); 10509744SJordan.Brown@Sun.COM domains = calloc(nresults + 1, sizeof (*domains)); 10519744SJordan.Brown@Sun.COM if (domains == NULL) 10529744SJordan.Brown@Sun.COM goto err; 10538671SJulian.Pullen@Sun.COM 10549744SJordan.Brown@Sun.COM for (entry = ldap_first_entry(*ld, result); 10559744SJordan.Brown@Sun.COM entry != NULL; 10569744SJordan.Brown@Sun.COM entry = ldap_next_entry(*ld, entry)) { 10579744SJordan.Brown@Sun.COM struct berval **sid_ber; 10589744SJordan.Brown@Sun.COM adutils_sid_t sid; 10599744SJordan.Brown@Sun.COM char *sid_str; 10609744SJordan.Brown@Sun.COM char *name; 106110966SJordan.Brown@Sun.COM char *dn; 10628671SJulian.Pullen@Sun.COM 10639744SJordan.Brown@Sun.COM sid_ber = ldap_get_values_len(*ld, entry, 10649744SJordan.Brown@Sun.COM "objectSid"); 10659744SJordan.Brown@Sun.COM if (sid_ber == NULL) 10669744SJordan.Brown@Sun.COM continue; 10679744SJordan.Brown@Sun.COM 10689744SJordan.Brown@Sun.COM rc = adutils_getsid(sid_ber[0], &sid); 10699744SJordan.Brown@Sun.COM ldap_value_free_len(sid_ber); 10709744SJordan.Brown@Sun.COM if (rc < 0) 10719744SJordan.Brown@Sun.COM goto err; 10728671SJulian.Pullen@Sun.COM 10739744SJordan.Brown@Sun.COM if ((sid_str = adutils_sid2txt(&sid)) == NULL) 10749744SJordan.Brown@Sun.COM goto err; 10759744SJordan.Brown@Sun.COM 10769744SJordan.Brown@Sun.COM strcpy(domains[ndomains].sid, sid_str); 10779744SJordan.Brown@Sun.COM free(sid_str); 10789744SJordan.Brown@Sun.COM 107910966SJordan.Brown@Sun.COM dn = ldap_get_dn(*ld, entry); 108010966SJordan.Brown@Sun.COM name = DN_to_DNS(dn); 108110966SJordan.Brown@Sun.COM free(dn); 10829744SJordan.Brown@Sun.COM if (name == NULL) 10839744SJordan.Brown@Sun.COM goto err; 10849744SJordan.Brown@Sun.COM 10859744SJordan.Brown@Sun.COM strcpy(domains[ndomains].domain, name); 10869744SJordan.Brown@Sun.COM free(name); 10879744SJordan.Brown@Sun.COM 10889744SJordan.Brown@Sun.COM logger(LOG_DEBUG, " found %s", domains[ndomains].domain); 10899744SJordan.Brown@Sun.COM 10909744SJordan.Brown@Sun.COM ndomains++; 10918671SJulian.Pullen@Sun.COM } 10929744SJordan.Brown@Sun.COM 10939744SJordan.Brown@Sun.COM if (ndomains == 0) 10949744SJordan.Brown@Sun.COM goto err; 10959744SJordan.Brown@Sun.COM 10969744SJordan.Brown@Sun.COM if (ndomains < nresults) { 10979744SJordan.Brown@Sun.COM ad_disc_domainsinforest_t *tmp; 109810122SJordan.Brown@Sun.COM tmp = realloc(domains, (ndomains + 1) * sizeof (*domains)); 10999744SJordan.Brown@Sun.COM if (tmp == NULL) 11009744SJordan.Brown@Sun.COM goto err; 11019744SJordan.Brown@Sun.COM domains = tmp; 11029744SJordan.Brown@Sun.COM } 11039744SJordan.Brown@Sun.COM 11048671SJulian.Pullen@Sun.COM if (result != NULL) 11058671SJulian.Pullen@Sun.COM ldap_msgfree(result); 11068671SJulian.Pullen@Sun.COM 11078671SJulian.Pullen@Sun.COM return (domains); 11089744SJordan.Brown@Sun.COM 11099744SJordan.Brown@Sun.COM err: 11109744SJordan.Brown@Sun.COM free(domains); 11119744SJordan.Brown@Sun.COM if (result != NULL) 11129744SJordan.Brown@Sun.COM ldap_msgfree(result); 11139744SJordan.Brown@Sun.COM return (NULL); 11148671SJulian.Pullen@Sun.COM } 11158671SJulian.Pullen@Sun.COM 11168671SJulian.Pullen@Sun.COM 11178671SJulian.Pullen@Sun.COM ad_disc_t 11188671SJulian.Pullen@Sun.COM ad_disc_init(void) 11198671SJulian.Pullen@Sun.COM { 11208671SJulian.Pullen@Sun.COM struct ad_disc *ctx; 11218671SJulian.Pullen@Sun.COM ctx = calloc(1, sizeof (struct ad_disc)); 11228671SJulian.Pullen@Sun.COM if (ctx != NULL) 11238671SJulian.Pullen@Sun.COM DO_RES_NINIT(ctx); 11248671SJulian.Pullen@Sun.COM 11258671SJulian.Pullen@Sun.COM ctx->domain_name.type = AD_STRING; 11268671SJulian.Pullen@Sun.COM ctx->domain_controller.type = AD_DIRECTORY; 11278671SJulian.Pullen@Sun.COM ctx->site_name.type = AD_STRING; 11288671SJulian.Pullen@Sun.COM ctx->forest_name.type = AD_STRING; 11298671SJulian.Pullen@Sun.COM ctx->global_catalog.type = AD_DIRECTORY; 11308671SJulian.Pullen@Sun.COM ctx->domains_in_forest.type = AD_DOMAINS_IN_FOREST; 11318671SJulian.Pullen@Sun.COM ctx->trusted_domains.type = AD_TRUSTED_DOMAINS; 11328671SJulian.Pullen@Sun.COM /* Site specific versions */ 11338671SJulian.Pullen@Sun.COM ctx->site_domain_controller.type = AD_DIRECTORY; 11348671SJulian.Pullen@Sun.COM ctx->site_global_catalog.type = AD_DIRECTORY; 11358671SJulian.Pullen@Sun.COM return (ctx); 11368671SJulian.Pullen@Sun.COM } 11378671SJulian.Pullen@Sun.COM 11388671SJulian.Pullen@Sun.COM 11398671SJulian.Pullen@Sun.COM void 11408671SJulian.Pullen@Sun.COM ad_disc_fini(ad_disc_t ctx) 11418671SJulian.Pullen@Sun.COM { 11428671SJulian.Pullen@Sun.COM if (ctx == NULL) 11438671SJulian.Pullen@Sun.COM return; 11448671SJulian.Pullen@Sun.COM 11458671SJulian.Pullen@Sun.COM if (ctx->res_ninitted) 11468671SJulian.Pullen@Sun.COM res_ndestroy(&ctx->res_state); 11478671SJulian.Pullen@Sun.COM 11488671SJulian.Pullen@Sun.COM if (ctx->subnets != NULL) 11498671SJulian.Pullen@Sun.COM free(ctx->subnets); 11508671SJulian.Pullen@Sun.COM 11518671SJulian.Pullen@Sun.COM if (ctx->domain_name.value != NULL) 11528671SJulian.Pullen@Sun.COM free(ctx->domain_name.value); 11538671SJulian.Pullen@Sun.COM 11548671SJulian.Pullen@Sun.COM if (ctx->domain_controller.value != NULL) 11558671SJulian.Pullen@Sun.COM free(ctx->domain_controller.value); 11568671SJulian.Pullen@Sun.COM 11578671SJulian.Pullen@Sun.COM if (ctx->site_name.value != NULL) 11588671SJulian.Pullen@Sun.COM free(ctx->site_name.value); 11598671SJulian.Pullen@Sun.COM 11608671SJulian.Pullen@Sun.COM if (ctx->forest_name.value != NULL) 11618671SJulian.Pullen@Sun.COM free(ctx->forest_name.value); 11628671SJulian.Pullen@Sun.COM 11638671SJulian.Pullen@Sun.COM if (ctx->global_catalog.value != NULL) 11648671SJulian.Pullen@Sun.COM free(ctx->global_catalog.value); 11658671SJulian.Pullen@Sun.COM 11668671SJulian.Pullen@Sun.COM if (ctx->domains_in_forest.value != NULL) 11678671SJulian.Pullen@Sun.COM free(ctx->domains_in_forest.value); 11688671SJulian.Pullen@Sun.COM 11698671SJulian.Pullen@Sun.COM if (ctx->trusted_domains.value != NULL) 11708671SJulian.Pullen@Sun.COM free(ctx->trusted_domains.value); 11718671SJulian.Pullen@Sun.COM 11728671SJulian.Pullen@Sun.COM /* Site specific versions */ 11738671SJulian.Pullen@Sun.COM if (ctx->site_domain_controller.value != NULL) 11748671SJulian.Pullen@Sun.COM free(ctx->site_domain_controller.value); 11758671SJulian.Pullen@Sun.COM 11768671SJulian.Pullen@Sun.COM if (ctx->site_global_catalog.value != NULL) 11778671SJulian.Pullen@Sun.COM free(ctx->site_global_catalog.value); 11788671SJulian.Pullen@Sun.COM 11798671SJulian.Pullen@Sun.COM free(ctx); 11808671SJulian.Pullen@Sun.COM } 11818671SJulian.Pullen@Sun.COM 11828671SJulian.Pullen@Sun.COM void 11838671SJulian.Pullen@Sun.COM ad_disc_refresh(ad_disc_t ctx) 11848671SJulian.Pullen@Sun.COM { 11858671SJulian.Pullen@Sun.COM if (ctx->res_ninitted) 11868671SJulian.Pullen@Sun.COM res_ndestroy(&ctx->res_state); 11878671SJulian.Pullen@Sun.COM (void) memset(&ctx->res_state, 0, sizeof (ctx->res_state)); 11888671SJulian.Pullen@Sun.COM ctx->res_ninitted = res_ninit(&ctx->res_state) != -1; 11898671SJulian.Pullen@Sun.COM 11908671SJulian.Pullen@Sun.COM if (ctx->domain_name.state == AD_STATE_AUTO) 11918671SJulian.Pullen@Sun.COM ctx->domain_name.state = AD_STATE_INVALID; 11928671SJulian.Pullen@Sun.COM 11938671SJulian.Pullen@Sun.COM if (ctx->domain_controller.state == AD_STATE_AUTO) 11948671SJulian.Pullen@Sun.COM ctx->domain_controller.state = AD_STATE_INVALID; 11958671SJulian.Pullen@Sun.COM 11968671SJulian.Pullen@Sun.COM if (ctx->site_name.state == AD_STATE_AUTO) 11978671SJulian.Pullen@Sun.COM ctx->site_name.state = AD_STATE_INVALID; 11988671SJulian.Pullen@Sun.COM 11998671SJulian.Pullen@Sun.COM if (ctx->forest_name.state == AD_STATE_AUTO) 12008671SJulian.Pullen@Sun.COM ctx->forest_name.state = AD_STATE_INVALID; 12018671SJulian.Pullen@Sun.COM 12028671SJulian.Pullen@Sun.COM if (ctx->global_catalog.state == AD_STATE_AUTO) 12038671SJulian.Pullen@Sun.COM ctx->global_catalog.state = AD_STATE_INVALID; 12048671SJulian.Pullen@Sun.COM 12058671SJulian.Pullen@Sun.COM if (ctx->domains_in_forest.state == AD_STATE_AUTO) 12068671SJulian.Pullen@Sun.COM ctx->domains_in_forest.state = AD_STATE_INVALID; 12078671SJulian.Pullen@Sun.COM 12088671SJulian.Pullen@Sun.COM if (ctx->trusted_domains.state == AD_STATE_AUTO) 12098671SJulian.Pullen@Sun.COM ctx->trusted_domains.state = AD_STATE_INVALID; 12108671SJulian.Pullen@Sun.COM 12118671SJulian.Pullen@Sun.COM if (ctx->site_domain_controller.state == AD_STATE_AUTO) 12128671SJulian.Pullen@Sun.COM ctx->site_domain_controller.state = AD_STATE_INVALID; 12138671SJulian.Pullen@Sun.COM 12148671SJulian.Pullen@Sun.COM if (ctx->site_global_catalog.state == AD_STATE_AUTO) 12158671SJulian.Pullen@Sun.COM ctx->site_global_catalog.state = AD_STATE_INVALID; 12168671SJulian.Pullen@Sun.COM } 12178671SJulian.Pullen@Sun.COM 12188671SJulian.Pullen@Sun.COM 1219*12065SKeyur.Desai@Sun.COM /* 1220*12065SKeyur.Desai@Sun.COM * Called when the discovery cycle is done. Sets a master TTL 1221*12065SKeyur.Desai@Sun.COM * that will avoid doing new time-based discoveries too soon after 1222*12065SKeyur.Desai@Sun.COM * the last discovery cycle. Most interesting when the discovery 1223*12065SKeyur.Desai@Sun.COM * cycle failed, because then the TTLs on the individual items will 1224*12065SKeyur.Desai@Sun.COM * not be updated and may go stale. 1225*12065SKeyur.Desai@Sun.COM */ 1226*12065SKeyur.Desai@Sun.COM void 1227*12065SKeyur.Desai@Sun.COM ad_disc_done(ad_disc_t ctx) 1228*12065SKeyur.Desai@Sun.COM { 1229*12065SKeyur.Desai@Sun.COM time_t now = time(NULL); 1230*12065SKeyur.Desai@Sun.COM 1231*12065SKeyur.Desai@Sun.COM ctx->expires_not_before = now + MINIMUM_TTL; 1232*12065SKeyur.Desai@Sun.COM ctx->expires_not_after = now + MAXIMUM_TTL; 1233*12065SKeyur.Desai@Sun.COM } 1234*12065SKeyur.Desai@Sun.COM 12358671SJulian.Pullen@Sun.COM 12368671SJulian.Pullen@Sun.COM /* Discover joined Active Directory domainName */ 12378671SJulian.Pullen@Sun.COM static ad_item_t * 12388671SJulian.Pullen@Sun.COM validate_DomainName(ad_disc_t ctx) 12398671SJulian.Pullen@Sun.COM { 12408671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t *domain_controller = NULL; 12418671SJulian.Pullen@Sun.COM char *dname, *srvname; 12428671SJulian.Pullen@Sun.COM uint32_t ttl = 0; 12439744SJordan.Brown@Sun.COM int len; 12448671SJulian.Pullen@Sun.COM 12458671SJulian.Pullen@Sun.COM if (is_valid(&ctx->domain_name)) 12468671SJulian.Pullen@Sun.COM return (&ctx->domain_name); 12478671SJulian.Pullen@Sun.COM 12488671SJulian.Pullen@Sun.COM 12498671SJulian.Pullen@Sun.COM /* Try to find our domain by searching for DCs for it */ 12508671SJulian.Pullen@Sun.COM DO_RES_NINIT(ctx); 12518671SJulian.Pullen@Sun.COM domain_controller = srv_query(&ctx->res_state, LDAP_SRV_HEAD 12528671SJulian.Pullen@Sun.COM DC_SRV_TAIL, ctx->domain_name.value, &srvname, &ttl); 12538671SJulian.Pullen@Sun.COM 12548671SJulian.Pullen@Sun.COM /* 12558671SJulian.Pullen@Sun.COM * If we can't find DCs by via res_nsearch() then there's no 12568671SJulian.Pullen@Sun.COM * point in trying anything else to discover the AD domain name. 12578671SJulian.Pullen@Sun.COM */ 12588671SJulian.Pullen@Sun.COM if (domain_controller == NULL) 12598671SJulian.Pullen@Sun.COM return (NULL); 12608671SJulian.Pullen@Sun.COM 12618671SJulian.Pullen@Sun.COM free(domain_controller); 12628671SJulian.Pullen@Sun.COM /* 12638671SJulian.Pullen@Sun.COM * We have the FQDN of the SRV RR name, so now we extract the 12648671SJulian.Pullen@Sun.COM * domainname suffix from it. 12658671SJulian.Pullen@Sun.COM */ 12668671SJulian.Pullen@Sun.COM dname = strdup(srvname + strlen(LDAP_SRV_HEAD DC_SRV_TAIL) + 12678671SJulian.Pullen@Sun.COM 1 /* for the dot between RR name and domainname */); 12688671SJulian.Pullen@Sun.COM 12698671SJulian.Pullen@Sun.COM free(srvname); 12708671SJulian.Pullen@Sun.COM 12718671SJulian.Pullen@Sun.COM if (dname == NULL) { 12728671SJulian.Pullen@Sun.COM logger(LOG_ERR, "Out of memory"); 12738671SJulian.Pullen@Sun.COM return (NULL); 12748671SJulian.Pullen@Sun.COM } 12758671SJulian.Pullen@Sun.COM 12768671SJulian.Pullen@Sun.COM /* Eat any trailing dot */ 12779744SJordan.Brown@Sun.COM len = strlen(dname); 127810122SJordan.Brown@Sun.COM if (len > 0 && dname[len - 1] == '.') 127910122SJordan.Brown@Sun.COM dname[len - 1] = '\0'; 12808671SJulian.Pullen@Sun.COM 12818671SJulian.Pullen@Sun.COM update_item(&ctx->domain_name, dname, AD_STATE_AUTO, ttl); 12828671SJulian.Pullen@Sun.COM 12838671SJulian.Pullen@Sun.COM return (&ctx->domain_name); 12848671SJulian.Pullen@Sun.COM } 12858671SJulian.Pullen@Sun.COM 12868671SJulian.Pullen@Sun.COM 12878671SJulian.Pullen@Sun.COM char * 12888671SJulian.Pullen@Sun.COM ad_disc_get_DomainName(ad_disc_t ctx, boolean_t *auto_discovered) 12898671SJulian.Pullen@Sun.COM { 12908671SJulian.Pullen@Sun.COM char *domain_name = NULL; 12918671SJulian.Pullen@Sun.COM ad_item_t *domain_name_item; 12928671SJulian.Pullen@Sun.COM 12938671SJulian.Pullen@Sun.COM domain_name_item = validate_DomainName(ctx); 12948671SJulian.Pullen@Sun.COM 12958671SJulian.Pullen@Sun.COM if (domain_name_item) { 12968671SJulian.Pullen@Sun.COM domain_name = strdup(domain_name_item->value); 12978671SJulian.Pullen@Sun.COM if (auto_discovered != NULL) 12988671SJulian.Pullen@Sun.COM *auto_discovered = 12998671SJulian.Pullen@Sun.COM (domain_name_item->state == AD_STATE_AUTO); 13008671SJulian.Pullen@Sun.COM } else if (auto_discovered != NULL) 13018671SJulian.Pullen@Sun.COM *auto_discovered = B_FALSE; 13028671SJulian.Pullen@Sun.COM 13038671SJulian.Pullen@Sun.COM return (domain_name); 13048671SJulian.Pullen@Sun.COM } 13058671SJulian.Pullen@Sun.COM 13068671SJulian.Pullen@Sun.COM 13078671SJulian.Pullen@Sun.COM /* Discover domain controllers */ 13088671SJulian.Pullen@Sun.COM static ad_item_t * 13098671SJulian.Pullen@Sun.COM validate_DomainController(ad_disc_t ctx, enum ad_disc_req req) 13108671SJulian.Pullen@Sun.COM { 13118671SJulian.Pullen@Sun.COM uint32_t ttl = 0; 13128671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t *domain_controller = NULL; 13138671SJulian.Pullen@Sun.COM boolean_t validate_global = B_FALSE; 13148671SJulian.Pullen@Sun.COM boolean_t validate_site = B_FALSE; 13158671SJulian.Pullen@Sun.COM ad_item_t *domain_name_item; 13168671SJulian.Pullen@Sun.COM ad_item_t *site_name_item = NULL; 13178671SJulian.Pullen@Sun.COM 13188671SJulian.Pullen@Sun.COM /* If the values is fixed there will not be a site specific version */ 13198671SJulian.Pullen@Sun.COM if (is_fixed(&ctx->domain_controller)) 13208671SJulian.Pullen@Sun.COM return (&ctx->domain_controller); 13218671SJulian.Pullen@Sun.COM 13228671SJulian.Pullen@Sun.COM domain_name_item = validate_DomainName(ctx); 13238671SJulian.Pullen@Sun.COM if (domain_name_item == NULL) 13248671SJulian.Pullen@Sun.COM return (NULL); 13258671SJulian.Pullen@Sun.COM 13268671SJulian.Pullen@Sun.COM if (req == AD_DISC_GLOBAL) 13278671SJulian.Pullen@Sun.COM validate_global = B_TRUE; 13288671SJulian.Pullen@Sun.COM else { 13298671SJulian.Pullen@Sun.COM site_name_item = validate_SiteName(ctx); 13308671SJulian.Pullen@Sun.COM if (site_name_item != NULL) 13318671SJulian.Pullen@Sun.COM validate_site = B_TRUE; 13328671SJulian.Pullen@Sun.COM else if (req == AD_DISC_PREFER_SITE) 13338671SJulian.Pullen@Sun.COM validate_global = B_TRUE; 13348671SJulian.Pullen@Sun.COM } 13358671SJulian.Pullen@Sun.COM 13368671SJulian.Pullen@Sun.COM if (validate_global) { 13378671SJulian.Pullen@Sun.COM if (!is_valid(&ctx->domain_controller) || 13388671SJulian.Pullen@Sun.COM is_changed(&ctx->domain_controller, PARAM1, 13398671SJulian.Pullen@Sun.COM domain_name_item)) { 13408671SJulian.Pullen@Sun.COM /* 13418671SJulian.Pullen@Sun.COM * Lookup DNS SRV RR named 13428671SJulian.Pullen@Sun.COM * _ldap._tcp.dc._msdcs.<DomainName> 13438671SJulian.Pullen@Sun.COM */ 13448671SJulian.Pullen@Sun.COM DO_RES_NINIT(ctx); 13458671SJulian.Pullen@Sun.COM domain_controller = srv_query(&ctx->res_state, 13468671SJulian.Pullen@Sun.COM LDAP_SRV_HEAD DC_SRV_TAIL, 13478671SJulian.Pullen@Sun.COM domain_name_item->value, NULL, &ttl); 13488671SJulian.Pullen@Sun.COM 13498671SJulian.Pullen@Sun.COM if (domain_controller == NULL) 13508671SJulian.Pullen@Sun.COM return (NULL); 13518671SJulian.Pullen@Sun.COM 13528671SJulian.Pullen@Sun.COM update_item(&ctx->domain_controller, domain_controller, 13538671SJulian.Pullen@Sun.COM AD_STATE_AUTO, ttl); 13548671SJulian.Pullen@Sun.COM update_version(&ctx->domain_controller, PARAM1, 13558671SJulian.Pullen@Sun.COM domain_name_item); 13568671SJulian.Pullen@Sun.COM } 13578671SJulian.Pullen@Sun.COM return (&ctx->domain_controller); 13588671SJulian.Pullen@Sun.COM } 13598671SJulian.Pullen@Sun.COM 13608671SJulian.Pullen@Sun.COM if (validate_site) { 13618671SJulian.Pullen@Sun.COM if (!is_valid(&ctx->site_domain_controller) || 13628671SJulian.Pullen@Sun.COM is_changed(&ctx->site_domain_controller, PARAM1, 13638671SJulian.Pullen@Sun.COM domain_name_item) || 13648671SJulian.Pullen@Sun.COM is_changed(&ctx->site_domain_controller, PARAM2, 13658671SJulian.Pullen@Sun.COM site_name_item)) { 13668671SJulian.Pullen@Sun.COM char rr_name[DNS_MAX_NAME]; 13678671SJulian.Pullen@Sun.COM /* 13688671SJulian.Pullen@Sun.COM * Lookup DNS SRV RR named 13698671SJulian.Pullen@Sun.COM * _ldap._tcp.<SiteName>._sites.dc._msdcs.<DomainName> 13708671SJulian.Pullen@Sun.COM */ 13718671SJulian.Pullen@Sun.COM (void) snprintf(rr_name, sizeof (rr_name), 13728671SJulian.Pullen@Sun.COM LDAP_SRV_HEAD SITE_SRV_MIDDLE DC_SRV_TAIL, 13738671SJulian.Pullen@Sun.COM site_name_item->value); 13748671SJulian.Pullen@Sun.COM DO_RES_NINIT(ctx); 13758671SJulian.Pullen@Sun.COM domain_controller = srv_query(&ctx->res_state, rr_name, 13768671SJulian.Pullen@Sun.COM domain_name_item->value, NULL, &ttl); 13778671SJulian.Pullen@Sun.COM if (domain_controller == NULL) 13788671SJulian.Pullen@Sun.COM return (NULL); 13798671SJulian.Pullen@Sun.COM 13808671SJulian.Pullen@Sun.COM update_item(&ctx->site_domain_controller, 13818671SJulian.Pullen@Sun.COM domain_controller, AD_STATE_AUTO, ttl); 13828671SJulian.Pullen@Sun.COM update_version(&ctx->site_domain_controller, PARAM1, 13838671SJulian.Pullen@Sun.COM domain_name_item); 13848671SJulian.Pullen@Sun.COM update_version(&ctx->site_domain_controller, PARAM2, 13858671SJulian.Pullen@Sun.COM site_name_item); 13868671SJulian.Pullen@Sun.COM } 13878671SJulian.Pullen@Sun.COM return (&ctx->site_domain_controller); 13888671SJulian.Pullen@Sun.COM } 13898671SJulian.Pullen@Sun.COM return (NULL); 13908671SJulian.Pullen@Sun.COM } 13918671SJulian.Pullen@Sun.COM 13928671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t * 13938671SJulian.Pullen@Sun.COM ad_disc_get_DomainController(ad_disc_t ctx, enum ad_disc_req req, 13948671SJulian.Pullen@Sun.COM boolean_t *auto_discovered) 13958671SJulian.Pullen@Sun.COM { 13968671SJulian.Pullen@Sun.COM ad_item_t *domain_controller_item; 13978671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t *domain_controller = NULL; 13988671SJulian.Pullen@Sun.COM 13998671SJulian.Pullen@Sun.COM domain_controller_item = validate_DomainController(ctx, req); 14008671SJulian.Pullen@Sun.COM 14018671SJulian.Pullen@Sun.COM if (domain_controller_item != NULL) { 14028671SJulian.Pullen@Sun.COM domain_controller = ds_dup(domain_controller_item->value); 14038671SJulian.Pullen@Sun.COM if (auto_discovered != NULL) 14048671SJulian.Pullen@Sun.COM *auto_discovered = 14058671SJulian.Pullen@Sun.COM (domain_controller_item->state == AD_STATE_AUTO); 14068671SJulian.Pullen@Sun.COM } else if (auto_discovered != NULL) 14078671SJulian.Pullen@Sun.COM *auto_discovered = B_FALSE; 14088671SJulian.Pullen@Sun.COM 14098671SJulian.Pullen@Sun.COM return (domain_controller); 14108671SJulian.Pullen@Sun.COM } 14118671SJulian.Pullen@Sun.COM 14128671SJulian.Pullen@Sun.COM 14138671SJulian.Pullen@Sun.COM /* Discover site name (for multi-homed systems the first one found wins) */ 14148671SJulian.Pullen@Sun.COM static ad_item_t * 14158671SJulian.Pullen@Sun.COM validate_SiteName(ad_disc_t ctx) 14168671SJulian.Pullen@Sun.COM { 14178671SJulian.Pullen@Sun.COM LDAP *ld = NULL; 14188671SJulian.Pullen@Sun.COM ad_subnet_t *subnets = NULL; 14198671SJulian.Pullen@Sun.COM char **dn_subnets = NULL; 14208671SJulian.Pullen@Sun.COM char *dn_root[2]; 14218671SJulian.Pullen@Sun.COM char *config_naming_context = NULL; 14228671SJulian.Pullen@Sun.COM char *site_object = NULL; 14238671SJulian.Pullen@Sun.COM char *site_name = NULL; 14248671SJulian.Pullen@Sun.COM char *forest_name; 14258671SJulian.Pullen@Sun.COM int len; 14268671SJulian.Pullen@Sun.COM int i; 14278671SJulian.Pullen@Sun.COM boolean_t update_required = B_FALSE; 14288671SJulian.Pullen@Sun.COM ad_item_t *domain_controller_item; 14298671SJulian.Pullen@Sun.COM 14308671SJulian.Pullen@Sun.COM if (is_fixed(&ctx->site_name)) 14318671SJulian.Pullen@Sun.COM return (&ctx->site_name); 14328671SJulian.Pullen@Sun.COM 14338671SJulian.Pullen@Sun.COM /* Can't rely on site-specific DCs */ 14348671SJulian.Pullen@Sun.COM domain_controller_item = validate_DomainController(ctx, AD_DISC_GLOBAL); 14358671SJulian.Pullen@Sun.COM if (domain_controller_item == NULL) 14368671SJulian.Pullen@Sun.COM return (NULL); 14378671SJulian.Pullen@Sun.COM 14388671SJulian.Pullen@Sun.COM if (!is_valid(&ctx->site_name) || 1439*12065SKeyur.Desai@Sun.COM is_changed(&ctx->site_name, PARAM1, domain_controller_item) || 14408671SJulian.Pullen@Sun.COM ctx->subnets == NULL || ctx->subnets_changed) { 14418671SJulian.Pullen@Sun.COM subnets = find_subnets(); 14428671SJulian.Pullen@Sun.COM ctx->subnets_last_check = time(NULL); 14438671SJulian.Pullen@Sun.COM update_required = B_TRUE; 14448671SJulian.Pullen@Sun.COM } else if (ctx->subnets_last_check + 60 < time(NULL)) { 1445*12065SKeyur.Desai@Sun.COM /* NEEDSWORK magic constant 60 above */ 14468671SJulian.Pullen@Sun.COM subnets = find_subnets(); 14478671SJulian.Pullen@Sun.COM ctx->subnets_last_check = time(NULL); 14488671SJulian.Pullen@Sun.COM if (cmpsubnets(ctx->subnets, subnets) != 0) 14498671SJulian.Pullen@Sun.COM update_required = B_TRUE; 14508671SJulian.Pullen@Sun.COM } 14518671SJulian.Pullen@Sun.COM 14528671SJulian.Pullen@Sun.COM if (!update_required) { 14538671SJulian.Pullen@Sun.COM free(subnets); 14548671SJulian.Pullen@Sun.COM return (&ctx->site_name); 14558671SJulian.Pullen@Sun.COM } 14568671SJulian.Pullen@Sun.COM 14578671SJulian.Pullen@Sun.COM if (subnets == NULL) 14588671SJulian.Pullen@Sun.COM return (NULL); 14598671SJulian.Pullen@Sun.COM 14608671SJulian.Pullen@Sun.COM dn_root[0] = ""; 14618671SJulian.Pullen@Sun.COM dn_root[1] = NULL; 14628671SJulian.Pullen@Sun.COM 14638671SJulian.Pullen@Sun.COM config_naming_context = ldap_lookup_entry_attr( 14648671SJulian.Pullen@Sun.COM &ld, ctx->domain_controller.value, 14658671SJulian.Pullen@Sun.COM dn_root, "configurationNamingContext"); 14668671SJulian.Pullen@Sun.COM if (config_naming_context == NULL) 14678671SJulian.Pullen@Sun.COM goto out; 14688671SJulian.Pullen@Sun.COM /* 14698671SJulian.Pullen@Sun.COM * configurationNamingContext also provides the Forest 14708671SJulian.Pullen@Sun.COM * Name. 14718671SJulian.Pullen@Sun.COM */ 14728671SJulian.Pullen@Sun.COM if (!is_fixed(&ctx->forest_name)) { 14738671SJulian.Pullen@Sun.COM /* 14748671SJulian.Pullen@Sun.COM * The configurationNamingContext should be of 14758671SJulian.Pullen@Sun.COM * form: 14768671SJulian.Pullen@Sun.COM * CN=Configuration,<DNforestName> 14778671SJulian.Pullen@Sun.COM * Remove the first part and convert to DNS form 14788671SJulian.Pullen@Sun.COM * (replace ",DC=" with ".") 14798671SJulian.Pullen@Sun.COM */ 14808671SJulian.Pullen@Sun.COM char *str = "CN=Configuration,"; 14818671SJulian.Pullen@Sun.COM int len = strlen(str); 14828671SJulian.Pullen@Sun.COM if (strncasecmp(config_naming_context, str, len) == 0) { 14838671SJulian.Pullen@Sun.COM forest_name = DN_to_DNS(config_naming_context + len); 14848671SJulian.Pullen@Sun.COM update_item(&ctx->forest_name, forest_name, 14858671SJulian.Pullen@Sun.COM AD_STATE_AUTO, 0); 1486*12065SKeyur.Desai@Sun.COM update_version(&ctx->forest_name, PARAM1, 1487*12065SKeyur.Desai@Sun.COM domain_controller_item); 14888671SJulian.Pullen@Sun.COM } 14898671SJulian.Pullen@Sun.COM } 14908671SJulian.Pullen@Sun.COM 14918671SJulian.Pullen@Sun.COM dn_subnets = subnets_to_DNs(subnets, config_naming_context); 14928671SJulian.Pullen@Sun.COM if (dn_subnets == NULL) 14938671SJulian.Pullen@Sun.COM goto out; 14948671SJulian.Pullen@Sun.COM 14958671SJulian.Pullen@Sun.COM site_object = ldap_lookup_entry_attr( 14968671SJulian.Pullen@Sun.COM &ld, domain_controller_item->value, 14978671SJulian.Pullen@Sun.COM dn_subnets, "siteobject"); 14988671SJulian.Pullen@Sun.COM if (site_object != NULL) { 14998671SJulian.Pullen@Sun.COM /* 15008671SJulian.Pullen@Sun.COM * The site object should be of the form 15018671SJulian.Pullen@Sun.COM * CN=<site>,CN=Sites,CN=Configuration, 15028671SJulian.Pullen@Sun.COM * <DN Domain> 15038671SJulian.Pullen@Sun.COM */ 15048671SJulian.Pullen@Sun.COM if (strncasecmp(site_object, "CN=", 3) == 0) { 15058671SJulian.Pullen@Sun.COM for (len = 0; site_object[len + 3] != ','; len++) 15068671SJulian.Pullen@Sun.COM ; 15078671SJulian.Pullen@Sun.COM site_name = malloc(len + 1); 15088671SJulian.Pullen@Sun.COM (void) strncpy(site_name, &site_object[3], len); 15098671SJulian.Pullen@Sun.COM site_name[len] = '\0'; 15108671SJulian.Pullen@Sun.COM update_item(&ctx->site_name, site_name, 15118671SJulian.Pullen@Sun.COM AD_STATE_AUTO, 0); 1512*12065SKeyur.Desai@Sun.COM update_version(&ctx->site_name, PARAM1, 1513*12065SKeyur.Desai@Sun.COM domain_controller_item); 15148671SJulian.Pullen@Sun.COM } 15158671SJulian.Pullen@Sun.COM } 15168671SJulian.Pullen@Sun.COM 15178671SJulian.Pullen@Sun.COM if (ctx->subnets != NULL) { 15188671SJulian.Pullen@Sun.COM free(ctx->subnets); 15198671SJulian.Pullen@Sun.COM ctx->subnets = NULL; 15208671SJulian.Pullen@Sun.COM } 15218671SJulian.Pullen@Sun.COM ctx->subnets = subnets; 15228671SJulian.Pullen@Sun.COM subnets = NULL; 15238671SJulian.Pullen@Sun.COM ctx->subnets_changed = B_FALSE; 15248671SJulian.Pullen@Sun.COM 15258671SJulian.Pullen@Sun.COM out: 15268671SJulian.Pullen@Sun.COM if (ld != NULL) 15278671SJulian.Pullen@Sun.COM (void) ldap_unbind(ld); 15288671SJulian.Pullen@Sun.COM 15298671SJulian.Pullen@Sun.COM if (dn_subnets != NULL) { 15308671SJulian.Pullen@Sun.COM for (i = 0; dn_subnets[i] != NULL; i++) 15318671SJulian.Pullen@Sun.COM free(dn_subnets[i]); 15328671SJulian.Pullen@Sun.COM free(dn_subnets); 15338671SJulian.Pullen@Sun.COM } 15348671SJulian.Pullen@Sun.COM if (config_naming_context != NULL) 15358671SJulian.Pullen@Sun.COM free(config_naming_context); 15368671SJulian.Pullen@Sun.COM if (site_object != NULL) 15378671SJulian.Pullen@Sun.COM free(site_object); 15388671SJulian.Pullen@Sun.COM 15398671SJulian.Pullen@Sun.COM free(subnets); 15408671SJulian.Pullen@Sun.COM if (site_name == NULL) 15418671SJulian.Pullen@Sun.COM return (NULL); 15428671SJulian.Pullen@Sun.COM return (&ctx->site_name); 15438671SJulian.Pullen@Sun.COM 15448671SJulian.Pullen@Sun.COM } 15458671SJulian.Pullen@Sun.COM 15468671SJulian.Pullen@Sun.COM 15478671SJulian.Pullen@Sun.COM char * 15488671SJulian.Pullen@Sun.COM ad_disc_get_SiteName(ad_disc_t ctx, boolean_t *auto_discovered) 15498671SJulian.Pullen@Sun.COM { 15508671SJulian.Pullen@Sun.COM ad_item_t *site_name_item; 15518671SJulian.Pullen@Sun.COM char *site_name = NULL; 15528671SJulian.Pullen@Sun.COM 15538671SJulian.Pullen@Sun.COM site_name_item = validate_SiteName(ctx); 15548671SJulian.Pullen@Sun.COM if (site_name_item != NULL) { 15558671SJulian.Pullen@Sun.COM site_name = strdup(site_name_item->value); 15568671SJulian.Pullen@Sun.COM if (auto_discovered != NULL) 15578671SJulian.Pullen@Sun.COM *auto_discovered = 15588671SJulian.Pullen@Sun.COM (site_name_item->state == AD_STATE_AUTO); 15598671SJulian.Pullen@Sun.COM } else if (auto_discovered != NULL) 15608671SJulian.Pullen@Sun.COM *auto_discovered = B_FALSE; 15618671SJulian.Pullen@Sun.COM 15628671SJulian.Pullen@Sun.COM return (site_name); 15638671SJulian.Pullen@Sun.COM } 15648671SJulian.Pullen@Sun.COM 15658671SJulian.Pullen@Sun.COM 15668671SJulian.Pullen@Sun.COM 15678671SJulian.Pullen@Sun.COM /* Discover forest name */ 15688671SJulian.Pullen@Sun.COM static ad_item_t * 15698671SJulian.Pullen@Sun.COM validate_ForestName(ad_disc_t ctx) 15708671SJulian.Pullen@Sun.COM { 15718671SJulian.Pullen@Sun.COM LDAP *ld = NULL; 15728671SJulian.Pullen@Sun.COM char *config_naming_context; 15738671SJulian.Pullen@Sun.COM char *forest_name = NULL; 15748671SJulian.Pullen@Sun.COM char *dn_list[2]; 15758671SJulian.Pullen@Sun.COM ad_item_t *domain_controller_item; 15768671SJulian.Pullen@Sun.COM 15778671SJulian.Pullen@Sun.COM if (is_fixed(&ctx->forest_name)) 15788671SJulian.Pullen@Sun.COM return (&ctx->forest_name); 15798671SJulian.Pullen@Sun.COM /* 15808671SJulian.Pullen@Sun.COM * We may not have a site name yet, so we won't rely on 15818671SJulian.Pullen@Sun.COM * site-specific DCs. (But maybe we could replace 15828671SJulian.Pullen@Sun.COM * validate_ForestName() with validate_siteName()?) 15838671SJulian.Pullen@Sun.COM */ 15848671SJulian.Pullen@Sun.COM domain_controller_item = validate_DomainController(ctx, AD_DISC_GLOBAL); 15858671SJulian.Pullen@Sun.COM if (domain_controller_item == NULL) 15868671SJulian.Pullen@Sun.COM return (NULL); 15878671SJulian.Pullen@Sun.COM 15888671SJulian.Pullen@Sun.COM if (!is_valid(&ctx->forest_name) || 15898671SJulian.Pullen@Sun.COM is_changed(&ctx->forest_name, PARAM1, domain_controller_item)) { 15908671SJulian.Pullen@Sun.COM 15918671SJulian.Pullen@Sun.COM dn_list[0] = ""; 15928671SJulian.Pullen@Sun.COM dn_list[1] = NULL; 15938671SJulian.Pullen@Sun.COM config_naming_context = ldap_lookup_entry_attr( 15948671SJulian.Pullen@Sun.COM &ld, ctx->domain_controller.value, 15958671SJulian.Pullen@Sun.COM dn_list, "configurationNamingContext"); 15968671SJulian.Pullen@Sun.COM if (config_naming_context != NULL) { 15978671SJulian.Pullen@Sun.COM /* 15988671SJulian.Pullen@Sun.COM * The configurationNamingContext should be of 15998671SJulian.Pullen@Sun.COM * form: 16008671SJulian.Pullen@Sun.COM * CN=Configuration,<DNforestName> 16018671SJulian.Pullen@Sun.COM * Remove the first part and convert to DNS form 16028671SJulian.Pullen@Sun.COM * (replace ",DC=" with ".") 16038671SJulian.Pullen@Sun.COM */ 16048671SJulian.Pullen@Sun.COM char *str = "CN=Configuration,"; 16058671SJulian.Pullen@Sun.COM int len = strlen(str); 16068671SJulian.Pullen@Sun.COM if (strncasecmp(config_naming_context, str, len) == 0) { 16078671SJulian.Pullen@Sun.COM forest_name = DN_to_DNS( 16088671SJulian.Pullen@Sun.COM config_naming_context + len); 16098671SJulian.Pullen@Sun.COM } 16108671SJulian.Pullen@Sun.COM free(config_naming_context); 16118671SJulian.Pullen@Sun.COM } 16128671SJulian.Pullen@Sun.COM if (ld != NULL) 16138671SJulian.Pullen@Sun.COM (void) ldap_unbind(ld); 16148671SJulian.Pullen@Sun.COM 16158671SJulian.Pullen@Sun.COM if (forest_name == NULL) 16168671SJulian.Pullen@Sun.COM return (NULL); 16178671SJulian.Pullen@Sun.COM 16188671SJulian.Pullen@Sun.COM update_item(&ctx->forest_name, forest_name, AD_STATE_AUTO, 0); 16198671SJulian.Pullen@Sun.COM update_version(&ctx->forest_name, PARAM1, 16208671SJulian.Pullen@Sun.COM domain_controller_item); 16218671SJulian.Pullen@Sun.COM } 16228671SJulian.Pullen@Sun.COM return (&ctx->forest_name); 16238671SJulian.Pullen@Sun.COM } 16248671SJulian.Pullen@Sun.COM 16258671SJulian.Pullen@Sun.COM 16268671SJulian.Pullen@Sun.COM char * 16278671SJulian.Pullen@Sun.COM ad_disc_get_ForestName(ad_disc_t ctx, boolean_t *auto_discovered) 16288671SJulian.Pullen@Sun.COM { 16298671SJulian.Pullen@Sun.COM ad_item_t *forest_name_item; 16308671SJulian.Pullen@Sun.COM char *forest_name = NULL; 16318671SJulian.Pullen@Sun.COM 16328671SJulian.Pullen@Sun.COM forest_name_item = validate_ForestName(ctx); 16338671SJulian.Pullen@Sun.COM 16348671SJulian.Pullen@Sun.COM if (forest_name_item != NULL) { 16358671SJulian.Pullen@Sun.COM forest_name = strdup(forest_name_item->value); 16368671SJulian.Pullen@Sun.COM if (auto_discovered != NULL) 16378671SJulian.Pullen@Sun.COM *auto_discovered = 16388671SJulian.Pullen@Sun.COM (forest_name_item->state == AD_STATE_AUTO); 16398671SJulian.Pullen@Sun.COM } else if (auto_discovered != NULL) 16408671SJulian.Pullen@Sun.COM *auto_discovered = B_FALSE; 16418671SJulian.Pullen@Sun.COM 16428671SJulian.Pullen@Sun.COM return (forest_name); 16438671SJulian.Pullen@Sun.COM } 16448671SJulian.Pullen@Sun.COM 16458671SJulian.Pullen@Sun.COM 16468671SJulian.Pullen@Sun.COM /* Discover global catalog servers */ 16478671SJulian.Pullen@Sun.COM static ad_item_t * 16488671SJulian.Pullen@Sun.COM validate_GlobalCatalog(ad_disc_t ctx, enum ad_disc_req req) 16498671SJulian.Pullen@Sun.COM { 16508671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t *global_catalog = NULL; 16518671SJulian.Pullen@Sun.COM uint32_t ttl = 0; 16528671SJulian.Pullen@Sun.COM boolean_t validate_global = B_FALSE; 16538671SJulian.Pullen@Sun.COM boolean_t validate_site = B_FALSE; 16548671SJulian.Pullen@Sun.COM ad_item_t *forest_name_item; 16558671SJulian.Pullen@Sun.COM ad_item_t *site_name_item; 16568671SJulian.Pullen@Sun.COM 16578671SJulian.Pullen@Sun.COM /* If the values is fixed there will not be a site specific version */ 16588671SJulian.Pullen@Sun.COM if (is_fixed(&ctx->global_catalog)) 16598671SJulian.Pullen@Sun.COM return (&ctx->global_catalog); 16608671SJulian.Pullen@Sun.COM 16618671SJulian.Pullen@Sun.COM forest_name_item = validate_ForestName(ctx); 16628671SJulian.Pullen@Sun.COM if (forest_name_item == NULL) 16638671SJulian.Pullen@Sun.COM return (NULL); 16648671SJulian.Pullen@Sun.COM 16658671SJulian.Pullen@Sun.COM if (req == AD_DISC_GLOBAL) 16668671SJulian.Pullen@Sun.COM validate_global = B_TRUE; 16678671SJulian.Pullen@Sun.COM else { 16688671SJulian.Pullen@Sun.COM site_name_item = validate_SiteName(ctx); 16698671SJulian.Pullen@Sun.COM if (site_name_item != NULL) 16708671SJulian.Pullen@Sun.COM validate_site = B_TRUE; 16718671SJulian.Pullen@Sun.COM else if (req == AD_DISC_PREFER_SITE) 16728671SJulian.Pullen@Sun.COM validate_global = B_TRUE; 16738671SJulian.Pullen@Sun.COM } 16748671SJulian.Pullen@Sun.COM 16758671SJulian.Pullen@Sun.COM if (validate_global) { 16768671SJulian.Pullen@Sun.COM if (!is_valid(&ctx->global_catalog) || 16778671SJulian.Pullen@Sun.COM is_changed(&ctx->global_catalog, PARAM1, 16788671SJulian.Pullen@Sun.COM forest_name_item)) { 16798671SJulian.Pullen@Sun.COM /* 16808671SJulian.Pullen@Sun.COM * Lookup DNS SRV RR named 16818671SJulian.Pullen@Sun.COM * _ldap._tcp.gc._msdcs.<ForestName> 16828671SJulian.Pullen@Sun.COM */ 16838671SJulian.Pullen@Sun.COM DO_RES_NINIT(ctx); 16848671SJulian.Pullen@Sun.COM global_catalog = 16858671SJulian.Pullen@Sun.COM srv_query(&ctx->res_state, 16868671SJulian.Pullen@Sun.COM LDAP_SRV_HEAD GC_SRV_TAIL, 16878671SJulian.Pullen@Sun.COM ctx->forest_name.value, NULL, &ttl); 16888671SJulian.Pullen@Sun.COM 16898671SJulian.Pullen@Sun.COM if (global_catalog == NULL) 16908671SJulian.Pullen@Sun.COM return (NULL); 16918671SJulian.Pullen@Sun.COM 16928671SJulian.Pullen@Sun.COM update_item(&ctx->global_catalog, global_catalog, 16938671SJulian.Pullen@Sun.COM AD_STATE_AUTO, ttl); 16948671SJulian.Pullen@Sun.COM update_version(&ctx->global_catalog, PARAM1, 16958671SJulian.Pullen@Sun.COM forest_name_item); 16968671SJulian.Pullen@Sun.COM } 16978671SJulian.Pullen@Sun.COM return (&ctx->global_catalog); 16988671SJulian.Pullen@Sun.COM } 16998671SJulian.Pullen@Sun.COM 17008671SJulian.Pullen@Sun.COM if (validate_site) { 17018671SJulian.Pullen@Sun.COM if (!is_valid(&ctx->site_global_catalog) || 17028671SJulian.Pullen@Sun.COM is_changed(&ctx->site_global_catalog, PARAM1, 17038671SJulian.Pullen@Sun.COM forest_name_item) || 17048671SJulian.Pullen@Sun.COM is_changed(&ctx->site_global_catalog, PARAM2, 17058671SJulian.Pullen@Sun.COM site_name_item)) { 17068671SJulian.Pullen@Sun.COM char rr_name[DNS_MAX_NAME]; 17078671SJulian.Pullen@Sun.COM 17088671SJulian.Pullen@Sun.COM /* 17098671SJulian.Pullen@Sun.COM * Lookup DNS SRV RR named: 17108671SJulian.Pullen@Sun.COM * _ldap._tcp.<siteName>._sites.gc. 17118671SJulian.Pullen@Sun.COM * _msdcs.<ForestName> 17128671SJulian.Pullen@Sun.COM */ 17138671SJulian.Pullen@Sun.COM (void) snprintf(rr_name, 17148671SJulian.Pullen@Sun.COM sizeof (rr_name), 17158671SJulian.Pullen@Sun.COM LDAP_SRV_HEAD SITE_SRV_MIDDLE GC_SRV_TAIL, 17168671SJulian.Pullen@Sun.COM ctx->site_name.value); 17178671SJulian.Pullen@Sun.COM DO_RES_NINIT(ctx); 17188671SJulian.Pullen@Sun.COM global_catalog = srv_query(&ctx->res_state, rr_name, 17198671SJulian.Pullen@Sun.COM ctx->forest_name.value, NULL, &ttl); 17208671SJulian.Pullen@Sun.COM 17218671SJulian.Pullen@Sun.COM if (global_catalog == NULL) 17228671SJulian.Pullen@Sun.COM return (NULL); 17238671SJulian.Pullen@Sun.COM update_item(&ctx->site_global_catalog, global_catalog, 17248671SJulian.Pullen@Sun.COM AD_STATE_AUTO, ttl); 17258671SJulian.Pullen@Sun.COM update_version(&ctx->site_global_catalog, PARAM1, 17268671SJulian.Pullen@Sun.COM forest_name_item); 17278671SJulian.Pullen@Sun.COM update_version(&ctx->site_global_catalog, PARAM2, 17288671SJulian.Pullen@Sun.COM site_name_item); 17298671SJulian.Pullen@Sun.COM } 17308671SJulian.Pullen@Sun.COM return (&ctx->site_global_catalog); 17318671SJulian.Pullen@Sun.COM } 17328671SJulian.Pullen@Sun.COM return (NULL); 17338671SJulian.Pullen@Sun.COM } 17348671SJulian.Pullen@Sun.COM 17358671SJulian.Pullen@Sun.COM 17368671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t * 17378671SJulian.Pullen@Sun.COM ad_disc_get_GlobalCatalog(ad_disc_t ctx, enum ad_disc_req req, 17388671SJulian.Pullen@Sun.COM boolean_t *auto_discovered) 17398671SJulian.Pullen@Sun.COM { 17408671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t *global_catalog = NULL; 17418671SJulian.Pullen@Sun.COM ad_item_t *global_catalog_item; 17428671SJulian.Pullen@Sun.COM 17438671SJulian.Pullen@Sun.COM global_catalog_item = validate_GlobalCatalog(ctx, req); 17448671SJulian.Pullen@Sun.COM 17458671SJulian.Pullen@Sun.COM if (global_catalog_item != NULL) { 17468671SJulian.Pullen@Sun.COM global_catalog = ds_dup(global_catalog_item->value); 17478671SJulian.Pullen@Sun.COM if (auto_discovered != NULL) 17488671SJulian.Pullen@Sun.COM *auto_discovered = 17498671SJulian.Pullen@Sun.COM (global_catalog_item->state == AD_STATE_AUTO); 17508671SJulian.Pullen@Sun.COM } else if (auto_discovered != NULL) 17518671SJulian.Pullen@Sun.COM *auto_discovered = B_FALSE; 17528671SJulian.Pullen@Sun.COM 17538671SJulian.Pullen@Sun.COM return (global_catalog); 17548671SJulian.Pullen@Sun.COM } 17558671SJulian.Pullen@Sun.COM 17568671SJulian.Pullen@Sun.COM 17578671SJulian.Pullen@Sun.COM static ad_item_t * 17588671SJulian.Pullen@Sun.COM validate_TrustedDomains(ad_disc_t ctx) 17598671SJulian.Pullen@Sun.COM { 17608671SJulian.Pullen@Sun.COM LDAP *ld = NULL; 17618671SJulian.Pullen@Sun.COM ad_item_t *global_catalog_item; 17628671SJulian.Pullen@Sun.COM ad_item_t *forest_name_item; 17638671SJulian.Pullen@Sun.COM ad_disc_trusteddomains_t *trusted_domains; 17648671SJulian.Pullen@Sun.COM char *dn = NULL; 17658671SJulian.Pullen@Sun.COM char *forest_name_dn; 17668671SJulian.Pullen@Sun.COM int len; 17678671SJulian.Pullen@Sun.COM int num_parts; 17688671SJulian.Pullen@Sun.COM 17698671SJulian.Pullen@Sun.COM if (is_fixed(&ctx->trusted_domains)) 17708671SJulian.Pullen@Sun.COM return (&ctx->trusted_domains); 17718671SJulian.Pullen@Sun.COM 17728671SJulian.Pullen@Sun.COM global_catalog_item = validate_GlobalCatalog(ctx, AD_DISC_GLOBAL); 17738671SJulian.Pullen@Sun.COM if (global_catalog_item == NULL) 17748671SJulian.Pullen@Sun.COM return (NULL); 17758671SJulian.Pullen@Sun.COM 17768671SJulian.Pullen@Sun.COM forest_name_item = validate_ForestName(ctx); 17778671SJulian.Pullen@Sun.COM if (forest_name_item == NULL) 17788671SJulian.Pullen@Sun.COM return (NULL); 17798671SJulian.Pullen@Sun.COM 17808671SJulian.Pullen@Sun.COM if (!is_valid(&ctx->trusted_domains) || 17818671SJulian.Pullen@Sun.COM is_changed(&ctx->trusted_domains, PARAM1, global_catalog_item) || 17828671SJulian.Pullen@Sun.COM is_changed(&ctx->trusted_domains, PARAM2, forest_name_item)) { 17838671SJulian.Pullen@Sun.COM 17848671SJulian.Pullen@Sun.COM forest_name_dn = ldap_dns_to_dn(forest_name_item->value, 17858671SJulian.Pullen@Sun.COM &num_parts); 17868671SJulian.Pullen@Sun.COM if (forest_name_dn == NULL) 17878671SJulian.Pullen@Sun.COM return (NULL); 17888671SJulian.Pullen@Sun.COM 17898671SJulian.Pullen@Sun.COM len = snprintf(NULL, 0, "CN=System,%s", forest_name_dn) + 1; 17908671SJulian.Pullen@Sun.COM dn = malloc(len); 17918671SJulian.Pullen@Sun.COM if (dn == NULL) { 17928671SJulian.Pullen@Sun.COM free(forest_name_dn); 17938671SJulian.Pullen@Sun.COM return (NULL); 17948671SJulian.Pullen@Sun.COM } 17958671SJulian.Pullen@Sun.COM (void) snprintf(dn, len, "CN=System,%s", forest_name_dn); 17968671SJulian.Pullen@Sun.COM free(forest_name_dn); 17978671SJulian.Pullen@Sun.COM 17988671SJulian.Pullen@Sun.COM trusted_domains = ldap_lookup_trusted_domains( 17998671SJulian.Pullen@Sun.COM &ld, global_catalog_item->value, dn); 18008671SJulian.Pullen@Sun.COM 18018671SJulian.Pullen@Sun.COM if (ld != NULL) 18028671SJulian.Pullen@Sun.COM (void) ldap_unbind(ld); 18038671SJulian.Pullen@Sun.COM free(dn); 18048671SJulian.Pullen@Sun.COM 18058671SJulian.Pullen@Sun.COM if (trusted_domains == NULL) 18068671SJulian.Pullen@Sun.COM return (NULL); 18078671SJulian.Pullen@Sun.COM 18088671SJulian.Pullen@Sun.COM update_item(&ctx->trusted_domains, trusted_domains, 18098671SJulian.Pullen@Sun.COM AD_STATE_AUTO, 0); 18108671SJulian.Pullen@Sun.COM update_version(&ctx->trusted_domains, PARAM1, 18118671SJulian.Pullen@Sun.COM global_catalog_item); 18128671SJulian.Pullen@Sun.COM update_version(&ctx->trusted_domains, PARAM2, 18138671SJulian.Pullen@Sun.COM forest_name_item); 18148671SJulian.Pullen@Sun.COM } 18158671SJulian.Pullen@Sun.COM 18168671SJulian.Pullen@Sun.COM return (&ctx->trusted_domains); 18178671SJulian.Pullen@Sun.COM } 18188671SJulian.Pullen@Sun.COM 18198671SJulian.Pullen@Sun.COM 18208671SJulian.Pullen@Sun.COM ad_disc_trusteddomains_t * 18218671SJulian.Pullen@Sun.COM ad_disc_get_TrustedDomains(ad_disc_t ctx, boolean_t *auto_discovered) 18228671SJulian.Pullen@Sun.COM { 18238671SJulian.Pullen@Sun.COM ad_disc_trusteddomains_t *trusted_domains = NULL; 18248671SJulian.Pullen@Sun.COM ad_item_t *trusted_domains_item; 18258671SJulian.Pullen@Sun.COM 18268671SJulian.Pullen@Sun.COM trusted_domains_item = validate_TrustedDomains(ctx); 18278671SJulian.Pullen@Sun.COM 18288671SJulian.Pullen@Sun.COM if (trusted_domains_item != NULL) { 18298671SJulian.Pullen@Sun.COM trusted_domains = td_dup(trusted_domains_item->value); 18308671SJulian.Pullen@Sun.COM if (auto_discovered != NULL) 18318671SJulian.Pullen@Sun.COM *auto_discovered = 18328671SJulian.Pullen@Sun.COM (trusted_domains_item->state == AD_STATE_AUTO); 18338671SJulian.Pullen@Sun.COM } else if (auto_discovered != NULL) 18348671SJulian.Pullen@Sun.COM *auto_discovered = B_FALSE; 18358671SJulian.Pullen@Sun.COM 18368671SJulian.Pullen@Sun.COM return (trusted_domains); 18378671SJulian.Pullen@Sun.COM } 18388671SJulian.Pullen@Sun.COM 18398671SJulian.Pullen@Sun.COM 18408671SJulian.Pullen@Sun.COM static ad_item_t * 18418671SJulian.Pullen@Sun.COM validate_DomainsInForest(ad_disc_t ctx) 18428671SJulian.Pullen@Sun.COM { 18438671SJulian.Pullen@Sun.COM ad_item_t *global_catalog_item; 18448671SJulian.Pullen@Sun.COM LDAP *ld = NULL; 18458671SJulian.Pullen@Sun.COM ad_disc_domainsinforest_t *domains_in_forest; 18468671SJulian.Pullen@Sun.COM 18478671SJulian.Pullen@Sun.COM if (is_fixed(&ctx->domains_in_forest)) 18488671SJulian.Pullen@Sun.COM return (&ctx->domains_in_forest); 18498671SJulian.Pullen@Sun.COM 18508671SJulian.Pullen@Sun.COM global_catalog_item = validate_GlobalCatalog(ctx, AD_DISC_GLOBAL); 18518671SJulian.Pullen@Sun.COM if (global_catalog_item == NULL) 18528671SJulian.Pullen@Sun.COM return (NULL); 18538671SJulian.Pullen@Sun.COM 18548671SJulian.Pullen@Sun.COM if (!is_valid(&ctx->domains_in_forest) || 18558671SJulian.Pullen@Sun.COM is_changed(&ctx->domains_in_forest, PARAM1, global_catalog_item)) { 18568671SJulian.Pullen@Sun.COM 18578671SJulian.Pullen@Sun.COM domains_in_forest = ldap_lookup_domains_in_forest( 18588671SJulian.Pullen@Sun.COM &ld, global_catalog_item->value); 18598671SJulian.Pullen@Sun.COM 18608671SJulian.Pullen@Sun.COM if (ld != NULL) 18618671SJulian.Pullen@Sun.COM (void) ldap_unbind(ld); 18628671SJulian.Pullen@Sun.COM 18638671SJulian.Pullen@Sun.COM if (domains_in_forest == NULL) 18648671SJulian.Pullen@Sun.COM return (NULL); 18658671SJulian.Pullen@Sun.COM 18668671SJulian.Pullen@Sun.COM update_item(&ctx->domains_in_forest, domains_in_forest, 18678671SJulian.Pullen@Sun.COM AD_STATE_AUTO, 0); 18688671SJulian.Pullen@Sun.COM update_version(&ctx->domains_in_forest, PARAM1, 18698671SJulian.Pullen@Sun.COM global_catalog_item); 18708671SJulian.Pullen@Sun.COM } 18718671SJulian.Pullen@Sun.COM return (&ctx->domains_in_forest); 18728671SJulian.Pullen@Sun.COM } 18738671SJulian.Pullen@Sun.COM 18748671SJulian.Pullen@Sun.COM 18758671SJulian.Pullen@Sun.COM ad_disc_domainsinforest_t * 18768671SJulian.Pullen@Sun.COM ad_disc_get_DomainsInForest(ad_disc_t ctx, boolean_t *auto_discovered) 18778671SJulian.Pullen@Sun.COM { 18788671SJulian.Pullen@Sun.COM ad_disc_domainsinforest_t *domains_in_forest = NULL; 18798671SJulian.Pullen@Sun.COM ad_item_t *domains_in_forest_item; 18808671SJulian.Pullen@Sun.COM 18818671SJulian.Pullen@Sun.COM domains_in_forest_item = validate_DomainsInForest(ctx); 18828671SJulian.Pullen@Sun.COM 18838671SJulian.Pullen@Sun.COM if (domains_in_forest_item != NULL) { 18848671SJulian.Pullen@Sun.COM domains_in_forest = df_dup(domains_in_forest_item->value); 18858671SJulian.Pullen@Sun.COM if (auto_discovered != NULL) 18868671SJulian.Pullen@Sun.COM *auto_discovered = 18878671SJulian.Pullen@Sun.COM (domains_in_forest_item->state == AD_STATE_AUTO); 18888671SJulian.Pullen@Sun.COM } else if (auto_discovered != NULL) 18898671SJulian.Pullen@Sun.COM *auto_discovered = B_FALSE; 18908671SJulian.Pullen@Sun.COM 18918671SJulian.Pullen@Sun.COM return (domains_in_forest); 18928671SJulian.Pullen@Sun.COM } 18938671SJulian.Pullen@Sun.COM 18948671SJulian.Pullen@Sun.COM 18958671SJulian.Pullen@Sun.COM 18968671SJulian.Pullen@Sun.COM 18978671SJulian.Pullen@Sun.COM int 18988671SJulian.Pullen@Sun.COM ad_disc_set_DomainName(ad_disc_t ctx, const char *domainName) 18998671SJulian.Pullen@Sun.COM { 19008671SJulian.Pullen@Sun.COM char *domain_name = NULL; 19018671SJulian.Pullen@Sun.COM if (domainName != NULL) { 19028671SJulian.Pullen@Sun.COM domain_name = strdup(domainName); 19038671SJulian.Pullen@Sun.COM if (domain_name == NULL) 19048671SJulian.Pullen@Sun.COM return (-1); 19058671SJulian.Pullen@Sun.COM update_item(&ctx->domain_name, domain_name, 19068671SJulian.Pullen@Sun.COM AD_STATE_FIXED, 0); 19078671SJulian.Pullen@Sun.COM } else if (ctx->domain_name.state == AD_STATE_FIXED) 19088671SJulian.Pullen@Sun.COM ctx->domain_name.state = AD_STATE_INVALID; 19098671SJulian.Pullen@Sun.COM return (0); 19108671SJulian.Pullen@Sun.COM } 19118671SJulian.Pullen@Sun.COM 19128671SJulian.Pullen@Sun.COM 19138671SJulian.Pullen@Sun.COM int 19148671SJulian.Pullen@Sun.COM ad_disc_set_DomainController(ad_disc_t ctx, 19158671SJulian.Pullen@Sun.COM const idmap_ad_disc_ds_t *domainController) 19168671SJulian.Pullen@Sun.COM { 19178671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t *domain_controller = NULL; 19188671SJulian.Pullen@Sun.COM if (domainController != NULL) { 19198671SJulian.Pullen@Sun.COM domain_controller = ds_dup(domainController); 19208671SJulian.Pullen@Sun.COM if (domain_controller == NULL) 19218671SJulian.Pullen@Sun.COM return (-1); 19228671SJulian.Pullen@Sun.COM update_item(&ctx->domain_controller, domain_controller, 19238671SJulian.Pullen@Sun.COM AD_STATE_FIXED, 0); 19248671SJulian.Pullen@Sun.COM } else if (ctx->domain_controller.state == AD_STATE_FIXED) 19258671SJulian.Pullen@Sun.COM ctx->domain_controller.state = AD_STATE_INVALID; 19268671SJulian.Pullen@Sun.COM return (0); 19278671SJulian.Pullen@Sun.COM } 19288671SJulian.Pullen@Sun.COM 19298671SJulian.Pullen@Sun.COM 19308671SJulian.Pullen@Sun.COM int 19318671SJulian.Pullen@Sun.COM ad_disc_set_SiteName(ad_disc_t ctx, const char *siteName) 19328671SJulian.Pullen@Sun.COM { 19338671SJulian.Pullen@Sun.COM char *site_name = NULL; 19348671SJulian.Pullen@Sun.COM if (siteName != NULL) { 19358671SJulian.Pullen@Sun.COM site_name = strdup(siteName); 19368671SJulian.Pullen@Sun.COM if (site_name == NULL) 19378671SJulian.Pullen@Sun.COM return (-1); 19388671SJulian.Pullen@Sun.COM update_item(&ctx->site_name, site_name, AD_STATE_FIXED, 0); 19398671SJulian.Pullen@Sun.COM } else if (ctx->site_name.state == AD_STATE_FIXED) 19408671SJulian.Pullen@Sun.COM ctx->site_name.state = AD_STATE_INVALID; 19418671SJulian.Pullen@Sun.COM return (0); 19428671SJulian.Pullen@Sun.COM } 19438671SJulian.Pullen@Sun.COM 19448671SJulian.Pullen@Sun.COM int 19458671SJulian.Pullen@Sun.COM ad_disc_set_ForestName(ad_disc_t ctx, const char *forestName) 19468671SJulian.Pullen@Sun.COM { 19478671SJulian.Pullen@Sun.COM char *forest_name = NULL; 19488671SJulian.Pullen@Sun.COM if (forestName != NULL) { 19498671SJulian.Pullen@Sun.COM forest_name = strdup(forestName); 19508671SJulian.Pullen@Sun.COM if (forest_name == NULL) 19518671SJulian.Pullen@Sun.COM return (-1); 19528671SJulian.Pullen@Sun.COM update_item(&ctx->forest_name, forest_name, 19538671SJulian.Pullen@Sun.COM AD_STATE_FIXED, 0); 19548671SJulian.Pullen@Sun.COM } else if (ctx->forest_name.state == AD_STATE_FIXED) 19558671SJulian.Pullen@Sun.COM ctx->forest_name.state = AD_STATE_INVALID; 19568671SJulian.Pullen@Sun.COM return (0); 19578671SJulian.Pullen@Sun.COM } 19588671SJulian.Pullen@Sun.COM 19598671SJulian.Pullen@Sun.COM int 19608671SJulian.Pullen@Sun.COM ad_disc_set_GlobalCatalog(ad_disc_t ctx, 19618671SJulian.Pullen@Sun.COM const idmap_ad_disc_ds_t *globalCatalog) 19628671SJulian.Pullen@Sun.COM { 19638671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t *global_catalog = NULL; 19648671SJulian.Pullen@Sun.COM if (globalCatalog != NULL) { 19658671SJulian.Pullen@Sun.COM global_catalog = ds_dup(globalCatalog); 19668671SJulian.Pullen@Sun.COM if (global_catalog == NULL) 19678671SJulian.Pullen@Sun.COM return (-1); 19688671SJulian.Pullen@Sun.COM update_item(&ctx->global_catalog, global_catalog, 19698671SJulian.Pullen@Sun.COM AD_STATE_FIXED, 0); 19708671SJulian.Pullen@Sun.COM } else if (ctx->global_catalog.state == AD_STATE_FIXED) 19718671SJulian.Pullen@Sun.COM ctx->global_catalog.state = AD_STATE_INVALID; 19728671SJulian.Pullen@Sun.COM return (0); 19738671SJulian.Pullen@Sun.COM } 19748671SJulian.Pullen@Sun.COM 19758671SJulian.Pullen@Sun.COM 19768671SJulian.Pullen@Sun.COM int 19778671SJulian.Pullen@Sun.COM ad_disc_unset(ad_disc_t ctx) 19788671SJulian.Pullen@Sun.COM { 19798671SJulian.Pullen@Sun.COM if (ctx->domain_name.state == AD_STATE_FIXED) 19808671SJulian.Pullen@Sun.COM ctx->domain_name.state = AD_STATE_INVALID; 19818671SJulian.Pullen@Sun.COM 19828671SJulian.Pullen@Sun.COM if (ctx->domain_controller.state == AD_STATE_FIXED) 19838671SJulian.Pullen@Sun.COM ctx->domain_controller.state = AD_STATE_INVALID; 19848671SJulian.Pullen@Sun.COM 19858671SJulian.Pullen@Sun.COM if (ctx->site_name.state == AD_STATE_FIXED) 19868671SJulian.Pullen@Sun.COM ctx->site_name.state = AD_STATE_INVALID; 19878671SJulian.Pullen@Sun.COM 19888671SJulian.Pullen@Sun.COM if (ctx->forest_name.state == AD_STATE_FIXED) 19898671SJulian.Pullen@Sun.COM ctx->forest_name.state = AD_STATE_INVALID; 19908671SJulian.Pullen@Sun.COM 19918671SJulian.Pullen@Sun.COM if (ctx->global_catalog.state == AD_STATE_FIXED) 19928671SJulian.Pullen@Sun.COM ctx->global_catalog.state = AD_STATE_INVALID; 19938671SJulian.Pullen@Sun.COM 19948671SJulian.Pullen@Sun.COM return (0); 19958671SJulian.Pullen@Sun.COM } 19968671SJulian.Pullen@Sun.COM 19978671SJulian.Pullen@Sun.COM /* 19988671SJulian.Pullen@Sun.COM * ad_disc_get_TTL 19998671SJulian.Pullen@Sun.COM * 20008671SJulian.Pullen@Sun.COM * This routines the time to live for AD 20018671SJulian.Pullen@Sun.COM * auto discovered items. 20028671SJulian.Pullen@Sun.COM * 20038671SJulian.Pullen@Sun.COM * Returns: 20048671SJulian.Pullen@Sun.COM * -1 if there are no TTL items 20058671SJulian.Pullen@Sun.COM * 0 if there are expired items 20068671SJulian.Pullen@Sun.COM * else the number of seconds 20078671SJulian.Pullen@Sun.COM * 20088671SJulian.Pullen@Sun.COM * The MIN_GT_ZERO(x, y) macro return the lesser of x and y, provided it 20098671SJulian.Pullen@Sun.COM * is positive -- min() greater than zero. 20108671SJulian.Pullen@Sun.COM */ 20118671SJulian.Pullen@Sun.COM #define MIN_GT_ZERO(x, y) (((x) <= 0) ? (((y) <= 0) ? \ 20128671SJulian.Pullen@Sun.COM (-1) : (y)) : (((y) <= 0) ? (x) : (((x) > (y)) ? (y) : (x)))) 20138671SJulian.Pullen@Sun.COM int 20148671SJulian.Pullen@Sun.COM ad_disc_get_TTL(ad_disc_t ctx) 20158671SJulian.Pullen@Sun.COM { 2016*12065SKeyur.Desai@Sun.COM time_t expires; 20178671SJulian.Pullen@Sun.COM int ttl; 20188671SJulian.Pullen@Sun.COM 2019*12065SKeyur.Desai@Sun.COM expires = MIN_GT_ZERO(ctx->domain_controller.expires, 2020*12065SKeyur.Desai@Sun.COM ctx->global_catalog.expires); 2021*12065SKeyur.Desai@Sun.COM expires = MIN_GT_ZERO(expires, ctx->site_domain_controller.expires); 2022*12065SKeyur.Desai@Sun.COM expires = MIN_GT_ZERO(expires, ctx->site_global_catalog.expires); 2023*12065SKeyur.Desai@Sun.COM 2024*12065SKeyur.Desai@Sun.COM if (expires == -1) { 2025*12065SKeyur.Desai@Sun.COM return (-1); 2026*12065SKeyur.Desai@Sun.COM } 20278671SJulian.Pullen@Sun.COM 2028*12065SKeyur.Desai@Sun.COM if (ctx->expires_not_before != 0 && 2029*12065SKeyur.Desai@Sun.COM expires < ctx->expires_not_before) { 2030*12065SKeyur.Desai@Sun.COM expires = ctx->expires_not_before; 2031*12065SKeyur.Desai@Sun.COM } 2032*12065SKeyur.Desai@Sun.COM 2033*12065SKeyur.Desai@Sun.COM if (ctx->expires_not_after != 0 && 2034*12065SKeyur.Desai@Sun.COM expires > ctx->expires_not_after) { 2035*12065SKeyur.Desai@Sun.COM expires = ctx->expires_not_after; 2036*12065SKeyur.Desai@Sun.COM } 2037*12065SKeyur.Desai@Sun.COM 2038*12065SKeyur.Desai@Sun.COM ttl = expires - time(NULL); 2039*12065SKeyur.Desai@Sun.COM 2040*12065SKeyur.Desai@Sun.COM if (ttl < 0) { 20418671SJulian.Pullen@Sun.COM return (0); 2042*12065SKeyur.Desai@Sun.COM } 20438671SJulian.Pullen@Sun.COM return (ttl); 20448671SJulian.Pullen@Sun.COM } 20458671SJulian.Pullen@Sun.COM 20468671SJulian.Pullen@Sun.COM boolean_t 20478671SJulian.Pullen@Sun.COM ad_disc_SubnetChanged(ad_disc_t ctx) 20488671SJulian.Pullen@Sun.COM { 20498671SJulian.Pullen@Sun.COM ad_subnet_t *subnets; 20508671SJulian.Pullen@Sun.COM 20518671SJulian.Pullen@Sun.COM if (ctx->subnets_changed || ctx->subnets == NULL) 20528671SJulian.Pullen@Sun.COM return (B_TRUE); 20538671SJulian.Pullen@Sun.COM 20548671SJulian.Pullen@Sun.COM if ((subnets = find_subnets()) != NULL) { 20558671SJulian.Pullen@Sun.COM if (cmpsubnets(subnets, ctx->subnets) != 0) 20568671SJulian.Pullen@Sun.COM ctx->subnets_changed = B_TRUE; 20578671SJulian.Pullen@Sun.COM free(subnets); 20588671SJulian.Pullen@Sun.COM } 20598671SJulian.Pullen@Sun.COM 20608671SJulian.Pullen@Sun.COM return (ctx->subnets_changed); 20618671SJulian.Pullen@Sun.COM } 2062