18040SBaban.Kenkre@Sun.COM /* 28040SBaban.Kenkre@Sun.COM * CDDL HEADER START 38040SBaban.Kenkre@Sun.COM * 48040SBaban.Kenkre@Sun.COM * The contents of this file are subject to the terms of the 58040SBaban.Kenkre@Sun.COM * Common Development and Distribution License (the "License"). 68040SBaban.Kenkre@Sun.COM * You may not use this file except in compliance with the License. 78040SBaban.Kenkre@Sun.COM * 88040SBaban.Kenkre@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 98040SBaban.Kenkre@Sun.COM * or http://www.opensolaris.org/os/licensing. 108040SBaban.Kenkre@Sun.COM * See the License for the specific language governing permissions 118040SBaban.Kenkre@Sun.COM * and limitations under the License. 128040SBaban.Kenkre@Sun.COM * 138040SBaban.Kenkre@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 148040SBaban.Kenkre@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 158040SBaban.Kenkre@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 168040SBaban.Kenkre@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 178040SBaban.Kenkre@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 188040SBaban.Kenkre@Sun.COM * 198040SBaban.Kenkre@Sun.COM * CDDL HEADER END 208040SBaban.Kenkre@Sun.COM */ 218040SBaban.Kenkre@Sun.COM /* 228671SJulian.Pullen@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 238040SBaban.Kenkre@Sun.COM * Use is subject to license terms. 248040SBaban.Kenkre@Sun.COM */ 258040SBaban.Kenkre@Sun.COM 268040SBaban.Kenkre@Sun.COM #include <alloca.h> 278040SBaban.Kenkre@Sun.COM #include <string.h> 288040SBaban.Kenkre@Sun.COM #include <strings.h> 298040SBaban.Kenkre@Sun.COM #include <lber.h> 308040SBaban.Kenkre@Sun.COM #include <sasl/sasl.h> 318040SBaban.Kenkre@Sun.COM #include <string.h> 328040SBaban.Kenkre@Sun.COM #include <ctype.h> 338040SBaban.Kenkre@Sun.COM #include <synch.h> 348040SBaban.Kenkre@Sun.COM #include <atomic.h> 358040SBaban.Kenkre@Sun.COM #include <errno.h> 368040SBaban.Kenkre@Sun.COM #include <assert.h> 378040SBaban.Kenkre@Sun.COM #include <limits.h> 388671SJulian.Pullen@Sun.COM #include <syslog.h> 398040SBaban.Kenkre@Sun.COM #include <sys/u8_textprep.h> 408040SBaban.Kenkre@Sun.COM #include <sys/varargs.h> 418040SBaban.Kenkre@Sun.COM #include "libadutils.h" 428040SBaban.Kenkre@Sun.COM #include "adutils_impl.h" 438040SBaban.Kenkre@Sun.COM 448040SBaban.Kenkre@Sun.COM /* List of DSs, needed by the idle connection reaper thread */ 458040SBaban.Kenkre@Sun.COM static pthread_mutex_t adhostlock = PTHREAD_MUTEX_INITIALIZER; 468040SBaban.Kenkre@Sun.COM static adutils_host_t *host_head = NULL; 478040SBaban.Kenkre@Sun.COM 488040SBaban.Kenkre@Sun.COM /* 498040SBaban.Kenkre@Sun.COM * List of query state structs -- needed so we can "route" LDAP results 508040SBaban.Kenkre@Sun.COM * to the right context if multiple threads should be using the same 518040SBaban.Kenkre@Sun.COM * connection concurrently 528040SBaban.Kenkre@Sun.COM */ 538040SBaban.Kenkre@Sun.COM static pthread_mutex_t qstatelock = PTHREAD_MUTEX_INITIALIZER; 548040SBaban.Kenkre@Sun.COM static adutils_query_state_t *qstatehead = NULL; 558040SBaban.Kenkre@Sun.COM 568040SBaban.Kenkre@Sun.COM static char *adutils_sid_ber2str(BerValue *bvalues); 578040SBaban.Kenkre@Sun.COM static void adutils_lookup_batch_unlock(adutils_query_state_t **state); 588040SBaban.Kenkre@Sun.COM static void delete_ds(adutils_ad_t *ad, const char *host, int port); 598040SBaban.Kenkre@Sun.COM 608040SBaban.Kenkre@Sun.COM typedef struct binary_attrs { 618040SBaban.Kenkre@Sun.COM const char *name; 628040SBaban.Kenkre@Sun.COM char *(*ber2str)(BerValue *bvalues); 638040SBaban.Kenkre@Sun.COM } binary_attrs_t; 648040SBaban.Kenkre@Sun.COM 658040SBaban.Kenkre@Sun.COM static binary_attrs_t binattrs[] = { 668040SBaban.Kenkre@Sun.COM {"objectSID", adutils_sid_ber2str}, 678040SBaban.Kenkre@Sun.COM {NULL, NULL} 688040SBaban.Kenkre@Sun.COM }; 698040SBaban.Kenkre@Sun.COM 708361SJulian.Pullen@Sun.COM 718671SJulian.Pullen@Sun.COM adutils_logger logger = syslog; 728671SJulian.Pullen@Sun.COM 738671SJulian.Pullen@Sun.COM 748040SBaban.Kenkre@Sun.COM void 758671SJulian.Pullen@Sun.COM adutils_set_logger(adutils_logger funct) 768040SBaban.Kenkre@Sun.COM { 778671SJulian.Pullen@Sun.COM logger = funct; 788040SBaban.Kenkre@Sun.COM } 798040SBaban.Kenkre@Sun.COM 808361SJulian.Pullen@Sun.COM 818040SBaban.Kenkre@Sun.COM /* 828040SBaban.Kenkre@Sun.COM * Turn "foo.bar.com" into "dc=foo,dc=bar,dc=com" 838040SBaban.Kenkre@Sun.COM */ 848040SBaban.Kenkre@Sun.COM static 858040SBaban.Kenkre@Sun.COM char * 868040SBaban.Kenkre@Sun.COM adutils_dns2dn(const char *dns) 878040SBaban.Kenkre@Sun.COM { 888671SJulian.Pullen@Sun.COM int num_parts; 898671SJulian.Pullen@Sun.COM 908671SJulian.Pullen@Sun.COM return (ldap_dns_to_dn((char *)dns, &num_parts)); 918040SBaban.Kenkre@Sun.COM } 928040SBaban.Kenkre@Sun.COM 938361SJulian.Pullen@Sun.COM 948040SBaban.Kenkre@Sun.COM /* 958040SBaban.Kenkre@Sun.COM * Turn "dc=foo,dc=bar,dc=com" into "foo.bar.com"; ignores any other 968040SBaban.Kenkre@Sun.COM * attributes (CN, etc...). 978040SBaban.Kenkre@Sun.COM */ 988040SBaban.Kenkre@Sun.COM char * 998040SBaban.Kenkre@Sun.COM adutils_dn2dns(const char *dn) 1008040SBaban.Kenkre@Sun.COM { 1018671SJulian.Pullen@Sun.COM return (DN_to_DNS(dn)); 1028671SJulian.Pullen@Sun.COM } 1038040SBaban.Kenkre@Sun.COM 1048040SBaban.Kenkre@Sun.COM 1058040SBaban.Kenkre@Sun.COM /* 1068040SBaban.Kenkre@Sun.COM * Convert a binary SID in a BerValue to a adutils_sid_t 1078040SBaban.Kenkre@Sun.COM */ 1088040SBaban.Kenkre@Sun.COM int 1098671SJulian.Pullen@Sun.COM adutils_getsid(BerValue *bval, adutils_sid_t *sidp) 1108040SBaban.Kenkre@Sun.COM { 1118040SBaban.Kenkre@Sun.COM int i, j; 1128040SBaban.Kenkre@Sun.COM uchar_t *v; 1138040SBaban.Kenkre@Sun.COM uint32_t a; 1148040SBaban.Kenkre@Sun.COM 1158040SBaban.Kenkre@Sun.COM /* 1168040SBaban.Kenkre@Sun.COM * The binary format of a SID is as follows: 1178040SBaban.Kenkre@Sun.COM * 1188040SBaban.Kenkre@Sun.COM * byte #0: version, always 0x01 1198040SBaban.Kenkre@Sun.COM * byte #1: RID count, always <= 0x0f 1208040SBaban.Kenkre@Sun.COM * bytes #2-#7: SID authority, big-endian 48-bit unsigned int 1218040SBaban.Kenkre@Sun.COM * 1228040SBaban.Kenkre@Sun.COM * followed by RID count RIDs, each a little-endian, unsigned 1238040SBaban.Kenkre@Sun.COM * 32-bit int. 1248040SBaban.Kenkre@Sun.COM */ 1258040SBaban.Kenkre@Sun.COM /* 1268040SBaban.Kenkre@Sun.COM * Sanity checks: must have at least one RID, version must be 1278040SBaban.Kenkre@Sun.COM * 0x01, and the length must be 8 + rid count * 4 1288040SBaban.Kenkre@Sun.COM */ 1298040SBaban.Kenkre@Sun.COM if (bval->bv_len > 8 && bval->bv_val[0] == 0x01 && 1308040SBaban.Kenkre@Sun.COM bval->bv_len == 1 + 1 + 6 + bval->bv_val[1] * 4) { 1318040SBaban.Kenkre@Sun.COM v = (uchar_t *)bval->bv_val; 1328040SBaban.Kenkre@Sun.COM sidp->version = v[0]; 1338040SBaban.Kenkre@Sun.COM sidp->sub_authority_count = v[1]; 1348040SBaban.Kenkre@Sun.COM sidp->authority = 1358040SBaban.Kenkre@Sun.COM /* big endian -- so start from the left */ 1368040SBaban.Kenkre@Sun.COM ((u_longlong_t)v[2] << 40) | 1378040SBaban.Kenkre@Sun.COM ((u_longlong_t)v[3] << 32) | 1388040SBaban.Kenkre@Sun.COM ((u_longlong_t)v[4] << 24) | 1398040SBaban.Kenkre@Sun.COM ((u_longlong_t)v[5] << 16) | 1408040SBaban.Kenkre@Sun.COM ((u_longlong_t)v[6] << 8) | 1418040SBaban.Kenkre@Sun.COM (u_longlong_t)v[7]; 1428040SBaban.Kenkre@Sun.COM for (i = 0; i < sidp->sub_authority_count; i++) { 1438040SBaban.Kenkre@Sun.COM j = 8 + (i * 4); 1448040SBaban.Kenkre@Sun.COM /* little endian -- so start from the right */ 1458040SBaban.Kenkre@Sun.COM a = (v[j + 3] << 24) | (v[j + 2] << 16) | 1468040SBaban.Kenkre@Sun.COM (v[j + 1] << 8) | (v[j]); 1478040SBaban.Kenkre@Sun.COM sidp->sub_authorities[i] = a; 1488040SBaban.Kenkre@Sun.COM } 1498040SBaban.Kenkre@Sun.COM return (0); 1508040SBaban.Kenkre@Sun.COM } 1518040SBaban.Kenkre@Sun.COM return (-1); 1528040SBaban.Kenkre@Sun.COM } 1538040SBaban.Kenkre@Sun.COM 1548040SBaban.Kenkre@Sun.COM /* 1558040SBaban.Kenkre@Sun.COM * Convert a adutils_sid_t to S-1-... 1568040SBaban.Kenkre@Sun.COM */ 1578040SBaban.Kenkre@Sun.COM char * 1588671SJulian.Pullen@Sun.COM adutils_sid2txt(adutils_sid_t *sidp) 1598040SBaban.Kenkre@Sun.COM { 1608040SBaban.Kenkre@Sun.COM int rlen, i, len; 1618040SBaban.Kenkre@Sun.COM char *str, *cp; 1628040SBaban.Kenkre@Sun.COM 1638040SBaban.Kenkre@Sun.COM if (sidp->version != 1) 1648040SBaban.Kenkre@Sun.COM return (NULL); 1658040SBaban.Kenkre@Sun.COM 1668040SBaban.Kenkre@Sun.COM len = sizeof ("S-1-") - 1; 1678040SBaban.Kenkre@Sun.COM 1688040SBaban.Kenkre@Sun.COM /* 1698040SBaban.Kenkre@Sun.COM * We could optimize like so, but, why? 1708040SBaban.Kenkre@Sun.COM * if (sidp->authority < 10) 1718040SBaban.Kenkre@Sun.COM * len += 2; 1728040SBaban.Kenkre@Sun.COM * else if (sidp->authority < 100) 1738040SBaban.Kenkre@Sun.COM * len += 3; 1748040SBaban.Kenkre@Sun.COM * else 1758040SBaban.Kenkre@Sun.COM * len += snprintf(NULL, 0"%llu", sidp->authority); 1768040SBaban.Kenkre@Sun.COM */ 1778040SBaban.Kenkre@Sun.COM len += snprintf(NULL, 0, "%llu", sidp->authority); 1788040SBaban.Kenkre@Sun.COM 1798040SBaban.Kenkre@Sun.COM /* Max length of a uint32_t printed out in ASCII is 10 bytes */ 1808040SBaban.Kenkre@Sun.COM len += 1 + (sidp->sub_authority_count + 1) * 10; 1818040SBaban.Kenkre@Sun.COM 1828040SBaban.Kenkre@Sun.COM if ((cp = str = malloc(len)) == NULL) 1838040SBaban.Kenkre@Sun.COM return (NULL); 1848040SBaban.Kenkre@Sun.COM 1858040SBaban.Kenkre@Sun.COM rlen = snprintf(str, len, "S-1-%llu", sidp->authority); 1868040SBaban.Kenkre@Sun.COM 1878040SBaban.Kenkre@Sun.COM cp += rlen; 1888040SBaban.Kenkre@Sun.COM len -= rlen; 1898040SBaban.Kenkre@Sun.COM 1908040SBaban.Kenkre@Sun.COM for (i = 0; i < sidp->sub_authority_count; i++) { 1918040SBaban.Kenkre@Sun.COM assert(len > 0); 1928040SBaban.Kenkre@Sun.COM rlen = snprintf(cp, len, "-%u", sidp->sub_authorities[i]); 1938040SBaban.Kenkre@Sun.COM cp += rlen; 1948040SBaban.Kenkre@Sun.COM len -= rlen; 1958040SBaban.Kenkre@Sun.COM assert(len >= 0); 1968040SBaban.Kenkre@Sun.COM } 1978040SBaban.Kenkre@Sun.COM 1988040SBaban.Kenkre@Sun.COM return (str); 1998040SBaban.Kenkre@Sun.COM } 2008040SBaban.Kenkre@Sun.COM 2018040SBaban.Kenkre@Sun.COM /* 2028040SBaban.Kenkre@Sun.COM * Convert a adutils_sid_t to on-the-wire encoding 2038040SBaban.Kenkre@Sun.COM */ 2048040SBaban.Kenkre@Sun.COM static 2058040SBaban.Kenkre@Sun.COM int 2068040SBaban.Kenkre@Sun.COM sid2binsid(adutils_sid_t *sid, uchar_t *binsid, int binsidlen) 2078040SBaban.Kenkre@Sun.COM { 2088040SBaban.Kenkre@Sun.COM uchar_t *p; 2098040SBaban.Kenkre@Sun.COM int i; 2108040SBaban.Kenkre@Sun.COM uint64_t a; 2118040SBaban.Kenkre@Sun.COM uint32_t r; 2128040SBaban.Kenkre@Sun.COM 2138040SBaban.Kenkre@Sun.COM if (sid->version != 1 || 2148040SBaban.Kenkre@Sun.COM binsidlen != (1 + 1 + 6 + sid->sub_authority_count * 4)) 2158040SBaban.Kenkre@Sun.COM return (-1); 2168040SBaban.Kenkre@Sun.COM 2178040SBaban.Kenkre@Sun.COM p = binsid; 2188040SBaban.Kenkre@Sun.COM *p++ = 0x01; /* version */ 2198040SBaban.Kenkre@Sun.COM /* sub authority count */ 2208040SBaban.Kenkre@Sun.COM *p++ = sid->sub_authority_count; 2218040SBaban.Kenkre@Sun.COM /* Authority */ 2228040SBaban.Kenkre@Sun.COM a = sid->authority; 2238040SBaban.Kenkre@Sun.COM /* big-endian -- start from left */ 2248040SBaban.Kenkre@Sun.COM *p++ = (a >> 40) & 0xFF; 2258040SBaban.Kenkre@Sun.COM *p++ = (a >> 32) & 0xFF; 2268040SBaban.Kenkre@Sun.COM *p++ = (a >> 24) & 0xFF; 2278040SBaban.Kenkre@Sun.COM *p++ = (a >> 16) & 0xFF; 2288040SBaban.Kenkre@Sun.COM *p++ = (a >> 8) & 0xFF; 2298040SBaban.Kenkre@Sun.COM *p++ = a & 0xFF; 2308040SBaban.Kenkre@Sun.COM 2318040SBaban.Kenkre@Sun.COM /* sub-authorities */ 2328040SBaban.Kenkre@Sun.COM for (i = 0; i < sid->sub_authority_count; i++) { 2338040SBaban.Kenkre@Sun.COM r = sid->sub_authorities[i]; 2348040SBaban.Kenkre@Sun.COM /* little-endian -- start from right */ 2358040SBaban.Kenkre@Sun.COM *p++ = (r & 0x000000FF); 2368040SBaban.Kenkre@Sun.COM *p++ = (r & 0x0000FF00) >> 8; 2378040SBaban.Kenkre@Sun.COM *p++ = (r & 0x00FF0000) >> 16; 2388040SBaban.Kenkre@Sun.COM *p++ = (r & 0xFF000000) >> 24; 2398040SBaban.Kenkre@Sun.COM } 2408040SBaban.Kenkre@Sun.COM 2418040SBaban.Kenkre@Sun.COM return (0); 2428040SBaban.Kenkre@Sun.COM } 2438040SBaban.Kenkre@Sun.COM 2448040SBaban.Kenkre@Sun.COM /* 2458040SBaban.Kenkre@Sun.COM * Convert a stringified SID (S-1-...) into a hex-encoded version of the 2468040SBaban.Kenkre@Sun.COM * on-the-wire encoding, but with each pair of hex digits pre-pended 2478040SBaban.Kenkre@Sun.COM * with a '\', so we can pass this to libldap. 2488040SBaban.Kenkre@Sun.COM */ 2498040SBaban.Kenkre@Sun.COM int 2508040SBaban.Kenkre@Sun.COM adutils_txtsid2hexbinsid(const char *txt, const uint32_t *rid, 2518040SBaban.Kenkre@Sun.COM char *hexbinsid, int hexbinsidlen) 2528040SBaban.Kenkre@Sun.COM { 2538040SBaban.Kenkre@Sun.COM adutils_sid_t sid = { 0 }; 2548040SBaban.Kenkre@Sun.COM int i, j; 2558040SBaban.Kenkre@Sun.COM const char *cp; 2568040SBaban.Kenkre@Sun.COM char *ecp; 2578040SBaban.Kenkre@Sun.COM u_longlong_t a; 2588040SBaban.Kenkre@Sun.COM unsigned long r; 2598040SBaban.Kenkre@Sun.COM uchar_t *binsid, b, hb; 2608040SBaban.Kenkre@Sun.COM 2618040SBaban.Kenkre@Sun.COM /* Only version 1 SIDs please */ 2628040SBaban.Kenkre@Sun.COM if (strncmp(txt, "S-1-", strlen("S-1-")) != 0) 2638040SBaban.Kenkre@Sun.COM return (-1); 2648040SBaban.Kenkre@Sun.COM 2658040SBaban.Kenkre@Sun.COM if (strlen(txt) < (strlen("S-1-") + 1)) 2668040SBaban.Kenkre@Sun.COM return (-1); 2678040SBaban.Kenkre@Sun.COM 2688040SBaban.Kenkre@Sun.COM /* count '-'s */ 2698040SBaban.Kenkre@Sun.COM for (j = 0, cp = strchr(txt, '-'); 2708040SBaban.Kenkre@Sun.COM cp != NULL && *cp != '\0'; 2718040SBaban.Kenkre@Sun.COM j++, cp = strchr(cp + 1, '-')) { 2728040SBaban.Kenkre@Sun.COM /* can't end on a '-' */ 2738040SBaban.Kenkre@Sun.COM if (*(cp + 1) == '\0') 2748040SBaban.Kenkre@Sun.COM return (-1); 2758040SBaban.Kenkre@Sun.COM } 2768040SBaban.Kenkre@Sun.COM 2778040SBaban.Kenkre@Sun.COM /* Adjust count for version and authority */ 2788040SBaban.Kenkre@Sun.COM j -= 2; 2798040SBaban.Kenkre@Sun.COM 2808040SBaban.Kenkre@Sun.COM /* we know the version number and RID count */ 2818040SBaban.Kenkre@Sun.COM sid.version = 1; 2828040SBaban.Kenkre@Sun.COM sid.sub_authority_count = (rid != NULL) ? j + 1 : j; 2838040SBaban.Kenkre@Sun.COM 2848040SBaban.Kenkre@Sun.COM /* must have at least one RID, but not too many */ 2858040SBaban.Kenkre@Sun.COM if (sid.sub_authority_count < 1 || 2868040SBaban.Kenkre@Sun.COM sid.sub_authority_count > ADUTILS_SID_MAX_SUB_AUTHORITIES) 2878040SBaban.Kenkre@Sun.COM return (-1); 2888040SBaban.Kenkre@Sun.COM 2898040SBaban.Kenkre@Sun.COM /* check that we only have digits and '-' */ 2908040SBaban.Kenkre@Sun.COM if (strspn(txt + 1, "0123456789-") < (strlen(txt) - 1)) 2918040SBaban.Kenkre@Sun.COM return (-1); 2928040SBaban.Kenkre@Sun.COM 2938040SBaban.Kenkre@Sun.COM cp = txt + strlen("S-1-"); 2948040SBaban.Kenkre@Sun.COM 2958040SBaban.Kenkre@Sun.COM /* 64-bit safe parsing of unsigned 48-bit authority value */ 2968040SBaban.Kenkre@Sun.COM errno = 0; 2978040SBaban.Kenkre@Sun.COM a = strtoull(cp, &ecp, 10); 2988040SBaban.Kenkre@Sun.COM 2998040SBaban.Kenkre@Sun.COM /* errors parsing the authority or too many bits */ 3008040SBaban.Kenkre@Sun.COM if (cp == ecp || (a == 0 && errno == EINVAL) || 3018040SBaban.Kenkre@Sun.COM (a == ULLONG_MAX && errno == ERANGE) || 3028040SBaban.Kenkre@Sun.COM (a & 0x0000ffffffffffffULL) != a) 3038040SBaban.Kenkre@Sun.COM return (-1); 3048040SBaban.Kenkre@Sun.COM 3058040SBaban.Kenkre@Sun.COM cp = ecp; 3068040SBaban.Kenkre@Sun.COM 3078040SBaban.Kenkre@Sun.COM sid.authority = (uint64_t)a; 3088040SBaban.Kenkre@Sun.COM 3098040SBaban.Kenkre@Sun.COM for (i = 0; i < j; i++) { 3108040SBaban.Kenkre@Sun.COM if (*cp++ != '-') 3118040SBaban.Kenkre@Sun.COM return (-1); 3128040SBaban.Kenkre@Sun.COM /* 64-bit safe parsing of unsigned 32-bit RID */ 3138040SBaban.Kenkre@Sun.COM errno = 0; 3148040SBaban.Kenkre@Sun.COM r = strtoul(cp, &ecp, 10); 3158040SBaban.Kenkre@Sun.COM /* errors parsing the RID or too many bits */ 3168040SBaban.Kenkre@Sun.COM if (cp == ecp || (r == 0 && errno == EINVAL) || 3178040SBaban.Kenkre@Sun.COM (r == ULONG_MAX && errno == ERANGE) || 3188040SBaban.Kenkre@Sun.COM (r & 0xffffffffUL) != r) 3198040SBaban.Kenkre@Sun.COM return (-1); 3208040SBaban.Kenkre@Sun.COM sid.sub_authorities[i] = (uint32_t)r; 3218040SBaban.Kenkre@Sun.COM cp = ecp; 3228040SBaban.Kenkre@Sun.COM } 3238040SBaban.Kenkre@Sun.COM 3248040SBaban.Kenkre@Sun.COM /* check that all of the string SID has been consumed */ 3258040SBaban.Kenkre@Sun.COM if (*cp != '\0') 3268040SBaban.Kenkre@Sun.COM return (-1); 3278040SBaban.Kenkre@Sun.COM 3288040SBaban.Kenkre@Sun.COM if (rid != NULL) 3298040SBaban.Kenkre@Sun.COM sid.sub_authorities[j] = *rid; 3308040SBaban.Kenkre@Sun.COM 3318040SBaban.Kenkre@Sun.COM j = 1 + 1 + 6 + sid.sub_authority_count * 4; 3328040SBaban.Kenkre@Sun.COM 3338040SBaban.Kenkre@Sun.COM if (hexbinsidlen < (j * 3)) 3348040SBaban.Kenkre@Sun.COM return (-2); 3358040SBaban.Kenkre@Sun.COM 3368040SBaban.Kenkre@Sun.COM /* binary encode the SID */ 3378040SBaban.Kenkre@Sun.COM binsid = (uchar_t *)alloca(j); 3388040SBaban.Kenkre@Sun.COM (void) sid2binsid(&sid, binsid, j); 3398040SBaban.Kenkre@Sun.COM 3408040SBaban.Kenkre@Sun.COM /* hex encode, with a backslash before each byte */ 3418040SBaban.Kenkre@Sun.COM for (ecp = hexbinsid, i = 0; i < j; i++) { 3428040SBaban.Kenkre@Sun.COM b = binsid[i]; 3438040SBaban.Kenkre@Sun.COM *ecp++ = '\\'; 3448040SBaban.Kenkre@Sun.COM hb = (b >> 4) & 0xF; 3458040SBaban.Kenkre@Sun.COM *ecp++ = (hb <= 0x9 ? hb + '0' : hb - 10 + 'A'); 3468040SBaban.Kenkre@Sun.COM hb = b & 0xF; 3478040SBaban.Kenkre@Sun.COM *ecp++ = (hb <= 0x9 ? hb + '0' : hb - 10 + 'A'); 3488040SBaban.Kenkre@Sun.COM } 3498040SBaban.Kenkre@Sun.COM *ecp = '\0'; 3508040SBaban.Kenkre@Sun.COM 3518040SBaban.Kenkre@Sun.COM return (0); 3528040SBaban.Kenkre@Sun.COM } 3538040SBaban.Kenkre@Sun.COM 3548040SBaban.Kenkre@Sun.COM static 3558040SBaban.Kenkre@Sun.COM char * 3568040SBaban.Kenkre@Sun.COM convert_bval2sid(BerValue *bval, uint32_t *rid) 3578040SBaban.Kenkre@Sun.COM { 3588040SBaban.Kenkre@Sun.COM adutils_sid_t sid; 3598040SBaban.Kenkre@Sun.COM 3608671SJulian.Pullen@Sun.COM if (adutils_getsid(bval, &sid) < 0) 3618040SBaban.Kenkre@Sun.COM return (NULL); 3628040SBaban.Kenkre@Sun.COM 3638040SBaban.Kenkre@Sun.COM /* 3648040SBaban.Kenkre@Sun.COM * If desired and if the SID is what should be a domain/computer 3658040SBaban.Kenkre@Sun.COM * user or group SID (i.e., S-1-5-w-x-y-z-<user/group RID>) then 3668040SBaban.Kenkre@Sun.COM * save the last RID and truncate the SID 3678040SBaban.Kenkre@Sun.COM */ 3688040SBaban.Kenkre@Sun.COM if (rid != NULL && sid.authority == 5 && sid.sub_authority_count == 5) 3698040SBaban.Kenkre@Sun.COM *rid = sid.sub_authorities[--sid.sub_authority_count]; 3708671SJulian.Pullen@Sun.COM return (adutils_sid2txt(&sid)); 3718040SBaban.Kenkre@Sun.COM } 3728040SBaban.Kenkre@Sun.COM 3738040SBaban.Kenkre@Sun.COM 3748040SBaban.Kenkre@Sun.COM /* 3758040SBaban.Kenkre@Sun.COM * Return a NUL-terminated stringified SID from the value of an 3768040SBaban.Kenkre@Sun.COM * objectSid attribute and put the last RID in *rid. 3778040SBaban.Kenkre@Sun.COM */ 3788040SBaban.Kenkre@Sun.COM char * 3798040SBaban.Kenkre@Sun.COM adutils_bv_objsid2sidstr(BerValue *bval, uint32_t *rid) 3808040SBaban.Kenkre@Sun.COM { 3818040SBaban.Kenkre@Sun.COM char *sid; 3828040SBaban.Kenkre@Sun.COM 3838040SBaban.Kenkre@Sun.COM if (bval == NULL) 3848040SBaban.Kenkre@Sun.COM return (NULL); 3858040SBaban.Kenkre@Sun.COM /* objectSid is single valued */ 3868040SBaban.Kenkre@Sun.COM if ((sid = convert_bval2sid(bval, rid)) == NULL) 3878040SBaban.Kenkre@Sun.COM return (NULL); 3888040SBaban.Kenkre@Sun.COM return (sid); 3898040SBaban.Kenkre@Sun.COM } 3908040SBaban.Kenkre@Sun.COM 3918040SBaban.Kenkre@Sun.COM static 3928040SBaban.Kenkre@Sun.COM char * 3938040SBaban.Kenkre@Sun.COM adutils_sid_ber2str(BerValue *bval) 3948040SBaban.Kenkre@Sun.COM { 3958040SBaban.Kenkre@Sun.COM return (adutils_bv_objsid2sidstr(bval, NULL)); 3968040SBaban.Kenkre@Sun.COM } 3978040SBaban.Kenkre@Sun.COM 3988040SBaban.Kenkre@Sun.COM 3998040SBaban.Kenkre@Sun.COM /* Return a NUL-terminated string from the Ber value */ 4008040SBaban.Kenkre@Sun.COM char * 4018040SBaban.Kenkre@Sun.COM adutils_bv_name2str(BerValue *bval) 4028040SBaban.Kenkre@Sun.COM { 4038040SBaban.Kenkre@Sun.COM char *s; 4048040SBaban.Kenkre@Sun.COM 4058040SBaban.Kenkre@Sun.COM if (bval == NULL || bval->bv_val == NULL) 4068040SBaban.Kenkre@Sun.COM return (NULL); 4078040SBaban.Kenkre@Sun.COM if ((s = malloc(bval->bv_len + 1)) == NULL) 4088040SBaban.Kenkre@Sun.COM return (NULL); 4098040SBaban.Kenkre@Sun.COM (void) snprintf(s, bval->bv_len + 1, "%.*s", bval->bv_len, 4108040SBaban.Kenkre@Sun.COM bval->bv_val); 4118040SBaban.Kenkre@Sun.COM return (s); 4128040SBaban.Kenkre@Sun.COM } 4138040SBaban.Kenkre@Sun.COM 4148040SBaban.Kenkre@Sun.COM /*ARGSUSED*/ 4158040SBaban.Kenkre@Sun.COM int 4168040SBaban.Kenkre@Sun.COM saslcallback(LDAP *ld, unsigned flags, void *defaults, void *prompts) 4178040SBaban.Kenkre@Sun.COM { 4188040SBaban.Kenkre@Sun.COM sasl_interact_t *interact; 4198040SBaban.Kenkre@Sun.COM 4208040SBaban.Kenkre@Sun.COM if (prompts == NULL || flags != LDAP_SASL_INTERACTIVE) 4218040SBaban.Kenkre@Sun.COM return (LDAP_PARAM_ERROR); 4228040SBaban.Kenkre@Sun.COM 4238040SBaban.Kenkre@Sun.COM /* There should be no extra arguemnts for SASL/GSSAPI authentication */ 4248040SBaban.Kenkre@Sun.COM for (interact = prompts; interact->id != SASL_CB_LIST_END; 4258040SBaban.Kenkre@Sun.COM interact++) { 4268040SBaban.Kenkre@Sun.COM interact->result = NULL; 4278040SBaban.Kenkre@Sun.COM interact->len = 0; 4288040SBaban.Kenkre@Sun.COM } 4298040SBaban.Kenkre@Sun.COM return (LDAP_SUCCESS); 4308040SBaban.Kenkre@Sun.COM } 4318040SBaban.Kenkre@Sun.COM 4328040SBaban.Kenkre@Sun.COM 4338040SBaban.Kenkre@Sun.COM #define ADCONN_TIME 300 4348040SBaban.Kenkre@Sun.COM 4358040SBaban.Kenkre@Sun.COM /* 4368040SBaban.Kenkre@Sun.COM * Idle connection reaping side of connection management 4378040SBaban.Kenkre@Sun.COM */ 4388040SBaban.Kenkre@Sun.COM void 4398040SBaban.Kenkre@Sun.COM adutils_reap_idle_connections() 4408040SBaban.Kenkre@Sun.COM { 4418040SBaban.Kenkre@Sun.COM adutils_host_t *adh; 4428040SBaban.Kenkre@Sun.COM time_t now; 4438040SBaban.Kenkre@Sun.COM 4448040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&adhostlock); 4458040SBaban.Kenkre@Sun.COM now = time(NULL); 4468040SBaban.Kenkre@Sun.COM for (adh = host_head; adh != NULL; adh = adh->next) { 4478040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&adh->lock); 4488040SBaban.Kenkre@Sun.COM if (adh->ref == 0 && adh->idletime != 0 && 4498040SBaban.Kenkre@Sun.COM adh->idletime + ADCONN_TIME < now) { 4508040SBaban.Kenkre@Sun.COM if (adh->ld) { 4518040SBaban.Kenkre@Sun.COM (void) ldap_unbind(adh->ld); 4528040SBaban.Kenkre@Sun.COM adh->ld = NULL; 4538040SBaban.Kenkre@Sun.COM adh->idletime = 0; 4548040SBaban.Kenkre@Sun.COM adh->ref = 0; 4558040SBaban.Kenkre@Sun.COM } 4568040SBaban.Kenkre@Sun.COM } 4578040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 4588040SBaban.Kenkre@Sun.COM } 4598040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adhostlock); 4608040SBaban.Kenkre@Sun.COM } 4618040SBaban.Kenkre@Sun.COM 4628040SBaban.Kenkre@Sun.COM 4638040SBaban.Kenkre@Sun.COM adutils_rc 4648040SBaban.Kenkre@Sun.COM adutils_ad_alloc(adutils_ad_t **new_ad, const char *default_domain, 4658040SBaban.Kenkre@Sun.COM adutils_ad_partition_t part) 4668040SBaban.Kenkre@Sun.COM { 4678040SBaban.Kenkre@Sun.COM adutils_ad_t *ad; 4688040SBaban.Kenkre@Sun.COM 4698040SBaban.Kenkre@Sun.COM *new_ad = NULL; 4708040SBaban.Kenkre@Sun.COM 4718040SBaban.Kenkre@Sun.COM if ((default_domain == NULL || *default_domain == '\0') && 4728040SBaban.Kenkre@Sun.COM part != ADUTILS_AD_GLOBAL_CATALOG) 4738040SBaban.Kenkre@Sun.COM return (ADUTILS_ERR_DOMAIN); 4748040SBaban.Kenkre@Sun.COM if ((ad = calloc(1, sizeof (*ad))) == NULL) 4758040SBaban.Kenkre@Sun.COM return (ADUTILS_ERR_MEMORY); 4768040SBaban.Kenkre@Sun.COM ad->ref = 1; 4778040SBaban.Kenkre@Sun.COM ad->partition = part; 4788040SBaban.Kenkre@Sun.COM if (default_domain == NULL) 4798040SBaban.Kenkre@Sun.COM default_domain = ""; 4808040SBaban.Kenkre@Sun.COM if ((ad->dflt_w2k_dom = strdup(default_domain)) == NULL) 4818040SBaban.Kenkre@Sun.COM goto err; 4828040SBaban.Kenkre@Sun.COM if (pthread_mutex_init(&ad->lock, NULL) != 0) 4838040SBaban.Kenkre@Sun.COM goto err; 4848040SBaban.Kenkre@Sun.COM *new_ad = ad; 4858040SBaban.Kenkre@Sun.COM return (ADUTILS_SUCCESS); 4868040SBaban.Kenkre@Sun.COM 4878040SBaban.Kenkre@Sun.COM err: 4888040SBaban.Kenkre@Sun.COM if (ad->dflt_w2k_dom != NULL) 4898040SBaban.Kenkre@Sun.COM free(ad->dflt_w2k_dom); 4908040SBaban.Kenkre@Sun.COM free(ad); 4918040SBaban.Kenkre@Sun.COM return (ADUTILS_ERR_MEMORY); 4928040SBaban.Kenkre@Sun.COM } 4938040SBaban.Kenkre@Sun.COM 4948040SBaban.Kenkre@Sun.COM void 4958040SBaban.Kenkre@Sun.COM adutils_ad_free(adutils_ad_t **ad) 4968040SBaban.Kenkre@Sun.COM { 4978040SBaban.Kenkre@Sun.COM adutils_host_t *p; 4988040SBaban.Kenkre@Sun.COM adutils_host_t *prev; 4998040SBaban.Kenkre@Sun.COM 5008040SBaban.Kenkre@Sun.COM if (ad == NULL || *ad == NULL) 5018040SBaban.Kenkre@Sun.COM return; 5028040SBaban.Kenkre@Sun.COM 5038040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&(*ad)->lock); 5048040SBaban.Kenkre@Sun.COM 5058040SBaban.Kenkre@Sun.COM if (atomic_dec_32_nv(&(*ad)->ref) > 0) { 5068040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&(*ad)->lock); 5078040SBaban.Kenkre@Sun.COM *ad = NULL; 5088040SBaban.Kenkre@Sun.COM return; 5098040SBaban.Kenkre@Sun.COM } 5108040SBaban.Kenkre@Sun.COM 5118040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&adhostlock); 5128040SBaban.Kenkre@Sun.COM prev = NULL; 5138040SBaban.Kenkre@Sun.COM p = host_head; 5148040SBaban.Kenkre@Sun.COM while (p != NULL) { 5158040SBaban.Kenkre@Sun.COM if (p->owner != (*ad)) { 5168040SBaban.Kenkre@Sun.COM prev = p; 5178040SBaban.Kenkre@Sun.COM p = p->next; 5188040SBaban.Kenkre@Sun.COM continue; 5198040SBaban.Kenkre@Sun.COM } else { 5208040SBaban.Kenkre@Sun.COM delete_ds((*ad), p->host, p->port); 5218040SBaban.Kenkre@Sun.COM if (prev == NULL) 5228040SBaban.Kenkre@Sun.COM p = host_head; 5238040SBaban.Kenkre@Sun.COM else 5248040SBaban.Kenkre@Sun.COM p = prev->next; 5258040SBaban.Kenkre@Sun.COM } 5268040SBaban.Kenkre@Sun.COM } 5278040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adhostlock); 5288040SBaban.Kenkre@Sun.COM 5298040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&(*ad)->lock); 5308040SBaban.Kenkre@Sun.COM (void) pthread_mutex_destroy(&(*ad)->lock); 5318040SBaban.Kenkre@Sun.COM 5328361SJulian.Pullen@Sun.COM if ((*ad)->known_domains) 5338361SJulian.Pullen@Sun.COM free((*ad)->known_domains); 5348040SBaban.Kenkre@Sun.COM free((*ad)->dflt_w2k_dom); 5358040SBaban.Kenkre@Sun.COM free(*ad); 5368040SBaban.Kenkre@Sun.COM 5378040SBaban.Kenkre@Sun.COM *ad = NULL; 5388040SBaban.Kenkre@Sun.COM } 5398040SBaban.Kenkre@Sun.COM 5408040SBaban.Kenkre@Sun.COM static 5418040SBaban.Kenkre@Sun.COM int 5428040SBaban.Kenkre@Sun.COM open_conn(adutils_host_t *adh, int timeoutsecs) 5438040SBaban.Kenkre@Sun.COM { 5448040SBaban.Kenkre@Sun.COM int zero = 0; 5458040SBaban.Kenkre@Sun.COM int ldversion, rc; 5468040SBaban.Kenkre@Sun.COM int timeoutms = timeoutsecs * 1000; 5478040SBaban.Kenkre@Sun.COM 5488040SBaban.Kenkre@Sun.COM if (adh == NULL) 5498040SBaban.Kenkre@Sun.COM return (0); 5508040SBaban.Kenkre@Sun.COM 5518040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&adh->lock); 5528040SBaban.Kenkre@Sun.COM 5538040SBaban.Kenkre@Sun.COM if (!adh->dead && adh->ld != NULL) 5548040SBaban.Kenkre@Sun.COM /* done! */ 5558040SBaban.Kenkre@Sun.COM goto out; 5568040SBaban.Kenkre@Sun.COM 5578040SBaban.Kenkre@Sun.COM if (adh->ld != NULL) { 5588040SBaban.Kenkre@Sun.COM (void) ldap_unbind(adh->ld); 5598040SBaban.Kenkre@Sun.COM adh->ld = NULL; 5608040SBaban.Kenkre@Sun.COM } 5618040SBaban.Kenkre@Sun.COM adh->num_requests = 0; 5628040SBaban.Kenkre@Sun.COM 5638040SBaban.Kenkre@Sun.COM atomic_inc_64(&adh->generation); 5648040SBaban.Kenkre@Sun.COM 5658040SBaban.Kenkre@Sun.COM /* Open and bind an LDAP connection */ 5668040SBaban.Kenkre@Sun.COM adh->ld = ldap_init(adh->host, adh->port); 5678040SBaban.Kenkre@Sun.COM if (adh->ld == NULL) { 5688671SJulian.Pullen@Sun.COM logger(LOG_INFO, "ldap_init() to server " 5698040SBaban.Kenkre@Sun.COM "%s port %d failed. (%s)", adh->host, 5708040SBaban.Kenkre@Sun.COM adh->port, strerror(errno)); 5718040SBaban.Kenkre@Sun.COM goto out; 5728040SBaban.Kenkre@Sun.COM } 5738040SBaban.Kenkre@Sun.COM ldversion = LDAP_VERSION3; 5748040SBaban.Kenkre@Sun.COM (void) ldap_set_option(adh->ld, LDAP_OPT_PROTOCOL_VERSION, &ldversion); 5758040SBaban.Kenkre@Sun.COM (void) ldap_set_option(adh->ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); 5768040SBaban.Kenkre@Sun.COM (void) ldap_set_option(adh->ld, LDAP_OPT_TIMELIMIT, &zero); 5778040SBaban.Kenkre@Sun.COM (void) ldap_set_option(adh->ld, LDAP_OPT_SIZELIMIT, &zero); 5788040SBaban.Kenkre@Sun.COM (void) ldap_set_option(adh->ld, LDAP_X_OPT_CONNECT_TIMEOUT, &timeoutms); 5798040SBaban.Kenkre@Sun.COM (void) ldap_set_option(adh->ld, LDAP_OPT_RESTART, LDAP_OPT_ON); 5808040SBaban.Kenkre@Sun.COM rc = ldap_sasl_interactive_bind_s(adh->ld, "" /* binddn */, 5818040SBaban.Kenkre@Sun.COM adh->saslmech, NULL, NULL, adh->saslflags, &saslcallback, 5828040SBaban.Kenkre@Sun.COM NULL); 5838040SBaban.Kenkre@Sun.COM 5848040SBaban.Kenkre@Sun.COM if (rc != LDAP_SUCCESS) { 5858040SBaban.Kenkre@Sun.COM (void) ldap_unbind(adh->ld); 5868040SBaban.Kenkre@Sun.COM adh->ld = NULL; 5878671SJulian.Pullen@Sun.COM logger(LOG_INFO, "ldap_sasl_interactive_bind_s() to server " 5888040SBaban.Kenkre@Sun.COM "%s port %d failed. (%s)", adh->host, adh->port, 5898040SBaban.Kenkre@Sun.COM ldap_err2string(rc)); 5908040SBaban.Kenkre@Sun.COM } 5918040SBaban.Kenkre@Sun.COM 5928671SJulian.Pullen@Sun.COM logger(LOG_DEBUG, "Using global catalog server %s:%d", 5938040SBaban.Kenkre@Sun.COM adh->host, adh->port); 5948040SBaban.Kenkre@Sun.COM 5958040SBaban.Kenkre@Sun.COM out: 5968040SBaban.Kenkre@Sun.COM if (adh->ld != NULL) { 5978040SBaban.Kenkre@Sun.COM atomic_inc_32(&adh->ref); 5988040SBaban.Kenkre@Sun.COM adh->idletime = time(NULL); 5998040SBaban.Kenkre@Sun.COM adh->dead = 0; 6008040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 6018040SBaban.Kenkre@Sun.COM return (1); 6028040SBaban.Kenkre@Sun.COM } 6038040SBaban.Kenkre@Sun.COM 6048040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 6058040SBaban.Kenkre@Sun.COM return (0); 6068040SBaban.Kenkre@Sun.COM } 6078040SBaban.Kenkre@Sun.COM 6088040SBaban.Kenkre@Sun.COM 6098040SBaban.Kenkre@Sun.COM /* 6108040SBaban.Kenkre@Sun.COM * Connection management: find an open connection or open one 6118040SBaban.Kenkre@Sun.COM */ 6128040SBaban.Kenkre@Sun.COM static 6138040SBaban.Kenkre@Sun.COM adutils_host_t * 6148040SBaban.Kenkre@Sun.COM get_conn(adutils_ad_t *ad) 6158040SBaban.Kenkre@Sun.COM { 6168040SBaban.Kenkre@Sun.COM adutils_host_t *adh = NULL; 6178040SBaban.Kenkre@Sun.COM int tries; 6188040SBaban.Kenkre@Sun.COM int dscount = 0; 6198040SBaban.Kenkre@Sun.COM int timeoutsecs = ADUTILS_LDAP_OPEN_TIMEOUT; 6208040SBaban.Kenkre@Sun.COM 6218040SBaban.Kenkre@Sun.COM retry: 6228040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&adhostlock); 6238040SBaban.Kenkre@Sun.COM 6248040SBaban.Kenkre@Sun.COM if (host_head == NULL) { 6258040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adhostlock); 6268040SBaban.Kenkre@Sun.COM goto out; 6278040SBaban.Kenkre@Sun.COM } 6288040SBaban.Kenkre@Sun.COM 6298040SBaban.Kenkre@Sun.COM if (dscount == 0) { 6308040SBaban.Kenkre@Sun.COM /* 6318040SBaban.Kenkre@Sun.COM * First try: count the number of DSes. 6328040SBaban.Kenkre@Sun.COM * 6338040SBaban.Kenkre@Sun.COM * Integer overflow is not an issue -- we can't have so many 6348040SBaban.Kenkre@Sun.COM * DSes because they won't fit even DNS over TCP, and SMF 6358040SBaban.Kenkre@Sun.COM * shouldn't let you set so many. 6368040SBaban.Kenkre@Sun.COM */ 6378040SBaban.Kenkre@Sun.COM for (adh = host_head, tries = 0; adh != NULL; adh = adh->next) { 6388040SBaban.Kenkre@Sun.COM if (adh->owner == ad) 6398040SBaban.Kenkre@Sun.COM dscount++; 6408040SBaban.Kenkre@Sun.COM } 6418040SBaban.Kenkre@Sun.COM 6428040SBaban.Kenkre@Sun.COM if (dscount == 0) { 6438040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adhostlock); 6448040SBaban.Kenkre@Sun.COM goto out; 6458040SBaban.Kenkre@Sun.COM } 6468040SBaban.Kenkre@Sun.COM 6478040SBaban.Kenkre@Sun.COM tries = dscount * 3; /* three tries per-ds */ 6488040SBaban.Kenkre@Sun.COM 6498040SBaban.Kenkre@Sun.COM /* 6508040SBaban.Kenkre@Sun.COM * Begin round-robin at the next DS in the list after the last 6518040SBaban.Kenkre@Sun.COM * one that we had a connection to, else start with the first 6528040SBaban.Kenkre@Sun.COM * DS in the list. 6538040SBaban.Kenkre@Sun.COM */ 6548040SBaban.Kenkre@Sun.COM adh = ad->last_adh; 6558040SBaban.Kenkre@Sun.COM } 6568040SBaban.Kenkre@Sun.COM 6578040SBaban.Kenkre@Sun.COM /* 6588040SBaban.Kenkre@Sun.COM * Round-robin -- pick the next one on the list; if the list 6598040SBaban.Kenkre@Sun.COM * changes on us, no big deal, we'll just potentially go 6608040SBaban.Kenkre@Sun.COM * around the wrong number of times. 6618040SBaban.Kenkre@Sun.COM */ 6628040SBaban.Kenkre@Sun.COM for (;;) { 6638361SJulian.Pullen@Sun.COM if (adh != NULL && adh->owner == ad && adh->ld != NULL && 6648361SJulian.Pullen@Sun.COM !adh->dead) 6658040SBaban.Kenkre@Sun.COM break; 6668040SBaban.Kenkre@Sun.COM if (adh == NULL || (adh = adh->next) == NULL) 6678040SBaban.Kenkre@Sun.COM adh = host_head; 6688040SBaban.Kenkre@Sun.COM if (adh->owner == ad) 6698040SBaban.Kenkre@Sun.COM break; 6708040SBaban.Kenkre@Sun.COM } 6718040SBaban.Kenkre@Sun.COM 6728040SBaban.Kenkre@Sun.COM ad->last_adh = adh; 6738040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adhostlock); 6748040SBaban.Kenkre@Sun.COM 6758040SBaban.Kenkre@Sun.COM /* Found suitable DS, open it if not already opened */ 6768040SBaban.Kenkre@Sun.COM if (open_conn(adh, timeoutsecs)) 6778040SBaban.Kenkre@Sun.COM return (adh); 6788040SBaban.Kenkre@Sun.COM 6798040SBaban.Kenkre@Sun.COM tries--; 6808040SBaban.Kenkre@Sun.COM if ((tries % dscount) == 0) 6818040SBaban.Kenkre@Sun.COM timeoutsecs *= 2; 6828040SBaban.Kenkre@Sun.COM if (tries > 0) 6838040SBaban.Kenkre@Sun.COM goto retry; 6848040SBaban.Kenkre@Sun.COM 6858040SBaban.Kenkre@Sun.COM out: 6868671SJulian.Pullen@Sun.COM logger(LOG_NOTICE, "Couldn't open an LDAP connection to any global " 6878040SBaban.Kenkre@Sun.COM "catalog server!"); 6888040SBaban.Kenkre@Sun.COM return (NULL); 6898040SBaban.Kenkre@Sun.COM } 6908040SBaban.Kenkre@Sun.COM 6918040SBaban.Kenkre@Sun.COM static 6928040SBaban.Kenkre@Sun.COM void 6938040SBaban.Kenkre@Sun.COM release_conn(adutils_host_t *adh) 6948040SBaban.Kenkre@Sun.COM { 6958040SBaban.Kenkre@Sun.COM int delete = 0; 6968040SBaban.Kenkre@Sun.COM 6978040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&adh->lock); 6988040SBaban.Kenkre@Sun.COM if (atomic_dec_32_nv(&adh->ref) == 0) { 6998040SBaban.Kenkre@Sun.COM if (adh->owner == NULL) 7008040SBaban.Kenkre@Sun.COM delete = 1; 7018040SBaban.Kenkre@Sun.COM adh->idletime = time(NULL); 7028040SBaban.Kenkre@Sun.COM } 7038040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 7048040SBaban.Kenkre@Sun.COM 7058040SBaban.Kenkre@Sun.COM /* Free this host if its owner no longer exists. */ 7068040SBaban.Kenkre@Sun.COM if (delete) { 7078040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&adhostlock); 7088040SBaban.Kenkre@Sun.COM delete_ds(NULL, adh->host, adh->port); 7098040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adhostlock); 7108040SBaban.Kenkre@Sun.COM } 7118040SBaban.Kenkre@Sun.COM } 7128040SBaban.Kenkre@Sun.COM 7138040SBaban.Kenkre@Sun.COM /* 7148040SBaban.Kenkre@Sun.COM * Create a adutils_host_t, populate it and add it to the list of hosts. 7158040SBaban.Kenkre@Sun.COM */ 7168040SBaban.Kenkre@Sun.COM adutils_rc 7178040SBaban.Kenkre@Sun.COM adutils_add_ds(adutils_ad_t *ad, const char *host, int port) 7188040SBaban.Kenkre@Sun.COM { 7198040SBaban.Kenkre@Sun.COM adutils_host_t *p; 7208040SBaban.Kenkre@Sun.COM adutils_host_t *new = NULL; 7218040SBaban.Kenkre@Sun.COM int ret; 7228040SBaban.Kenkre@Sun.COM adutils_rc rc; 7238040SBaban.Kenkre@Sun.COM 7248040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&adhostlock); 7258040SBaban.Kenkre@Sun.COM for (p = host_head; p != NULL; p = p->next) { 7268040SBaban.Kenkre@Sun.COM if (p->owner != ad) 7278040SBaban.Kenkre@Sun.COM continue; 7288040SBaban.Kenkre@Sun.COM 7298040SBaban.Kenkre@Sun.COM if (strcmp(host, p->host) == 0 && p->port == port) { 7308040SBaban.Kenkre@Sun.COM /* already added */ 7318040SBaban.Kenkre@Sun.COM rc = ADUTILS_SUCCESS; 7328040SBaban.Kenkre@Sun.COM goto err; 7338040SBaban.Kenkre@Sun.COM } 7348040SBaban.Kenkre@Sun.COM } 7358040SBaban.Kenkre@Sun.COM 7368040SBaban.Kenkre@Sun.COM rc = ADUTILS_ERR_MEMORY; 7378040SBaban.Kenkre@Sun.COM 7388040SBaban.Kenkre@Sun.COM /* add new entry */ 7398040SBaban.Kenkre@Sun.COM new = (adutils_host_t *)calloc(1, sizeof (*new)); 7408040SBaban.Kenkre@Sun.COM if (new == NULL) 7418040SBaban.Kenkre@Sun.COM goto err; 7428040SBaban.Kenkre@Sun.COM new->owner = ad; 7438040SBaban.Kenkre@Sun.COM new->port = port; 7448040SBaban.Kenkre@Sun.COM new->dead = 0; 7458040SBaban.Kenkre@Sun.COM new->max_requests = 80; 7468040SBaban.Kenkre@Sun.COM new->num_requests = 0; 7478040SBaban.Kenkre@Sun.COM if ((new->host = strdup(host)) == NULL) 7488040SBaban.Kenkre@Sun.COM goto err; 7498040SBaban.Kenkre@Sun.COM new->saslflags = LDAP_SASL_INTERACTIVE; 7508040SBaban.Kenkre@Sun.COM new->saslmech = "GSSAPI"; 7518040SBaban.Kenkre@Sun.COM 7528040SBaban.Kenkre@Sun.COM if ((ret = pthread_mutex_init(&new->lock, NULL)) != 0) { 7538040SBaban.Kenkre@Sun.COM free(new->host); 7548040SBaban.Kenkre@Sun.COM new->host = NULL; 7558040SBaban.Kenkre@Sun.COM errno = ret; 7568040SBaban.Kenkre@Sun.COM rc = ADUTILS_ERR_INTERNAL; 7578040SBaban.Kenkre@Sun.COM goto err; 7588040SBaban.Kenkre@Sun.COM } 7598040SBaban.Kenkre@Sun.COM 7608040SBaban.Kenkre@Sun.COM /* link in */ 7618040SBaban.Kenkre@Sun.COM rc = ADUTILS_SUCCESS; 7628040SBaban.Kenkre@Sun.COM new->next = host_head; 7638040SBaban.Kenkre@Sun.COM host_head = new; 7648040SBaban.Kenkre@Sun.COM 7658040SBaban.Kenkre@Sun.COM err: 7668040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adhostlock); 7678040SBaban.Kenkre@Sun.COM 7688040SBaban.Kenkre@Sun.COM if (rc != 0 && new != NULL) { 7698040SBaban.Kenkre@Sun.COM if (new->host != NULL) { 7708040SBaban.Kenkre@Sun.COM (void) pthread_mutex_destroy(&new->lock); 7718040SBaban.Kenkre@Sun.COM free(new->host); 7728040SBaban.Kenkre@Sun.COM } 7738040SBaban.Kenkre@Sun.COM free(new); 7748040SBaban.Kenkre@Sun.COM } 7758040SBaban.Kenkre@Sun.COM 7768040SBaban.Kenkre@Sun.COM return (rc); 7778040SBaban.Kenkre@Sun.COM } 7788040SBaban.Kenkre@Sun.COM 7798040SBaban.Kenkre@Sun.COM /* 7808040SBaban.Kenkre@Sun.COM * Free a DS configuration. 7818040SBaban.Kenkre@Sun.COM * Caller must lock the adhostlock mutex 7828040SBaban.Kenkre@Sun.COM */ 7838040SBaban.Kenkre@Sun.COM static 7848040SBaban.Kenkre@Sun.COM void 7858040SBaban.Kenkre@Sun.COM delete_ds(adutils_ad_t *ad, const char *host, int port) 7868040SBaban.Kenkre@Sun.COM { 7878040SBaban.Kenkre@Sun.COM adutils_host_t **p, *q; 7888040SBaban.Kenkre@Sun.COM 7898040SBaban.Kenkre@Sun.COM for (p = &host_head; *p != NULL; p = &((*p)->next)) { 7908040SBaban.Kenkre@Sun.COM if ((*p)->owner != ad || strcmp(host, (*p)->host) != 0 || 7918040SBaban.Kenkre@Sun.COM (*p)->port != port) 7928040SBaban.Kenkre@Sun.COM continue; 7938040SBaban.Kenkre@Sun.COM /* found */ 7948040SBaban.Kenkre@Sun.COM 7958040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&((*p)->lock)); 7968040SBaban.Kenkre@Sun.COM if ((*p)->ref > 0) { 7978040SBaban.Kenkre@Sun.COM /* 7988040SBaban.Kenkre@Sun.COM * Still in use. Set its owner to NULL so 7998040SBaban.Kenkre@Sun.COM * that it can be freed when its ref count 8008040SBaban.Kenkre@Sun.COM * becomes 0. 8018040SBaban.Kenkre@Sun.COM */ 8028040SBaban.Kenkre@Sun.COM (*p)->owner = NULL; 8038040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&((*p)->lock)); 8048040SBaban.Kenkre@Sun.COM break; 8058040SBaban.Kenkre@Sun.COM } 8068040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&((*p)->lock)); 8078040SBaban.Kenkre@Sun.COM 8088040SBaban.Kenkre@Sun.COM q = *p; 8098040SBaban.Kenkre@Sun.COM *p = (*p)->next; 8108040SBaban.Kenkre@Sun.COM 8118040SBaban.Kenkre@Sun.COM (void) pthread_mutex_destroy(&q->lock); 8128040SBaban.Kenkre@Sun.COM 8138040SBaban.Kenkre@Sun.COM if (q->ld) 8148040SBaban.Kenkre@Sun.COM (void) ldap_unbind(q->ld); 8158040SBaban.Kenkre@Sun.COM if (q->host) 8168040SBaban.Kenkre@Sun.COM free(q->host); 8178040SBaban.Kenkre@Sun.COM free(q); 8188040SBaban.Kenkre@Sun.COM break; 8198040SBaban.Kenkre@Sun.COM } 8208040SBaban.Kenkre@Sun.COM 8218040SBaban.Kenkre@Sun.COM } 8228361SJulian.Pullen@Sun.COM /* 8238361SJulian.Pullen@Sun.COM * Add known domain name and domain SID to AD configuration. 8248361SJulian.Pullen@Sun.COM */ 8258361SJulian.Pullen@Sun.COM 8268361SJulian.Pullen@Sun.COM adutils_rc 8278361SJulian.Pullen@Sun.COM adutils_add_domain(adutils_ad_t *ad, const char *domain, const char *sid) 8288361SJulian.Pullen@Sun.COM { 8298361SJulian.Pullen@Sun.COM struct known_domain *new; 8308361SJulian.Pullen@Sun.COM int num = ad->num_known_domains; 8318361SJulian.Pullen@Sun.COM 8328361SJulian.Pullen@Sun.COM ad->num_known_domains++; 8338361SJulian.Pullen@Sun.COM new = realloc(ad->known_domains, 8348361SJulian.Pullen@Sun.COM sizeof (struct known_domain) * ad->num_known_domains); 8358361SJulian.Pullen@Sun.COM if (new != NULL) { 8368361SJulian.Pullen@Sun.COM ad->known_domains = new; 8378361SJulian.Pullen@Sun.COM (void) strlcpy(ad->known_domains[num].name, domain, 8388361SJulian.Pullen@Sun.COM sizeof (ad->known_domains[num].name)); 8398361SJulian.Pullen@Sun.COM (void) strlcpy(ad->known_domains[num].sid, sid, 8408361SJulian.Pullen@Sun.COM sizeof (ad->known_domains[num].sid)); 8418361SJulian.Pullen@Sun.COM return (ADUTILS_SUCCESS); 8428361SJulian.Pullen@Sun.COM } else { 8438361SJulian.Pullen@Sun.COM if (ad->known_domains != NULL) { 8448361SJulian.Pullen@Sun.COM free(ad->known_domains); 8458361SJulian.Pullen@Sun.COM ad->known_domains = NULL; 8468361SJulian.Pullen@Sun.COM } 8478361SJulian.Pullen@Sun.COM ad->num_known_domains = 0; 8488361SJulian.Pullen@Sun.COM return (ADUTILS_ERR_MEMORY); 8498361SJulian.Pullen@Sun.COM } 8508361SJulian.Pullen@Sun.COM } 8518361SJulian.Pullen@Sun.COM 8528361SJulian.Pullen@Sun.COM 8538361SJulian.Pullen@Sun.COM /* 8548361SJulian.Pullen@Sun.COM * Check that this AD supports this domain. 8558361SJulian.Pullen@Sun.COM * If there are no known domains assume that the 8568361SJulian.Pullen@Sun.COM * domain is supported by this AD. 8578361SJulian.Pullen@Sun.COM * 8588361SJulian.Pullen@Sun.COM * Returns 1 if this domain is supported by this AD 8598361SJulian.Pullen@Sun.COM * else returns 0; 8608361SJulian.Pullen@Sun.COM */ 8618361SJulian.Pullen@Sun.COM 8628361SJulian.Pullen@Sun.COM int 8638361SJulian.Pullen@Sun.COM adutils_lookup_check_domain(adutils_query_state_t *qs, const char *domain) 8648361SJulian.Pullen@Sun.COM { 8658361SJulian.Pullen@Sun.COM adutils_ad_t *ad = qs->qadh->owner; 866*10122SJordan.Brown@Sun.COM int i; 8678361SJulian.Pullen@Sun.COM 8688361SJulian.Pullen@Sun.COM for (i = 0; i < ad->num_known_domains; i++) { 869*10122SJordan.Brown@Sun.COM if (domain_eq(domain, ad->known_domains[i].name)) 8708361SJulian.Pullen@Sun.COM return (1); 8718361SJulian.Pullen@Sun.COM } 8728361SJulian.Pullen@Sun.COM 8738361SJulian.Pullen@Sun.COM return ((i == 0) ? 1 : 0); 8748361SJulian.Pullen@Sun.COM } 8758361SJulian.Pullen@Sun.COM 8768361SJulian.Pullen@Sun.COM 8778361SJulian.Pullen@Sun.COM /* 8788361SJulian.Pullen@Sun.COM * Check that this AD supports the SID prefix. 8798361SJulian.Pullen@Sun.COM * The SID prefix should match the domain SID. 8808361SJulian.Pullen@Sun.COM * If there are no known domains assume that the 8818361SJulian.Pullen@Sun.COM * SID prefix is supported by this AD. 8828361SJulian.Pullen@Sun.COM * 8838361SJulian.Pullen@Sun.COM * Returns 1 if this sid prefix is supported by this AD 8848361SJulian.Pullen@Sun.COM * else returns 0; 8858361SJulian.Pullen@Sun.COM */ 8868361SJulian.Pullen@Sun.COM 8878361SJulian.Pullen@Sun.COM int 8888361SJulian.Pullen@Sun.COM adutils_lookup_check_sid_prefix(adutils_query_state_t *qs, const char *sid) 8898361SJulian.Pullen@Sun.COM { 8908361SJulian.Pullen@Sun.COM adutils_ad_t *ad = qs->qadh->owner; 8918361SJulian.Pullen@Sun.COM int i; 8928361SJulian.Pullen@Sun.COM 8938361SJulian.Pullen@Sun.COM 8948361SJulian.Pullen@Sun.COM for (i = 0; i < ad->num_known_domains; i++) { 8958361SJulian.Pullen@Sun.COM if (strcmp(sid, ad->known_domains[i].sid) == 0) 8968361SJulian.Pullen@Sun.COM return (1); 8978361SJulian.Pullen@Sun.COM } 8988361SJulian.Pullen@Sun.COM 8998361SJulian.Pullen@Sun.COM return ((i == 0) ? 1 : 0); 9008361SJulian.Pullen@Sun.COM } 9018361SJulian.Pullen@Sun.COM 9028040SBaban.Kenkre@Sun.COM 9038040SBaban.Kenkre@Sun.COM adutils_rc 9048040SBaban.Kenkre@Sun.COM adutils_lookup_batch_start(adutils_ad_t *ad, int nqueries, 9058040SBaban.Kenkre@Sun.COM adutils_ldap_res_search_cb ldap_res_search_cb, 9068040SBaban.Kenkre@Sun.COM void *ldap_res_search_argp, 9078040SBaban.Kenkre@Sun.COM adutils_query_state_t **state) 9088040SBaban.Kenkre@Sun.COM { 9098040SBaban.Kenkre@Sun.COM adutils_query_state_t *new_state; 9108040SBaban.Kenkre@Sun.COM adutils_host_t *adh = NULL; 9118040SBaban.Kenkre@Sun.COM 9128040SBaban.Kenkre@Sun.COM if (ad == NULL) 9138040SBaban.Kenkre@Sun.COM return (ADUTILS_ERR_INTERNAL); 9148040SBaban.Kenkre@Sun.COM 9158040SBaban.Kenkre@Sun.COM *state = NULL; 9168040SBaban.Kenkre@Sun.COM adh = get_conn(ad); 9178040SBaban.Kenkre@Sun.COM if (adh == NULL) 9188040SBaban.Kenkre@Sun.COM return (ADUTILS_ERR_RETRIABLE_NET_ERR); 9198040SBaban.Kenkre@Sun.COM 9208040SBaban.Kenkre@Sun.COM new_state = calloc(1, sizeof (adutils_query_state_t) + 9218040SBaban.Kenkre@Sun.COM (nqueries - 1) * sizeof (adutils_q_t)); 9228040SBaban.Kenkre@Sun.COM if (new_state == NULL) 9238040SBaban.Kenkre@Sun.COM return (ADUTILS_ERR_MEMORY); 9248040SBaban.Kenkre@Sun.COM 9258040SBaban.Kenkre@Sun.COM /* 9268040SBaban.Kenkre@Sun.COM * Save default domain from the ad object so that we don't 9278040SBaban.Kenkre@Sun.COM * have to access the 'ad' object later. 9288040SBaban.Kenkre@Sun.COM */ 9298040SBaban.Kenkre@Sun.COM new_state->default_domain = strdup(adh->owner->dflt_w2k_dom); 9308040SBaban.Kenkre@Sun.COM if (new_state->default_domain == NULL) { 9318040SBaban.Kenkre@Sun.COM free(new_state); 9328040SBaban.Kenkre@Sun.COM return (ADUTILS_ERR_MEMORY); 9338040SBaban.Kenkre@Sun.COM } 9348040SBaban.Kenkre@Sun.COM 9358040SBaban.Kenkre@Sun.COM if (ad->partition == ADUTILS_AD_DATA) 9368040SBaban.Kenkre@Sun.COM new_state->basedn = adutils_dns2dn(new_state->default_domain); 9378040SBaban.Kenkre@Sun.COM else 9388040SBaban.Kenkre@Sun.COM new_state->basedn = strdup(""); 9398040SBaban.Kenkre@Sun.COM if (new_state->basedn == NULL) { 9408040SBaban.Kenkre@Sun.COM free(new_state->default_domain); 9418040SBaban.Kenkre@Sun.COM free(new_state); 9428040SBaban.Kenkre@Sun.COM return (ADUTILS_ERR_MEMORY); 9438040SBaban.Kenkre@Sun.COM } 9448040SBaban.Kenkre@Sun.COM 9458040SBaban.Kenkre@Sun.COM new_state->ref_cnt = 1; 9468040SBaban.Kenkre@Sun.COM new_state->qadh = adh; 9478361SJulian.Pullen@Sun.COM new_state->qsize = nqueries; 9488040SBaban.Kenkre@Sun.COM new_state->qadh_gen = adh->generation; 9498361SJulian.Pullen@Sun.COM new_state->qcount = 0; 9508040SBaban.Kenkre@Sun.COM new_state->ldap_res_search_cb = ldap_res_search_cb; 9518040SBaban.Kenkre@Sun.COM new_state->ldap_res_search_argp = ldap_res_search_argp; 9528040SBaban.Kenkre@Sun.COM (void) pthread_cond_init(&new_state->cv, NULL); 9538040SBaban.Kenkre@Sun.COM 9548040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&qstatelock); 9558040SBaban.Kenkre@Sun.COM new_state->next = qstatehead; 9568040SBaban.Kenkre@Sun.COM qstatehead = new_state; 9578040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&qstatelock); 9588040SBaban.Kenkre@Sun.COM *state = new_state; 9598040SBaban.Kenkre@Sun.COM 9608040SBaban.Kenkre@Sun.COM return (ADUTILS_SUCCESS); 9618040SBaban.Kenkre@Sun.COM } 9628040SBaban.Kenkre@Sun.COM 9638040SBaban.Kenkre@Sun.COM /* 9648040SBaban.Kenkre@Sun.COM * Find the adutils_query_state_t to which a given LDAP result msgid on a 9658040SBaban.Kenkre@Sun.COM * given connection belongs. This routine increaments the reference count 9668040SBaban.Kenkre@Sun.COM * so that the object can not be freed. adutils_lookup_batch_unlock() 9678040SBaban.Kenkre@Sun.COM * must be called to decreament the reference count. 9688040SBaban.Kenkre@Sun.COM */ 9698040SBaban.Kenkre@Sun.COM static 9708040SBaban.Kenkre@Sun.COM int 9718040SBaban.Kenkre@Sun.COM msgid2query(adutils_host_t *adh, int msgid, 9728040SBaban.Kenkre@Sun.COM adutils_query_state_t **state, int *qid) 9738040SBaban.Kenkre@Sun.COM { 9748040SBaban.Kenkre@Sun.COM adutils_query_state_t *p; 9758040SBaban.Kenkre@Sun.COM int i; 9768040SBaban.Kenkre@Sun.COM int ret; 9778040SBaban.Kenkre@Sun.COM 9788040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&qstatelock); 9798040SBaban.Kenkre@Sun.COM for (p = qstatehead; p != NULL; p = p->next) { 9808040SBaban.Kenkre@Sun.COM if (p->qadh != adh || adh->generation != p->qadh_gen) 9818040SBaban.Kenkre@Sun.COM continue; 9828040SBaban.Kenkre@Sun.COM for (i = 0; i < p->qcount; i++) { 9838040SBaban.Kenkre@Sun.COM if ((p->queries[i]).msgid == msgid) { 9848040SBaban.Kenkre@Sun.COM if (!p->qdead) { 9858040SBaban.Kenkre@Sun.COM p->ref_cnt++; 9868040SBaban.Kenkre@Sun.COM *state = p; 9878040SBaban.Kenkre@Sun.COM *qid = i; 9888040SBaban.Kenkre@Sun.COM ret = 1; 9898040SBaban.Kenkre@Sun.COM } else 9908040SBaban.Kenkre@Sun.COM ret = 0; 9918040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&qstatelock); 9928040SBaban.Kenkre@Sun.COM return (ret); 9938040SBaban.Kenkre@Sun.COM } 9948040SBaban.Kenkre@Sun.COM } 9958040SBaban.Kenkre@Sun.COM } 9968040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&qstatelock); 9978040SBaban.Kenkre@Sun.COM return (0); 9988040SBaban.Kenkre@Sun.COM } 9998040SBaban.Kenkre@Sun.COM 10008040SBaban.Kenkre@Sun.COM static 10018040SBaban.Kenkre@Sun.COM int 10028040SBaban.Kenkre@Sun.COM check_for_binary_attrs(const char *attr) 10038040SBaban.Kenkre@Sun.COM { 10048040SBaban.Kenkre@Sun.COM int i; 10058040SBaban.Kenkre@Sun.COM for (i = 0; binattrs[i].name != NULL; i++) { 10068040SBaban.Kenkre@Sun.COM if (strcasecmp(binattrs[i].name, attr) == 0) 10078040SBaban.Kenkre@Sun.COM return (i); 10088040SBaban.Kenkre@Sun.COM } 10098040SBaban.Kenkre@Sun.COM return (-1); 10108040SBaban.Kenkre@Sun.COM } 10118040SBaban.Kenkre@Sun.COM 10128040SBaban.Kenkre@Sun.COM static 10138040SBaban.Kenkre@Sun.COM void 10148040SBaban.Kenkre@Sun.COM free_entry(adutils_entry_t *entry) 10158040SBaban.Kenkre@Sun.COM { 10168040SBaban.Kenkre@Sun.COM int i, j; 10178040SBaban.Kenkre@Sun.COM adutils_attr_t *ap; 10188040SBaban.Kenkre@Sun.COM 10198040SBaban.Kenkre@Sun.COM if (entry == NULL) 10208040SBaban.Kenkre@Sun.COM return; 10218040SBaban.Kenkre@Sun.COM if (entry->attr_nvpairs == NULL) { 10228040SBaban.Kenkre@Sun.COM free(entry); 10238040SBaban.Kenkre@Sun.COM return; 10248040SBaban.Kenkre@Sun.COM } 10258040SBaban.Kenkre@Sun.COM for (i = 0; i < entry->num_nvpairs; i++) { 10268040SBaban.Kenkre@Sun.COM ap = &entry->attr_nvpairs[i]; 10278040SBaban.Kenkre@Sun.COM if (ap->attr_name == NULL) { 10288040SBaban.Kenkre@Sun.COM ldap_value_free(ap->attr_values); 10298040SBaban.Kenkre@Sun.COM continue; 10308040SBaban.Kenkre@Sun.COM } 10318040SBaban.Kenkre@Sun.COM if (check_for_binary_attrs(ap->attr_name) >= 0) { 10328040SBaban.Kenkre@Sun.COM free(ap->attr_name); 10338040SBaban.Kenkre@Sun.COM if (ap->attr_values == NULL) 10348040SBaban.Kenkre@Sun.COM continue; 10358040SBaban.Kenkre@Sun.COM for (j = 0; j < ap->num_values; j++) 10368040SBaban.Kenkre@Sun.COM free(ap->attr_values[j]); 10378040SBaban.Kenkre@Sun.COM free(ap->attr_values); 10388040SBaban.Kenkre@Sun.COM } else if (strcasecmp(ap->attr_name, "dn") == 0) { 10398040SBaban.Kenkre@Sun.COM free(ap->attr_name); 10408040SBaban.Kenkre@Sun.COM ldap_memfree(ap->attr_values[0]); 10418040SBaban.Kenkre@Sun.COM free(ap->attr_values); 10428040SBaban.Kenkre@Sun.COM } else { 10438040SBaban.Kenkre@Sun.COM free(ap->attr_name); 10448040SBaban.Kenkre@Sun.COM ldap_value_free(ap->attr_values); 10458040SBaban.Kenkre@Sun.COM } 10468040SBaban.Kenkre@Sun.COM } 10478040SBaban.Kenkre@Sun.COM free(entry->attr_nvpairs); 10488040SBaban.Kenkre@Sun.COM free(entry); 10498040SBaban.Kenkre@Sun.COM } 10508040SBaban.Kenkre@Sun.COM 10518040SBaban.Kenkre@Sun.COM void 10528040SBaban.Kenkre@Sun.COM adutils_freeresult(adutils_result_t **result) 10538040SBaban.Kenkre@Sun.COM { 10548040SBaban.Kenkre@Sun.COM adutils_entry_t *e, *next; 10558040SBaban.Kenkre@Sun.COM 10568040SBaban.Kenkre@Sun.COM if (result == NULL || *result == NULL) 10578040SBaban.Kenkre@Sun.COM return; 10588040SBaban.Kenkre@Sun.COM if ((*result)->entries == NULL) { 10598040SBaban.Kenkre@Sun.COM free(*result); 10608040SBaban.Kenkre@Sun.COM *result = NULL; 10618040SBaban.Kenkre@Sun.COM return; 10628040SBaban.Kenkre@Sun.COM } 10638040SBaban.Kenkre@Sun.COM for (e = (*result)->entries; e != NULL; e = next) { 10648040SBaban.Kenkre@Sun.COM next = e->next; 10658040SBaban.Kenkre@Sun.COM free_entry(e); 10668040SBaban.Kenkre@Sun.COM } 10678040SBaban.Kenkre@Sun.COM free(*result); 10688040SBaban.Kenkre@Sun.COM *result = NULL; 10698040SBaban.Kenkre@Sun.COM } 10708040SBaban.Kenkre@Sun.COM 10718040SBaban.Kenkre@Sun.COM const adutils_entry_t * 10728040SBaban.Kenkre@Sun.COM adutils_getfirstentry(adutils_result_t *result) 10738040SBaban.Kenkre@Sun.COM { 10748040SBaban.Kenkre@Sun.COM if (result != NULL) 10758040SBaban.Kenkre@Sun.COM return (result->entries); 10768040SBaban.Kenkre@Sun.COM return (NULL); 10778040SBaban.Kenkre@Sun.COM } 10788040SBaban.Kenkre@Sun.COM 10798040SBaban.Kenkre@Sun.COM 10808040SBaban.Kenkre@Sun.COM char ** 10818040SBaban.Kenkre@Sun.COM adutils_getattr(const adutils_entry_t *entry, const char *attrname) 10828040SBaban.Kenkre@Sun.COM { 10838040SBaban.Kenkre@Sun.COM int i; 10848040SBaban.Kenkre@Sun.COM adutils_attr_t *ap; 10858040SBaban.Kenkre@Sun.COM 10868040SBaban.Kenkre@Sun.COM if (entry == NULL || entry->attr_nvpairs == NULL) 10878040SBaban.Kenkre@Sun.COM return (NULL); 10888040SBaban.Kenkre@Sun.COM for (i = 0; i < entry->num_nvpairs; i++) { 10898040SBaban.Kenkre@Sun.COM ap = &entry->attr_nvpairs[i]; 10908040SBaban.Kenkre@Sun.COM if (ap->attr_name != NULL && 10918040SBaban.Kenkre@Sun.COM strcasecmp(ap->attr_name, attrname) == 0) 10928040SBaban.Kenkre@Sun.COM return (ap->attr_values); 10938040SBaban.Kenkre@Sun.COM } 10948040SBaban.Kenkre@Sun.COM return (NULL); 10958040SBaban.Kenkre@Sun.COM } 10968040SBaban.Kenkre@Sun.COM 10978040SBaban.Kenkre@Sun.COM 10988040SBaban.Kenkre@Sun.COM /* 10998040SBaban.Kenkre@Sun.COM * Queue LDAP result for the given query. 11008040SBaban.Kenkre@Sun.COM * 11018040SBaban.Kenkre@Sun.COM * Return values: 11028040SBaban.Kenkre@Sun.COM * 0 success 11038040SBaban.Kenkre@Sun.COM * -1 ignore result 11048040SBaban.Kenkre@Sun.COM * -2 error 11058040SBaban.Kenkre@Sun.COM */ 11068040SBaban.Kenkre@Sun.COM static 11078040SBaban.Kenkre@Sun.COM int 11088040SBaban.Kenkre@Sun.COM make_entry(adutils_q_t *q, adutils_host_t *adh, LDAPMessage *search_res, 11098040SBaban.Kenkre@Sun.COM adutils_entry_t **entry) 11108040SBaban.Kenkre@Sun.COM { 11118040SBaban.Kenkre@Sun.COM BerElement *ber = NULL; 11128040SBaban.Kenkre@Sun.COM BerValue **bvalues = NULL; 11138040SBaban.Kenkre@Sun.COM char **strvalues; 11148040SBaban.Kenkre@Sun.COM char *attr = NULL, *dn = NULL, *domain = NULL; 11158040SBaban.Kenkre@Sun.COM adutils_entry_t *ep; 11168040SBaban.Kenkre@Sun.COM adutils_attr_t *ap; 1117*10122SJordan.Brown@Sun.COM int i, j, b, ret = -2; 11188040SBaban.Kenkre@Sun.COM 11198040SBaban.Kenkre@Sun.COM *entry = NULL; 11208040SBaban.Kenkre@Sun.COM 11218040SBaban.Kenkre@Sun.COM /* Check that this is the domain that we were looking for */ 11228040SBaban.Kenkre@Sun.COM if ((dn = ldap_get_dn(adh->ld, search_res)) == NULL) 11238040SBaban.Kenkre@Sun.COM return (-2); 11248040SBaban.Kenkre@Sun.COM if ((domain = adutils_dn2dns(dn)) == NULL) { 11258040SBaban.Kenkre@Sun.COM ldap_memfree(dn); 11268040SBaban.Kenkre@Sun.COM return (-2); 11278040SBaban.Kenkre@Sun.COM } 11288040SBaban.Kenkre@Sun.COM if (q->edomain != NULL) { 1129*10122SJordan.Brown@Sun.COM if (!domain_eq(q->edomain, domain)) { 11308040SBaban.Kenkre@Sun.COM ldap_memfree(dn); 11318040SBaban.Kenkre@Sun.COM free(domain); 11328040SBaban.Kenkre@Sun.COM return (-1); 11338040SBaban.Kenkre@Sun.COM } 11348040SBaban.Kenkre@Sun.COM } 11358040SBaban.Kenkre@Sun.COM free(domain); 11368040SBaban.Kenkre@Sun.COM 11378040SBaban.Kenkre@Sun.COM /* Allocate memory for the entry */ 11388040SBaban.Kenkre@Sun.COM if ((ep = calloc(1, sizeof (*ep))) == NULL) 11398040SBaban.Kenkre@Sun.COM goto out; 11408040SBaban.Kenkre@Sun.COM 11418040SBaban.Kenkre@Sun.COM /* For 'dn' */ 11428040SBaban.Kenkre@Sun.COM ep->num_nvpairs = 1; 11438040SBaban.Kenkre@Sun.COM 11448040SBaban.Kenkre@Sun.COM /* Count the number of name-value pairs for this entry */ 11458040SBaban.Kenkre@Sun.COM for (attr = ldap_first_attribute(adh->ld, search_res, &ber); 11468040SBaban.Kenkre@Sun.COM attr != NULL; 11478040SBaban.Kenkre@Sun.COM attr = ldap_next_attribute(adh->ld, search_res, ber)) { 11488040SBaban.Kenkre@Sun.COM ep->num_nvpairs++; 11498040SBaban.Kenkre@Sun.COM ldap_memfree(attr); 11508040SBaban.Kenkre@Sun.COM } 11518040SBaban.Kenkre@Sun.COM ber_free(ber, 0); 11528040SBaban.Kenkre@Sun.COM ber = NULL; 11538040SBaban.Kenkre@Sun.COM 11548040SBaban.Kenkre@Sun.COM /* Allocate array for the attribute name-value pairs */ 11558040SBaban.Kenkre@Sun.COM ep->attr_nvpairs = calloc(ep->num_nvpairs, sizeof (*ep->attr_nvpairs)); 11568040SBaban.Kenkre@Sun.COM if (ep->attr_nvpairs == NULL) { 11578040SBaban.Kenkre@Sun.COM ep->num_nvpairs = 0; 11588040SBaban.Kenkre@Sun.COM goto out; 11598040SBaban.Kenkre@Sun.COM } 11608040SBaban.Kenkre@Sun.COM 11618040SBaban.Kenkre@Sun.COM /* For dn */ 11628040SBaban.Kenkre@Sun.COM ap = &ep->attr_nvpairs[0]; 11638040SBaban.Kenkre@Sun.COM if ((ap->attr_name = strdup("dn")) == NULL) 11648040SBaban.Kenkre@Sun.COM goto out; 11658040SBaban.Kenkre@Sun.COM ap->num_values = 1; 11668040SBaban.Kenkre@Sun.COM ap->attr_values = calloc(ap->num_values, sizeof (*ap->attr_values)); 11678040SBaban.Kenkre@Sun.COM if (ap->attr_values == NULL) { 11688040SBaban.Kenkre@Sun.COM ap->num_values = 0; 11698040SBaban.Kenkre@Sun.COM goto out; 11708040SBaban.Kenkre@Sun.COM } 11718040SBaban.Kenkre@Sun.COM ap->attr_values[0] = dn; 11728040SBaban.Kenkre@Sun.COM dn = NULL; 11738040SBaban.Kenkre@Sun.COM 11748040SBaban.Kenkre@Sun.COM for (attr = ldap_first_attribute(adh->ld, search_res, &ber), i = 1; 11758040SBaban.Kenkre@Sun.COM attr != NULL; 11768040SBaban.Kenkre@Sun.COM ldap_memfree(attr), i++, 11778040SBaban.Kenkre@Sun.COM attr = ldap_next_attribute(adh->ld, search_res, ber)) { 11788040SBaban.Kenkre@Sun.COM ap = &ep->attr_nvpairs[i]; 11798040SBaban.Kenkre@Sun.COM if ((ap->attr_name = strdup(attr)) == NULL) 11808040SBaban.Kenkre@Sun.COM goto out; 11818040SBaban.Kenkre@Sun.COM 11828040SBaban.Kenkre@Sun.COM if ((b = check_for_binary_attrs(attr)) >= 0) { 11838040SBaban.Kenkre@Sun.COM bvalues = 11848040SBaban.Kenkre@Sun.COM ldap_get_values_len(adh->ld, search_res, attr); 11858040SBaban.Kenkre@Sun.COM if (bvalues == NULL) 11868040SBaban.Kenkre@Sun.COM continue; 11878040SBaban.Kenkre@Sun.COM ap->num_values = ldap_count_values_len(bvalues); 11888040SBaban.Kenkre@Sun.COM if (ap->num_values == 0) { 11898040SBaban.Kenkre@Sun.COM ldap_value_free_len(bvalues); 11908040SBaban.Kenkre@Sun.COM bvalues = NULL; 11918040SBaban.Kenkre@Sun.COM continue; 11928040SBaban.Kenkre@Sun.COM } 11938040SBaban.Kenkre@Sun.COM ap->attr_values = calloc(ap->num_values, 11948040SBaban.Kenkre@Sun.COM sizeof (*ap->attr_values)); 11958040SBaban.Kenkre@Sun.COM if (ap->attr_values == NULL) { 11968040SBaban.Kenkre@Sun.COM ap->num_values = 0; 11978040SBaban.Kenkre@Sun.COM goto out; 11988040SBaban.Kenkre@Sun.COM } 11998040SBaban.Kenkre@Sun.COM for (j = 0; j < ap->num_values; j++) { 12008040SBaban.Kenkre@Sun.COM ap->attr_values[j] = 12018040SBaban.Kenkre@Sun.COM binattrs[b].ber2str(bvalues[j]); 12028040SBaban.Kenkre@Sun.COM if (ap->attr_values[j] == NULL) 12038040SBaban.Kenkre@Sun.COM goto out; 12048040SBaban.Kenkre@Sun.COM } 12058040SBaban.Kenkre@Sun.COM ldap_value_free_len(bvalues); 12068040SBaban.Kenkre@Sun.COM bvalues = NULL; 12078040SBaban.Kenkre@Sun.COM continue; 12088040SBaban.Kenkre@Sun.COM } 12098040SBaban.Kenkre@Sun.COM 12108040SBaban.Kenkre@Sun.COM strvalues = ldap_get_values(adh->ld, search_res, attr); 12118040SBaban.Kenkre@Sun.COM if (strvalues == NULL) 12128040SBaban.Kenkre@Sun.COM continue; 12138040SBaban.Kenkre@Sun.COM ap->num_values = ldap_count_values(strvalues); 12148040SBaban.Kenkre@Sun.COM if (ap->num_values == 0) { 12158040SBaban.Kenkre@Sun.COM ldap_value_free(strvalues); 12168040SBaban.Kenkre@Sun.COM continue; 12178040SBaban.Kenkre@Sun.COM } 12188040SBaban.Kenkre@Sun.COM ap->attr_values = strvalues; 12198040SBaban.Kenkre@Sun.COM } 12208040SBaban.Kenkre@Sun.COM 12218040SBaban.Kenkre@Sun.COM ret = 0; 12228040SBaban.Kenkre@Sun.COM out: 12238040SBaban.Kenkre@Sun.COM ldap_memfree(attr); 12248040SBaban.Kenkre@Sun.COM ldap_memfree(dn); 12258040SBaban.Kenkre@Sun.COM ber_free(ber, 0); 12268040SBaban.Kenkre@Sun.COM ldap_value_free_len(bvalues); 12278040SBaban.Kenkre@Sun.COM if (ret < 0) 12288040SBaban.Kenkre@Sun.COM free_entry(ep); 12298040SBaban.Kenkre@Sun.COM else 12308040SBaban.Kenkre@Sun.COM *entry = ep; 12318040SBaban.Kenkre@Sun.COM return (ret); 12328040SBaban.Kenkre@Sun.COM } 12338040SBaban.Kenkre@Sun.COM 12348040SBaban.Kenkre@Sun.COM /* 12358040SBaban.Kenkre@Sun.COM * Put the search result onto the given adutils_q_t. 12368040SBaban.Kenkre@Sun.COM * Returns: 0 success 12378040SBaban.Kenkre@Sun.COM * < 0 error 12388040SBaban.Kenkre@Sun.COM */ 12398040SBaban.Kenkre@Sun.COM static 12408040SBaban.Kenkre@Sun.COM int 12418040SBaban.Kenkre@Sun.COM add_entry(adutils_host_t *adh, adutils_q_t *q, LDAPMessage *search_res) 12428040SBaban.Kenkre@Sun.COM { 12438040SBaban.Kenkre@Sun.COM int ret = -1; 12448040SBaban.Kenkre@Sun.COM adutils_entry_t *entry = NULL; 12458040SBaban.Kenkre@Sun.COM adutils_result_t *res; 12468040SBaban.Kenkre@Sun.COM 12478040SBaban.Kenkre@Sun.COM ret = make_entry(q, adh, search_res, &entry); 12488040SBaban.Kenkre@Sun.COM if (ret < -1) { 12498040SBaban.Kenkre@Sun.COM *q->rc = ADUTILS_ERR_MEMORY; 12508040SBaban.Kenkre@Sun.COM goto out; 12518040SBaban.Kenkre@Sun.COM } else if (ret == -1) { 12528040SBaban.Kenkre@Sun.COM /* ignore result */ 12538040SBaban.Kenkre@Sun.COM goto out; 12548040SBaban.Kenkre@Sun.COM } 12558040SBaban.Kenkre@Sun.COM if (*q->result == NULL) { 12568040SBaban.Kenkre@Sun.COM res = calloc(1, sizeof (*res)); 12578040SBaban.Kenkre@Sun.COM if (res == NULL) { 12588040SBaban.Kenkre@Sun.COM *q->rc = ADUTILS_ERR_MEMORY; 12598040SBaban.Kenkre@Sun.COM goto out; 12608040SBaban.Kenkre@Sun.COM } 12618040SBaban.Kenkre@Sun.COM res->num_entries = 1; 12628040SBaban.Kenkre@Sun.COM res->entries = entry; 12638040SBaban.Kenkre@Sun.COM *q->result = res; 12648040SBaban.Kenkre@Sun.COM } else { 12658040SBaban.Kenkre@Sun.COM res = *q->result; 12668040SBaban.Kenkre@Sun.COM entry->next = res->entries; 12678040SBaban.Kenkre@Sun.COM res->entries = entry; 12688040SBaban.Kenkre@Sun.COM res->num_entries++; 12698040SBaban.Kenkre@Sun.COM } 12708040SBaban.Kenkre@Sun.COM *q->rc = ADUTILS_SUCCESS; 12718040SBaban.Kenkre@Sun.COM entry = NULL; 12728040SBaban.Kenkre@Sun.COM ret = 0; 12738040SBaban.Kenkre@Sun.COM 12748040SBaban.Kenkre@Sun.COM out: 12758040SBaban.Kenkre@Sun.COM free_entry(entry); 12768040SBaban.Kenkre@Sun.COM return (ret); 12778040SBaban.Kenkre@Sun.COM } 12788040SBaban.Kenkre@Sun.COM 12798040SBaban.Kenkre@Sun.COM /* 12808040SBaban.Kenkre@Sun.COM * Try to get a result; if there is one, find the corresponding 12818040SBaban.Kenkre@Sun.COM * adutils_q_t and process the result. 12828040SBaban.Kenkre@Sun.COM * 12838040SBaban.Kenkre@Sun.COM * Returns: 0 success 12848040SBaban.Kenkre@Sun.COM * -1 error 12858040SBaban.Kenkre@Sun.COM */ 12868040SBaban.Kenkre@Sun.COM static 12878040SBaban.Kenkre@Sun.COM int 12888040SBaban.Kenkre@Sun.COM get_adobject_batch(adutils_host_t *adh, struct timeval *timeout) 12898040SBaban.Kenkre@Sun.COM { 12908040SBaban.Kenkre@Sun.COM adutils_query_state_t *query_state; 12918040SBaban.Kenkre@Sun.COM LDAPMessage *res = NULL; 12928040SBaban.Kenkre@Sun.COM int rc, ret, msgid, qid; 12938040SBaban.Kenkre@Sun.COM adutils_q_t *que; 12948040SBaban.Kenkre@Sun.COM int num; 12958040SBaban.Kenkre@Sun.COM 12968040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&adh->lock); 12978040SBaban.Kenkre@Sun.COM if (adh->dead || adh->num_requests == 0) { 12988040SBaban.Kenkre@Sun.COM ret = (adh->dead) ? -1 : -2; 12998040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 13008040SBaban.Kenkre@Sun.COM return (ret); 13018040SBaban.Kenkre@Sun.COM } 13028040SBaban.Kenkre@Sun.COM 13038040SBaban.Kenkre@Sun.COM /* Get one result */ 13048040SBaban.Kenkre@Sun.COM rc = ldap_result(adh->ld, LDAP_RES_ANY, 0, timeout, &res); 13058040SBaban.Kenkre@Sun.COM if ((timeout != NULL && timeout->tv_sec > 0 && rc == LDAP_SUCCESS) || 13068040SBaban.Kenkre@Sun.COM rc < 0) 13078040SBaban.Kenkre@Sun.COM adh->dead = 1; 13088040SBaban.Kenkre@Sun.COM 13098040SBaban.Kenkre@Sun.COM if (rc == LDAP_RES_SEARCH_RESULT && adh->num_requests > 0) 13108040SBaban.Kenkre@Sun.COM adh->num_requests--; 13118040SBaban.Kenkre@Sun.COM if (adh->dead) { 13128040SBaban.Kenkre@Sun.COM num = adh->num_requests; 13138040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 13148671SJulian.Pullen@Sun.COM logger(LOG_DEBUG, 13158040SBaban.Kenkre@Sun.COM "AD ldap_result error - %d queued requests", num); 13168040SBaban.Kenkre@Sun.COM return (-1); 13178040SBaban.Kenkre@Sun.COM } 13188040SBaban.Kenkre@Sun.COM 13198040SBaban.Kenkre@Sun.COM switch (rc) { 13208040SBaban.Kenkre@Sun.COM case LDAP_RES_SEARCH_RESULT: 13218040SBaban.Kenkre@Sun.COM msgid = ldap_msgid(res); 13228040SBaban.Kenkre@Sun.COM if (msgid2query(adh, msgid, &query_state, &qid)) { 13238040SBaban.Kenkre@Sun.COM if (query_state->ldap_res_search_cb != NULL) { 13248040SBaban.Kenkre@Sun.COM /* 13258040SBaban.Kenkre@Sun.COM * We use the caller-provided callback 13268040SBaban.Kenkre@Sun.COM * to process the result. 13278040SBaban.Kenkre@Sun.COM */ 13288040SBaban.Kenkre@Sun.COM query_state->ldap_res_search_cb( 13298040SBaban.Kenkre@Sun.COM adh->ld, &res, rc, qid, 13308040SBaban.Kenkre@Sun.COM query_state->ldap_res_search_argp); 13318040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 13328040SBaban.Kenkre@Sun.COM } else { 13338040SBaban.Kenkre@Sun.COM /* 13348040SBaban.Kenkre@Sun.COM * No callback. We fallback to our 13358040SBaban.Kenkre@Sun.COM * default behaviour. All the entries 13368040SBaban.Kenkre@Sun.COM * gotten from this search have been 13378040SBaban.Kenkre@Sun.COM * added to the result list during 13388040SBaban.Kenkre@Sun.COM * LDAP_RES_SEARCH_ENTRY (see below). 13398040SBaban.Kenkre@Sun.COM * Here we set the return status to 13408040SBaban.Kenkre@Sun.COM * notfound if the result is still empty. 13418040SBaban.Kenkre@Sun.COM */ 13428040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 13438040SBaban.Kenkre@Sun.COM que = &(query_state->queries[qid]); 13448040SBaban.Kenkre@Sun.COM if (*que->result == NULL) 13458040SBaban.Kenkre@Sun.COM *que->rc = ADUTILS_ERR_NOTFOUND; 13468040SBaban.Kenkre@Sun.COM } 13478040SBaban.Kenkre@Sun.COM atomic_dec_32(&query_state->qinflight); 13488040SBaban.Kenkre@Sun.COM adutils_lookup_batch_unlock(&query_state); 13498040SBaban.Kenkre@Sun.COM } else { 13508040SBaban.Kenkre@Sun.COM num = adh->num_requests; 13518040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 13528671SJulian.Pullen@Sun.COM logger(LOG_DEBUG, 13538040SBaban.Kenkre@Sun.COM "AD cannot find message ID (%d) " 13548040SBaban.Kenkre@Sun.COM "- %d queued requests", 13558040SBaban.Kenkre@Sun.COM msgid, num); 13568040SBaban.Kenkre@Sun.COM } 13578040SBaban.Kenkre@Sun.COM (void) ldap_msgfree(res); 13588040SBaban.Kenkre@Sun.COM ret = 0; 13598040SBaban.Kenkre@Sun.COM break; 13608040SBaban.Kenkre@Sun.COM 13618040SBaban.Kenkre@Sun.COM case LDAP_RES_SEARCH_ENTRY: 13628040SBaban.Kenkre@Sun.COM msgid = ldap_msgid(res); 13638040SBaban.Kenkre@Sun.COM if (msgid2query(adh, msgid, &query_state, &qid)) { 13648040SBaban.Kenkre@Sun.COM if (query_state->ldap_res_search_cb != NULL) { 13658040SBaban.Kenkre@Sun.COM /* 13668040SBaban.Kenkre@Sun.COM * We use the caller-provided callback 13678040SBaban.Kenkre@Sun.COM * to process the entry. 13688040SBaban.Kenkre@Sun.COM */ 13698040SBaban.Kenkre@Sun.COM query_state->ldap_res_search_cb( 13708040SBaban.Kenkre@Sun.COM adh->ld, &res, rc, qid, 13718040SBaban.Kenkre@Sun.COM query_state->ldap_res_search_argp); 13728040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 13738040SBaban.Kenkre@Sun.COM } else { 13748040SBaban.Kenkre@Sun.COM /* 13758040SBaban.Kenkre@Sun.COM * No callback. We fallback to our 13768040SBaban.Kenkre@Sun.COM * default behaviour. This entry 13778040SBaban.Kenkre@Sun.COM * will be added to the result list. 13788040SBaban.Kenkre@Sun.COM */ 13798040SBaban.Kenkre@Sun.COM que = &(query_state->queries[qid]); 13808040SBaban.Kenkre@Sun.COM rc = add_entry(adh, que, res); 13818040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 13828040SBaban.Kenkre@Sun.COM if (rc < 0) { 13838671SJulian.Pullen@Sun.COM logger(LOG_DEBUG, 13848040SBaban.Kenkre@Sun.COM "Failed to queue entry by " 13858040SBaban.Kenkre@Sun.COM "message ID (%d) " 13868040SBaban.Kenkre@Sun.COM "- %d queued requests", 13878040SBaban.Kenkre@Sun.COM msgid, num); 13888040SBaban.Kenkre@Sun.COM } 13898040SBaban.Kenkre@Sun.COM } 13908040SBaban.Kenkre@Sun.COM adutils_lookup_batch_unlock(&query_state); 13918040SBaban.Kenkre@Sun.COM } else { 13928040SBaban.Kenkre@Sun.COM num = adh->num_requests; 13938040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 13948671SJulian.Pullen@Sun.COM logger(LOG_DEBUG, 13958040SBaban.Kenkre@Sun.COM "AD cannot find message ID (%d) " 13968040SBaban.Kenkre@Sun.COM "- %d queued requests", 13978040SBaban.Kenkre@Sun.COM msgid, num); 13988040SBaban.Kenkre@Sun.COM } 13998040SBaban.Kenkre@Sun.COM (void) ldap_msgfree(res); 14008040SBaban.Kenkre@Sun.COM ret = 0; 14018040SBaban.Kenkre@Sun.COM break; 14028040SBaban.Kenkre@Sun.COM 14038040SBaban.Kenkre@Sun.COM case LDAP_RES_SEARCH_REFERENCE: 14048040SBaban.Kenkre@Sun.COM /* 14058040SBaban.Kenkre@Sun.COM * We have no need for these at the moment. Eventually, 14068040SBaban.Kenkre@Sun.COM * when we query things that we can't expect to find in 14078040SBaban.Kenkre@Sun.COM * the Global Catalog then we'll need to learn to follow 14088040SBaban.Kenkre@Sun.COM * references. 14098040SBaban.Kenkre@Sun.COM */ 14108040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 14118040SBaban.Kenkre@Sun.COM (void) ldap_msgfree(res); 14128040SBaban.Kenkre@Sun.COM ret = 0; 14138040SBaban.Kenkre@Sun.COM break; 14148040SBaban.Kenkre@Sun.COM 14158040SBaban.Kenkre@Sun.COM default: 14168040SBaban.Kenkre@Sun.COM /* timeout or error; treat the same */ 14178040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 14188040SBaban.Kenkre@Sun.COM ret = -1; 14198040SBaban.Kenkre@Sun.COM break; 14208040SBaban.Kenkre@Sun.COM } 14218040SBaban.Kenkre@Sun.COM 14228040SBaban.Kenkre@Sun.COM return (ret); 14238040SBaban.Kenkre@Sun.COM } 14248040SBaban.Kenkre@Sun.COM 14258040SBaban.Kenkre@Sun.COM /* 14268040SBaban.Kenkre@Sun.COM * This routine decreament the reference count of the 14278040SBaban.Kenkre@Sun.COM * adutils_query_state_t 14288040SBaban.Kenkre@Sun.COM */ 14298040SBaban.Kenkre@Sun.COM static void 14308040SBaban.Kenkre@Sun.COM adutils_lookup_batch_unlock(adutils_query_state_t **state) 14318040SBaban.Kenkre@Sun.COM { 14328040SBaban.Kenkre@Sun.COM /* 14338040SBaban.Kenkre@Sun.COM * Decrement reference count with qstatelock locked 14348040SBaban.Kenkre@Sun.COM */ 14358040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&qstatelock); 14368040SBaban.Kenkre@Sun.COM (*state)->ref_cnt--; 14378040SBaban.Kenkre@Sun.COM /* 14388040SBaban.Kenkre@Sun.COM * If there are no references wakup the allocating thread 14398040SBaban.Kenkre@Sun.COM */ 14408040SBaban.Kenkre@Sun.COM if ((*state)->ref_cnt <= 1) 14418040SBaban.Kenkre@Sun.COM (void) pthread_cond_signal(&(*state)->cv); 14428040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&qstatelock); 14438040SBaban.Kenkre@Sun.COM *state = NULL; 14448040SBaban.Kenkre@Sun.COM } 14458040SBaban.Kenkre@Sun.COM 14468040SBaban.Kenkre@Sun.COM /* 14478040SBaban.Kenkre@Sun.COM * This routine frees the adutils_query_state_t structure 14488040SBaban.Kenkre@Sun.COM * If the reference count is greater than 1 it waits 14498040SBaban.Kenkre@Sun.COM * for the other threads to finish using it. 14508040SBaban.Kenkre@Sun.COM */ 14518040SBaban.Kenkre@Sun.COM void 14528040SBaban.Kenkre@Sun.COM adutils_lookup_batch_release(adutils_query_state_t **state) 14538040SBaban.Kenkre@Sun.COM { 14548040SBaban.Kenkre@Sun.COM adutils_query_state_t **p; 14558040SBaban.Kenkre@Sun.COM int i; 14568040SBaban.Kenkre@Sun.COM 14578040SBaban.Kenkre@Sun.COM if (state == NULL || *state == NULL) 14588040SBaban.Kenkre@Sun.COM return; 14598040SBaban.Kenkre@Sun.COM 14608040SBaban.Kenkre@Sun.COM /* 14618040SBaban.Kenkre@Sun.COM * Set state to dead to stop further operations. 14628040SBaban.Kenkre@Sun.COM * Wait for reference count with qstatelock locked 14638040SBaban.Kenkre@Sun.COM * to get to one. 14648040SBaban.Kenkre@Sun.COM */ 14658040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&qstatelock); 14668040SBaban.Kenkre@Sun.COM (*state)->qdead = 1; 14678040SBaban.Kenkre@Sun.COM while ((*state)->ref_cnt > 1) { 14688040SBaban.Kenkre@Sun.COM (void) pthread_cond_wait(&(*state)->cv, &qstatelock); 14698040SBaban.Kenkre@Sun.COM } 14708040SBaban.Kenkre@Sun.COM 14718040SBaban.Kenkre@Sun.COM /* Remove this state struct from the list of state structs */ 14728040SBaban.Kenkre@Sun.COM for (p = &qstatehead; *p != NULL; p = &(*p)->next) { 14738040SBaban.Kenkre@Sun.COM if (*p == (*state)) { 14748040SBaban.Kenkre@Sun.COM *p = (*state)->next; 14758040SBaban.Kenkre@Sun.COM break; 14768040SBaban.Kenkre@Sun.COM } 14778040SBaban.Kenkre@Sun.COM } 14788040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&qstatelock); 14798040SBaban.Kenkre@Sun.COM (void) pthread_cond_destroy(&(*state)->cv); 14808040SBaban.Kenkre@Sun.COM release_conn((*state)->qadh); 14818040SBaban.Kenkre@Sun.COM 14828040SBaban.Kenkre@Sun.COM /* Clear results for queries that failed */ 14838040SBaban.Kenkre@Sun.COM for (i = 0; i < (*state)->qcount; i++) { 14848040SBaban.Kenkre@Sun.COM if (*(*state)->queries[i].rc != ADUTILS_SUCCESS) { 14858040SBaban.Kenkre@Sun.COM adutils_freeresult((*state)->queries[i].result); 14868040SBaban.Kenkre@Sun.COM } 14878040SBaban.Kenkre@Sun.COM } 14888040SBaban.Kenkre@Sun.COM free((*state)->default_domain); 14898040SBaban.Kenkre@Sun.COM free((*state)->basedn); 14908040SBaban.Kenkre@Sun.COM free(*state); 14918040SBaban.Kenkre@Sun.COM *state = NULL; 14928040SBaban.Kenkre@Sun.COM } 14938040SBaban.Kenkre@Sun.COM 14948040SBaban.Kenkre@Sun.COM 14958040SBaban.Kenkre@Sun.COM /* 14968040SBaban.Kenkre@Sun.COM * This routine waits for other threads using the 14978040SBaban.Kenkre@Sun.COM * adutils_query_state_t structure to finish. 14988040SBaban.Kenkre@Sun.COM * If the reference count is greater than 1 it waits 14998040SBaban.Kenkre@Sun.COM * for the other threads to finish using it. 15008040SBaban.Kenkre@Sun.COM */ 15018040SBaban.Kenkre@Sun.COM static 15028040SBaban.Kenkre@Sun.COM void 15038040SBaban.Kenkre@Sun.COM adutils_lookup_batch_wait(adutils_query_state_t *state) 15048040SBaban.Kenkre@Sun.COM { 15058040SBaban.Kenkre@Sun.COM /* 15068040SBaban.Kenkre@Sun.COM * Set state to dead to stop further operation. 15078040SBaban.Kenkre@Sun.COM * stating. 15088040SBaban.Kenkre@Sun.COM * Wait for reference count to get to one 15098040SBaban.Kenkre@Sun.COM * with qstatelock locked. 15108040SBaban.Kenkre@Sun.COM */ 15118040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&qstatelock); 15128040SBaban.Kenkre@Sun.COM state->qdead = 1; 15138040SBaban.Kenkre@Sun.COM while (state->ref_cnt > 1) { 15148040SBaban.Kenkre@Sun.COM (void) pthread_cond_wait(&state->cv, &qstatelock); 15158040SBaban.Kenkre@Sun.COM } 15168040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&qstatelock); 15178040SBaban.Kenkre@Sun.COM } 15188040SBaban.Kenkre@Sun.COM 15198040SBaban.Kenkre@Sun.COM /* 15208040SBaban.Kenkre@Sun.COM * Process active queries in the AD lookup batch and then finalize the 15218040SBaban.Kenkre@Sun.COM * result. 15228040SBaban.Kenkre@Sun.COM */ 15238040SBaban.Kenkre@Sun.COM adutils_rc 15248040SBaban.Kenkre@Sun.COM adutils_lookup_batch_end(adutils_query_state_t **state) 15258040SBaban.Kenkre@Sun.COM { 15268040SBaban.Kenkre@Sun.COM int rc = LDAP_SUCCESS; 15278040SBaban.Kenkre@Sun.COM adutils_rc ad_rc = ADUTILS_SUCCESS; 15288040SBaban.Kenkre@Sun.COM struct timeval tv; 15298040SBaban.Kenkre@Sun.COM 15308040SBaban.Kenkre@Sun.COM tv.tv_sec = ADUTILS_SEARCH_TIMEOUT; 15318040SBaban.Kenkre@Sun.COM tv.tv_usec = 0; 15328040SBaban.Kenkre@Sun.COM 15338040SBaban.Kenkre@Sun.COM /* Process results until done or until timeout, if given */ 15348040SBaban.Kenkre@Sun.COM while ((*state)->qinflight > 0) { 15358040SBaban.Kenkre@Sun.COM if ((rc = get_adobject_batch((*state)->qadh, 15368040SBaban.Kenkre@Sun.COM &tv)) != 0) 15378040SBaban.Kenkre@Sun.COM break; 15388040SBaban.Kenkre@Sun.COM } 15398040SBaban.Kenkre@Sun.COM (*state)->qdead = 1; 15408040SBaban.Kenkre@Sun.COM /* Wait for other threads processing search result to finish */ 15418040SBaban.Kenkre@Sun.COM adutils_lookup_batch_wait(*state); 15428040SBaban.Kenkre@Sun.COM if (rc == -1 || (*state)->qinflight != 0) 15438040SBaban.Kenkre@Sun.COM ad_rc = ADUTILS_ERR_RETRIABLE_NET_ERR; 15448040SBaban.Kenkre@Sun.COM adutils_lookup_batch_release(state); 15458040SBaban.Kenkre@Sun.COM return (ad_rc); 15468040SBaban.Kenkre@Sun.COM } 15478040SBaban.Kenkre@Sun.COM 15488040SBaban.Kenkre@Sun.COM const char * 15498040SBaban.Kenkre@Sun.COM adutils_lookup_batch_getdefdomain(adutils_query_state_t *state) 15508040SBaban.Kenkre@Sun.COM { 15518040SBaban.Kenkre@Sun.COM return (state->default_domain); 15528040SBaban.Kenkre@Sun.COM } 15538040SBaban.Kenkre@Sun.COM 15548040SBaban.Kenkre@Sun.COM /* 15558040SBaban.Kenkre@Sun.COM * Send one prepared search, queue up msgid, process what results are 15568040SBaban.Kenkre@Sun.COM * available 15578040SBaban.Kenkre@Sun.COM */ 15588040SBaban.Kenkre@Sun.COM adutils_rc 15598040SBaban.Kenkre@Sun.COM adutils_lookup_batch_add(adutils_query_state_t *state, 1560*10122SJordan.Brown@Sun.COM const char *filter, const char * const *attrs, const char *edomain, 15618040SBaban.Kenkre@Sun.COM adutils_result_t **result, adutils_rc *rc) 15628040SBaban.Kenkre@Sun.COM { 15638040SBaban.Kenkre@Sun.COM adutils_rc retcode = ADUTILS_SUCCESS; 15648040SBaban.Kenkre@Sun.COM int lrc, qid; 15658040SBaban.Kenkre@Sun.COM int num; 15668040SBaban.Kenkre@Sun.COM int dead; 15678040SBaban.Kenkre@Sun.COM struct timeval tv; 15688040SBaban.Kenkre@Sun.COM adutils_q_t *q; 15698040SBaban.Kenkre@Sun.COM 15708361SJulian.Pullen@Sun.COM qid = atomic_inc_32_nv(&state->qcount) - 1; 15718040SBaban.Kenkre@Sun.COM q = &(state->queries[qid]); 15728040SBaban.Kenkre@Sun.COM 15738361SJulian.Pullen@Sun.COM assert(qid < state->qsize); 15748361SJulian.Pullen@Sun.COM 15758040SBaban.Kenkre@Sun.COM /* 15768040SBaban.Kenkre@Sun.COM * Remember the expected domain so we can check the results 15778040SBaban.Kenkre@Sun.COM * against it 15788040SBaban.Kenkre@Sun.COM */ 15798040SBaban.Kenkre@Sun.COM q->edomain = edomain; 15808040SBaban.Kenkre@Sun.COM 15818040SBaban.Kenkre@Sun.COM /* Remember where to put the results */ 15828040SBaban.Kenkre@Sun.COM q->result = result; 15838040SBaban.Kenkre@Sun.COM q->rc = rc; 15848040SBaban.Kenkre@Sun.COM 15858040SBaban.Kenkre@Sun.COM /* 15868040SBaban.Kenkre@Sun.COM * Provide sane defaults for the results in case we never hear 15878040SBaban.Kenkre@Sun.COM * back from the DS before closing the connection. 15888040SBaban.Kenkre@Sun.COM */ 15898040SBaban.Kenkre@Sun.COM *rc = ADUTILS_ERR_RETRIABLE_NET_ERR; 15908040SBaban.Kenkre@Sun.COM if (result != NULL) 15918040SBaban.Kenkre@Sun.COM *result = NULL; 15928040SBaban.Kenkre@Sun.COM 15938040SBaban.Kenkre@Sun.COM /* Check the number of queued requests first */ 15948040SBaban.Kenkre@Sun.COM tv.tv_sec = ADUTILS_SEARCH_TIMEOUT; 15958040SBaban.Kenkre@Sun.COM tv.tv_usec = 0; 15968040SBaban.Kenkre@Sun.COM while (!state->qadh->dead && 15978040SBaban.Kenkre@Sun.COM state->qadh->num_requests > state->qadh->max_requests) { 15988040SBaban.Kenkre@Sun.COM if (get_adobject_batch(state->qadh, &tv) != 0) 15998040SBaban.Kenkre@Sun.COM break; 16008040SBaban.Kenkre@Sun.COM } 16018040SBaban.Kenkre@Sun.COM 16028040SBaban.Kenkre@Sun.COM /* Send this lookup, don't wait for a result here */ 16038040SBaban.Kenkre@Sun.COM lrc = LDAP_SUCCESS; 16048040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&state->qadh->lock); 16058040SBaban.Kenkre@Sun.COM 16068040SBaban.Kenkre@Sun.COM if (!state->qadh->dead) { 16078040SBaban.Kenkre@Sun.COM state->qadh->idletime = time(NULL); 16088040SBaban.Kenkre@Sun.COM lrc = ldap_search_ext(state->qadh->ld, state->basedn, 16098040SBaban.Kenkre@Sun.COM LDAP_SCOPE_SUBTREE, filter, (char **)attrs, 16108040SBaban.Kenkre@Sun.COM 0, NULL, NULL, NULL, -1, &q->msgid); 16118040SBaban.Kenkre@Sun.COM 16128040SBaban.Kenkre@Sun.COM if (lrc == LDAP_SUCCESS) { 16138040SBaban.Kenkre@Sun.COM state->qadh->num_requests++; 16148040SBaban.Kenkre@Sun.COM } else if (lrc == LDAP_BUSY || lrc == LDAP_UNAVAILABLE || 16158040SBaban.Kenkre@Sun.COM lrc == LDAP_CONNECT_ERROR || lrc == LDAP_SERVER_DOWN || 16168040SBaban.Kenkre@Sun.COM lrc == LDAP_UNWILLING_TO_PERFORM) { 16178040SBaban.Kenkre@Sun.COM retcode = ADUTILS_ERR_RETRIABLE_NET_ERR; 16188040SBaban.Kenkre@Sun.COM state->qadh->dead = 1; 16198040SBaban.Kenkre@Sun.COM } else { 16208040SBaban.Kenkre@Sun.COM retcode = ADUTILS_ERR_OTHER; 16218040SBaban.Kenkre@Sun.COM state->qadh->dead = 1; 16228040SBaban.Kenkre@Sun.COM } 16238040SBaban.Kenkre@Sun.COM } 16248040SBaban.Kenkre@Sun.COM dead = state->qadh->dead; 16258040SBaban.Kenkre@Sun.COM num = state->qadh->num_requests; 16268040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&state->qadh->lock); 16278040SBaban.Kenkre@Sun.COM 16288040SBaban.Kenkre@Sun.COM if (dead) { 16298040SBaban.Kenkre@Sun.COM if (lrc != LDAP_SUCCESS) 16308671SJulian.Pullen@Sun.COM logger(LOG_DEBUG, 16318040SBaban.Kenkre@Sun.COM "AD ldap_search_ext error (%s) " 16328040SBaban.Kenkre@Sun.COM "- %d queued requests", 16338040SBaban.Kenkre@Sun.COM ldap_err2string(lrc), num); 16348040SBaban.Kenkre@Sun.COM return (retcode); 16358040SBaban.Kenkre@Sun.COM } 16368040SBaban.Kenkre@Sun.COM 16378040SBaban.Kenkre@Sun.COM atomic_inc_32(&state->qinflight); 16388040SBaban.Kenkre@Sun.COM 16398040SBaban.Kenkre@Sun.COM /* 16408040SBaban.Kenkre@Sun.COM * Reap as many requests as we can _without_ waiting to prevent 16418040SBaban.Kenkre@Sun.COM * any possible TCP socket buffer starvation deadlocks. 16428040SBaban.Kenkre@Sun.COM */ 16438040SBaban.Kenkre@Sun.COM (void) memset(&tv, 0, sizeof (tv)); 16448040SBaban.Kenkre@Sun.COM while (get_adobject_batch(state->qadh, &tv) == 0) 16458040SBaban.Kenkre@Sun.COM ; 16468040SBaban.Kenkre@Sun.COM 16478040SBaban.Kenkre@Sun.COM return (ADUTILS_SUCCESS); 16488040SBaban.Kenkre@Sun.COM } 16498040SBaban.Kenkre@Sun.COM 16508040SBaban.Kenkre@Sun.COM /* 16518040SBaban.Kenkre@Sun.COM * Single AD lookup request implemented on top of the batch API. 16528040SBaban.Kenkre@Sun.COM */ 16538040SBaban.Kenkre@Sun.COM adutils_rc 16548040SBaban.Kenkre@Sun.COM adutils_lookup(adutils_ad_t *ad, const char *filter, const char **attrs, 16558040SBaban.Kenkre@Sun.COM const char *domain, adutils_result_t **result) 16568040SBaban.Kenkre@Sun.COM { 16578040SBaban.Kenkre@Sun.COM adutils_rc rc, brc; 16588040SBaban.Kenkre@Sun.COM adutils_query_state_t *qs; 16598040SBaban.Kenkre@Sun.COM 16608040SBaban.Kenkre@Sun.COM rc = adutils_lookup_batch_start(ad, 1, NULL, NULL, &qs); 16618040SBaban.Kenkre@Sun.COM if (rc != ADUTILS_SUCCESS) 16628040SBaban.Kenkre@Sun.COM return (rc); 16638040SBaban.Kenkre@Sun.COM 16648040SBaban.Kenkre@Sun.COM rc = adutils_lookup_batch_add(qs, filter, attrs, domain, result, &brc); 16658040SBaban.Kenkre@Sun.COM if (rc != ADUTILS_SUCCESS) { 16668040SBaban.Kenkre@Sun.COM adutils_lookup_batch_release(&qs); 16678040SBaban.Kenkre@Sun.COM return (rc); 16688040SBaban.Kenkre@Sun.COM } 16698040SBaban.Kenkre@Sun.COM 16708040SBaban.Kenkre@Sun.COM rc = adutils_lookup_batch_end(&qs); 16718040SBaban.Kenkre@Sun.COM if (rc != ADUTILS_SUCCESS) 16728040SBaban.Kenkre@Sun.COM return (rc); 16738040SBaban.Kenkre@Sun.COM return (brc); 16748040SBaban.Kenkre@Sun.COM } 1675*10122SJordan.Brown@Sun.COM 1676*10122SJordan.Brown@Sun.COM boolean_t 1677*10122SJordan.Brown@Sun.COM domain_eq(const char *a, const char *b) 1678*10122SJordan.Brown@Sun.COM { 1679*10122SJordan.Brown@Sun.COM int err; 1680*10122SJordan.Brown@Sun.COM 1681*10122SJordan.Brown@Sun.COM return (u8_strcmp(a, b, 0, U8_STRCMP_CI_LOWER, U8_UNICODE_LATEST, &err) 1682*10122SJordan.Brown@Sun.COM == 0 && err == 0); 1683*10122SJordan.Brown@Sun.COM } 1684