1*8671SJulian.Pullen@Sun.COM /* 2*8671SJulian.Pullen@Sun.COM * CDDL HEADER START 3*8671SJulian.Pullen@Sun.COM * 4*8671SJulian.Pullen@Sun.COM * The contents of this file are subject to the terms of the 5*8671SJulian.Pullen@Sun.COM * Common Development and Distribution License (the "License"). 6*8671SJulian.Pullen@Sun.COM * You may not use this file except in compliance with the License. 7*8671SJulian.Pullen@Sun.COM * 8*8671SJulian.Pullen@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*8671SJulian.Pullen@Sun.COM * or http://www.opensolaris.org/os/licensing. 10*8671SJulian.Pullen@Sun.COM * See the License for the specific language governing permissions 11*8671SJulian.Pullen@Sun.COM * and limitations under the License. 12*8671SJulian.Pullen@Sun.COM * 13*8671SJulian.Pullen@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 14*8671SJulian.Pullen@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*8671SJulian.Pullen@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 16*8671SJulian.Pullen@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 17*8671SJulian.Pullen@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 18*8671SJulian.Pullen@Sun.COM * 19*8671SJulian.Pullen@Sun.COM * CDDL HEADER END 20*8671SJulian.Pullen@Sun.COM */ 21*8671SJulian.Pullen@Sun.COM 22*8671SJulian.Pullen@Sun.COM /* 23*8671SJulian.Pullen@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24*8671SJulian.Pullen@Sun.COM * Use is subject to license terms. 25*8671SJulian.Pullen@Sun.COM */ 26*8671SJulian.Pullen@Sun.COM 27*8671SJulian.Pullen@Sun.COM /* 28*8671SJulian.Pullen@Sun.COM * Active Directory Auto-Discovery. 29*8671SJulian.Pullen@Sun.COM * 30*8671SJulian.Pullen@Sun.COM * This [project private] API allows the caller to provide whatever 31*8671SJulian.Pullen@Sun.COM * details it knows a priori (i.e., provided via configuration so as to 32*8671SJulian.Pullen@Sun.COM * override auto-discovery) and in any order. Then the caller can ask 33*8671SJulian.Pullen@Sun.COM * for any of the auto-discoverable parameters in any order. 34*8671SJulian.Pullen@Sun.COM * 35*8671SJulian.Pullen@Sun.COM * But there is an actual order in which discovery must be done. Given 36*8671SJulian.Pullen@Sun.COM * the discovery mechanism implemented here, that order is: 37*8671SJulian.Pullen@Sun.COM * 38*8671SJulian.Pullen@Sun.COM * - the domain name joined must be discovered first 39*8671SJulian.Pullen@Sun.COM * - then the domain controllers 40*8671SJulian.Pullen@Sun.COM * - then the forest name and site name 41*8671SJulian.Pullen@Sun.COM * - then the global catalog servers, and site-specific domain 42*8671SJulian.Pullen@Sun.COM * controllers and global catalog servers. 43*8671SJulian.Pullen@Sun.COM * 44*8671SJulian.Pullen@Sun.COM * The API does not require it be called in the same order because there 45*8671SJulian.Pullen@Sun.COM * may be other discovery mechanisms in the future, and exposing 46*8671SJulian.Pullen@Sun.COM * ordering requirements of the current mechanism now can create trouble 47*8671SJulian.Pullen@Sun.COM * down the line. Also, this makes the API easier to use now, which 48*8671SJulian.Pullen@Sun.COM * means less work to do some day when we make this a public API. 49*8671SJulian.Pullen@Sun.COM * 50*8671SJulian.Pullen@Sun.COM * Domain discovery is done by res_nsearch() of the DNS SRV RR name for 51*8671SJulian.Pullen@Sun.COM * domain controllers. As long as the joined domain appears in the DNS 52*8671SJulian.Pullen@Sun.COM * resolver's search list then we'll find it. 53*8671SJulian.Pullen@Sun.COM * 54*8671SJulian.Pullen@Sun.COM * Domain controller discovery is a matter of formatting the DNS SRV RR 55*8671SJulian.Pullen@Sun.COM * FQDN for domain controllers and doing a lookup for them. Knowledge 56*8671SJulian.Pullen@Sun.COM * of the domain name is not fundamentally required, but we separate the 57*8671SJulian.Pullen@Sun.COM * two processes, which in practice can lead to one more DNS lookup than 58*8671SJulian.Pullen@Sun.COM * is strictly required. 59*8671SJulian.Pullen@Sun.COM * 60*8671SJulian.Pullen@Sun.COM * Forest and site name discovery require an LDAP search of the AD 61*8671SJulian.Pullen@Sun.COM * "configuration partition" at a domain controller for the joined 62*8671SJulian.Pullen@Sun.COM * domain. Forest and site name discovery depend on knowing the joined 63*8671SJulian.Pullen@Sun.COM * domain name and domain controllers for that domain. 64*8671SJulian.Pullen@Sun.COM * 65*8671SJulian.Pullen@Sun.COM * Global catalog server discovery requires knowledge of the forest 66*8671SJulian.Pullen@Sun.COM * name in order to format the DNS SRV RR FQDN to lookup. Site-specific 67*8671SJulian.Pullen@Sun.COM * domain controller discovery depends on knowing the site name (and, 68*8671SJulian.Pullen@Sun.COM * therefore, joined domain, ...). Site-specific global catalog server 69*8671SJulian.Pullen@Sun.COM * discovery depends on knowledge of the forest and site names, which 70*8671SJulian.Pullen@Sun.COM * depend on... 71*8671SJulian.Pullen@Sun.COM * 72*8671SJulian.Pullen@Sun.COM * All the work of discovering particular items is done by functions 73*8671SJulian.Pullen@Sun.COM * named validate_<item>(). Each such function calls validate_<item>() 74*8671SJulian.Pullen@Sun.COM * for any items that it depends on. 75*8671SJulian.Pullen@Sun.COM * 76*8671SJulian.Pullen@Sun.COM * This API is not thread-safe. 77*8671SJulian.Pullen@Sun.COM */ 78*8671SJulian.Pullen@Sun.COM 79*8671SJulian.Pullen@Sun.COM 80*8671SJulian.Pullen@Sun.COM #include <stdio.h> 81*8671SJulian.Pullen@Sun.COM #include <string.h> 82*8671SJulian.Pullen@Sun.COM #include <strings.h> 83*8671SJulian.Pullen@Sun.COM #include <unistd.h> 84*8671SJulian.Pullen@Sun.COM #include <assert.h> 85*8671SJulian.Pullen@Sun.COM #include <stdlib.h> 86*8671SJulian.Pullen@Sun.COM #include <net/if.h> 87*8671SJulian.Pullen@Sun.COM #include <net/if.h> 88*8671SJulian.Pullen@Sun.COM #include <sys/types.h> 89*8671SJulian.Pullen@Sun.COM #include <sys/socket.h> 90*8671SJulian.Pullen@Sun.COM #include <sys/sockio.h> 91*8671SJulian.Pullen@Sun.COM #include <netinet/in.h> 92*8671SJulian.Pullen@Sun.COM #include <netinet/in.h> 93*8671SJulian.Pullen@Sun.COM #include <arpa/inet.h> 94*8671SJulian.Pullen@Sun.COM #include <arpa/nameser.h> 95*8671SJulian.Pullen@Sun.COM #include <resolv.h> 96*8671SJulian.Pullen@Sun.COM #include <netdb.h> 97*8671SJulian.Pullen@Sun.COM #include <ctype.h> 98*8671SJulian.Pullen@Sun.COM #include <errno.h> 99*8671SJulian.Pullen@Sun.COM #include <ldap.h> 100*8671SJulian.Pullen@Sun.COM #include <sasl/sasl.h> 101*8671SJulian.Pullen@Sun.COM #include <sys/u8_textprep.h> 102*8671SJulian.Pullen@Sun.COM #include <syslog.h> 103*8671SJulian.Pullen@Sun.COM #include "adutils_impl.h" 104*8671SJulian.Pullen@Sun.COM #include "addisc.h" 105*8671SJulian.Pullen@Sun.COM 106*8671SJulian.Pullen@Sun.COM 107*8671SJulian.Pullen@Sun.COM enum ad_item_state { 108*8671SJulian.Pullen@Sun.COM AD_STATE_INVALID = 0, /* The value is not valid */ 109*8671SJulian.Pullen@Sun.COM AD_STATE_FIXED, /* The value was fixed by caller */ 110*8671SJulian.Pullen@Sun.COM AD_STATE_AUTO /* The value is auto discovered */ 111*8671SJulian.Pullen@Sun.COM }; 112*8671SJulian.Pullen@Sun.COM 113*8671SJulian.Pullen@Sun.COM enum ad_data_type { 114*8671SJulian.Pullen@Sun.COM AD_STRING = 123, 115*8671SJulian.Pullen@Sun.COM AD_DIRECTORY, 116*8671SJulian.Pullen@Sun.COM AD_DOMAINS_IN_FOREST, 117*8671SJulian.Pullen@Sun.COM AD_TRUSTED_DOMAINS 118*8671SJulian.Pullen@Sun.COM }; 119*8671SJulian.Pullen@Sun.COM 120*8671SJulian.Pullen@Sun.COM 121*8671SJulian.Pullen@Sun.COM typedef struct ad_subnet { 122*8671SJulian.Pullen@Sun.COM char subnet[24]; 123*8671SJulian.Pullen@Sun.COM } ad_subnet_t; 124*8671SJulian.Pullen@Sun.COM 125*8671SJulian.Pullen@Sun.COM 126*8671SJulian.Pullen@Sun.COM typedef struct ad_item { 127*8671SJulian.Pullen@Sun.COM enum ad_item_state state; 128*8671SJulian.Pullen@Sun.COM enum ad_data_type type; 129*8671SJulian.Pullen@Sun.COM void *value; 130*8671SJulian.Pullen@Sun.COM time_t ttl; 131*8671SJulian.Pullen@Sun.COM unsigned int version; /* Version is only changed */ 132*8671SJulian.Pullen@Sun.COM /* if the value changes */ 133*8671SJulian.Pullen@Sun.COM #define PARAM1 0 134*8671SJulian.Pullen@Sun.COM #define PARAM2 1 135*8671SJulian.Pullen@Sun.COM int param_version[2]; 136*8671SJulian.Pullen@Sun.COM /* These holds the version of */ 137*8671SJulian.Pullen@Sun.COM /* dependents so that a dependent */ 138*8671SJulian.Pullen@Sun.COM /* change can be detected */ 139*8671SJulian.Pullen@Sun.COM } ad_item_t; 140*8671SJulian.Pullen@Sun.COM 141*8671SJulian.Pullen@Sun.COM typedef struct ad_disc { 142*8671SJulian.Pullen@Sun.COM struct __res_state res_state; 143*8671SJulian.Pullen@Sun.COM int res_ninitted; 144*8671SJulian.Pullen@Sun.COM ad_subnet_t *subnets; 145*8671SJulian.Pullen@Sun.COM boolean_t subnets_changed; 146*8671SJulian.Pullen@Sun.COM time_t subnets_last_check; 147*8671SJulian.Pullen@Sun.COM ad_item_t domain_name; /* DNS hostname string */ 148*8671SJulian.Pullen@Sun.COM ad_item_t domain_controller; /* Directory hostname and */ 149*8671SJulian.Pullen@Sun.COM /* port array */ 150*8671SJulian.Pullen@Sun.COM ad_item_t site_name; /* String */ 151*8671SJulian.Pullen@Sun.COM ad_item_t forest_name; /* DNS forestname string */ 152*8671SJulian.Pullen@Sun.COM ad_item_t global_catalog; /* Directory hostname and */ 153*8671SJulian.Pullen@Sun.COM /* port array */ 154*8671SJulian.Pullen@Sun.COM ad_item_t domains_in_forest; /* DNS domainname and SID */ 155*8671SJulian.Pullen@Sun.COM /* array */ 156*8671SJulian.Pullen@Sun.COM ad_item_t trusted_domains; /* DNS domainname and trust */ 157*8671SJulian.Pullen@Sun.COM /* direction array */ 158*8671SJulian.Pullen@Sun.COM /* Site specfic versions */ 159*8671SJulian.Pullen@Sun.COM ad_item_t site_domain_controller; /* Directory hostname and */ 160*8671SJulian.Pullen@Sun.COM /* port array */ 161*8671SJulian.Pullen@Sun.COM ad_item_t site_global_catalog; /* Directory hostname and */ 162*8671SJulian.Pullen@Sun.COM /* port array */ 163*8671SJulian.Pullen@Sun.COM } ad_disc; 164*8671SJulian.Pullen@Sun.COM 165*8671SJulian.Pullen@Sun.COM 166*8671SJulian.Pullen@Sun.COM #define DNS_MAX_NAME NS_MAXDNAME 167*8671SJulian.Pullen@Sun.COM 168*8671SJulian.Pullen@Sun.COM 169*8671SJulian.Pullen@Sun.COM /* SRV RR names for various queries */ 170*8671SJulian.Pullen@Sun.COM #define LDAP_SRV_HEAD "_ldap._tcp." 171*8671SJulian.Pullen@Sun.COM #define SITE_SRV_MIDDLE "%s._sites." 172*8671SJulian.Pullen@Sun.COM #define GC_SRV_TAIL "gc._msdcs" 173*8671SJulian.Pullen@Sun.COM #define DC_SRV_TAIL "dc._msdcs" 174*8671SJulian.Pullen@Sun.COM #define ALL_GC_SRV_TAIL "_gc._tcp" 175*8671SJulian.Pullen@Sun.COM #define PDC_SRV "_ldap._tcp.pdc._msdcs.%s" 176*8671SJulian.Pullen@Sun.COM 177*8671SJulian.Pullen@Sun.COM /* A RR name for all GCs -- last resort this works */ 178*8671SJulian.Pullen@Sun.COM #define GC_ALL_A_NAME_FSTR "gc._msdcs.%s." 179*8671SJulian.Pullen@Sun.COM 180*8671SJulian.Pullen@Sun.COM 181*8671SJulian.Pullen@Sun.COM /* 182*8671SJulian.Pullen@Sun.COM * We try res_ninit() whenever we don't have one. res_ninit() fails if 183*8671SJulian.Pullen@Sun.COM * idmapd is running before the network is up! 184*8671SJulian.Pullen@Sun.COM */ 185*8671SJulian.Pullen@Sun.COM #define DO_RES_NINIT(ctx) if (!(ctx)->res_ninitted) \ 186*8671SJulian.Pullen@Sun.COM (ctx)->res_ninitted = (res_ninit(&ctx->res_state) != -1) 187*8671SJulian.Pullen@Sun.COM 188*8671SJulian.Pullen@Sun.COM #define is_fixed(item) \ 189*8671SJulian.Pullen@Sun.COM ((item)->state == AD_STATE_FIXED) 190*8671SJulian.Pullen@Sun.COM 191*8671SJulian.Pullen@Sun.COM #define is_changed(item, num, param) \ 192*8671SJulian.Pullen@Sun.COM ((item)->param_version[num] != (param)->version) 193*8671SJulian.Pullen@Sun.COM 194*8671SJulian.Pullen@Sun.COM /*LINTLIBRARY*/ 195*8671SJulian.Pullen@Sun.COM 196*8671SJulian.Pullen@Sun.COM /* 197*8671SJulian.Pullen@Sun.COM * Function definitions 198*8671SJulian.Pullen@Sun.COM */ 199*8671SJulian.Pullen@Sun.COM static ad_item_t * 200*8671SJulian.Pullen@Sun.COM validate_SiteName(ad_disc_t ctx); 201*8671SJulian.Pullen@Sun.COM 202*8671SJulian.Pullen@Sun.COM 203*8671SJulian.Pullen@Sun.COM 204*8671SJulian.Pullen@Sun.COM static void 205*8671SJulian.Pullen@Sun.COM update_version(ad_item_t *item, int num, ad_item_t *param) 206*8671SJulian.Pullen@Sun.COM { 207*8671SJulian.Pullen@Sun.COM item->param_version[num] = param->version; 208*8671SJulian.Pullen@Sun.COM } 209*8671SJulian.Pullen@Sun.COM 210*8671SJulian.Pullen@Sun.COM 211*8671SJulian.Pullen@Sun.COM 212*8671SJulian.Pullen@Sun.COM static boolean_t 213*8671SJulian.Pullen@Sun.COM is_valid(ad_item_t *item) 214*8671SJulian.Pullen@Sun.COM { 215*8671SJulian.Pullen@Sun.COM if (item->value != NULL) { 216*8671SJulian.Pullen@Sun.COM if (item->state == AD_STATE_FIXED) 217*8671SJulian.Pullen@Sun.COM return (B_TRUE); 218*8671SJulian.Pullen@Sun.COM if (item->state == AD_STATE_AUTO && 219*8671SJulian.Pullen@Sun.COM (item->ttl == 0 || item->ttl > time(NULL))) 220*8671SJulian.Pullen@Sun.COM return (B_TRUE); 221*8671SJulian.Pullen@Sun.COM } 222*8671SJulian.Pullen@Sun.COM return (B_FALSE); 223*8671SJulian.Pullen@Sun.COM } 224*8671SJulian.Pullen@Sun.COM 225*8671SJulian.Pullen@Sun.COM 226*8671SJulian.Pullen@Sun.COM static void 227*8671SJulian.Pullen@Sun.COM update_item(ad_item_t *item, void *value, enum ad_item_state state, 228*8671SJulian.Pullen@Sun.COM uint32_t ttl) 229*8671SJulian.Pullen@Sun.COM { 230*8671SJulian.Pullen@Sun.COM if (item->value != NULL && value != NULL) { 231*8671SJulian.Pullen@Sun.COM if ((item->type == AD_STRING && 232*8671SJulian.Pullen@Sun.COM strcmp(item->value, value) != 0) || 233*8671SJulian.Pullen@Sun.COM (item->type == AD_DIRECTORY && 234*8671SJulian.Pullen@Sun.COM ad_disc_compare_ds(item->value, value) != 0)|| 235*8671SJulian.Pullen@Sun.COM (item->type == AD_DOMAINS_IN_FOREST && 236*8671SJulian.Pullen@Sun.COM ad_disc_compare_domainsinforest(item->value, value) != 0) || 237*8671SJulian.Pullen@Sun.COM (item->type == AD_TRUSTED_DOMAINS && 238*8671SJulian.Pullen@Sun.COM ad_disc_compare_trusteddomains(item->value, value) != 0)) 239*8671SJulian.Pullen@Sun.COM item->version++; 240*8671SJulian.Pullen@Sun.COM } else if (item->value != value) 241*8671SJulian.Pullen@Sun.COM item->version++; 242*8671SJulian.Pullen@Sun.COM 243*8671SJulian.Pullen@Sun.COM if (item->value != NULL) 244*8671SJulian.Pullen@Sun.COM free(item->value); 245*8671SJulian.Pullen@Sun.COM 246*8671SJulian.Pullen@Sun.COM item->value = value; 247*8671SJulian.Pullen@Sun.COM item->state = state; 248*8671SJulian.Pullen@Sun.COM 249*8671SJulian.Pullen@Sun.COM if (ttl == 0) 250*8671SJulian.Pullen@Sun.COM item->ttl = 0; 251*8671SJulian.Pullen@Sun.COM else 252*8671SJulian.Pullen@Sun.COM item->ttl = time(NULL) + ttl; 253*8671SJulian.Pullen@Sun.COM } 254*8671SJulian.Pullen@Sun.COM 255*8671SJulian.Pullen@Sun.COM 256*8671SJulian.Pullen@Sun.COM /* Compare DS lists */ 257*8671SJulian.Pullen@Sun.COM int 258*8671SJulian.Pullen@Sun.COM ad_disc_compare_ds(idmap_ad_disc_ds_t *ds1, idmap_ad_disc_ds_t *ds2) 259*8671SJulian.Pullen@Sun.COM { 260*8671SJulian.Pullen@Sun.COM int i, j; 261*8671SJulian.Pullen@Sun.COM int num_ds1; 262*8671SJulian.Pullen@Sun.COM int num_ds2; 263*8671SJulian.Pullen@Sun.COM boolean_t match; 264*8671SJulian.Pullen@Sun.COM 265*8671SJulian.Pullen@Sun.COM for (i = 0; ds1[i].host[0] != '\0'; i++) 266*8671SJulian.Pullen@Sun.COM continue; 267*8671SJulian.Pullen@Sun.COM num_ds1 = i; 268*8671SJulian.Pullen@Sun.COM for (j = 0; ds2[j].host[0] != '\0'; j++) 269*8671SJulian.Pullen@Sun.COM continue; 270*8671SJulian.Pullen@Sun.COM num_ds2 = j; 271*8671SJulian.Pullen@Sun.COM if (num_ds1 != num_ds2) 272*8671SJulian.Pullen@Sun.COM return (1); 273*8671SJulian.Pullen@Sun.COM 274*8671SJulian.Pullen@Sun.COM for (i = 0; i < num_ds1; i++) { 275*8671SJulian.Pullen@Sun.COM match = B_FALSE; 276*8671SJulian.Pullen@Sun.COM for (j = 0; j < num_ds2; j++) { 277*8671SJulian.Pullen@Sun.COM if (strcmp(ds1[i].host, ds2[i].host) == 0 && 278*8671SJulian.Pullen@Sun.COM ds1[i].port == ds2[i].port) { 279*8671SJulian.Pullen@Sun.COM match = B_TRUE; 280*8671SJulian.Pullen@Sun.COM break; 281*8671SJulian.Pullen@Sun.COM } 282*8671SJulian.Pullen@Sun.COM } 283*8671SJulian.Pullen@Sun.COM if (!match) 284*8671SJulian.Pullen@Sun.COM return (1); 285*8671SJulian.Pullen@Sun.COM } 286*8671SJulian.Pullen@Sun.COM return (0); 287*8671SJulian.Pullen@Sun.COM } 288*8671SJulian.Pullen@Sun.COM 289*8671SJulian.Pullen@Sun.COM 290*8671SJulian.Pullen@Sun.COM /* Copy a list of DSs */ 291*8671SJulian.Pullen@Sun.COM static idmap_ad_disc_ds_t * 292*8671SJulian.Pullen@Sun.COM ds_dup(const idmap_ad_disc_ds_t *srv) 293*8671SJulian.Pullen@Sun.COM { 294*8671SJulian.Pullen@Sun.COM int i; 295*8671SJulian.Pullen@Sun.COM int size; 296*8671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t *new = NULL; 297*8671SJulian.Pullen@Sun.COM 298*8671SJulian.Pullen@Sun.COM for (i = 0; srv[i].host[0] != '\0'; i++) 299*8671SJulian.Pullen@Sun.COM continue; 300*8671SJulian.Pullen@Sun.COM 301*8671SJulian.Pullen@Sun.COM size = (i + 1) * sizeof (idmap_ad_disc_ds_t); 302*8671SJulian.Pullen@Sun.COM new = malloc(size); 303*8671SJulian.Pullen@Sun.COM if (new != NULL) 304*8671SJulian.Pullen@Sun.COM memcpy(new, srv, size); 305*8671SJulian.Pullen@Sun.COM return (new); 306*8671SJulian.Pullen@Sun.COM } 307*8671SJulian.Pullen@Sun.COM 308*8671SJulian.Pullen@Sun.COM 309*8671SJulian.Pullen@Sun.COM int 310*8671SJulian.Pullen@Sun.COM ad_disc_compare_trusteddomains(ad_disc_trusteddomains_t *td1, 311*8671SJulian.Pullen@Sun.COM ad_disc_trusteddomains_t *td2) 312*8671SJulian.Pullen@Sun.COM { 313*8671SJulian.Pullen@Sun.COM int i, j; 314*8671SJulian.Pullen@Sun.COM int num_td1; 315*8671SJulian.Pullen@Sun.COM int num_td2; 316*8671SJulian.Pullen@Sun.COM boolean_t match; 317*8671SJulian.Pullen@Sun.COM int err; 318*8671SJulian.Pullen@Sun.COM 319*8671SJulian.Pullen@Sun.COM for (i = 0; td1[i].domain[0] != '\0'; i++) 320*8671SJulian.Pullen@Sun.COM continue; 321*8671SJulian.Pullen@Sun.COM num_td1 = i; 322*8671SJulian.Pullen@Sun.COM 323*8671SJulian.Pullen@Sun.COM for (j = 0; td2[j].domain[0] != '\0'; j++) 324*8671SJulian.Pullen@Sun.COM continue; 325*8671SJulian.Pullen@Sun.COM num_td2 = j; 326*8671SJulian.Pullen@Sun.COM 327*8671SJulian.Pullen@Sun.COM if (num_td1 != num_td2) 328*8671SJulian.Pullen@Sun.COM return (1); 329*8671SJulian.Pullen@Sun.COM 330*8671SJulian.Pullen@Sun.COM for (i = 0; i < num_td1; i++) { 331*8671SJulian.Pullen@Sun.COM match = B_FALSE; 332*8671SJulian.Pullen@Sun.COM for (j = 0; j < num_td2; j++) { 333*8671SJulian.Pullen@Sun.COM if (u8_strcmp(td1[i].domain, td2[i].domain, 0, 334*8671SJulian.Pullen@Sun.COM U8_STRCMP_CI_LOWER, U8_UNICODE_LATEST, &err) == 0 && 335*8671SJulian.Pullen@Sun.COM err == 0) { 336*8671SJulian.Pullen@Sun.COM match = B_TRUE; 337*8671SJulian.Pullen@Sun.COM break; 338*8671SJulian.Pullen@Sun.COM } 339*8671SJulian.Pullen@Sun.COM } 340*8671SJulian.Pullen@Sun.COM if (!match) 341*8671SJulian.Pullen@Sun.COM return (1); 342*8671SJulian.Pullen@Sun.COM } 343*8671SJulian.Pullen@Sun.COM return (0); 344*8671SJulian.Pullen@Sun.COM } 345*8671SJulian.Pullen@Sun.COM 346*8671SJulian.Pullen@Sun.COM 347*8671SJulian.Pullen@Sun.COM 348*8671SJulian.Pullen@Sun.COM /* Copy a list of Trusted Domains */ 349*8671SJulian.Pullen@Sun.COM static ad_disc_trusteddomains_t * 350*8671SJulian.Pullen@Sun.COM td_dup(const ad_disc_trusteddomains_t *td) 351*8671SJulian.Pullen@Sun.COM { 352*8671SJulian.Pullen@Sun.COM int i; 353*8671SJulian.Pullen@Sun.COM int size; 354*8671SJulian.Pullen@Sun.COM ad_disc_trusteddomains_t *new = NULL; 355*8671SJulian.Pullen@Sun.COM 356*8671SJulian.Pullen@Sun.COM for (i = 0; td[i].domain[0] != '\0'; i++) 357*8671SJulian.Pullen@Sun.COM continue; 358*8671SJulian.Pullen@Sun.COM 359*8671SJulian.Pullen@Sun.COM size = (i + 1) * sizeof (ad_disc_trusteddomains_t); 360*8671SJulian.Pullen@Sun.COM new = malloc(size); 361*8671SJulian.Pullen@Sun.COM if (new != NULL) 362*8671SJulian.Pullen@Sun.COM memcpy(new, td, size); 363*8671SJulian.Pullen@Sun.COM return (new); 364*8671SJulian.Pullen@Sun.COM } 365*8671SJulian.Pullen@Sun.COM 366*8671SJulian.Pullen@Sun.COM 367*8671SJulian.Pullen@Sun.COM 368*8671SJulian.Pullen@Sun.COM int 369*8671SJulian.Pullen@Sun.COM ad_disc_compare_domainsinforest(ad_disc_domainsinforest_t *df1, 370*8671SJulian.Pullen@Sun.COM ad_disc_domainsinforest_t *df2) 371*8671SJulian.Pullen@Sun.COM { 372*8671SJulian.Pullen@Sun.COM int i, j; 373*8671SJulian.Pullen@Sun.COM int num_df1; 374*8671SJulian.Pullen@Sun.COM int num_df2; 375*8671SJulian.Pullen@Sun.COM boolean_t match; 376*8671SJulian.Pullen@Sun.COM int err; 377*8671SJulian.Pullen@Sun.COM 378*8671SJulian.Pullen@Sun.COM for (i = 0; df1[i].domain[0] != '\0'; i++) 379*8671SJulian.Pullen@Sun.COM continue; 380*8671SJulian.Pullen@Sun.COM num_df1 = i; 381*8671SJulian.Pullen@Sun.COM 382*8671SJulian.Pullen@Sun.COM for (j = 0; df2[j].domain[0] != '\0'; j++) 383*8671SJulian.Pullen@Sun.COM continue; 384*8671SJulian.Pullen@Sun.COM num_df2 = j; 385*8671SJulian.Pullen@Sun.COM 386*8671SJulian.Pullen@Sun.COM if (num_df1 != num_df2) 387*8671SJulian.Pullen@Sun.COM return (1); 388*8671SJulian.Pullen@Sun.COM 389*8671SJulian.Pullen@Sun.COM for (i = 0; i < num_df1; i++) { 390*8671SJulian.Pullen@Sun.COM match = B_FALSE; 391*8671SJulian.Pullen@Sun.COM for (j = 0; j < num_df2; j++) { 392*8671SJulian.Pullen@Sun.COM if (u8_strcmp(df1[i].domain, df2[i].domain, 0, 393*8671SJulian.Pullen@Sun.COM U8_STRCMP_CI_LOWER, U8_UNICODE_LATEST, &err) == 0 && 394*8671SJulian.Pullen@Sun.COM err == 0 && 395*8671SJulian.Pullen@Sun.COM strcmp(df1[i].sid, df2[i].sid) == 0) { 396*8671SJulian.Pullen@Sun.COM match = B_TRUE; 397*8671SJulian.Pullen@Sun.COM break; 398*8671SJulian.Pullen@Sun.COM } 399*8671SJulian.Pullen@Sun.COM } 400*8671SJulian.Pullen@Sun.COM if (!match) 401*8671SJulian.Pullen@Sun.COM return (1); 402*8671SJulian.Pullen@Sun.COM } 403*8671SJulian.Pullen@Sun.COM return (0); 404*8671SJulian.Pullen@Sun.COM } 405*8671SJulian.Pullen@Sun.COM 406*8671SJulian.Pullen@Sun.COM 407*8671SJulian.Pullen@Sun.COM 408*8671SJulian.Pullen@Sun.COM /* Copy a list of Trusted Domains */ 409*8671SJulian.Pullen@Sun.COM static ad_disc_domainsinforest_t * 410*8671SJulian.Pullen@Sun.COM df_dup(const ad_disc_domainsinforest_t *df) 411*8671SJulian.Pullen@Sun.COM { 412*8671SJulian.Pullen@Sun.COM int i; 413*8671SJulian.Pullen@Sun.COM int size; 414*8671SJulian.Pullen@Sun.COM ad_disc_domainsinforest_t *new = NULL; 415*8671SJulian.Pullen@Sun.COM 416*8671SJulian.Pullen@Sun.COM for (i = 0; df[i].domain[0] != '\0'; i++) 417*8671SJulian.Pullen@Sun.COM continue; 418*8671SJulian.Pullen@Sun.COM 419*8671SJulian.Pullen@Sun.COM size = (i + 1) * sizeof (ad_disc_domainsinforest_t); 420*8671SJulian.Pullen@Sun.COM new = malloc(size); 421*8671SJulian.Pullen@Sun.COM if (new != NULL) 422*8671SJulian.Pullen@Sun.COM memcpy(new, df, size); 423*8671SJulian.Pullen@Sun.COM return (new); 424*8671SJulian.Pullen@Sun.COM } 425*8671SJulian.Pullen@Sun.COM 426*8671SJulian.Pullen@Sun.COM 427*8671SJulian.Pullen@Sun.COM 428*8671SJulian.Pullen@Sun.COM 429*8671SJulian.Pullen@Sun.COM 430*8671SJulian.Pullen@Sun.COM /* 431*8671SJulian.Pullen@Sun.COM * Returns an array of IPv4 address/prefix length 432*8671SJulian.Pullen@Sun.COM * The last subnet is NULL 433*8671SJulian.Pullen@Sun.COM */ 434*8671SJulian.Pullen@Sun.COM static ad_subnet_t * 435*8671SJulian.Pullen@Sun.COM find_subnets() 436*8671SJulian.Pullen@Sun.COM { 437*8671SJulian.Pullen@Sun.COM int sock, n, i; 438*8671SJulian.Pullen@Sun.COM struct lifconf lifc; 439*8671SJulian.Pullen@Sun.COM struct lifreq lifr, *lifrp; 440*8671SJulian.Pullen@Sun.COM struct lifnum lifn; 441*8671SJulian.Pullen@Sun.COM uint32_t prefix_len; 442*8671SJulian.Pullen@Sun.COM char *s; 443*8671SJulian.Pullen@Sun.COM ad_subnet_t *results; 444*8671SJulian.Pullen@Sun.COM 445*8671SJulian.Pullen@Sun.COM lifrp = &lifr; 446*8671SJulian.Pullen@Sun.COM 447*8671SJulian.Pullen@Sun.COM if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 448*8671SJulian.Pullen@Sun.COM logger(LOG_ERR, "Failed to open IPv4 socket for " 449*8671SJulian.Pullen@Sun.COM "listing network interfaces (%s)", strerror(errno)); 450*8671SJulian.Pullen@Sun.COM return (NULL); 451*8671SJulian.Pullen@Sun.COM } 452*8671SJulian.Pullen@Sun.COM 453*8671SJulian.Pullen@Sun.COM lifn.lifn_family = AF_INET; 454*8671SJulian.Pullen@Sun.COM lifn.lifn_flags = 0; 455*8671SJulian.Pullen@Sun.COM if (ioctl(sock, SIOCGLIFNUM, (char *)&lifn) < 0) { 456*8671SJulian.Pullen@Sun.COM logger(LOG_ERR, 457*8671SJulian.Pullen@Sun.COM "Failed to find the number of network interfaces (%s)", 458*8671SJulian.Pullen@Sun.COM strerror(errno)); 459*8671SJulian.Pullen@Sun.COM close(sock); 460*8671SJulian.Pullen@Sun.COM return (NULL); 461*8671SJulian.Pullen@Sun.COM } 462*8671SJulian.Pullen@Sun.COM 463*8671SJulian.Pullen@Sun.COM if (lifn.lifn_count < 1) { 464*8671SJulian.Pullen@Sun.COM logger(LOG_ERR, "No IPv4 network interfaces found"); 465*8671SJulian.Pullen@Sun.COM close(sock); 466*8671SJulian.Pullen@Sun.COM return (NULL); 467*8671SJulian.Pullen@Sun.COM } 468*8671SJulian.Pullen@Sun.COM 469*8671SJulian.Pullen@Sun.COM lifc.lifc_family = AF_INET; 470*8671SJulian.Pullen@Sun.COM lifc.lifc_flags = 0; 471*8671SJulian.Pullen@Sun.COM lifc.lifc_len = lifn.lifn_count * sizeof (struct lifreq); 472*8671SJulian.Pullen@Sun.COM lifc.lifc_buf = malloc(lifc.lifc_len); 473*8671SJulian.Pullen@Sun.COM 474*8671SJulian.Pullen@Sun.COM if (lifc.lifc_buf == NULL) { 475*8671SJulian.Pullen@Sun.COM logger(LOG_ERR, "Out of memory"); 476*8671SJulian.Pullen@Sun.COM close(sock); 477*8671SJulian.Pullen@Sun.COM return (NULL); 478*8671SJulian.Pullen@Sun.COM } 479*8671SJulian.Pullen@Sun.COM 480*8671SJulian.Pullen@Sun.COM if (ioctl(sock, SIOCGLIFCONF, (char *)&lifc) < 0) { 481*8671SJulian.Pullen@Sun.COM logger(LOG_ERR, "Failed to list network interfaces (%s)", 482*8671SJulian.Pullen@Sun.COM strerror(errno)); 483*8671SJulian.Pullen@Sun.COM free(lifc.lifc_buf); 484*8671SJulian.Pullen@Sun.COM close(sock); 485*8671SJulian.Pullen@Sun.COM return (NULL); 486*8671SJulian.Pullen@Sun.COM } 487*8671SJulian.Pullen@Sun.COM 488*8671SJulian.Pullen@Sun.COM n = lifc.lifc_len / (int)sizeof (struct lifreq); 489*8671SJulian.Pullen@Sun.COM 490*8671SJulian.Pullen@Sun.COM if ((results = calloc(n + 1, sizeof (ad_subnet_t))) == NULL) { 491*8671SJulian.Pullen@Sun.COM free(lifc.lifc_buf); 492*8671SJulian.Pullen@Sun.COM close(sock); 493*8671SJulian.Pullen@Sun.COM return (NULL); 494*8671SJulian.Pullen@Sun.COM } 495*8671SJulian.Pullen@Sun.COM 496*8671SJulian.Pullen@Sun.COM for (i = 0, lifrp = lifc.lifc_req; i < n; i++, lifrp++) { 497*8671SJulian.Pullen@Sun.COM if (ioctl(sock, SIOCGLIFFLAGS, lifrp) < 0) 498*8671SJulian.Pullen@Sun.COM continue; 499*8671SJulian.Pullen@Sun.COM 500*8671SJulian.Pullen@Sun.COM if ((lifrp->lifr_flags & IFF_UP) == 0) 501*8671SJulian.Pullen@Sun.COM continue; 502*8671SJulian.Pullen@Sun.COM 503*8671SJulian.Pullen@Sun.COM if (ioctl(sock, SIOCGLIFSUBNET, lifrp) < 0) 504*8671SJulian.Pullen@Sun.COM continue; 505*8671SJulian.Pullen@Sun.COM 506*8671SJulian.Pullen@Sun.COM prefix_len = lifrp->lifr_addrlen; 507*8671SJulian.Pullen@Sun.COM 508*8671SJulian.Pullen@Sun.COM s = inet_ntoa(((struct sockaddr_in *) 509*8671SJulian.Pullen@Sun.COM &lifrp->lifr_addr)->sin_addr); 510*8671SJulian.Pullen@Sun.COM 511*8671SJulian.Pullen@Sun.COM (void) snprintf(results[i].subnet, sizeof (ad_subnet_t), 512*8671SJulian.Pullen@Sun.COM "%s/%d", s, prefix_len); 513*8671SJulian.Pullen@Sun.COM } 514*8671SJulian.Pullen@Sun.COM 515*8671SJulian.Pullen@Sun.COM free(lifc.lifc_buf); 516*8671SJulian.Pullen@Sun.COM close(sock); 517*8671SJulian.Pullen@Sun.COM 518*8671SJulian.Pullen@Sun.COM return (results); 519*8671SJulian.Pullen@Sun.COM } 520*8671SJulian.Pullen@Sun.COM 521*8671SJulian.Pullen@Sun.COM static int 522*8671SJulian.Pullen@Sun.COM cmpsubnets(ad_subnet_t *subnets1, ad_subnet_t *subnets2) 523*8671SJulian.Pullen@Sun.COM { 524*8671SJulian.Pullen@Sun.COM int num_subnets1; 525*8671SJulian.Pullen@Sun.COM int num_subnets2; 526*8671SJulian.Pullen@Sun.COM boolean_t matched; 527*8671SJulian.Pullen@Sun.COM int i, j; 528*8671SJulian.Pullen@Sun.COM 529*8671SJulian.Pullen@Sun.COM for (i = 0; subnets1[i].subnet[0] != '\0'; i++) 530*8671SJulian.Pullen@Sun.COM continue; 531*8671SJulian.Pullen@Sun.COM num_subnets1 = i; 532*8671SJulian.Pullen@Sun.COM 533*8671SJulian.Pullen@Sun.COM for (i = 0; subnets2[i].subnet[0] != '\0'; i++) 534*8671SJulian.Pullen@Sun.COM continue; 535*8671SJulian.Pullen@Sun.COM num_subnets2 = i; 536*8671SJulian.Pullen@Sun.COM 537*8671SJulian.Pullen@Sun.COM if (num_subnets1 != num_subnets2) 538*8671SJulian.Pullen@Sun.COM return (1); 539*8671SJulian.Pullen@Sun.COM 540*8671SJulian.Pullen@Sun.COM for (i = 0; i < num_subnets1; i++) { 541*8671SJulian.Pullen@Sun.COM matched = B_FALSE; 542*8671SJulian.Pullen@Sun.COM for (j = 0; j < num_subnets2; j++) { 543*8671SJulian.Pullen@Sun.COM if (strcmp(subnets1[i].subnet, 544*8671SJulian.Pullen@Sun.COM subnets2[j].subnet) == 0) { 545*8671SJulian.Pullen@Sun.COM matched = B_TRUE; 546*8671SJulian.Pullen@Sun.COM break; 547*8671SJulian.Pullen@Sun.COM } 548*8671SJulian.Pullen@Sun.COM } 549*8671SJulian.Pullen@Sun.COM if (!matched) 550*8671SJulian.Pullen@Sun.COM return (1); 551*8671SJulian.Pullen@Sun.COM } 552*8671SJulian.Pullen@Sun.COM return (0); 553*8671SJulian.Pullen@Sun.COM } 554*8671SJulian.Pullen@Sun.COM 555*8671SJulian.Pullen@Sun.COM 556*8671SJulian.Pullen@Sun.COM 557*8671SJulian.Pullen@Sun.COM 558*8671SJulian.Pullen@Sun.COM /* Convert a DN's DC components into a DNS domainname */ 559*8671SJulian.Pullen@Sun.COM char * 560*8671SJulian.Pullen@Sun.COM DN_to_DNS(const char *dn_name) 561*8671SJulian.Pullen@Sun.COM { 562*8671SJulian.Pullen@Sun.COM char dns[DNS_MAX_NAME]; 563*8671SJulian.Pullen@Sun.COM char *dns_name; 564*8671SJulian.Pullen@Sun.COM int i, j; 565*8671SJulian.Pullen@Sun.COM int num = 0; 566*8671SJulian.Pullen@Sun.COM 567*8671SJulian.Pullen@Sun.COM j = 0; 568*8671SJulian.Pullen@Sun.COM i = 0; 569*8671SJulian.Pullen@Sun.COM 570*8671SJulian.Pullen@Sun.COM if (dn_name == NULL) 571*8671SJulian.Pullen@Sun.COM return (NULL); 572*8671SJulian.Pullen@Sun.COM /* 573*8671SJulian.Pullen@Sun.COM * Find all DC=<value> and form DNS name of the 574*8671SJulian.Pullen@Sun.COM * form <value1>.<value2>... 575*8671SJulian.Pullen@Sun.COM */ 576*8671SJulian.Pullen@Sun.COM while (dn_name[i] != '\0') { 577*8671SJulian.Pullen@Sun.COM if (strncasecmp(&dn_name[i], "DC=", 3) == 0) { 578*8671SJulian.Pullen@Sun.COM i += 3; 579*8671SJulian.Pullen@Sun.COM if (dn_name[i] != '\0' && num > 0) 580*8671SJulian.Pullen@Sun.COM dns[j++] = '.'; 581*8671SJulian.Pullen@Sun.COM while (dn_name[i] != '\0' && 582*8671SJulian.Pullen@Sun.COM dn_name[i] != ',' && dn_name[i] != '+') 583*8671SJulian.Pullen@Sun.COM dns[j++] = dn_name[i++]; 584*8671SJulian.Pullen@Sun.COM num++; 585*8671SJulian.Pullen@Sun.COM } else { 586*8671SJulian.Pullen@Sun.COM /* Skip attr=value as it is not DC= */ 587*8671SJulian.Pullen@Sun.COM while (dn_name[i] != '\0' && 588*8671SJulian.Pullen@Sun.COM dn_name[i] != ',' && dn_name[i] != '+') 589*8671SJulian.Pullen@Sun.COM i++; 590*8671SJulian.Pullen@Sun.COM } 591*8671SJulian.Pullen@Sun.COM /* Skip over separator ',' or '+' */ 592*8671SJulian.Pullen@Sun.COM if (dn_name[i] != '\0') i++; 593*8671SJulian.Pullen@Sun.COM } 594*8671SJulian.Pullen@Sun.COM dns[j] = '\0'; 595*8671SJulian.Pullen@Sun.COM dns_name = malloc(j + 1); 596*8671SJulian.Pullen@Sun.COM if (dns_name != NULL) 597*8671SJulian.Pullen@Sun.COM (void) strlcpy(dns_name, dns, j + 1); 598*8671SJulian.Pullen@Sun.COM return (dns_name); 599*8671SJulian.Pullen@Sun.COM } 600*8671SJulian.Pullen@Sun.COM 601*8671SJulian.Pullen@Sun.COM 602*8671SJulian.Pullen@Sun.COM /* Format the DN of an AD LDAP subnet object for some subnet */ 603*8671SJulian.Pullen@Sun.COM static char * 604*8671SJulian.Pullen@Sun.COM subnet_to_DN(const char *subnet, const char *baseDN) 605*8671SJulian.Pullen@Sun.COM { 606*8671SJulian.Pullen@Sun.COM char *result; 607*8671SJulian.Pullen@Sun.COM int len; 608*8671SJulian.Pullen@Sun.COM 609*8671SJulian.Pullen@Sun.COM len = snprintf(NULL, 0, 610*8671SJulian.Pullen@Sun.COM "CN=%s,CN=Subnets,CN=Sites,%s", 611*8671SJulian.Pullen@Sun.COM subnet, baseDN) + 1; 612*8671SJulian.Pullen@Sun.COM 613*8671SJulian.Pullen@Sun.COM result = malloc(len); 614*8671SJulian.Pullen@Sun.COM if (result != NULL) 615*8671SJulian.Pullen@Sun.COM (void) snprintf(result, len, 616*8671SJulian.Pullen@Sun.COM "CN=%s,CN=Subnets,CN=Sites,%s", 617*8671SJulian.Pullen@Sun.COM subnet, baseDN); 618*8671SJulian.Pullen@Sun.COM return (result); 619*8671SJulian.Pullen@Sun.COM } 620*8671SJulian.Pullen@Sun.COM 621*8671SJulian.Pullen@Sun.COM 622*8671SJulian.Pullen@Sun.COM /* Make a list of subnet object DNs from a list of subnets */ 623*8671SJulian.Pullen@Sun.COM static char ** 624*8671SJulian.Pullen@Sun.COM subnets_to_DNs(ad_subnet_t *subnets, const char *base_dn) 625*8671SJulian.Pullen@Sun.COM { 626*8671SJulian.Pullen@Sun.COM char **results; 627*8671SJulian.Pullen@Sun.COM int i, j; 628*8671SJulian.Pullen@Sun.COM 629*8671SJulian.Pullen@Sun.COM for (i = 0; subnets[i].subnet[0] != '\0'; i++) 630*8671SJulian.Pullen@Sun.COM continue; 631*8671SJulian.Pullen@Sun.COM 632*8671SJulian.Pullen@Sun.COM results = calloc(i + 1, sizeof (char *)); 633*8671SJulian.Pullen@Sun.COM if (results == NULL) 634*8671SJulian.Pullen@Sun.COM return (NULL); 635*8671SJulian.Pullen@Sun.COM 636*8671SJulian.Pullen@Sun.COM for (i = 0; subnets[i].subnet[0] != '\0'; i++) { 637*8671SJulian.Pullen@Sun.COM if ((results[i] = subnet_to_DN(subnets[i].subnet, base_dn)) 638*8671SJulian.Pullen@Sun.COM == NULL) { 639*8671SJulian.Pullen@Sun.COM for (j = 0; j < i; j++) 640*8671SJulian.Pullen@Sun.COM free(results[j]); 641*8671SJulian.Pullen@Sun.COM free(results); 642*8671SJulian.Pullen@Sun.COM return (NULL); 643*8671SJulian.Pullen@Sun.COM } 644*8671SJulian.Pullen@Sun.COM } 645*8671SJulian.Pullen@Sun.COM 646*8671SJulian.Pullen@Sun.COM return (results); 647*8671SJulian.Pullen@Sun.COM } 648*8671SJulian.Pullen@Sun.COM 649*8671SJulian.Pullen@Sun.COM 650*8671SJulian.Pullen@Sun.COM /* Compare SRC RRs; used with qsort() */ 651*8671SJulian.Pullen@Sun.COM static int 652*8671SJulian.Pullen@Sun.COM srvcmp(idmap_ad_disc_ds_t *s1, idmap_ad_disc_ds_t *s2) 653*8671SJulian.Pullen@Sun.COM { 654*8671SJulian.Pullen@Sun.COM if (s1->priority < s2->priority) 655*8671SJulian.Pullen@Sun.COM return (1); 656*8671SJulian.Pullen@Sun.COM else if (s1->priority > s2->priority) 657*8671SJulian.Pullen@Sun.COM return (-1); 658*8671SJulian.Pullen@Sun.COM 659*8671SJulian.Pullen@Sun.COM if (s1->weight < s2->weight) 660*8671SJulian.Pullen@Sun.COM return (1); 661*8671SJulian.Pullen@Sun.COM else if (s1->weight > s2->weight) 662*8671SJulian.Pullen@Sun.COM return (-1); 663*8671SJulian.Pullen@Sun.COM 664*8671SJulian.Pullen@Sun.COM return (0); 665*8671SJulian.Pullen@Sun.COM } 666*8671SJulian.Pullen@Sun.COM 667*8671SJulian.Pullen@Sun.COM 668*8671SJulian.Pullen@Sun.COM /* 669*8671SJulian.Pullen@Sun.COM * Query or search the SRV RRs for a given name. 670*8671SJulian.Pullen@Sun.COM * 671*8671SJulian.Pullen@Sun.COM * If name == NULL then search (as in res_nsearch(3RESOLV), honoring any 672*8671SJulian.Pullen@Sun.COM * search list/option), else query (as in res_nquery(3RESOLV)). 673*8671SJulian.Pullen@Sun.COM * 674*8671SJulian.Pullen@Sun.COM * The output TTL will be the one of the SRV RR with the lowest TTL. 675*8671SJulian.Pullen@Sun.COM */ 676*8671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t * 677*8671SJulian.Pullen@Sun.COM srv_query(res_state state, const char *svc_name, const char *dname, 678*8671SJulian.Pullen@Sun.COM char **rrname, uint32_t *ttl) 679*8671SJulian.Pullen@Sun.COM { 680*8671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t *srv; 681*8671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t *srv_res; 682*8671SJulian.Pullen@Sun.COM union { 683*8671SJulian.Pullen@Sun.COM HEADER hdr; 684*8671SJulian.Pullen@Sun.COM uchar_t buf[NS_MAXMSG]; 685*8671SJulian.Pullen@Sun.COM } msg; 686*8671SJulian.Pullen@Sun.COM int len, cnt, qdcount, ancount; 687*8671SJulian.Pullen@Sun.COM uchar_t *ptr, *eom; 688*8671SJulian.Pullen@Sun.COM uchar_t *end; 689*8671SJulian.Pullen@Sun.COM uint16_t type; 690*8671SJulian.Pullen@Sun.COM /* LINTED E_FUNC_SET_NOT_USED */ 691*8671SJulian.Pullen@Sun.COM uint16_t class; 692*8671SJulian.Pullen@Sun.COM uint32_t rttl; 693*8671SJulian.Pullen@Sun.COM uint16_t size; 694*8671SJulian.Pullen@Sun.COM char namebuf[NS_MAXDNAME]; 695*8671SJulian.Pullen@Sun.COM 696*8671SJulian.Pullen@Sun.COM if (state == NULL) 697*8671SJulian.Pullen@Sun.COM return (NULL); 698*8671SJulian.Pullen@Sun.COM 699*8671SJulian.Pullen@Sun.COM /* Set negative result TTL */ 700*8671SJulian.Pullen@Sun.COM *ttl = 5 * 60; 701*8671SJulian.Pullen@Sun.COM 702*8671SJulian.Pullen@Sun.COM /* 1. query necessary resource records */ 703*8671SJulian.Pullen@Sun.COM 704*8671SJulian.Pullen@Sun.COM /* Search, querydomain or query */ 705*8671SJulian.Pullen@Sun.COM if (rrname != NULL) { 706*8671SJulian.Pullen@Sun.COM *rrname = NULL; 707*8671SJulian.Pullen@Sun.COM len = res_nsearch(state, svc_name, C_IN, T_SRV, 708*8671SJulian.Pullen@Sun.COM msg.buf, sizeof (msg.buf)); 709*8671SJulian.Pullen@Sun.COM logger(LOG_DEBUG, "Searching DNS for SRV RRs named '%s'", 710*8671SJulian.Pullen@Sun.COM svc_name); 711*8671SJulian.Pullen@Sun.COM if (len < 0) { 712*8671SJulian.Pullen@Sun.COM logger(LOG_DEBUG, "DNS search for '%s' failed (%s)", 713*8671SJulian.Pullen@Sun.COM svc_name, hstrerror(state->res_h_errno)); 714*8671SJulian.Pullen@Sun.COM return (NULL); 715*8671SJulian.Pullen@Sun.COM } 716*8671SJulian.Pullen@Sun.COM } else if (dname != NULL) { 717*8671SJulian.Pullen@Sun.COM len = res_nquerydomain(state, svc_name, dname, C_IN, T_SRV, 718*8671SJulian.Pullen@Sun.COM msg.buf, sizeof (msg.buf)); 719*8671SJulian.Pullen@Sun.COM logger(LOG_DEBUG, 720*8671SJulian.Pullen@Sun.COM "Querying DNS for SRV RRs named '%s' for '%s' ", 721*8671SJulian.Pullen@Sun.COM svc_name, dname); 722*8671SJulian.Pullen@Sun.COM 723*8671SJulian.Pullen@Sun.COM if (len < 0) { 724*8671SJulian.Pullen@Sun.COM logger(LOG_DEBUG, 725*8671SJulian.Pullen@Sun.COM "DNS query for '%s' for '%s' failed (%s)", 726*8671SJulian.Pullen@Sun.COM svc_name, dname, hstrerror(state->res_h_errno)); 727*8671SJulian.Pullen@Sun.COM return (NULL); 728*8671SJulian.Pullen@Sun.COM } 729*8671SJulian.Pullen@Sun.COM } 730*8671SJulian.Pullen@Sun.COM 731*8671SJulian.Pullen@Sun.COM if (len > sizeof (msg.buf)) { 732*8671SJulian.Pullen@Sun.COM logger(LOG_ERR, "DNS query %ib message doesn't fit" 733*8671SJulian.Pullen@Sun.COM " into %ib buffer", 734*8671SJulian.Pullen@Sun.COM len, sizeof (msg.buf)); 735*8671SJulian.Pullen@Sun.COM return (NULL); 736*8671SJulian.Pullen@Sun.COM } 737*8671SJulian.Pullen@Sun.COM 738*8671SJulian.Pullen@Sun.COM /* 2. parse the reply, skip header and question sections */ 739*8671SJulian.Pullen@Sun.COM 740*8671SJulian.Pullen@Sun.COM ptr = msg.buf + sizeof (msg.hdr); 741*8671SJulian.Pullen@Sun.COM eom = msg.buf + len; 742*8671SJulian.Pullen@Sun.COM qdcount = ntohs(msg.hdr.qdcount); 743*8671SJulian.Pullen@Sun.COM ancount = ntohs(msg.hdr.ancount); 744*8671SJulian.Pullen@Sun.COM 745*8671SJulian.Pullen@Sun.COM for (cnt = qdcount; cnt > 0; --cnt) { 746*8671SJulian.Pullen@Sun.COM if ((len = dn_skipname(ptr, eom)) < 0) { 747*8671SJulian.Pullen@Sun.COM logger(LOG_ERR, "DNS query invalid message format"); 748*8671SJulian.Pullen@Sun.COM return (NULL); 749*8671SJulian.Pullen@Sun.COM } 750*8671SJulian.Pullen@Sun.COM ptr += len + QFIXEDSZ; 751*8671SJulian.Pullen@Sun.COM } 752*8671SJulian.Pullen@Sun.COM 753*8671SJulian.Pullen@Sun.COM /* 3. walk through the answer section */ 754*8671SJulian.Pullen@Sun.COM 755*8671SJulian.Pullen@Sun.COM srv_res = calloc(ancount + 1, sizeof (idmap_ad_disc_ds_t)); 756*8671SJulian.Pullen@Sun.COM *ttl = (uint32_t)-1; 757*8671SJulian.Pullen@Sun.COM 758*8671SJulian.Pullen@Sun.COM for (srv = srv_res, cnt = ancount; 759*8671SJulian.Pullen@Sun.COM cnt > 0; --cnt, srv++) { 760*8671SJulian.Pullen@Sun.COM 761*8671SJulian.Pullen@Sun.COM len = dn_expand(msg.buf, eom, ptr, namebuf, 762*8671SJulian.Pullen@Sun.COM sizeof (namebuf)); 763*8671SJulian.Pullen@Sun.COM if (len < 0) { 764*8671SJulian.Pullen@Sun.COM logger(LOG_ERR, "DNS query invalid message format"); 765*8671SJulian.Pullen@Sun.COM return (NULL); 766*8671SJulian.Pullen@Sun.COM } 767*8671SJulian.Pullen@Sun.COM if (rrname != NULL && *rrname == NULL) 768*8671SJulian.Pullen@Sun.COM *rrname = strdup(namebuf); 769*8671SJulian.Pullen@Sun.COM ptr += len; 770*8671SJulian.Pullen@Sun.COM NS_GET16(type, ptr); 771*8671SJulian.Pullen@Sun.COM NS_GET16(class, ptr); 772*8671SJulian.Pullen@Sun.COM NS_GET32(rttl, ptr); 773*8671SJulian.Pullen@Sun.COM NS_GET16(size, ptr); 774*8671SJulian.Pullen@Sun.COM if ((end = ptr + size) > eom) { 775*8671SJulian.Pullen@Sun.COM logger(LOG_ERR, "DNS query invalid message format"); 776*8671SJulian.Pullen@Sun.COM return (NULL); 777*8671SJulian.Pullen@Sun.COM } 778*8671SJulian.Pullen@Sun.COM 779*8671SJulian.Pullen@Sun.COM if (type != T_SRV) { 780*8671SJulian.Pullen@Sun.COM ptr = end; 781*8671SJulian.Pullen@Sun.COM continue; 782*8671SJulian.Pullen@Sun.COM } 783*8671SJulian.Pullen@Sun.COM 784*8671SJulian.Pullen@Sun.COM NS_GET16(srv->priority, ptr); 785*8671SJulian.Pullen@Sun.COM NS_GET16(srv->weight, ptr); 786*8671SJulian.Pullen@Sun.COM NS_GET16(srv->port, ptr); 787*8671SJulian.Pullen@Sun.COM len = dn_expand(msg.buf, eom, ptr, srv->host, 788*8671SJulian.Pullen@Sun.COM sizeof (srv->host)); 789*8671SJulian.Pullen@Sun.COM if (len < 0) { 790*8671SJulian.Pullen@Sun.COM logger(LOG_ERR, "DNS query invalid SRV record"); 791*8671SJulian.Pullen@Sun.COM return (NULL); 792*8671SJulian.Pullen@Sun.COM } 793*8671SJulian.Pullen@Sun.COM 794*8671SJulian.Pullen@Sun.COM if (rttl < *ttl) 795*8671SJulian.Pullen@Sun.COM *ttl = rttl; 796*8671SJulian.Pullen@Sun.COM 797*8671SJulian.Pullen@Sun.COM logger(LOG_DEBUG, "Found %s %d IN SRV [%d][%d] %s:%d", 798*8671SJulian.Pullen@Sun.COM namebuf, rttl, srv->priority, srv->weight, srv->host, 799*8671SJulian.Pullen@Sun.COM srv->port); 800*8671SJulian.Pullen@Sun.COM 801*8671SJulian.Pullen@Sun.COM /* 3. move ptr to the end of current record */ 802*8671SJulian.Pullen@Sun.COM 803*8671SJulian.Pullen@Sun.COM ptr = end; 804*8671SJulian.Pullen@Sun.COM } 805*8671SJulian.Pullen@Sun.COM 806*8671SJulian.Pullen@Sun.COM if (ancount > 1) 807*8671SJulian.Pullen@Sun.COM qsort(srv_res, ancount, sizeof (*srv_res), 808*8671SJulian.Pullen@Sun.COM (int (*)(const void *, const void *))srvcmp); 809*8671SJulian.Pullen@Sun.COM 810*8671SJulian.Pullen@Sun.COM return (srv_res); 811*8671SJulian.Pullen@Sun.COM } 812*8671SJulian.Pullen@Sun.COM 813*8671SJulian.Pullen@Sun.COM 814*8671SJulian.Pullen@Sun.COM /* 815*8671SJulian.Pullen@Sun.COM * A utility function to bind to a Directory server 816*8671SJulian.Pullen@Sun.COM */ 817*8671SJulian.Pullen@Sun.COM 818*8671SJulian.Pullen@Sun.COM static LDAP* 819*8671SJulian.Pullen@Sun.COM ldap_lookup_init(idmap_ad_disc_ds_t *ds) 820*8671SJulian.Pullen@Sun.COM { 821*8671SJulian.Pullen@Sun.COM int i; 822*8671SJulian.Pullen@Sun.COM int rc, ldversion; 823*8671SJulian.Pullen@Sun.COM int zero = 0; 824*8671SJulian.Pullen@Sun.COM int timeoutms = 5 * 1000; 825*8671SJulian.Pullen@Sun.COM char *saslmech = "GSSAPI"; 826*8671SJulian.Pullen@Sun.COM uint32_t saslflags = LDAP_SASL_INTERACTIVE; 827*8671SJulian.Pullen@Sun.COM LDAP *ld = NULL; 828*8671SJulian.Pullen@Sun.COM 829*8671SJulian.Pullen@Sun.COM for (i = 0; ds[i].host[0] != '\0'; i++) { 830*8671SJulian.Pullen@Sun.COM ld = ldap_init(ds[i].host, ds[i].port); 831*8671SJulian.Pullen@Sun.COM if (ld == NULL) { 832*8671SJulian.Pullen@Sun.COM logger(LOG_DEBUG, "Couldn't connect to " 833*8671SJulian.Pullen@Sun.COM "AD DC %s:%d (%s)", 834*8671SJulian.Pullen@Sun.COM ds[i].host, ds[i].port, 835*8671SJulian.Pullen@Sun.COM strerror(errno)); 836*8671SJulian.Pullen@Sun.COM continue; 837*8671SJulian.Pullen@Sun.COM } 838*8671SJulian.Pullen@Sun.COM 839*8671SJulian.Pullen@Sun.COM ldversion = LDAP_VERSION3; 840*8671SJulian.Pullen@Sun.COM (void) ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, 841*8671SJulian.Pullen@Sun.COM &ldversion); 842*8671SJulian.Pullen@Sun.COM 843*8671SJulian.Pullen@Sun.COM (void) ldap_set_option(ld, LDAP_OPT_REFERRALS, 844*8671SJulian.Pullen@Sun.COM LDAP_OPT_OFF); 845*8671SJulian.Pullen@Sun.COM (void) ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &zero); 846*8671SJulian.Pullen@Sun.COM (void) ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &zero); 847*8671SJulian.Pullen@Sun.COM /* setup TCP/IP connect timeout */ 848*8671SJulian.Pullen@Sun.COM (void) ldap_set_option(ld, LDAP_X_OPT_CONNECT_TIMEOUT, 849*8671SJulian.Pullen@Sun.COM &timeoutms); 850*8671SJulian.Pullen@Sun.COM (void) ldap_set_option(ld, LDAP_OPT_RESTART, 851*8671SJulian.Pullen@Sun.COM LDAP_OPT_ON); 852*8671SJulian.Pullen@Sun.COM 853*8671SJulian.Pullen@Sun.COM rc = ldap_sasl_interactive_bind_s(ld, "" /* binddn */, 854*8671SJulian.Pullen@Sun.COM saslmech, NULL, NULL, saslflags, &saslcallback, 855*8671SJulian.Pullen@Sun.COM NULL /* defaults */); 856*8671SJulian.Pullen@Sun.COM if (rc == LDAP_SUCCESS) 857*8671SJulian.Pullen@Sun.COM break; 858*8671SJulian.Pullen@Sun.COM 859*8671SJulian.Pullen@Sun.COM logger(LOG_INFO, "LDAP SASL bind to %s:%d failed (%s)", 860*8671SJulian.Pullen@Sun.COM ds[i].host, ds[i].port, ldap_err2string(rc)); 861*8671SJulian.Pullen@Sun.COM (void) ldap_unbind(ld); 862*8671SJulian.Pullen@Sun.COM ld = NULL; 863*8671SJulian.Pullen@Sun.COM } 864*8671SJulian.Pullen@Sun.COM return (ld); 865*8671SJulian.Pullen@Sun.COM } 866*8671SJulian.Pullen@Sun.COM 867*8671SJulian.Pullen@Sun.COM 868*8671SJulian.Pullen@Sun.COM 869*8671SJulian.Pullen@Sun.COM /* 870*8671SJulian.Pullen@Sun.COM * A utility function to get the value of some attribute of one of one 871*8671SJulian.Pullen@Sun.COM * or more AD LDAP objects named by the dn_list; first found one wins. 872*8671SJulian.Pullen@Sun.COM */ 873*8671SJulian.Pullen@Sun.COM static char * 874*8671SJulian.Pullen@Sun.COM ldap_lookup_entry_attr(LDAP **ld, idmap_ad_disc_ds_t *domainControllers, 875*8671SJulian.Pullen@Sun.COM char **dn_list, char *attr) 876*8671SJulian.Pullen@Sun.COM { 877*8671SJulian.Pullen@Sun.COM int i; 878*8671SJulian.Pullen@Sun.COM int rc; 879*8671SJulian.Pullen@Sun.COM int scope = LDAP_SCOPE_BASE; 880*8671SJulian.Pullen@Sun.COM char *attrs[2]; 881*8671SJulian.Pullen@Sun.COM LDAPMessage *results = NULL; 882*8671SJulian.Pullen@Sun.COM LDAPMessage *entry; 883*8671SJulian.Pullen@Sun.COM char **values = NULL; 884*8671SJulian.Pullen@Sun.COM char *val = NULL; 885*8671SJulian.Pullen@Sun.COM 886*8671SJulian.Pullen@Sun.COM attrs[0] = attr; 887*8671SJulian.Pullen@Sun.COM attrs[1] = NULL; 888*8671SJulian.Pullen@Sun.COM 889*8671SJulian.Pullen@Sun.COM if (*ld == NULL) 890*8671SJulian.Pullen@Sun.COM *ld = ldap_lookup_init(domainControllers); 891*8671SJulian.Pullen@Sun.COM 892*8671SJulian.Pullen@Sun.COM if (*ld == NULL) 893*8671SJulian.Pullen@Sun.COM return (NULL); 894*8671SJulian.Pullen@Sun.COM 895*8671SJulian.Pullen@Sun.COM for (i = 0; dn_list[i] != NULL; i++) { 896*8671SJulian.Pullen@Sun.COM rc = ldap_search_s(*ld, dn_list[i], scope, 897*8671SJulian.Pullen@Sun.COM "(objectclass=*)", attrs, 0, &results); 898*8671SJulian.Pullen@Sun.COM if (rc == LDAP_SUCCESS) { 899*8671SJulian.Pullen@Sun.COM for (entry = ldap_first_entry(*ld, results); 900*8671SJulian.Pullen@Sun.COM entry != NULL && values == NULL; 901*8671SJulian.Pullen@Sun.COM entry = ldap_next_entry(*ld, entry)) { 902*8671SJulian.Pullen@Sun.COM values = ldap_get_values( 903*8671SJulian.Pullen@Sun.COM *ld, entry, attr); 904*8671SJulian.Pullen@Sun.COM } 905*8671SJulian.Pullen@Sun.COM 906*8671SJulian.Pullen@Sun.COM if (values != NULL) { 907*8671SJulian.Pullen@Sun.COM (void) ldap_msgfree(results); 908*8671SJulian.Pullen@Sun.COM val = strdup(values[0]); 909*8671SJulian.Pullen@Sun.COM ldap_value_free(values); 910*8671SJulian.Pullen@Sun.COM return (val); 911*8671SJulian.Pullen@Sun.COM } 912*8671SJulian.Pullen@Sun.COM } 913*8671SJulian.Pullen@Sun.COM if (results != NULL) { 914*8671SJulian.Pullen@Sun.COM (void) ldap_msgfree(results); 915*8671SJulian.Pullen@Sun.COM results = NULL; 916*8671SJulian.Pullen@Sun.COM } 917*8671SJulian.Pullen@Sun.COM } 918*8671SJulian.Pullen@Sun.COM 919*8671SJulian.Pullen@Sun.COM return (NULL); 920*8671SJulian.Pullen@Sun.COM } 921*8671SJulian.Pullen@Sun.COM 922*8671SJulian.Pullen@Sun.COM 923*8671SJulian.Pullen@Sun.COM /* 924*8671SJulian.Pullen@Sun.COM * Lookup the trusted domains in the global catalog. 925*8671SJulian.Pullen@Sun.COM * 926*8671SJulian.Pullen@Sun.COM * Returns: 927*8671SJulian.Pullen@Sun.COM * array of trusted domains which is terminated by 928*8671SJulian.Pullen@Sun.COM * an empty trusted domain. 929*8671SJulian.Pullen@Sun.COM * NULL an error occured 930*8671SJulian.Pullen@Sun.COM */ 931*8671SJulian.Pullen@Sun.COM ad_disc_trusteddomains_t * 932*8671SJulian.Pullen@Sun.COM ldap_lookup_trusted_domains(LDAP **ld, idmap_ad_disc_ds_t *globalCatalog, 933*8671SJulian.Pullen@Sun.COM char *base_dn) 934*8671SJulian.Pullen@Sun.COM { 935*8671SJulian.Pullen@Sun.COM int scope = LDAP_SCOPE_SUBTREE; 936*8671SJulian.Pullen@Sun.COM char *attrs[3]; 937*8671SJulian.Pullen@Sun.COM int rc; 938*8671SJulian.Pullen@Sun.COM LDAPMessage *results = NULL; 939*8671SJulian.Pullen@Sun.COM LDAPMessage *entry; 940*8671SJulian.Pullen@Sun.COM char *filter; 941*8671SJulian.Pullen@Sun.COM char **partner = NULL; 942*8671SJulian.Pullen@Sun.COM char **direction = NULL; 943*8671SJulian.Pullen@Sun.COM int num = 0; 944*8671SJulian.Pullen@Sun.COM ad_disc_trusteddomains_t *trusted_domains = NULL; 945*8671SJulian.Pullen@Sun.COM 946*8671SJulian.Pullen@Sun.COM 947*8671SJulian.Pullen@Sun.COM if (*ld == NULL) 948*8671SJulian.Pullen@Sun.COM *ld = ldap_lookup_init(globalCatalog); 949*8671SJulian.Pullen@Sun.COM 950*8671SJulian.Pullen@Sun.COM if (*ld == NULL) 951*8671SJulian.Pullen@Sun.COM return (NULL); 952*8671SJulian.Pullen@Sun.COM 953*8671SJulian.Pullen@Sun.COM attrs[0] = "trustPartner"; 954*8671SJulian.Pullen@Sun.COM attrs[1] = "trustDirection"; 955*8671SJulian.Pullen@Sun.COM attrs[2] = NULL; 956*8671SJulian.Pullen@Sun.COM 957*8671SJulian.Pullen@Sun.COM /* trustDirection values - inbound = 1 and bidirectional = 3 */ 958*8671SJulian.Pullen@Sun.COM filter = "(&(objectclass=trustedDomain)" 959*8671SJulian.Pullen@Sun.COM "(|(trustDirection=3)(trustDirection=1)))"; 960*8671SJulian.Pullen@Sun.COM 961*8671SJulian.Pullen@Sun.COM rc = ldap_search_s(*ld, base_dn, scope, filter, attrs, 0, &results); 962*8671SJulian.Pullen@Sun.COM if (rc == LDAP_SUCCESS) { 963*8671SJulian.Pullen@Sun.COM for (entry = ldap_first_entry(*ld, results); 964*8671SJulian.Pullen@Sun.COM entry != NULL; entry = ldap_next_entry(*ld, entry)) { 965*8671SJulian.Pullen@Sun.COM partner = ldap_get_values(*ld, entry, "trustPartner"); 966*8671SJulian.Pullen@Sun.COM direction = ldap_get_values( 967*8671SJulian.Pullen@Sun.COM *ld, entry, "trustDirection"); 968*8671SJulian.Pullen@Sun.COM 969*8671SJulian.Pullen@Sun.COM if (partner != NULL && direction != NULL) { 970*8671SJulian.Pullen@Sun.COM num++; 971*8671SJulian.Pullen@Sun.COM trusted_domains = realloc(trusted_domains, 972*8671SJulian.Pullen@Sun.COM (num + 1) * 973*8671SJulian.Pullen@Sun.COM sizeof (ad_disc_trusteddomains_t)); 974*8671SJulian.Pullen@Sun.COM if (trusted_domains == NULL) { 975*8671SJulian.Pullen@Sun.COM ldap_value_free(partner); 976*8671SJulian.Pullen@Sun.COM ldap_value_free(direction); 977*8671SJulian.Pullen@Sun.COM ldap_msgfree(results); 978*8671SJulian.Pullen@Sun.COM return (NULL); 979*8671SJulian.Pullen@Sun.COM } 980*8671SJulian.Pullen@Sun.COM /* Last element should be zero */ 981*8671SJulian.Pullen@Sun.COM memset(&trusted_domains[num], 0, 982*8671SJulian.Pullen@Sun.COM sizeof (ad_disc_trusteddomains_t)); 983*8671SJulian.Pullen@Sun.COM strcpy(trusted_domains[num - 1].domain, 984*8671SJulian.Pullen@Sun.COM partner[0]); 985*8671SJulian.Pullen@Sun.COM trusted_domains[num - 1].direction = 986*8671SJulian.Pullen@Sun.COM atoi(direction[0]); 987*8671SJulian.Pullen@Sun.COM } 988*8671SJulian.Pullen@Sun.COM if (partner != NULL) 989*8671SJulian.Pullen@Sun.COM ldap_value_free(partner); 990*8671SJulian.Pullen@Sun.COM if (direction != NULL) 991*8671SJulian.Pullen@Sun.COM ldap_value_free(direction); 992*8671SJulian.Pullen@Sun.COM } 993*8671SJulian.Pullen@Sun.COM } else if (rc == LDAP_NO_RESULTS_RETURNED) { 994*8671SJulian.Pullen@Sun.COM /* This is not an error - return empty trusted domain */ 995*8671SJulian.Pullen@Sun.COM trusted_domains = calloc(1, sizeof (ad_disc_trusteddomains_t)); 996*8671SJulian.Pullen@Sun.COM } 997*8671SJulian.Pullen@Sun.COM if (results != NULL) 998*8671SJulian.Pullen@Sun.COM ldap_msgfree(results); 999*8671SJulian.Pullen@Sun.COM 1000*8671SJulian.Pullen@Sun.COM return (trusted_domains); 1001*8671SJulian.Pullen@Sun.COM } 1002*8671SJulian.Pullen@Sun.COM 1003*8671SJulian.Pullen@Sun.COM 1004*8671SJulian.Pullen@Sun.COM /* 1005*8671SJulian.Pullen@Sun.COM * This functions finds all the domains in a forest. 1006*8671SJulian.Pullen@Sun.COM * It first finds all the naming contexts by finding the 1007*8671SJulian.Pullen@Sun.COM * root DSE attribute namingContext. For each naming context 1008*8671SJulian.Pullen@Sun.COM * it performes an entry search looking for Domain object class 1009*8671SJulian.Pullen@Sun.COM * returning the attribute objectSid. 1010*8671SJulian.Pullen@Sun.COM */ 1011*8671SJulian.Pullen@Sun.COM ad_disc_domainsinforest_t * 1012*8671SJulian.Pullen@Sun.COM ldap_lookup_domains_in_forest(LDAP **ld, idmap_ad_disc_ds_t *globalCatalogs) 1013*8671SJulian.Pullen@Sun.COM { 1014*8671SJulian.Pullen@Sun.COM int scope = LDAP_SCOPE_BASE; 1015*8671SJulian.Pullen@Sun.COM char *attrs[2]; 1016*8671SJulian.Pullen@Sun.COM char *root_attrs[2]; 1017*8671SJulian.Pullen@Sun.COM int rc; 1018*8671SJulian.Pullen@Sun.COM LDAPMessage *result = NULL; 1019*8671SJulian.Pullen@Sun.COM LDAPMessage *entry; 1020*8671SJulian.Pullen@Sun.COM char *filter; 1021*8671SJulian.Pullen@Sun.COM char **nc = NULL; 1022*8671SJulian.Pullen@Sun.COM struct berval **sid_ber; 1023*8671SJulian.Pullen@Sun.COM int num = 0; 1024*8671SJulian.Pullen@Sun.COM ad_disc_domainsinforest_t *domains = NULL; 1025*8671SJulian.Pullen@Sun.COM ad_disc_domainsinforest_t *tmp; 1026*8671SJulian.Pullen@Sun.COM int i; 1027*8671SJulian.Pullen@Sun.COM char *name; 1028*8671SJulian.Pullen@Sun.COM adutils_sid_t sid; 1029*8671SJulian.Pullen@Sun.COM char *sid_str; 1030*8671SJulian.Pullen@Sun.COM 1031*8671SJulian.Pullen@Sun.COM 1032*8671SJulian.Pullen@Sun.COM if (*ld == NULL) 1033*8671SJulian.Pullen@Sun.COM *ld = ldap_lookup_init(globalCatalogs); 1034*8671SJulian.Pullen@Sun.COM 1035*8671SJulian.Pullen@Sun.COM if (*ld == NULL) 1036*8671SJulian.Pullen@Sun.COM return (NULL); 1037*8671SJulian.Pullen@Sun.COM 1038*8671SJulian.Pullen@Sun.COM root_attrs[0] = "namingContexts"; 1039*8671SJulian.Pullen@Sun.COM root_attrs[1] = NULL; 1040*8671SJulian.Pullen@Sun.COM 1041*8671SJulian.Pullen@Sun.COM attrs[0] = "objectSid"; 1042*8671SJulian.Pullen@Sun.COM attrs[1] = NULL; 1043*8671SJulian.Pullen@Sun.COM 1044*8671SJulian.Pullen@Sun.COM filter = "(objectclass=Domain)"; 1045*8671SJulian.Pullen@Sun.COM 1046*8671SJulian.Pullen@Sun.COM /* Find naming contexts */ 1047*8671SJulian.Pullen@Sun.COM rc = ldap_search_s(*ld, LDAP_ROOT_DSE, scope, "(objectClass=*)", 1048*8671SJulian.Pullen@Sun.COM root_attrs, 0, &result); 1049*8671SJulian.Pullen@Sun.COM if (rc == LDAP_SUCCESS) { 1050*8671SJulian.Pullen@Sun.COM entry = ldap_first_entry(*ld, result); 1051*8671SJulian.Pullen@Sun.COM if (entry != NULL) { 1052*8671SJulian.Pullen@Sun.COM nc = ldap_get_values(*ld, entry, "namingContexts"); 1053*8671SJulian.Pullen@Sun.COM } 1054*8671SJulian.Pullen@Sun.COM } 1055*8671SJulian.Pullen@Sun.COM if (result != NULL) 1056*8671SJulian.Pullen@Sun.COM ldap_msgfree(result); 1057*8671SJulian.Pullen@Sun.COM if (nc == NULL) 1058*8671SJulian.Pullen@Sun.COM return (NULL); 1059*8671SJulian.Pullen@Sun.COM 1060*8671SJulian.Pullen@Sun.COM /* Find domains */ 1061*8671SJulian.Pullen@Sun.COM for (i = 0; nc[i] != NULL; i++) { 1062*8671SJulian.Pullen@Sun.COM rc = ldap_search_s(*ld, nc[i], scope, filter, attrs, 0, 1063*8671SJulian.Pullen@Sun.COM &result); 1064*8671SJulian.Pullen@Sun.COM if (rc == LDAP_SUCCESS) { 1065*8671SJulian.Pullen@Sun.COM entry = ldap_first_entry(*ld, result); 1066*8671SJulian.Pullen@Sun.COM if (entry != NULL) { 1067*8671SJulian.Pullen@Sun.COM sid_ber = ldap_get_values_len(*ld, entry, 1068*8671SJulian.Pullen@Sun.COM "objectSid"); 1069*8671SJulian.Pullen@Sun.COM if (sid_ber != NULL) { 1070*8671SJulian.Pullen@Sun.COM num++; 1071*8671SJulian.Pullen@Sun.COM tmp = realloc(domains, 1072*8671SJulian.Pullen@Sun.COM (num + 1) * 1073*8671SJulian.Pullen@Sun.COM sizeof (ad_disc_domainsinforest_t)); 1074*8671SJulian.Pullen@Sun.COM if (tmp == NULL) { 1075*8671SJulian.Pullen@Sun.COM if (domains != NULL) 1076*8671SJulian.Pullen@Sun.COM free(domains); 1077*8671SJulian.Pullen@Sun.COM ldap_value_free_len(sid_ber); 1078*8671SJulian.Pullen@Sun.COM ldap_msgfree(result); 1079*8671SJulian.Pullen@Sun.COM ldap_value_free(nc); 1080*8671SJulian.Pullen@Sun.COM return (NULL); 1081*8671SJulian.Pullen@Sun.COM } 1082*8671SJulian.Pullen@Sun.COM domains = tmp; 1083*8671SJulian.Pullen@Sun.COM memset(&domains[num], 0, 1084*8671SJulian.Pullen@Sun.COM sizeof (ad_disc_domainsinforest_t)); 1085*8671SJulian.Pullen@Sun.COM 1086*8671SJulian.Pullen@Sun.COM if (adutils_getsid(sid_ber[0], &sid) 1087*8671SJulian.Pullen@Sun.COM < 0) { 1088*8671SJulian.Pullen@Sun.COM free(domains); 1089*8671SJulian.Pullen@Sun.COM ldap_value_free_len(sid_ber); 1090*8671SJulian.Pullen@Sun.COM ldap_msgfree(result); 1091*8671SJulian.Pullen@Sun.COM ldap_value_free(nc); 1092*8671SJulian.Pullen@Sun.COM return (NULL); 1093*8671SJulian.Pullen@Sun.COM } 1094*8671SJulian.Pullen@Sun.COM if ((sid_str = adutils_sid2txt(&sid)) 1095*8671SJulian.Pullen@Sun.COM == NULL) { 1096*8671SJulian.Pullen@Sun.COM free(domains); 1097*8671SJulian.Pullen@Sun.COM ldap_value_free_len(sid_ber); 1098*8671SJulian.Pullen@Sun.COM ldap_msgfree(result); 1099*8671SJulian.Pullen@Sun.COM ldap_value_free(nc); 1100*8671SJulian.Pullen@Sun.COM return (NULL); 1101*8671SJulian.Pullen@Sun.COM } 1102*8671SJulian.Pullen@Sun.COM 1103*8671SJulian.Pullen@Sun.COM ldap_value_free_len(sid_ber); 1104*8671SJulian.Pullen@Sun.COM strcpy(domains[num - 1].sid, sid_str); 1105*8671SJulian.Pullen@Sun.COM free(sid_str); 1106*8671SJulian.Pullen@Sun.COM 1107*8671SJulian.Pullen@Sun.COM name = DN_to_DNS(nc[i]); 1108*8671SJulian.Pullen@Sun.COM if (name == NULL) { 1109*8671SJulian.Pullen@Sun.COM free(domains); 1110*8671SJulian.Pullen@Sun.COM ldap_msgfree(result); 1111*8671SJulian.Pullen@Sun.COM ldap_value_free(nc); 1112*8671SJulian.Pullen@Sun.COM return (NULL); 1113*8671SJulian.Pullen@Sun.COM } 1114*8671SJulian.Pullen@Sun.COM strcpy(domains[num - 1].domain, name); 1115*8671SJulian.Pullen@Sun.COM free(name); 1116*8671SJulian.Pullen@Sun.COM } 1117*8671SJulian.Pullen@Sun.COM } 1118*8671SJulian.Pullen@Sun.COM } 1119*8671SJulian.Pullen@Sun.COM if (result != NULL) 1120*8671SJulian.Pullen@Sun.COM ldap_msgfree(result); 1121*8671SJulian.Pullen@Sun.COM } 1122*8671SJulian.Pullen@Sun.COM ldap_value_free(nc); 1123*8671SJulian.Pullen@Sun.COM 1124*8671SJulian.Pullen@Sun.COM return (domains); 1125*8671SJulian.Pullen@Sun.COM } 1126*8671SJulian.Pullen@Sun.COM 1127*8671SJulian.Pullen@Sun.COM 1128*8671SJulian.Pullen@Sun.COM ad_disc_t 1129*8671SJulian.Pullen@Sun.COM ad_disc_init(void) 1130*8671SJulian.Pullen@Sun.COM { 1131*8671SJulian.Pullen@Sun.COM struct ad_disc *ctx; 1132*8671SJulian.Pullen@Sun.COM ctx = calloc(1, sizeof (struct ad_disc)); 1133*8671SJulian.Pullen@Sun.COM if (ctx != NULL) 1134*8671SJulian.Pullen@Sun.COM DO_RES_NINIT(ctx); 1135*8671SJulian.Pullen@Sun.COM 1136*8671SJulian.Pullen@Sun.COM ctx->domain_name.type = AD_STRING; 1137*8671SJulian.Pullen@Sun.COM ctx->domain_controller.type = AD_DIRECTORY; 1138*8671SJulian.Pullen@Sun.COM ctx->site_name.type = AD_STRING; 1139*8671SJulian.Pullen@Sun.COM ctx->forest_name.type = AD_STRING; 1140*8671SJulian.Pullen@Sun.COM ctx->global_catalog.type = AD_DIRECTORY; 1141*8671SJulian.Pullen@Sun.COM ctx->domains_in_forest.type = AD_DOMAINS_IN_FOREST; 1142*8671SJulian.Pullen@Sun.COM ctx->trusted_domains.type = AD_TRUSTED_DOMAINS; 1143*8671SJulian.Pullen@Sun.COM /* Site specific versions */ 1144*8671SJulian.Pullen@Sun.COM ctx->site_domain_controller.type = AD_DIRECTORY; 1145*8671SJulian.Pullen@Sun.COM ctx->site_global_catalog.type = AD_DIRECTORY; 1146*8671SJulian.Pullen@Sun.COM return (ctx); 1147*8671SJulian.Pullen@Sun.COM } 1148*8671SJulian.Pullen@Sun.COM 1149*8671SJulian.Pullen@Sun.COM 1150*8671SJulian.Pullen@Sun.COM void 1151*8671SJulian.Pullen@Sun.COM ad_disc_fini(ad_disc_t ctx) 1152*8671SJulian.Pullen@Sun.COM { 1153*8671SJulian.Pullen@Sun.COM if (ctx == NULL) 1154*8671SJulian.Pullen@Sun.COM return; 1155*8671SJulian.Pullen@Sun.COM 1156*8671SJulian.Pullen@Sun.COM if (ctx->res_ninitted) 1157*8671SJulian.Pullen@Sun.COM res_ndestroy(&ctx->res_state); 1158*8671SJulian.Pullen@Sun.COM 1159*8671SJulian.Pullen@Sun.COM if (ctx->subnets != NULL) 1160*8671SJulian.Pullen@Sun.COM free(ctx->subnets); 1161*8671SJulian.Pullen@Sun.COM 1162*8671SJulian.Pullen@Sun.COM if (ctx->domain_name.value != NULL) 1163*8671SJulian.Pullen@Sun.COM free(ctx->domain_name.value); 1164*8671SJulian.Pullen@Sun.COM 1165*8671SJulian.Pullen@Sun.COM if (ctx->domain_controller.value != NULL) 1166*8671SJulian.Pullen@Sun.COM free(ctx->domain_controller.value); 1167*8671SJulian.Pullen@Sun.COM 1168*8671SJulian.Pullen@Sun.COM if (ctx->site_name.value != NULL) 1169*8671SJulian.Pullen@Sun.COM free(ctx->site_name.value); 1170*8671SJulian.Pullen@Sun.COM 1171*8671SJulian.Pullen@Sun.COM if (ctx->forest_name.value != NULL) 1172*8671SJulian.Pullen@Sun.COM free(ctx->forest_name.value); 1173*8671SJulian.Pullen@Sun.COM 1174*8671SJulian.Pullen@Sun.COM if (ctx->global_catalog.value != NULL) 1175*8671SJulian.Pullen@Sun.COM free(ctx->global_catalog.value); 1176*8671SJulian.Pullen@Sun.COM 1177*8671SJulian.Pullen@Sun.COM if (ctx->domains_in_forest.value != NULL) 1178*8671SJulian.Pullen@Sun.COM free(ctx->domains_in_forest.value); 1179*8671SJulian.Pullen@Sun.COM 1180*8671SJulian.Pullen@Sun.COM if (ctx->trusted_domains.value != NULL) 1181*8671SJulian.Pullen@Sun.COM free(ctx->trusted_domains.value); 1182*8671SJulian.Pullen@Sun.COM 1183*8671SJulian.Pullen@Sun.COM /* Site specific versions */ 1184*8671SJulian.Pullen@Sun.COM if (ctx->site_domain_controller.value != NULL) 1185*8671SJulian.Pullen@Sun.COM free(ctx->site_domain_controller.value); 1186*8671SJulian.Pullen@Sun.COM 1187*8671SJulian.Pullen@Sun.COM if (ctx->site_global_catalog.value != NULL) 1188*8671SJulian.Pullen@Sun.COM free(ctx->site_global_catalog.value); 1189*8671SJulian.Pullen@Sun.COM 1190*8671SJulian.Pullen@Sun.COM free(ctx); 1191*8671SJulian.Pullen@Sun.COM } 1192*8671SJulian.Pullen@Sun.COM 1193*8671SJulian.Pullen@Sun.COM void 1194*8671SJulian.Pullen@Sun.COM ad_disc_refresh(ad_disc_t ctx) 1195*8671SJulian.Pullen@Sun.COM { 1196*8671SJulian.Pullen@Sun.COM if (ctx->res_ninitted) 1197*8671SJulian.Pullen@Sun.COM res_ndestroy(&ctx->res_state); 1198*8671SJulian.Pullen@Sun.COM (void) memset(&ctx->res_state, 0, sizeof (ctx->res_state)); 1199*8671SJulian.Pullen@Sun.COM ctx->res_ninitted = res_ninit(&ctx->res_state) != -1; 1200*8671SJulian.Pullen@Sun.COM 1201*8671SJulian.Pullen@Sun.COM if (ctx->domain_name.state == AD_STATE_AUTO) 1202*8671SJulian.Pullen@Sun.COM ctx->domain_name.state = AD_STATE_INVALID; 1203*8671SJulian.Pullen@Sun.COM 1204*8671SJulian.Pullen@Sun.COM if (ctx->domain_controller.state == AD_STATE_AUTO) 1205*8671SJulian.Pullen@Sun.COM ctx->domain_controller.state = AD_STATE_INVALID; 1206*8671SJulian.Pullen@Sun.COM 1207*8671SJulian.Pullen@Sun.COM if (ctx->site_name.state == AD_STATE_AUTO) 1208*8671SJulian.Pullen@Sun.COM ctx->site_name.state = AD_STATE_INVALID; 1209*8671SJulian.Pullen@Sun.COM 1210*8671SJulian.Pullen@Sun.COM if (ctx->forest_name.state == AD_STATE_AUTO) 1211*8671SJulian.Pullen@Sun.COM ctx->forest_name.state = AD_STATE_INVALID; 1212*8671SJulian.Pullen@Sun.COM 1213*8671SJulian.Pullen@Sun.COM if (ctx->global_catalog.state == AD_STATE_AUTO) 1214*8671SJulian.Pullen@Sun.COM ctx->global_catalog.state = AD_STATE_INVALID; 1215*8671SJulian.Pullen@Sun.COM 1216*8671SJulian.Pullen@Sun.COM if (ctx->domains_in_forest.state == AD_STATE_AUTO) 1217*8671SJulian.Pullen@Sun.COM ctx->domains_in_forest.state = AD_STATE_INVALID; 1218*8671SJulian.Pullen@Sun.COM 1219*8671SJulian.Pullen@Sun.COM if (ctx->trusted_domains.state == AD_STATE_AUTO) 1220*8671SJulian.Pullen@Sun.COM ctx->trusted_domains.state = AD_STATE_INVALID; 1221*8671SJulian.Pullen@Sun.COM 1222*8671SJulian.Pullen@Sun.COM if (ctx->site_domain_controller.state == AD_STATE_AUTO) 1223*8671SJulian.Pullen@Sun.COM ctx->site_domain_controller.state = AD_STATE_INVALID; 1224*8671SJulian.Pullen@Sun.COM 1225*8671SJulian.Pullen@Sun.COM if (ctx->site_global_catalog.state == AD_STATE_AUTO) 1226*8671SJulian.Pullen@Sun.COM ctx->site_global_catalog.state = AD_STATE_INVALID; 1227*8671SJulian.Pullen@Sun.COM } 1228*8671SJulian.Pullen@Sun.COM 1229*8671SJulian.Pullen@Sun.COM 1230*8671SJulian.Pullen@Sun.COM 1231*8671SJulian.Pullen@Sun.COM /* Discover joined Active Directory domainName */ 1232*8671SJulian.Pullen@Sun.COM static ad_item_t * 1233*8671SJulian.Pullen@Sun.COM validate_DomainName(ad_disc_t ctx) 1234*8671SJulian.Pullen@Sun.COM { 1235*8671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t *domain_controller = NULL; 1236*8671SJulian.Pullen@Sun.COM char *dname, *srvname; 1237*8671SJulian.Pullen@Sun.COM uint32_t ttl = 0; 1238*8671SJulian.Pullen@Sun.COM 1239*8671SJulian.Pullen@Sun.COM if (is_valid(&ctx->domain_name)) 1240*8671SJulian.Pullen@Sun.COM return (&ctx->domain_name); 1241*8671SJulian.Pullen@Sun.COM 1242*8671SJulian.Pullen@Sun.COM 1243*8671SJulian.Pullen@Sun.COM /* Try to find our domain by searching for DCs for it */ 1244*8671SJulian.Pullen@Sun.COM DO_RES_NINIT(ctx); 1245*8671SJulian.Pullen@Sun.COM domain_controller = srv_query(&ctx->res_state, LDAP_SRV_HEAD 1246*8671SJulian.Pullen@Sun.COM DC_SRV_TAIL, ctx->domain_name.value, &srvname, &ttl); 1247*8671SJulian.Pullen@Sun.COM 1248*8671SJulian.Pullen@Sun.COM /* 1249*8671SJulian.Pullen@Sun.COM * If we can't find DCs by via res_nsearch() then there's no 1250*8671SJulian.Pullen@Sun.COM * point in trying anything else to discover the AD domain name. 1251*8671SJulian.Pullen@Sun.COM */ 1252*8671SJulian.Pullen@Sun.COM if (domain_controller == NULL) 1253*8671SJulian.Pullen@Sun.COM return (NULL); 1254*8671SJulian.Pullen@Sun.COM 1255*8671SJulian.Pullen@Sun.COM free(domain_controller); 1256*8671SJulian.Pullen@Sun.COM /* 1257*8671SJulian.Pullen@Sun.COM * We have the FQDN of the SRV RR name, so now we extract the 1258*8671SJulian.Pullen@Sun.COM * domainname suffix from it. 1259*8671SJulian.Pullen@Sun.COM */ 1260*8671SJulian.Pullen@Sun.COM dname = strdup(srvname + strlen(LDAP_SRV_HEAD DC_SRV_TAIL) + 1261*8671SJulian.Pullen@Sun.COM 1 /* for the dot between RR name and domainname */); 1262*8671SJulian.Pullen@Sun.COM 1263*8671SJulian.Pullen@Sun.COM free(srvname); 1264*8671SJulian.Pullen@Sun.COM 1265*8671SJulian.Pullen@Sun.COM if (dname == NULL) { 1266*8671SJulian.Pullen@Sun.COM logger(LOG_ERR, "Out of memory"); 1267*8671SJulian.Pullen@Sun.COM return (NULL); 1268*8671SJulian.Pullen@Sun.COM } 1269*8671SJulian.Pullen@Sun.COM 1270*8671SJulian.Pullen@Sun.COM /* Eat any trailing dot */ 1271*8671SJulian.Pullen@Sun.COM if (*(dname + strlen(dname)) == '.') 1272*8671SJulian.Pullen@Sun.COM *(dname + strlen(dname)) = '\0'; 1273*8671SJulian.Pullen@Sun.COM 1274*8671SJulian.Pullen@Sun.COM update_item(&ctx->domain_name, dname, AD_STATE_AUTO, ttl); 1275*8671SJulian.Pullen@Sun.COM 1276*8671SJulian.Pullen@Sun.COM return (&ctx->domain_name); 1277*8671SJulian.Pullen@Sun.COM } 1278*8671SJulian.Pullen@Sun.COM 1279*8671SJulian.Pullen@Sun.COM 1280*8671SJulian.Pullen@Sun.COM char * 1281*8671SJulian.Pullen@Sun.COM ad_disc_get_DomainName(ad_disc_t ctx, boolean_t *auto_discovered) 1282*8671SJulian.Pullen@Sun.COM { 1283*8671SJulian.Pullen@Sun.COM char *domain_name = NULL; 1284*8671SJulian.Pullen@Sun.COM ad_item_t *domain_name_item; 1285*8671SJulian.Pullen@Sun.COM 1286*8671SJulian.Pullen@Sun.COM domain_name_item = validate_DomainName(ctx); 1287*8671SJulian.Pullen@Sun.COM 1288*8671SJulian.Pullen@Sun.COM if (domain_name_item) { 1289*8671SJulian.Pullen@Sun.COM domain_name = strdup(domain_name_item->value); 1290*8671SJulian.Pullen@Sun.COM if (auto_discovered != NULL) 1291*8671SJulian.Pullen@Sun.COM *auto_discovered = 1292*8671SJulian.Pullen@Sun.COM (domain_name_item->state == AD_STATE_AUTO); 1293*8671SJulian.Pullen@Sun.COM } else if (auto_discovered != NULL) 1294*8671SJulian.Pullen@Sun.COM *auto_discovered = B_FALSE; 1295*8671SJulian.Pullen@Sun.COM 1296*8671SJulian.Pullen@Sun.COM return (domain_name); 1297*8671SJulian.Pullen@Sun.COM } 1298*8671SJulian.Pullen@Sun.COM 1299*8671SJulian.Pullen@Sun.COM 1300*8671SJulian.Pullen@Sun.COM /* Discover domain controllers */ 1301*8671SJulian.Pullen@Sun.COM static ad_item_t * 1302*8671SJulian.Pullen@Sun.COM validate_DomainController(ad_disc_t ctx, enum ad_disc_req req) 1303*8671SJulian.Pullen@Sun.COM { 1304*8671SJulian.Pullen@Sun.COM uint32_t ttl = 0; 1305*8671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t *domain_controller = NULL; 1306*8671SJulian.Pullen@Sun.COM boolean_t validate_global = B_FALSE; 1307*8671SJulian.Pullen@Sun.COM boolean_t validate_site = B_FALSE; 1308*8671SJulian.Pullen@Sun.COM ad_item_t *domain_name_item; 1309*8671SJulian.Pullen@Sun.COM ad_item_t *site_name_item = NULL; 1310*8671SJulian.Pullen@Sun.COM 1311*8671SJulian.Pullen@Sun.COM /* If the values is fixed there will not be a site specific version */ 1312*8671SJulian.Pullen@Sun.COM if (is_fixed(&ctx->domain_controller)) 1313*8671SJulian.Pullen@Sun.COM return (&ctx->domain_controller); 1314*8671SJulian.Pullen@Sun.COM 1315*8671SJulian.Pullen@Sun.COM domain_name_item = validate_DomainName(ctx); 1316*8671SJulian.Pullen@Sun.COM if (domain_name_item == NULL) 1317*8671SJulian.Pullen@Sun.COM return (NULL); 1318*8671SJulian.Pullen@Sun.COM 1319*8671SJulian.Pullen@Sun.COM if (req == AD_DISC_GLOBAL) 1320*8671SJulian.Pullen@Sun.COM validate_global = B_TRUE; 1321*8671SJulian.Pullen@Sun.COM else { 1322*8671SJulian.Pullen@Sun.COM site_name_item = validate_SiteName(ctx); 1323*8671SJulian.Pullen@Sun.COM if (site_name_item != NULL) 1324*8671SJulian.Pullen@Sun.COM validate_site = B_TRUE; 1325*8671SJulian.Pullen@Sun.COM else if (req == AD_DISC_PREFER_SITE) 1326*8671SJulian.Pullen@Sun.COM validate_global = B_TRUE; 1327*8671SJulian.Pullen@Sun.COM } 1328*8671SJulian.Pullen@Sun.COM 1329*8671SJulian.Pullen@Sun.COM if (validate_global) { 1330*8671SJulian.Pullen@Sun.COM if (!is_valid(&ctx->domain_controller) || 1331*8671SJulian.Pullen@Sun.COM is_changed(&ctx->domain_controller, PARAM1, 1332*8671SJulian.Pullen@Sun.COM domain_name_item)) { 1333*8671SJulian.Pullen@Sun.COM /* 1334*8671SJulian.Pullen@Sun.COM * Lookup DNS SRV RR named 1335*8671SJulian.Pullen@Sun.COM * _ldap._tcp.dc._msdcs.<DomainName> 1336*8671SJulian.Pullen@Sun.COM */ 1337*8671SJulian.Pullen@Sun.COM DO_RES_NINIT(ctx); 1338*8671SJulian.Pullen@Sun.COM domain_controller = srv_query(&ctx->res_state, 1339*8671SJulian.Pullen@Sun.COM LDAP_SRV_HEAD DC_SRV_TAIL, 1340*8671SJulian.Pullen@Sun.COM domain_name_item->value, NULL, &ttl); 1341*8671SJulian.Pullen@Sun.COM 1342*8671SJulian.Pullen@Sun.COM if (domain_controller == NULL) 1343*8671SJulian.Pullen@Sun.COM return (NULL); 1344*8671SJulian.Pullen@Sun.COM 1345*8671SJulian.Pullen@Sun.COM update_item(&ctx->domain_controller, domain_controller, 1346*8671SJulian.Pullen@Sun.COM AD_STATE_AUTO, ttl); 1347*8671SJulian.Pullen@Sun.COM update_version(&ctx->domain_controller, PARAM1, 1348*8671SJulian.Pullen@Sun.COM domain_name_item); 1349*8671SJulian.Pullen@Sun.COM } 1350*8671SJulian.Pullen@Sun.COM return (&ctx->domain_controller); 1351*8671SJulian.Pullen@Sun.COM } 1352*8671SJulian.Pullen@Sun.COM 1353*8671SJulian.Pullen@Sun.COM if (validate_site) { 1354*8671SJulian.Pullen@Sun.COM if (!is_valid(&ctx->site_domain_controller) || 1355*8671SJulian.Pullen@Sun.COM is_changed(&ctx->site_domain_controller, PARAM1, 1356*8671SJulian.Pullen@Sun.COM domain_name_item) || 1357*8671SJulian.Pullen@Sun.COM is_changed(&ctx->site_domain_controller, PARAM2, 1358*8671SJulian.Pullen@Sun.COM site_name_item)) { 1359*8671SJulian.Pullen@Sun.COM char rr_name[DNS_MAX_NAME]; 1360*8671SJulian.Pullen@Sun.COM /* 1361*8671SJulian.Pullen@Sun.COM * Lookup DNS SRV RR named 1362*8671SJulian.Pullen@Sun.COM * _ldap._tcp.<SiteName>._sites.dc._msdcs.<DomainName> 1363*8671SJulian.Pullen@Sun.COM */ 1364*8671SJulian.Pullen@Sun.COM (void) snprintf(rr_name, sizeof (rr_name), 1365*8671SJulian.Pullen@Sun.COM LDAP_SRV_HEAD SITE_SRV_MIDDLE DC_SRV_TAIL, 1366*8671SJulian.Pullen@Sun.COM site_name_item->value); 1367*8671SJulian.Pullen@Sun.COM DO_RES_NINIT(ctx); 1368*8671SJulian.Pullen@Sun.COM domain_controller = srv_query(&ctx->res_state, rr_name, 1369*8671SJulian.Pullen@Sun.COM domain_name_item->value, NULL, &ttl); 1370*8671SJulian.Pullen@Sun.COM if (domain_controller == NULL) 1371*8671SJulian.Pullen@Sun.COM return (NULL); 1372*8671SJulian.Pullen@Sun.COM 1373*8671SJulian.Pullen@Sun.COM update_item(&ctx->site_domain_controller, 1374*8671SJulian.Pullen@Sun.COM domain_controller, AD_STATE_AUTO, ttl); 1375*8671SJulian.Pullen@Sun.COM update_version(&ctx->site_domain_controller, PARAM1, 1376*8671SJulian.Pullen@Sun.COM domain_name_item); 1377*8671SJulian.Pullen@Sun.COM update_version(&ctx->site_domain_controller, PARAM2, 1378*8671SJulian.Pullen@Sun.COM site_name_item); 1379*8671SJulian.Pullen@Sun.COM } 1380*8671SJulian.Pullen@Sun.COM return (&ctx->site_domain_controller); 1381*8671SJulian.Pullen@Sun.COM } 1382*8671SJulian.Pullen@Sun.COM return (NULL); 1383*8671SJulian.Pullen@Sun.COM } 1384*8671SJulian.Pullen@Sun.COM 1385*8671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t * 1386*8671SJulian.Pullen@Sun.COM ad_disc_get_DomainController(ad_disc_t ctx, enum ad_disc_req req, 1387*8671SJulian.Pullen@Sun.COM boolean_t *auto_discovered) 1388*8671SJulian.Pullen@Sun.COM { 1389*8671SJulian.Pullen@Sun.COM ad_item_t *domain_controller_item; 1390*8671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t *domain_controller = NULL; 1391*8671SJulian.Pullen@Sun.COM 1392*8671SJulian.Pullen@Sun.COM domain_controller_item = validate_DomainController(ctx, req); 1393*8671SJulian.Pullen@Sun.COM 1394*8671SJulian.Pullen@Sun.COM if (domain_controller_item != NULL) { 1395*8671SJulian.Pullen@Sun.COM domain_controller = ds_dup(domain_controller_item->value); 1396*8671SJulian.Pullen@Sun.COM if (auto_discovered != NULL) 1397*8671SJulian.Pullen@Sun.COM *auto_discovered = 1398*8671SJulian.Pullen@Sun.COM (domain_controller_item->state == AD_STATE_AUTO); 1399*8671SJulian.Pullen@Sun.COM } else if (auto_discovered != NULL) 1400*8671SJulian.Pullen@Sun.COM *auto_discovered = B_FALSE; 1401*8671SJulian.Pullen@Sun.COM 1402*8671SJulian.Pullen@Sun.COM return (domain_controller); 1403*8671SJulian.Pullen@Sun.COM } 1404*8671SJulian.Pullen@Sun.COM 1405*8671SJulian.Pullen@Sun.COM 1406*8671SJulian.Pullen@Sun.COM /* Discover site name (for multi-homed systems the first one found wins) */ 1407*8671SJulian.Pullen@Sun.COM static ad_item_t * 1408*8671SJulian.Pullen@Sun.COM validate_SiteName(ad_disc_t ctx) 1409*8671SJulian.Pullen@Sun.COM { 1410*8671SJulian.Pullen@Sun.COM LDAP *ld = NULL; 1411*8671SJulian.Pullen@Sun.COM ad_subnet_t *subnets = NULL; 1412*8671SJulian.Pullen@Sun.COM char **dn_subnets = NULL; 1413*8671SJulian.Pullen@Sun.COM char *dn_root[2]; 1414*8671SJulian.Pullen@Sun.COM char *config_naming_context = NULL; 1415*8671SJulian.Pullen@Sun.COM char *site_object = NULL; 1416*8671SJulian.Pullen@Sun.COM char *site_name = NULL; 1417*8671SJulian.Pullen@Sun.COM char *forest_name; 1418*8671SJulian.Pullen@Sun.COM int len; 1419*8671SJulian.Pullen@Sun.COM int i; 1420*8671SJulian.Pullen@Sun.COM boolean_t update_required = B_FALSE; 1421*8671SJulian.Pullen@Sun.COM ad_item_t *domain_controller_item; 1422*8671SJulian.Pullen@Sun.COM 1423*8671SJulian.Pullen@Sun.COM if (is_fixed(&ctx->site_name)) 1424*8671SJulian.Pullen@Sun.COM return (&ctx->site_name); 1425*8671SJulian.Pullen@Sun.COM 1426*8671SJulian.Pullen@Sun.COM /* Can't rely on site-specific DCs */ 1427*8671SJulian.Pullen@Sun.COM domain_controller_item = validate_DomainController(ctx, AD_DISC_GLOBAL); 1428*8671SJulian.Pullen@Sun.COM if (domain_controller_item == NULL) 1429*8671SJulian.Pullen@Sun.COM return (NULL); 1430*8671SJulian.Pullen@Sun.COM 1431*8671SJulian.Pullen@Sun.COM if (!is_valid(&ctx->site_name) || 1432*8671SJulian.Pullen@Sun.COM is_changed(&ctx->site_name, PARAM1, &ctx->domain_controller) || 1433*8671SJulian.Pullen@Sun.COM ctx->subnets == NULL || ctx->subnets_changed) { 1434*8671SJulian.Pullen@Sun.COM subnets = find_subnets(); 1435*8671SJulian.Pullen@Sun.COM ctx->subnets_last_check = time(NULL); 1436*8671SJulian.Pullen@Sun.COM update_required = B_TRUE; 1437*8671SJulian.Pullen@Sun.COM } else if (ctx->subnets_last_check + 60 < time(NULL)) { 1438*8671SJulian.Pullen@Sun.COM subnets = find_subnets(); 1439*8671SJulian.Pullen@Sun.COM ctx->subnets_last_check = time(NULL); 1440*8671SJulian.Pullen@Sun.COM if (cmpsubnets(ctx->subnets, subnets) != 0) 1441*8671SJulian.Pullen@Sun.COM update_required = B_TRUE; 1442*8671SJulian.Pullen@Sun.COM } 1443*8671SJulian.Pullen@Sun.COM 1444*8671SJulian.Pullen@Sun.COM if (!update_required) { 1445*8671SJulian.Pullen@Sun.COM free(subnets); 1446*8671SJulian.Pullen@Sun.COM return (&ctx->site_name); 1447*8671SJulian.Pullen@Sun.COM } 1448*8671SJulian.Pullen@Sun.COM 1449*8671SJulian.Pullen@Sun.COM if (subnets == NULL) 1450*8671SJulian.Pullen@Sun.COM return (NULL); 1451*8671SJulian.Pullen@Sun.COM 1452*8671SJulian.Pullen@Sun.COM dn_root[0] = ""; 1453*8671SJulian.Pullen@Sun.COM dn_root[1] = NULL; 1454*8671SJulian.Pullen@Sun.COM 1455*8671SJulian.Pullen@Sun.COM config_naming_context = ldap_lookup_entry_attr( 1456*8671SJulian.Pullen@Sun.COM &ld, ctx->domain_controller.value, 1457*8671SJulian.Pullen@Sun.COM dn_root, "configurationNamingContext"); 1458*8671SJulian.Pullen@Sun.COM if (config_naming_context == NULL) 1459*8671SJulian.Pullen@Sun.COM goto out; 1460*8671SJulian.Pullen@Sun.COM /* 1461*8671SJulian.Pullen@Sun.COM * configurationNamingContext also provides the Forest 1462*8671SJulian.Pullen@Sun.COM * Name. 1463*8671SJulian.Pullen@Sun.COM */ 1464*8671SJulian.Pullen@Sun.COM if (!is_fixed(&ctx->forest_name)) { 1465*8671SJulian.Pullen@Sun.COM /* 1466*8671SJulian.Pullen@Sun.COM * The configurationNamingContext should be of 1467*8671SJulian.Pullen@Sun.COM * form: 1468*8671SJulian.Pullen@Sun.COM * CN=Configuration,<DNforestName> 1469*8671SJulian.Pullen@Sun.COM * Remove the first part and convert to DNS form 1470*8671SJulian.Pullen@Sun.COM * (replace ",DC=" with ".") 1471*8671SJulian.Pullen@Sun.COM */ 1472*8671SJulian.Pullen@Sun.COM char *str = "CN=Configuration,"; 1473*8671SJulian.Pullen@Sun.COM int len = strlen(str); 1474*8671SJulian.Pullen@Sun.COM if (strncasecmp(config_naming_context, str, len) == 0) { 1475*8671SJulian.Pullen@Sun.COM forest_name = DN_to_DNS(config_naming_context + len); 1476*8671SJulian.Pullen@Sun.COM update_item(&ctx->forest_name, forest_name, 1477*8671SJulian.Pullen@Sun.COM AD_STATE_AUTO, 0); 1478*8671SJulian.Pullen@Sun.COM } 1479*8671SJulian.Pullen@Sun.COM } 1480*8671SJulian.Pullen@Sun.COM 1481*8671SJulian.Pullen@Sun.COM dn_subnets = subnets_to_DNs(subnets, config_naming_context); 1482*8671SJulian.Pullen@Sun.COM if (dn_subnets == NULL) 1483*8671SJulian.Pullen@Sun.COM goto out; 1484*8671SJulian.Pullen@Sun.COM 1485*8671SJulian.Pullen@Sun.COM site_object = ldap_lookup_entry_attr( 1486*8671SJulian.Pullen@Sun.COM &ld, domain_controller_item->value, 1487*8671SJulian.Pullen@Sun.COM dn_subnets, "siteobject"); 1488*8671SJulian.Pullen@Sun.COM if (site_object != NULL) { 1489*8671SJulian.Pullen@Sun.COM /* 1490*8671SJulian.Pullen@Sun.COM * The site object should be of the form 1491*8671SJulian.Pullen@Sun.COM * CN=<site>,CN=Sites,CN=Configuration, 1492*8671SJulian.Pullen@Sun.COM * <DN Domain> 1493*8671SJulian.Pullen@Sun.COM */ 1494*8671SJulian.Pullen@Sun.COM if (strncasecmp(site_object, "CN=", 3) == 0) { 1495*8671SJulian.Pullen@Sun.COM for (len = 0; site_object[len + 3] != ','; len++) 1496*8671SJulian.Pullen@Sun.COM ; 1497*8671SJulian.Pullen@Sun.COM site_name = malloc(len + 1); 1498*8671SJulian.Pullen@Sun.COM (void) strncpy(site_name, &site_object[3], len); 1499*8671SJulian.Pullen@Sun.COM site_name[len] = '\0'; 1500*8671SJulian.Pullen@Sun.COM update_item(&ctx->site_name, site_name, 1501*8671SJulian.Pullen@Sun.COM AD_STATE_AUTO, 0); 1502*8671SJulian.Pullen@Sun.COM } 1503*8671SJulian.Pullen@Sun.COM } 1504*8671SJulian.Pullen@Sun.COM 1505*8671SJulian.Pullen@Sun.COM if (ctx->subnets != NULL) { 1506*8671SJulian.Pullen@Sun.COM free(ctx->subnets); 1507*8671SJulian.Pullen@Sun.COM ctx->subnets = NULL; 1508*8671SJulian.Pullen@Sun.COM } 1509*8671SJulian.Pullen@Sun.COM ctx->subnets = subnets; 1510*8671SJulian.Pullen@Sun.COM subnets = NULL; 1511*8671SJulian.Pullen@Sun.COM ctx->subnets_changed = B_FALSE; 1512*8671SJulian.Pullen@Sun.COM 1513*8671SJulian.Pullen@Sun.COM out: 1514*8671SJulian.Pullen@Sun.COM if (ld != NULL) 1515*8671SJulian.Pullen@Sun.COM (void) ldap_unbind(ld); 1516*8671SJulian.Pullen@Sun.COM 1517*8671SJulian.Pullen@Sun.COM if (dn_subnets != NULL) { 1518*8671SJulian.Pullen@Sun.COM for (i = 0; dn_subnets[i] != NULL; i++) 1519*8671SJulian.Pullen@Sun.COM free(dn_subnets[i]); 1520*8671SJulian.Pullen@Sun.COM free(dn_subnets); 1521*8671SJulian.Pullen@Sun.COM } 1522*8671SJulian.Pullen@Sun.COM if (config_naming_context != NULL) 1523*8671SJulian.Pullen@Sun.COM free(config_naming_context); 1524*8671SJulian.Pullen@Sun.COM if (site_object != NULL) 1525*8671SJulian.Pullen@Sun.COM free(site_object); 1526*8671SJulian.Pullen@Sun.COM 1527*8671SJulian.Pullen@Sun.COM free(subnets); 1528*8671SJulian.Pullen@Sun.COM if (site_name == NULL) 1529*8671SJulian.Pullen@Sun.COM return (NULL); 1530*8671SJulian.Pullen@Sun.COM return (&ctx->site_name); 1531*8671SJulian.Pullen@Sun.COM 1532*8671SJulian.Pullen@Sun.COM } 1533*8671SJulian.Pullen@Sun.COM 1534*8671SJulian.Pullen@Sun.COM 1535*8671SJulian.Pullen@Sun.COM char * 1536*8671SJulian.Pullen@Sun.COM ad_disc_get_SiteName(ad_disc_t ctx, boolean_t *auto_discovered) 1537*8671SJulian.Pullen@Sun.COM { 1538*8671SJulian.Pullen@Sun.COM ad_item_t *site_name_item; 1539*8671SJulian.Pullen@Sun.COM char *site_name = NULL; 1540*8671SJulian.Pullen@Sun.COM 1541*8671SJulian.Pullen@Sun.COM site_name_item = validate_SiteName(ctx); 1542*8671SJulian.Pullen@Sun.COM if (site_name_item != NULL) { 1543*8671SJulian.Pullen@Sun.COM site_name = strdup(site_name_item->value); 1544*8671SJulian.Pullen@Sun.COM if (auto_discovered != NULL) 1545*8671SJulian.Pullen@Sun.COM *auto_discovered = 1546*8671SJulian.Pullen@Sun.COM (site_name_item->state == AD_STATE_AUTO); 1547*8671SJulian.Pullen@Sun.COM } else if (auto_discovered != NULL) 1548*8671SJulian.Pullen@Sun.COM *auto_discovered = B_FALSE; 1549*8671SJulian.Pullen@Sun.COM 1550*8671SJulian.Pullen@Sun.COM return (site_name); 1551*8671SJulian.Pullen@Sun.COM } 1552*8671SJulian.Pullen@Sun.COM 1553*8671SJulian.Pullen@Sun.COM 1554*8671SJulian.Pullen@Sun.COM 1555*8671SJulian.Pullen@Sun.COM /* Discover forest name */ 1556*8671SJulian.Pullen@Sun.COM static ad_item_t * 1557*8671SJulian.Pullen@Sun.COM validate_ForestName(ad_disc_t ctx) 1558*8671SJulian.Pullen@Sun.COM { 1559*8671SJulian.Pullen@Sun.COM LDAP *ld = NULL; 1560*8671SJulian.Pullen@Sun.COM char *config_naming_context; 1561*8671SJulian.Pullen@Sun.COM char *forest_name = NULL; 1562*8671SJulian.Pullen@Sun.COM char *dn_list[2]; 1563*8671SJulian.Pullen@Sun.COM ad_item_t *domain_controller_item; 1564*8671SJulian.Pullen@Sun.COM 1565*8671SJulian.Pullen@Sun.COM if (is_fixed(&ctx->forest_name)) 1566*8671SJulian.Pullen@Sun.COM return (&ctx->forest_name); 1567*8671SJulian.Pullen@Sun.COM /* 1568*8671SJulian.Pullen@Sun.COM * We may not have a site name yet, so we won't rely on 1569*8671SJulian.Pullen@Sun.COM * site-specific DCs. (But maybe we could replace 1570*8671SJulian.Pullen@Sun.COM * validate_ForestName() with validate_siteName()?) 1571*8671SJulian.Pullen@Sun.COM */ 1572*8671SJulian.Pullen@Sun.COM domain_controller_item = validate_DomainController(ctx, AD_DISC_GLOBAL); 1573*8671SJulian.Pullen@Sun.COM if (domain_controller_item == NULL) 1574*8671SJulian.Pullen@Sun.COM return (NULL); 1575*8671SJulian.Pullen@Sun.COM 1576*8671SJulian.Pullen@Sun.COM if (!is_valid(&ctx->forest_name) || 1577*8671SJulian.Pullen@Sun.COM is_changed(&ctx->forest_name, PARAM1, domain_controller_item)) { 1578*8671SJulian.Pullen@Sun.COM 1579*8671SJulian.Pullen@Sun.COM dn_list[0] = ""; 1580*8671SJulian.Pullen@Sun.COM dn_list[1] = NULL; 1581*8671SJulian.Pullen@Sun.COM config_naming_context = ldap_lookup_entry_attr( 1582*8671SJulian.Pullen@Sun.COM &ld, ctx->domain_controller.value, 1583*8671SJulian.Pullen@Sun.COM dn_list, "configurationNamingContext"); 1584*8671SJulian.Pullen@Sun.COM if (config_naming_context != NULL) { 1585*8671SJulian.Pullen@Sun.COM /* 1586*8671SJulian.Pullen@Sun.COM * The configurationNamingContext should be of 1587*8671SJulian.Pullen@Sun.COM * form: 1588*8671SJulian.Pullen@Sun.COM * CN=Configuration,<DNforestName> 1589*8671SJulian.Pullen@Sun.COM * Remove the first part and convert to DNS form 1590*8671SJulian.Pullen@Sun.COM * (replace ",DC=" with ".") 1591*8671SJulian.Pullen@Sun.COM */ 1592*8671SJulian.Pullen@Sun.COM char *str = "CN=Configuration,"; 1593*8671SJulian.Pullen@Sun.COM int len = strlen(str); 1594*8671SJulian.Pullen@Sun.COM if (strncasecmp(config_naming_context, str, len) == 0) { 1595*8671SJulian.Pullen@Sun.COM forest_name = DN_to_DNS( 1596*8671SJulian.Pullen@Sun.COM config_naming_context + len); 1597*8671SJulian.Pullen@Sun.COM } 1598*8671SJulian.Pullen@Sun.COM free(config_naming_context); 1599*8671SJulian.Pullen@Sun.COM } 1600*8671SJulian.Pullen@Sun.COM if (ld != NULL) 1601*8671SJulian.Pullen@Sun.COM (void) ldap_unbind(ld); 1602*8671SJulian.Pullen@Sun.COM 1603*8671SJulian.Pullen@Sun.COM if (forest_name == NULL) 1604*8671SJulian.Pullen@Sun.COM return (NULL); 1605*8671SJulian.Pullen@Sun.COM 1606*8671SJulian.Pullen@Sun.COM update_item(&ctx->forest_name, forest_name, AD_STATE_AUTO, 0); 1607*8671SJulian.Pullen@Sun.COM update_version(&ctx->forest_name, PARAM1, 1608*8671SJulian.Pullen@Sun.COM domain_controller_item); 1609*8671SJulian.Pullen@Sun.COM } 1610*8671SJulian.Pullen@Sun.COM return (&ctx->forest_name); 1611*8671SJulian.Pullen@Sun.COM } 1612*8671SJulian.Pullen@Sun.COM 1613*8671SJulian.Pullen@Sun.COM 1614*8671SJulian.Pullen@Sun.COM char * 1615*8671SJulian.Pullen@Sun.COM ad_disc_get_ForestName(ad_disc_t ctx, boolean_t *auto_discovered) 1616*8671SJulian.Pullen@Sun.COM { 1617*8671SJulian.Pullen@Sun.COM ad_item_t *forest_name_item; 1618*8671SJulian.Pullen@Sun.COM char *forest_name = NULL; 1619*8671SJulian.Pullen@Sun.COM 1620*8671SJulian.Pullen@Sun.COM forest_name_item = validate_ForestName(ctx); 1621*8671SJulian.Pullen@Sun.COM 1622*8671SJulian.Pullen@Sun.COM if (forest_name_item != NULL) { 1623*8671SJulian.Pullen@Sun.COM forest_name = strdup(forest_name_item->value); 1624*8671SJulian.Pullen@Sun.COM if (auto_discovered != NULL) 1625*8671SJulian.Pullen@Sun.COM *auto_discovered = 1626*8671SJulian.Pullen@Sun.COM (forest_name_item->state == AD_STATE_AUTO); 1627*8671SJulian.Pullen@Sun.COM } else if (auto_discovered != NULL) 1628*8671SJulian.Pullen@Sun.COM *auto_discovered = B_FALSE; 1629*8671SJulian.Pullen@Sun.COM 1630*8671SJulian.Pullen@Sun.COM return (forest_name); 1631*8671SJulian.Pullen@Sun.COM } 1632*8671SJulian.Pullen@Sun.COM 1633*8671SJulian.Pullen@Sun.COM 1634*8671SJulian.Pullen@Sun.COM /* Discover global catalog servers */ 1635*8671SJulian.Pullen@Sun.COM static ad_item_t * 1636*8671SJulian.Pullen@Sun.COM validate_GlobalCatalog(ad_disc_t ctx, enum ad_disc_req req) 1637*8671SJulian.Pullen@Sun.COM { 1638*8671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t *global_catalog = NULL; 1639*8671SJulian.Pullen@Sun.COM uint32_t ttl = 0; 1640*8671SJulian.Pullen@Sun.COM boolean_t validate_global = B_FALSE; 1641*8671SJulian.Pullen@Sun.COM boolean_t validate_site = B_FALSE; 1642*8671SJulian.Pullen@Sun.COM ad_item_t *forest_name_item; 1643*8671SJulian.Pullen@Sun.COM ad_item_t *site_name_item; 1644*8671SJulian.Pullen@Sun.COM 1645*8671SJulian.Pullen@Sun.COM /* If the values is fixed there will not be a site specific version */ 1646*8671SJulian.Pullen@Sun.COM if (is_fixed(&ctx->global_catalog)) 1647*8671SJulian.Pullen@Sun.COM return (&ctx->global_catalog); 1648*8671SJulian.Pullen@Sun.COM 1649*8671SJulian.Pullen@Sun.COM forest_name_item = validate_ForestName(ctx); 1650*8671SJulian.Pullen@Sun.COM if (forest_name_item == NULL) 1651*8671SJulian.Pullen@Sun.COM return (NULL); 1652*8671SJulian.Pullen@Sun.COM 1653*8671SJulian.Pullen@Sun.COM if (req == AD_DISC_GLOBAL) 1654*8671SJulian.Pullen@Sun.COM validate_global = B_TRUE; 1655*8671SJulian.Pullen@Sun.COM else { 1656*8671SJulian.Pullen@Sun.COM site_name_item = validate_SiteName(ctx); 1657*8671SJulian.Pullen@Sun.COM if (site_name_item != NULL) 1658*8671SJulian.Pullen@Sun.COM validate_site = B_TRUE; 1659*8671SJulian.Pullen@Sun.COM else if (req == AD_DISC_PREFER_SITE) 1660*8671SJulian.Pullen@Sun.COM validate_global = B_TRUE; 1661*8671SJulian.Pullen@Sun.COM } 1662*8671SJulian.Pullen@Sun.COM 1663*8671SJulian.Pullen@Sun.COM if (validate_global) { 1664*8671SJulian.Pullen@Sun.COM if (!is_valid(&ctx->global_catalog) || 1665*8671SJulian.Pullen@Sun.COM is_changed(&ctx->global_catalog, PARAM1, 1666*8671SJulian.Pullen@Sun.COM forest_name_item)) { 1667*8671SJulian.Pullen@Sun.COM /* 1668*8671SJulian.Pullen@Sun.COM * Lookup DNS SRV RR named 1669*8671SJulian.Pullen@Sun.COM * _ldap._tcp.gc._msdcs.<ForestName> 1670*8671SJulian.Pullen@Sun.COM */ 1671*8671SJulian.Pullen@Sun.COM DO_RES_NINIT(ctx); 1672*8671SJulian.Pullen@Sun.COM global_catalog = 1673*8671SJulian.Pullen@Sun.COM srv_query(&ctx->res_state, 1674*8671SJulian.Pullen@Sun.COM LDAP_SRV_HEAD GC_SRV_TAIL, 1675*8671SJulian.Pullen@Sun.COM ctx->forest_name.value, NULL, &ttl); 1676*8671SJulian.Pullen@Sun.COM 1677*8671SJulian.Pullen@Sun.COM if (global_catalog == NULL) 1678*8671SJulian.Pullen@Sun.COM return (NULL); 1679*8671SJulian.Pullen@Sun.COM 1680*8671SJulian.Pullen@Sun.COM update_item(&ctx->global_catalog, global_catalog, 1681*8671SJulian.Pullen@Sun.COM AD_STATE_AUTO, ttl); 1682*8671SJulian.Pullen@Sun.COM update_version(&ctx->global_catalog, PARAM1, 1683*8671SJulian.Pullen@Sun.COM forest_name_item); 1684*8671SJulian.Pullen@Sun.COM } 1685*8671SJulian.Pullen@Sun.COM return (&ctx->global_catalog); 1686*8671SJulian.Pullen@Sun.COM } 1687*8671SJulian.Pullen@Sun.COM 1688*8671SJulian.Pullen@Sun.COM if (validate_site) { 1689*8671SJulian.Pullen@Sun.COM if (!is_valid(&ctx->site_global_catalog) || 1690*8671SJulian.Pullen@Sun.COM is_changed(&ctx->site_global_catalog, PARAM1, 1691*8671SJulian.Pullen@Sun.COM forest_name_item) || 1692*8671SJulian.Pullen@Sun.COM is_changed(&ctx->site_global_catalog, PARAM2, 1693*8671SJulian.Pullen@Sun.COM site_name_item)) { 1694*8671SJulian.Pullen@Sun.COM char rr_name[DNS_MAX_NAME]; 1695*8671SJulian.Pullen@Sun.COM 1696*8671SJulian.Pullen@Sun.COM /* 1697*8671SJulian.Pullen@Sun.COM * Lookup DNS SRV RR named: 1698*8671SJulian.Pullen@Sun.COM * _ldap._tcp.<siteName>._sites.gc. 1699*8671SJulian.Pullen@Sun.COM * _msdcs.<ForestName> 1700*8671SJulian.Pullen@Sun.COM */ 1701*8671SJulian.Pullen@Sun.COM (void) snprintf(rr_name, 1702*8671SJulian.Pullen@Sun.COM sizeof (rr_name), 1703*8671SJulian.Pullen@Sun.COM LDAP_SRV_HEAD SITE_SRV_MIDDLE GC_SRV_TAIL, 1704*8671SJulian.Pullen@Sun.COM ctx->site_name.value); 1705*8671SJulian.Pullen@Sun.COM DO_RES_NINIT(ctx); 1706*8671SJulian.Pullen@Sun.COM global_catalog = srv_query(&ctx->res_state, rr_name, 1707*8671SJulian.Pullen@Sun.COM ctx->forest_name.value, NULL, &ttl); 1708*8671SJulian.Pullen@Sun.COM 1709*8671SJulian.Pullen@Sun.COM if (global_catalog == NULL) 1710*8671SJulian.Pullen@Sun.COM return (NULL); 1711*8671SJulian.Pullen@Sun.COM update_item(&ctx->site_global_catalog, global_catalog, 1712*8671SJulian.Pullen@Sun.COM AD_STATE_AUTO, ttl); 1713*8671SJulian.Pullen@Sun.COM update_version(&ctx->site_global_catalog, PARAM1, 1714*8671SJulian.Pullen@Sun.COM forest_name_item); 1715*8671SJulian.Pullen@Sun.COM update_version(&ctx->site_global_catalog, PARAM2, 1716*8671SJulian.Pullen@Sun.COM site_name_item); 1717*8671SJulian.Pullen@Sun.COM } 1718*8671SJulian.Pullen@Sun.COM return (&ctx->site_global_catalog); 1719*8671SJulian.Pullen@Sun.COM } 1720*8671SJulian.Pullen@Sun.COM return (NULL); 1721*8671SJulian.Pullen@Sun.COM } 1722*8671SJulian.Pullen@Sun.COM 1723*8671SJulian.Pullen@Sun.COM 1724*8671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t * 1725*8671SJulian.Pullen@Sun.COM ad_disc_get_GlobalCatalog(ad_disc_t ctx, enum ad_disc_req req, 1726*8671SJulian.Pullen@Sun.COM boolean_t *auto_discovered) 1727*8671SJulian.Pullen@Sun.COM { 1728*8671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t *global_catalog = NULL; 1729*8671SJulian.Pullen@Sun.COM ad_item_t *global_catalog_item; 1730*8671SJulian.Pullen@Sun.COM 1731*8671SJulian.Pullen@Sun.COM global_catalog_item = validate_GlobalCatalog(ctx, req); 1732*8671SJulian.Pullen@Sun.COM 1733*8671SJulian.Pullen@Sun.COM if (global_catalog_item != NULL) { 1734*8671SJulian.Pullen@Sun.COM global_catalog = ds_dup(global_catalog_item->value); 1735*8671SJulian.Pullen@Sun.COM if (auto_discovered != NULL) 1736*8671SJulian.Pullen@Sun.COM *auto_discovered = 1737*8671SJulian.Pullen@Sun.COM (global_catalog_item->state == AD_STATE_AUTO); 1738*8671SJulian.Pullen@Sun.COM } else if (auto_discovered != NULL) 1739*8671SJulian.Pullen@Sun.COM *auto_discovered = B_FALSE; 1740*8671SJulian.Pullen@Sun.COM 1741*8671SJulian.Pullen@Sun.COM return (global_catalog); 1742*8671SJulian.Pullen@Sun.COM } 1743*8671SJulian.Pullen@Sun.COM 1744*8671SJulian.Pullen@Sun.COM 1745*8671SJulian.Pullen@Sun.COM static ad_item_t * 1746*8671SJulian.Pullen@Sun.COM validate_TrustedDomains(ad_disc_t ctx) 1747*8671SJulian.Pullen@Sun.COM { 1748*8671SJulian.Pullen@Sun.COM LDAP *ld = NULL; 1749*8671SJulian.Pullen@Sun.COM ad_item_t *global_catalog_item; 1750*8671SJulian.Pullen@Sun.COM ad_item_t *forest_name_item; 1751*8671SJulian.Pullen@Sun.COM ad_disc_trusteddomains_t *trusted_domains; 1752*8671SJulian.Pullen@Sun.COM char *dn = NULL; 1753*8671SJulian.Pullen@Sun.COM char *forest_name_dn; 1754*8671SJulian.Pullen@Sun.COM int len; 1755*8671SJulian.Pullen@Sun.COM int num_parts; 1756*8671SJulian.Pullen@Sun.COM 1757*8671SJulian.Pullen@Sun.COM if (is_fixed(&ctx->trusted_domains)) 1758*8671SJulian.Pullen@Sun.COM return (&ctx->trusted_domains); 1759*8671SJulian.Pullen@Sun.COM 1760*8671SJulian.Pullen@Sun.COM global_catalog_item = validate_GlobalCatalog(ctx, AD_DISC_GLOBAL); 1761*8671SJulian.Pullen@Sun.COM if (global_catalog_item == NULL) 1762*8671SJulian.Pullen@Sun.COM return (NULL); 1763*8671SJulian.Pullen@Sun.COM 1764*8671SJulian.Pullen@Sun.COM forest_name_item = validate_ForestName(ctx); 1765*8671SJulian.Pullen@Sun.COM if (forest_name_item == NULL) 1766*8671SJulian.Pullen@Sun.COM return (NULL); 1767*8671SJulian.Pullen@Sun.COM 1768*8671SJulian.Pullen@Sun.COM if (!is_valid(&ctx->trusted_domains) || 1769*8671SJulian.Pullen@Sun.COM is_changed(&ctx->trusted_domains, PARAM1, global_catalog_item) || 1770*8671SJulian.Pullen@Sun.COM is_changed(&ctx->trusted_domains, PARAM2, forest_name_item)) { 1771*8671SJulian.Pullen@Sun.COM 1772*8671SJulian.Pullen@Sun.COM forest_name_dn = ldap_dns_to_dn(forest_name_item->value, 1773*8671SJulian.Pullen@Sun.COM &num_parts); 1774*8671SJulian.Pullen@Sun.COM if (forest_name_dn == NULL) 1775*8671SJulian.Pullen@Sun.COM return (NULL); 1776*8671SJulian.Pullen@Sun.COM 1777*8671SJulian.Pullen@Sun.COM len = snprintf(NULL, 0, "CN=System,%s", forest_name_dn) + 1; 1778*8671SJulian.Pullen@Sun.COM dn = malloc(len); 1779*8671SJulian.Pullen@Sun.COM if (dn == NULL) { 1780*8671SJulian.Pullen@Sun.COM free(forest_name_dn); 1781*8671SJulian.Pullen@Sun.COM return (NULL); 1782*8671SJulian.Pullen@Sun.COM } 1783*8671SJulian.Pullen@Sun.COM (void) snprintf(dn, len, "CN=System,%s", forest_name_dn); 1784*8671SJulian.Pullen@Sun.COM free(forest_name_dn); 1785*8671SJulian.Pullen@Sun.COM 1786*8671SJulian.Pullen@Sun.COM trusted_domains = ldap_lookup_trusted_domains( 1787*8671SJulian.Pullen@Sun.COM &ld, global_catalog_item->value, dn); 1788*8671SJulian.Pullen@Sun.COM 1789*8671SJulian.Pullen@Sun.COM if (ld != NULL) 1790*8671SJulian.Pullen@Sun.COM (void) ldap_unbind(ld); 1791*8671SJulian.Pullen@Sun.COM free(dn); 1792*8671SJulian.Pullen@Sun.COM 1793*8671SJulian.Pullen@Sun.COM if (trusted_domains == NULL) 1794*8671SJulian.Pullen@Sun.COM return (NULL); 1795*8671SJulian.Pullen@Sun.COM 1796*8671SJulian.Pullen@Sun.COM update_item(&ctx->trusted_domains, trusted_domains, 1797*8671SJulian.Pullen@Sun.COM AD_STATE_AUTO, 0); 1798*8671SJulian.Pullen@Sun.COM update_version(&ctx->trusted_domains, PARAM1, 1799*8671SJulian.Pullen@Sun.COM global_catalog_item); 1800*8671SJulian.Pullen@Sun.COM update_version(&ctx->trusted_domains, PARAM2, 1801*8671SJulian.Pullen@Sun.COM forest_name_item); 1802*8671SJulian.Pullen@Sun.COM } 1803*8671SJulian.Pullen@Sun.COM 1804*8671SJulian.Pullen@Sun.COM return (&ctx->trusted_domains); 1805*8671SJulian.Pullen@Sun.COM } 1806*8671SJulian.Pullen@Sun.COM 1807*8671SJulian.Pullen@Sun.COM 1808*8671SJulian.Pullen@Sun.COM ad_disc_trusteddomains_t * 1809*8671SJulian.Pullen@Sun.COM ad_disc_get_TrustedDomains(ad_disc_t ctx, boolean_t *auto_discovered) 1810*8671SJulian.Pullen@Sun.COM { 1811*8671SJulian.Pullen@Sun.COM ad_disc_trusteddomains_t *trusted_domains = NULL; 1812*8671SJulian.Pullen@Sun.COM ad_item_t *trusted_domains_item; 1813*8671SJulian.Pullen@Sun.COM 1814*8671SJulian.Pullen@Sun.COM trusted_domains_item = validate_TrustedDomains(ctx); 1815*8671SJulian.Pullen@Sun.COM 1816*8671SJulian.Pullen@Sun.COM if (trusted_domains_item != NULL) { 1817*8671SJulian.Pullen@Sun.COM trusted_domains = td_dup(trusted_domains_item->value); 1818*8671SJulian.Pullen@Sun.COM if (auto_discovered != NULL) 1819*8671SJulian.Pullen@Sun.COM *auto_discovered = 1820*8671SJulian.Pullen@Sun.COM (trusted_domains_item->state == AD_STATE_AUTO); 1821*8671SJulian.Pullen@Sun.COM } else if (auto_discovered != NULL) 1822*8671SJulian.Pullen@Sun.COM *auto_discovered = B_FALSE; 1823*8671SJulian.Pullen@Sun.COM 1824*8671SJulian.Pullen@Sun.COM return (trusted_domains); 1825*8671SJulian.Pullen@Sun.COM } 1826*8671SJulian.Pullen@Sun.COM 1827*8671SJulian.Pullen@Sun.COM 1828*8671SJulian.Pullen@Sun.COM static ad_item_t * 1829*8671SJulian.Pullen@Sun.COM validate_DomainsInForest(ad_disc_t ctx) 1830*8671SJulian.Pullen@Sun.COM { 1831*8671SJulian.Pullen@Sun.COM ad_item_t *global_catalog_item; 1832*8671SJulian.Pullen@Sun.COM LDAP *ld = NULL; 1833*8671SJulian.Pullen@Sun.COM ad_disc_domainsinforest_t *domains_in_forest; 1834*8671SJulian.Pullen@Sun.COM 1835*8671SJulian.Pullen@Sun.COM if (is_fixed(&ctx->domains_in_forest)) 1836*8671SJulian.Pullen@Sun.COM return (&ctx->domains_in_forest); 1837*8671SJulian.Pullen@Sun.COM 1838*8671SJulian.Pullen@Sun.COM global_catalog_item = validate_GlobalCatalog(ctx, AD_DISC_GLOBAL); 1839*8671SJulian.Pullen@Sun.COM if (global_catalog_item == NULL) 1840*8671SJulian.Pullen@Sun.COM return (NULL); 1841*8671SJulian.Pullen@Sun.COM 1842*8671SJulian.Pullen@Sun.COM if (!is_valid(&ctx->domains_in_forest) || 1843*8671SJulian.Pullen@Sun.COM is_changed(&ctx->domains_in_forest, PARAM1, global_catalog_item)) { 1844*8671SJulian.Pullen@Sun.COM 1845*8671SJulian.Pullen@Sun.COM domains_in_forest = ldap_lookup_domains_in_forest( 1846*8671SJulian.Pullen@Sun.COM &ld, global_catalog_item->value); 1847*8671SJulian.Pullen@Sun.COM 1848*8671SJulian.Pullen@Sun.COM if (ld != NULL) 1849*8671SJulian.Pullen@Sun.COM (void) ldap_unbind(ld); 1850*8671SJulian.Pullen@Sun.COM 1851*8671SJulian.Pullen@Sun.COM if (domains_in_forest == NULL) 1852*8671SJulian.Pullen@Sun.COM return (NULL); 1853*8671SJulian.Pullen@Sun.COM 1854*8671SJulian.Pullen@Sun.COM update_item(&ctx->domains_in_forest, domains_in_forest, 1855*8671SJulian.Pullen@Sun.COM AD_STATE_AUTO, 0); 1856*8671SJulian.Pullen@Sun.COM update_version(&ctx->domains_in_forest, PARAM1, 1857*8671SJulian.Pullen@Sun.COM global_catalog_item); 1858*8671SJulian.Pullen@Sun.COM } 1859*8671SJulian.Pullen@Sun.COM return (&ctx->domains_in_forest); 1860*8671SJulian.Pullen@Sun.COM } 1861*8671SJulian.Pullen@Sun.COM 1862*8671SJulian.Pullen@Sun.COM 1863*8671SJulian.Pullen@Sun.COM ad_disc_domainsinforest_t * 1864*8671SJulian.Pullen@Sun.COM ad_disc_get_DomainsInForest(ad_disc_t ctx, boolean_t *auto_discovered) 1865*8671SJulian.Pullen@Sun.COM { 1866*8671SJulian.Pullen@Sun.COM ad_disc_domainsinforest_t *domains_in_forest = NULL; 1867*8671SJulian.Pullen@Sun.COM ad_item_t *domains_in_forest_item; 1868*8671SJulian.Pullen@Sun.COM 1869*8671SJulian.Pullen@Sun.COM domains_in_forest_item = validate_DomainsInForest(ctx); 1870*8671SJulian.Pullen@Sun.COM 1871*8671SJulian.Pullen@Sun.COM if (domains_in_forest_item != NULL) { 1872*8671SJulian.Pullen@Sun.COM domains_in_forest = df_dup(domains_in_forest_item->value); 1873*8671SJulian.Pullen@Sun.COM if (auto_discovered != NULL) 1874*8671SJulian.Pullen@Sun.COM *auto_discovered = 1875*8671SJulian.Pullen@Sun.COM (domains_in_forest_item->state == AD_STATE_AUTO); 1876*8671SJulian.Pullen@Sun.COM } else if (auto_discovered != NULL) 1877*8671SJulian.Pullen@Sun.COM *auto_discovered = B_FALSE; 1878*8671SJulian.Pullen@Sun.COM 1879*8671SJulian.Pullen@Sun.COM return (domains_in_forest); 1880*8671SJulian.Pullen@Sun.COM } 1881*8671SJulian.Pullen@Sun.COM 1882*8671SJulian.Pullen@Sun.COM 1883*8671SJulian.Pullen@Sun.COM 1884*8671SJulian.Pullen@Sun.COM 1885*8671SJulian.Pullen@Sun.COM int 1886*8671SJulian.Pullen@Sun.COM ad_disc_set_DomainName(ad_disc_t ctx, const char *domainName) 1887*8671SJulian.Pullen@Sun.COM { 1888*8671SJulian.Pullen@Sun.COM char *domain_name = NULL; 1889*8671SJulian.Pullen@Sun.COM if (domainName != NULL) { 1890*8671SJulian.Pullen@Sun.COM domain_name = strdup(domainName); 1891*8671SJulian.Pullen@Sun.COM if (domain_name == NULL) 1892*8671SJulian.Pullen@Sun.COM return (-1); 1893*8671SJulian.Pullen@Sun.COM update_item(&ctx->domain_name, domain_name, 1894*8671SJulian.Pullen@Sun.COM AD_STATE_FIXED, 0); 1895*8671SJulian.Pullen@Sun.COM } else if (ctx->domain_name.state == AD_STATE_FIXED) 1896*8671SJulian.Pullen@Sun.COM ctx->domain_name.state = AD_STATE_INVALID; 1897*8671SJulian.Pullen@Sun.COM return (0); 1898*8671SJulian.Pullen@Sun.COM } 1899*8671SJulian.Pullen@Sun.COM 1900*8671SJulian.Pullen@Sun.COM 1901*8671SJulian.Pullen@Sun.COM int 1902*8671SJulian.Pullen@Sun.COM ad_disc_set_DomainController(ad_disc_t ctx, 1903*8671SJulian.Pullen@Sun.COM const idmap_ad_disc_ds_t *domainController) 1904*8671SJulian.Pullen@Sun.COM { 1905*8671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t *domain_controller = NULL; 1906*8671SJulian.Pullen@Sun.COM if (domainController != NULL) { 1907*8671SJulian.Pullen@Sun.COM domain_controller = ds_dup(domainController); 1908*8671SJulian.Pullen@Sun.COM if (domain_controller == NULL) 1909*8671SJulian.Pullen@Sun.COM return (-1); 1910*8671SJulian.Pullen@Sun.COM update_item(&ctx->domain_controller, domain_controller, 1911*8671SJulian.Pullen@Sun.COM AD_STATE_FIXED, 0); 1912*8671SJulian.Pullen@Sun.COM } else if (ctx->domain_controller.state == AD_STATE_FIXED) 1913*8671SJulian.Pullen@Sun.COM ctx->domain_controller.state = AD_STATE_INVALID; 1914*8671SJulian.Pullen@Sun.COM return (0); 1915*8671SJulian.Pullen@Sun.COM } 1916*8671SJulian.Pullen@Sun.COM 1917*8671SJulian.Pullen@Sun.COM 1918*8671SJulian.Pullen@Sun.COM int 1919*8671SJulian.Pullen@Sun.COM ad_disc_set_SiteName(ad_disc_t ctx, const char *siteName) 1920*8671SJulian.Pullen@Sun.COM { 1921*8671SJulian.Pullen@Sun.COM char *site_name = NULL; 1922*8671SJulian.Pullen@Sun.COM if (siteName != NULL) { 1923*8671SJulian.Pullen@Sun.COM site_name = strdup(siteName); 1924*8671SJulian.Pullen@Sun.COM if (site_name == NULL) 1925*8671SJulian.Pullen@Sun.COM return (-1); 1926*8671SJulian.Pullen@Sun.COM update_item(&ctx->site_name, site_name, AD_STATE_FIXED, 0); 1927*8671SJulian.Pullen@Sun.COM } else if (ctx->site_name.state == AD_STATE_FIXED) 1928*8671SJulian.Pullen@Sun.COM ctx->site_name.state = AD_STATE_INVALID; 1929*8671SJulian.Pullen@Sun.COM return (0); 1930*8671SJulian.Pullen@Sun.COM } 1931*8671SJulian.Pullen@Sun.COM 1932*8671SJulian.Pullen@Sun.COM int 1933*8671SJulian.Pullen@Sun.COM ad_disc_set_ForestName(ad_disc_t ctx, const char *forestName) 1934*8671SJulian.Pullen@Sun.COM { 1935*8671SJulian.Pullen@Sun.COM char *forest_name = NULL; 1936*8671SJulian.Pullen@Sun.COM if (forestName != NULL) { 1937*8671SJulian.Pullen@Sun.COM forest_name = strdup(forestName); 1938*8671SJulian.Pullen@Sun.COM if (forest_name == NULL) 1939*8671SJulian.Pullen@Sun.COM return (-1); 1940*8671SJulian.Pullen@Sun.COM update_item(&ctx->forest_name, forest_name, 1941*8671SJulian.Pullen@Sun.COM AD_STATE_FIXED, 0); 1942*8671SJulian.Pullen@Sun.COM } else if (ctx->forest_name.state == AD_STATE_FIXED) 1943*8671SJulian.Pullen@Sun.COM ctx->forest_name.state = AD_STATE_INVALID; 1944*8671SJulian.Pullen@Sun.COM return (0); 1945*8671SJulian.Pullen@Sun.COM } 1946*8671SJulian.Pullen@Sun.COM 1947*8671SJulian.Pullen@Sun.COM int 1948*8671SJulian.Pullen@Sun.COM ad_disc_set_GlobalCatalog(ad_disc_t ctx, 1949*8671SJulian.Pullen@Sun.COM const idmap_ad_disc_ds_t *globalCatalog) 1950*8671SJulian.Pullen@Sun.COM { 1951*8671SJulian.Pullen@Sun.COM idmap_ad_disc_ds_t *global_catalog = NULL; 1952*8671SJulian.Pullen@Sun.COM if (globalCatalog != NULL) { 1953*8671SJulian.Pullen@Sun.COM global_catalog = ds_dup(globalCatalog); 1954*8671SJulian.Pullen@Sun.COM if (global_catalog == NULL) 1955*8671SJulian.Pullen@Sun.COM return (-1); 1956*8671SJulian.Pullen@Sun.COM update_item(&ctx->global_catalog, global_catalog, 1957*8671SJulian.Pullen@Sun.COM AD_STATE_FIXED, 0); 1958*8671SJulian.Pullen@Sun.COM } else if (ctx->global_catalog.state == AD_STATE_FIXED) 1959*8671SJulian.Pullen@Sun.COM ctx->global_catalog.state = AD_STATE_INVALID; 1960*8671SJulian.Pullen@Sun.COM return (0); 1961*8671SJulian.Pullen@Sun.COM } 1962*8671SJulian.Pullen@Sun.COM 1963*8671SJulian.Pullen@Sun.COM 1964*8671SJulian.Pullen@Sun.COM int 1965*8671SJulian.Pullen@Sun.COM ad_disc_unset(ad_disc_t ctx) 1966*8671SJulian.Pullen@Sun.COM { 1967*8671SJulian.Pullen@Sun.COM if (ctx->domain_name.state == AD_STATE_FIXED) 1968*8671SJulian.Pullen@Sun.COM ctx->domain_name.state = AD_STATE_INVALID; 1969*8671SJulian.Pullen@Sun.COM 1970*8671SJulian.Pullen@Sun.COM if (ctx->domain_controller.state == AD_STATE_FIXED) 1971*8671SJulian.Pullen@Sun.COM ctx->domain_controller.state = AD_STATE_INVALID; 1972*8671SJulian.Pullen@Sun.COM 1973*8671SJulian.Pullen@Sun.COM if (ctx->site_name.state == AD_STATE_FIXED) 1974*8671SJulian.Pullen@Sun.COM ctx->site_name.state = AD_STATE_INVALID; 1975*8671SJulian.Pullen@Sun.COM 1976*8671SJulian.Pullen@Sun.COM if (ctx->forest_name.state == AD_STATE_FIXED) 1977*8671SJulian.Pullen@Sun.COM ctx->forest_name.state = AD_STATE_INVALID; 1978*8671SJulian.Pullen@Sun.COM 1979*8671SJulian.Pullen@Sun.COM if (ctx->global_catalog.state == AD_STATE_FIXED) 1980*8671SJulian.Pullen@Sun.COM ctx->global_catalog.state = AD_STATE_INVALID; 1981*8671SJulian.Pullen@Sun.COM 1982*8671SJulian.Pullen@Sun.COM return (0); 1983*8671SJulian.Pullen@Sun.COM } 1984*8671SJulian.Pullen@Sun.COM 1985*8671SJulian.Pullen@Sun.COM /* 1986*8671SJulian.Pullen@Sun.COM * ad_disc_get_TTL 1987*8671SJulian.Pullen@Sun.COM * 1988*8671SJulian.Pullen@Sun.COM * This routines the time to live for AD 1989*8671SJulian.Pullen@Sun.COM * auto discovered items. 1990*8671SJulian.Pullen@Sun.COM * 1991*8671SJulian.Pullen@Sun.COM * Returns: 1992*8671SJulian.Pullen@Sun.COM * -1 if there are no TTL items 1993*8671SJulian.Pullen@Sun.COM * 0 if there are expired items 1994*8671SJulian.Pullen@Sun.COM * else the number of seconds 1995*8671SJulian.Pullen@Sun.COM * 1996*8671SJulian.Pullen@Sun.COM * The MIN_GT_ZERO(x, y) macro return the lesser of x and y, provided it 1997*8671SJulian.Pullen@Sun.COM * is positive -- min() greater than zero. 1998*8671SJulian.Pullen@Sun.COM */ 1999*8671SJulian.Pullen@Sun.COM #define MIN_GT_ZERO(x, y) (((x) <= 0) ? (((y) <= 0) ? \ 2000*8671SJulian.Pullen@Sun.COM (-1) : (y)) : (((y) <= 0) ? (x) : (((x) > (y)) ? (y) : (x)))) 2001*8671SJulian.Pullen@Sun.COM int 2002*8671SJulian.Pullen@Sun.COM ad_disc_get_TTL(ad_disc_t ctx) 2003*8671SJulian.Pullen@Sun.COM { 2004*8671SJulian.Pullen@Sun.COM int ttl; 2005*8671SJulian.Pullen@Sun.COM 2006*8671SJulian.Pullen@Sun.COM ttl = MIN_GT_ZERO(ctx->domain_controller.ttl, ctx->global_catalog.ttl); 2007*8671SJulian.Pullen@Sun.COM ttl = MIN_GT_ZERO(ttl, ctx->site_domain_controller.ttl); 2008*8671SJulian.Pullen@Sun.COM ttl = MIN_GT_ZERO(ttl, ctx->site_global_catalog.ttl); 2009*8671SJulian.Pullen@Sun.COM 2010*8671SJulian.Pullen@Sun.COM if (ttl == -1) 2011*8671SJulian.Pullen@Sun.COM return (-1); 2012*8671SJulian.Pullen@Sun.COM ttl -= time(NULL); 2013*8671SJulian.Pullen@Sun.COM if (ttl < 0) 2014*8671SJulian.Pullen@Sun.COM return (0); 2015*8671SJulian.Pullen@Sun.COM return (ttl); 2016*8671SJulian.Pullen@Sun.COM } 2017*8671SJulian.Pullen@Sun.COM 2018*8671SJulian.Pullen@Sun.COM boolean_t 2019*8671SJulian.Pullen@Sun.COM ad_disc_SubnetChanged(ad_disc_t ctx) 2020*8671SJulian.Pullen@Sun.COM { 2021*8671SJulian.Pullen@Sun.COM ad_subnet_t *subnets; 2022*8671SJulian.Pullen@Sun.COM 2023*8671SJulian.Pullen@Sun.COM if (ctx->subnets_changed || ctx->subnets == NULL) 2024*8671SJulian.Pullen@Sun.COM return (B_TRUE); 2025*8671SJulian.Pullen@Sun.COM 2026*8671SJulian.Pullen@Sun.COM if ((subnets = find_subnets()) != NULL) { 2027*8671SJulian.Pullen@Sun.COM if (cmpsubnets(subnets, ctx->subnets) != 0) 2028*8671SJulian.Pullen@Sun.COM ctx->subnets_changed = B_TRUE; 2029*8671SJulian.Pullen@Sun.COM free(subnets); 2030*8671SJulian.Pullen@Sun.COM } 2031*8671SJulian.Pullen@Sun.COM 2032*8671SJulian.Pullen@Sun.COM return (ctx->subnets_changed); 2033*8671SJulian.Pullen@Sun.COM } 2034