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 399*10504SKeyur.Desai@Sun.COM /* 400*10504SKeyur.Desai@Sun.COM * Extract an int from the Ber value 401*10504SKeyur.Desai@Sun.COM * Return B_TRUE if a valid integer was found, B_FALSE if not. 402*10504SKeyur.Desai@Sun.COM */ 403*10504SKeyur.Desai@Sun.COM boolean_t 404*10504SKeyur.Desai@Sun.COM adutils_bv_uint(BerValue *bval, unsigned int *result) 405*10504SKeyur.Desai@Sun.COM { 406*10504SKeyur.Desai@Sun.COM char buf[40]; /* big enough for any int */ 407*10504SKeyur.Desai@Sun.COM unsigned int tmp; 408*10504SKeyur.Desai@Sun.COM char *p; 409*10504SKeyur.Desai@Sun.COM 410*10504SKeyur.Desai@Sun.COM *result = 0; /* for error cases */ 411*10504SKeyur.Desai@Sun.COM 412*10504SKeyur.Desai@Sun.COM if (bval == NULL || bval->bv_val == NULL) 413*10504SKeyur.Desai@Sun.COM return (B_FALSE); 414*10504SKeyur.Desai@Sun.COM if (bval->bv_len >= sizeof (buf)) 415*10504SKeyur.Desai@Sun.COM return (B_FALSE); 416*10504SKeyur.Desai@Sun.COM 417*10504SKeyur.Desai@Sun.COM (void) memcpy(buf, bval->bv_val, bval->bv_len); 418*10504SKeyur.Desai@Sun.COM buf[bval->bv_len] = '\0'; 419*10504SKeyur.Desai@Sun.COM 420*10504SKeyur.Desai@Sun.COM tmp = strtoul(buf, &p, 10); 421*10504SKeyur.Desai@Sun.COM 422*10504SKeyur.Desai@Sun.COM /* Junk after the number? */ 423*10504SKeyur.Desai@Sun.COM if (*p != '\0') 424*10504SKeyur.Desai@Sun.COM return (B_FALSE); 425*10504SKeyur.Desai@Sun.COM 426*10504SKeyur.Desai@Sun.COM *result = tmp; 427*10504SKeyur.Desai@Sun.COM 428*10504SKeyur.Desai@Sun.COM return (B_TRUE); 429*10504SKeyur.Desai@Sun.COM } 430*10504SKeyur.Desai@Sun.COM 4318040SBaban.Kenkre@Sun.COM /* Return a NUL-terminated string from the Ber value */ 4328040SBaban.Kenkre@Sun.COM char * 433*10504SKeyur.Desai@Sun.COM adutils_bv_str(BerValue *bval) 4348040SBaban.Kenkre@Sun.COM { 4358040SBaban.Kenkre@Sun.COM char *s; 4368040SBaban.Kenkre@Sun.COM 4378040SBaban.Kenkre@Sun.COM if (bval == NULL || bval->bv_val == NULL) 4388040SBaban.Kenkre@Sun.COM return (NULL); 4398040SBaban.Kenkre@Sun.COM if ((s = malloc(bval->bv_len + 1)) == NULL) 4408040SBaban.Kenkre@Sun.COM return (NULL); 4418040SBaban.Kenkre@Sun.COM (void) snprintf(s, bval->bv_len + 1, "%.*s", bval->bv_len, 4428040SBaban.Kenkre@Sun.COM bval->bv_val); 4438040SBaban.Kenkre@Sun.COM return (s); 4448040SBaban.Kenkre@Sun.COM } 4458040SBaban.Kenkre@Sun.COM 4468040SBaban.Kenkre@Sun.COM /*ARGSUSED*/ 4478040SBaban.Kenkre@Sun.COM int 4488040SBaban.Kenkre@Sun.COM saslcallback(LDAP *ld, unsigned flags, void *defaults, void *prompts) 4498040SBaban.Kenkre@Sun.COM { 4508040SBaban.Kenkre@Sun.COM sasl_interact_t *interact; 4518040SBaban.Kenkre@Sun.COM 4528040SBaban.Kenkre@Sun.COM if (prompts == NULL || flags != LDAP_SASL_INTERACTIVE) 4538040SBaban.Kenkre@Sun.COM return (LDAP_PARAM_ERROR); 4548040SBaban.Kenkre@Sun.COM 4558040SBaban.Kenkre@Sun.COM /* There should be no extra arguemnts for SASL/GSSAPI authentication */ 4568040SBaban.Kenkre@Sun.COM for (interact = prompts; interact->id != SASL_CB_LIST_END; 4578040SBaban.Kenkre@Sun.COM interact++) { 4588040SBaban.Kenkre@Sun.COM interact->result = NULL; 4598040SBaban.Kenkre@Sun.COM interact->len = 0; 4608040SBaban.Kenkre@Sun.COM } 4618040SBaban.Kenkre@Sun.COM return (LDAP_SUCCESS); 4628040SBaban.Kenkre@Sun.COM } 4638040SBaban.Kenkre@Sun.COM 4648040SBaban.Kenkre@Sun.COM 4658040SBaban.Kenkre@Sun.COM #define ADCONN_TIME 300 4668040SBaban.Kenkre@Sun.COM 4678040SBaban.Kenkre@Sun.COM /* 4688040SBaban.Kenkre@Sun.COM * Idle connection reaping side of connection management 4698040SBaban.Kenkre@Sun.COM */ 4708040SBaban.Kenkre@Sun.COM void 4718040SBaban.Kenkre@Sun.COM adutils_reap_idle_connections() 4728040SBaban.Kenkre@Sun.COM { 4738040SBaban.Kenkre@Sun.COM adutils_host_t *adh; 4748040SBaban.Kenkre@Sun.COM time_t now; 4758040SBaban.Kenkre@Sun.COM 4768040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&adhostlock); 4778040SBaban.Kenkre@Sun.COM now = time(NULL); 4788040SBaban.Kenkre@Sun.COM for (adh = host_head; adh != NULL; adh = adh->next) { 4798040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&adh->lock); 4808040SBaban.Kenkre@Sun.COM if (adh->ref == 0 && adh->idletime != 0 && 4818040SBaban.Kenkre@Sun.COM adh->idletime + ADCONN_TIME < now) { 4828040SBaban.Kenkre@Sun.COM if (adh->ld) { 4838040SBaban.Kenkre@Sun.COM (void) ldap_unbind(adh->ld); 4848040SBaban.Kenkre@Sun.COM adh->ld = NULL; 4858040SBaban.Kenkre@Sun.COM adh->idletime = 0; 4868040SBaban.Kenkre@Sun.COM adh->ref = 0; 4878040SBaban.Kenkre@Sun.COM } 4888040SBaban.Kenkre@Sun.COM } 4898040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 4908040SBaban.Kenkre@Sun.COM } 4918040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adhostlock); 4928040SBaban.Kenkre@Sun.COM } 4938040SBaban.Kenkre@Sun.COM 4948040SBaban.Kenkre@Sun.COM 4958040SBaban.Kenkre@Sun.COM adutils_rc 496*10504SKeyur.Desai@Sun.COM adutils_ad_alloc(adutils_ad_t **new_ad, const char *domain_name, 4978040SBaban.Kenkre@Sun.COM adutils_ad_partition_t part) 4988040SBaban.Kenkre@Sun.COM { 4998040SBaban.Kenkre@Sun.COM adutils_ad_t *ad; 5008040SBaban.Kenkre@Sun.COM 5018040SBaban.Kenkre@Sun.COM *new_ad = NULL; 5028040SBaban.Kenkre@Sun.COM 5038040SBaban.Kenkre@Sun.COM if ((ad = calloc(1, sizeof (*ad))) == NULL) 5048040SBaban.Kenkre@Sun.COM return (ADUTILS_ERR_MEMORY); 5058040SBaban.Kenkre@Sun.COM ad->ref = 1; 5068040SBaban.Kenkre@Sun.COM ad->partition = part; 507*10504SKeyur.Desai@Sun.COM 508*10504SKeyur.Desai@Sun.COM /* domain_name is required iff we are talking directly to a DC */ 509*10504SKeyur.Desai@Sun.COM if (part == ADUTILS_AD_DATA) { 510*10504SKeyur.Desai@Sun.COM assert(domain_name != NULL); 511*10504SKeyur.Desai@Sun.COM assert(*domain_name != '\0'); 512*10504SKeyur.Desai@Sun.COM 513*10504SKeyur.Desai@Sun.COM ad->basedn = adutils_dns2dn(domain_name); 514*10504SKeyur.Desai@Sun.COM } else { 515*10504SKeyur.Desai@Sun.COM assert(domain_name == NULL); 516*10504SKeyur.Desai@Sun.COM ad->basedn = strdup(""); 517*10504SKeyur.Desai@Sun.COM } 518*10504SKeyur.Desai@Sun.COM if (ad->basedn == NULL) 5198040SBaban.Kenkre@Sun.COM goto err; 520*10504SKeyur.Desai@Sun.COM 5218040SBaban.Kenkre@Sun.COM if (pthread_mutex_init(&ad->lock, NULL) != 0) 5228040SBaban.Kenkre@Sun.COM goto err; 5238040SBaban.Kenkre@Sun.COM *new_ad = ad; 5248040SBaban.Kenkre@Sun.COM return (ADUTILS_SUCCESS); 5258040SBaban.Kenkre@Sun.COM 5268040SBaban.Kenkre@Sun.COM err: 527*10504SKeyur.Desai@Sun.COM free(ad->basedn); 5288040SBaban.Kenkre@Sun.COM free(ad); 5298040SBaban.Kenkre@Sun.COM return (ADUTILS_ERR_MEMORY); 5308040SBaban.Kenkre@Sun.COM } 5318040SBaban.Kenkre@Sun.COM 5328040SBaban.Kenkre@Sun.COM void 5338040SBaban.Kenkre@Sun.COM adutils_ad_free(adutils_ad_t **ad) 5348040SBaban.Kenkre@Sun.COM { 5358040SBaban.Kenkre@Sun.COM adutils_host_t *p; 5368040SBaban.Kenkre@Sun.COM adutils_host_t *prev; 5378040SBaban.Kenkre@Sun.COM 5388040SBaban.Kenkre@Sun.COM if (ad == NULL || *ad == NULL) 5398040SBaban.Kenkre@Sun.COM return; 5408040SBaban.Kenkre@Sun.COM 5418040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&(*ad)->lock); 5428040SBaban.Kenkre@Sun.COM 5438040SBaban.Kenkre@Sun.COM if (atomic_dec_32_nv(&(*ad)->ref) > 0) { 5448040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&(*ad)->lock); 5458040SBaban.Kenkre@Sun.COM *ad = NULL; 5468040SBaban.Kenkre@Sun.COM return; 5478040SBaban.Kenkre@Sun.COM } 5488040SBaban.Kenkre@Sun.COM 5498040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&adhostlock); 5508040SBaban.Kenkre@Sun.COM prev = NULL; 5518040SBaban.Kenkre@Sun.COM p = host_head; 5528040SBaban.Kenkre@Sun.COM while (p != NULL) { 5538040SBaban.Kenkre@Sun.COM if (p->owner != (*ad)) { 5548040SBaban.Kenkre@Sun.COM prev = p; 5558040SBaban.Kenkre@Sun.COM p = p->next; 5568040SBaban.Kenkre@Sun.COM continue; 5578040SBaban.Kenkre@Sun.COM } else { 5588040SBaban.Kenkre@Sun.COM delete_ds((*ad), p->host, p->port); 5598040SBaban.Kenkre@Sun.COM if (prev == NULL) 5608040SBaban.Kenkre@Sun.COM p = host_head; 5618040SBaban.Kenkre@Sun.COM else 5628040SBaban.Kenkre@Sun.COM p = prev->next; 5638040SBaban.Kenkre@Sun.COM } 5648040SBaban.Kenkre@Sun.COM } 5658040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adhostlock); 5668040SBaban.Kenkre@Sun.COM 5678040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&(*ad)->lock); 5688040SBaban.Kenkre@Sun.COM (void) pthread_mutex_destroy(&(*ad)->lock); 5698040SBaban.Kenkre@Sun.COM 5708361SJulian.Pullen@Sun.COM if ((*ad)->known_domains) 5718361SJulian.Pullen@Sun.COM free((*ad)->known_domains); 572*10504SKeyur.Desai@Sun.COM free((*ad)->basedn); 5738040SBaban.Kenkre@Sun.COM free(*ad); 5748040SBaban.Kenkre@Sun.COM 5758040SBaban.Kenkre@Sun.COM *ad = NULL; 5768040SBaban.Kenkre@Sun.COM } 5778040SBaban.Kenkre@Sun.COM 5788040SBaban.Kenkre@Sun.COM static 5798040SBaban.Kenkre@Sun.COM int 5808040SBaban.Kenkre@Sun.COM open_conn(adutils_host_t *adh, int timeoutsecs) 5818040SBaban.Kenkre@Sun.COM { 5828040SBaban.Kenkre@Sun.COM int zero = 0; 5838040SBaban.Kenkre@Sun.COM int ldversion, rc; 5848040SBaban.Kenkre@Sun.COM int timeoutms = timeoutsecs * 1000; 5858040SBaban.Kenkre@Sun.COM 5868040SBaban.Kenkre@Sun.COM if (adh == NULL) 5878040SBaban.Kenkre@Sun.COM return (0); 5888040SBaban.Kenkre@Sun.COM 5898040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&adh->lock); 5908040SBaban.Kenkre@Sun.COM 5918040SBaban.Kenkre@Sun.COM if (!adh->dead && adh->ld != NULL) 5928040SBaban.Kenkre@Sun.COM /* done! */ 5938040SBaban.Kenkre@Sun.COM goto out; 5948040SBaban.Kenkre@Sun.COM 5958040SBaban.Kenkre@Sun.COM if (adh->ld != NULL) { 5968040SBaban.Kenkre@Sun.COM (void) ldap_unbind(adh->ld); 5978040SBaban.Kenkre@Sun.COM adh->ld = NULL; 5988040SBaban.Kenkre@Sun.COM } 5998040SBaban.Kenkre@Sun.COM adh->num_requests = 0; 6008040SBaban.Kenkre@Sun.COM 6018040SBaban.Kenkre@Sun.COM atomic_inc_64(&adh->generation); 6028040SBaban.Kenkre@Sun.COM 6038040SBaban.Kenkre@Sun.COM /* Open and bind an LDAP connection */ 6048040SBaban.Kenkre@Sun.COM adh->ld = ldap_init(adh->host, adh->port); 6058040SBaban.Kenkre@Sun.COM if (adh->ld == NULL) { 6068671SJulian.Pullen@Sun.COM logger(LOG_INFO, "ldap_init() to server " 6078040SBaban.Kenkre@Sun.COM "%s port %d failed. (%s)", adh->host, 6088040SBaban.Kenkre@Sun.COM adh->port, strerror(errno)); 6098040SBaban.Kenkre@Sun.COM goto out; 6108040SBaban.Kenkre@Sun.COM } 6118040SBaban.Kenkre@Sun.COM ldversion = LDAP_VERSION3; 6128040SBaban.Kenkre@Sun.COM (void) ldap_set_option(adh->ld, LDAP_OPT_PROTOCOL_VERSION, &ldversion); 6138040SBaban.Kenkre@Sun.COM (void) ldap_set_option(adh->ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); 6148040SBaban.Kenkre@Sun.COM (void) ldap_set_option(adh->ld, LDAP_OPT_TIMELIMIT, &zero); 6158040SBaban.Kenkre@Sun.COM (void) ldap_set_option(adh->ld, LDAP_OPT_SIZELIMIT, &zero); 6168040SBaban.Kenkre@Sun.COM (void) ldap_set_option(adh->ld, LDAP_X_OPT_CONNECT_TIMEOUT, &timeoutms); 6178040SBaban.Kenkre@Sun.COM (void) ldap_set_option(adh->ld, LDAP_OPT_RESTART, LDAP_OPT_ON); 6188040SBaban.Kenkre@Sun.COM rc = ldap_sasl_interactive_bind_s(adh->ld, "" /* binddn */, 6198040SBaban.Kenkre@Sun.COM adh->saslmech, NULL, NULL, adh->saslflags, &saslcallback, 6208040SBaban.Kenkre@Sun.COM NULL); 6218040SBaban.Kenkre@Sun.COM 6228040SBaban.Kenkre@Sun.COM if (rc != LDAP_SUCCESS) { 6238040SBaban.Kenkre@Sun.COM (void) ldap_unbind(adh->ld); 6248040SBaban.Kenkre@Sun.COM adh->ld = NULL; 6258671SJulian.Pullen@Sun.COM logger(LOG_INFO, "ldap_sasl_interactive_bind_s() to server " 6268040SBaban.Kenkre@Sun.COM "%s port %d failed. (%s)", adh->host, adh->port, 6278040SBaban.Kenkre@Sun.COM ldap_err2string(rc)); 628*10504SKeyur.Desai@Sun.COM goto out; 6298040SBaban.Kenkre@Sun.COM } 6308040SBaban.Kenkre@Sun.COM 631*10504SKeyur.Desai@Sun.COM logger(LOG_DEBUG, "Using server %s:%d", 6328040SBaban.Kenkre@Sun.COM adh->host, adh->port); 6338040SBaban.Kenkre@Sun.COM 6348040SBaban.Kenkre@Sun.COM out: 6358040SBaban.Kenkre@Sun.COM if (adh->ld != NULL) { 6368040SBaban.Kenkre@Sun.COM atomic_inc_32(&adh->ref); 6378040SBaban.Kenkre@Sun.COM adh->idletime = time(NULL); 6388040SBaban.Kenkre@Sun.COM adh->dead = 0; 6398040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 6408040SBaban.Kenkre@Sun.COM return (1); 6418040SBaban.Kenkre@Sun.COM } 6428040SBaban.Kenkre@Sun.COM 6438040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 6448040SBaban.Kenkre@Sun.COM return (0); 6458040SBaban.Kenkre@Sun.COM } 6468040SBaban.Kenkre@Sun.COM 6478040SBaban.Kenkre@Sun.COM 6488040SBaban.Kenkre@Sun.COM /* 6498040SBaban.Kenkre@Sun.COM * Connection management: find an open connection or open one 6508040SBaban.Kenkre@Sun.COM */ 6518040SBaban.Kenkre@Sun.COM static 6528040SBaban.Kenkre@Sun.COM adutils_host_t * 6538040SBaban.Kenkre@Sun.COM get_conn(adutils_ad_t *ad) 6548040SBaban.Kenkre@Sun.COM { 6558040SBaban.Kenkre@Sun.COM adutils_host_t *adh = NULL; 6568040SBaban.Kenkre@Sun.COM int tries; 6578040SBaban.Kenkre@Sun.COM int dscount = 0; 6588040SBaban.Kenkre@Sun.COM int timeoutsecs = ADUTILS_LDAP_OPEN_TIMEOUT; 6598040SBaban.Kenkre@Sun.COM 6608040SBaban.Kenkre@Sun.COM retry: 6618040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&adhostlock); 6628040SBaban.Kenkre@Sun.COM 6638040SBaban.Kenkre@Sun.COM if (host_head == NULL) { 6648040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adhostlock); 6658040SBaban.Kenkre@Sun.COM goto out; 6668040SBaban.Kenkre@Sun.COM } 6678040SBaban.Kenkre@Sun.COM 6688040SBaban.Kenkre@Sun.COM if (dscount == 0) { 6698040SBaban.Kenkre@Sun.COM /* 6708040SBaban.Kenkre@Sun.COM * First try: count the number of DSes. 6718040SBaban.Kenkre@Sun.COM * 6728040SBaban.Kenkre@Sun.COM * Integer overflow is not an issue -- we can't have so many 6738040SBaban.Kenkre@Sun.COM * DSes because they won't fit even DNS over TCP, and SMF 6748040SBaban.Kenkre@Sun.COM * shouldn't let you set so many. 6758040SBaban.Kenkre@Sun.COM */ 6768040SBaban.Kenkre@Sun.COM for (adh = host_head, tries = 0; adh != NULL; adh = adh->next) { 6778040SBaban.Kenkre@Sun.COM if (adh->owner == ad) 6788040SBaban.Kenkre@Sun.COM dscount++; 6798040SBaban.Kenkre@Sun.COM } 6808040SBaban.Kenkre@Sun.COM 6818040SBaban.Kenkre@Sun.COM if (dscount == 0) { 6828040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adhostlock); 6838040SBaban.Kenkre@Sun.COM goto out; 6848040SBaban.Kenkre@Sun.COM } 6858040SBaban.Kenkre@Sun.COM 6868040SBaban.Kenkre@Sun.COM tries = dscount * 3; /* three tries per-ds */ 6878040SBaban.Kenkre@Sun.COM 6888040SBaban.Kenkre@Sun.COM /* 6898040SBaban.Kenkre@Sun.COM * Begin round-robin at the next DS in the list after the last 6908040SBaban.Kenkre@Sun.COM * one that we had a connection to, else start with the first 6918040SBaban.Kenkre@Sun.COM * DS in the list. 6928040SBaban.Kenkre@Sun.COM */ 6938040SBaban.Kenkre@Sun.COM adh = ad->last_adh; 6948040SBaban.Kenkre@Sun.COM } 6958040SBaban.Kenkre@Sun.COM 6968040SBaban.Kenkre@Sun.COM /* 6978040SBaban.Kenkre@Sun.COM * Round-robin -- pick the next one on the list; if the list 6988040SBaban.Kenkre@Sun.COM * changes on us, no big deal, we'll just potentially go 6998040SBaban.Kenkre@Sun.COM * around the wrong number of times. 7008040SBaban.Kenkre@Sun.COM */ 7018040SBaban.Kenkre@Sun.COM for (;;) { 7028361SJulian.Pullen@Sun.COM if (adh != NULL && adh->owner == ad && adh->ld != NULL && 7038361SJulian.Pullen@Sun.COM !adh->dead) 7048040SBaban.Kenkre@Sun.COM break; 7058040SBaban.Kenkre@Sun.COM if (adh == NULL || (adh = adh->next) == NULL) 7068040SBaban.Kenkre@Sun.COM adh = host_head; 7078040SBaban.Kenkre@Sun.COM if (adh->owner == ad) 7088040SBaban.Kenkre@Sun.COM break; 7098040SBaban.Kenkre@Sun.COM } 7108040SBaban.Kenkre@Sun.COM 7118040SBaban.Kenkre@Sun.COM ad->last_adh = adh; 7128040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adhostlock); 7138040SBaban.Kenkre@Sun.COM 7148040SBaban.Kenkre@Sun.COM /* Found suitable DS, open it if not already opened */ 7158040SBaban.Kenkre@Sun.COM if (open_conn(adh, timeoutsecs)) 7168040SBaban.Kenkre@Sun.COM return (adh); 7178040SBaban.Kenkre@Sun.COM 7188040SBaban.Kenkre@Sun.COM tries--; 7198040SBaban.Kenkre@Sun.COM if ((tries % dscount) == 0) 7208040SBaban.Kenkre@Sun.COM timeoutsecs *= 2; 7218040SBaban.Kenkre@Sun.COM if (tries > 0) 7228040SBaban.Kenkre@Sun.COM goto retry; 7238040SBaban.Kenkre@Sun.COM 7248040SBaban.Kenkre@Sun.COM out: 7258671SJulian.Pullen@Sun.COM logger(LOG_NOTICE, "Couldn't open an LDAP connection to any global " 7268040SBaban.Kenkre@Sun.COM "catalog server!"); 7278040SBaban.Kenkre@Sun.COM return (NULL); 7288040SBaban.Kenkre@Sun.COM } 7298040SBaban.Kenkre@Sun.COM 7308040SBaban.Kenkre@Sun.COM static 7318040SBaban.Kenkre@Sun.COM void 7328040SBaban.Kenkre@Sun.COM release_conn(adutils_host_t *adh) 7338040SBaban.Kenkre@Sun.COM { 7348040SBaban.Kenkre@Sun.COM int delete = 0; 7358040SBaban.Kenkre@Sun.COM 7368040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&adh->lock); 7378040SBaban.Kenkre@Sun.COM if (atomic_dec_32_nv(&adh->ref) == 0) { 7388040SBaban.Kenkre@Sun.COM if (adh->owner == NULL) 7398040SBaban.Kenkre@Sun.COM delete = 1; 7408040SBaban.Kenkre@Sun.COM adh->idletime = time(NULL); 7418040SBaban.Kenkre@Sun.COM } 7428040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 7438040SBaban.Kenkre@Sun.COM 7448040SBaban.Kenkre@Sun.COM /* Free this host if its owner no longer exists. */ 7458040SBaban.Kenkre@Sun.COM if (delete) { 7468040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&adhostlock); 7478040SBaban.Kenkre@Sun.COM delete_ds(NULL, adh->host, adh->port); 7488040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adhostlock); 7498040SBaban.Kenkre@Sun.COM } 7508040SBaban.Kenkre@Sun.COM } 7518040SBaban.Kenkre@Sun.COM 7528040SBaban.Kenkre@Sun.COM /* 7538040SBaban.Kenkre@Sun.COM * Create a adutils_host_t, populate it and add it to the list of hosts. 7548040SBaban.Kenkre@Sun.COM */ 7558040SBaban.Kenkre@Sun.COM adutils_rc 7568040SBaban.Kenkre@Sun.COM adutils_add_ds(adutils_ad_t *ad, const char *host, int port) 7578040SBaban.Kenkre@Sun.COM { 7588040SBaban.Kenkre@Sun.COM adutils_host_t *p; 7598040SBaban.Kenkre@Sun.COM adutils_host_t *new = NULL; 7608040SBaban.Kenkre@Sun.COM int ret; 7618040SBaban.Kenkre@Sun.COM adutils_rc rc; 7628040SBaban.Kenkre@Sun.COM 7638040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&adhostlock); 7648040SBaban.Kenkre@Sun.COM for (p = host_head; p != NULL; p = p->next) { 7658040SBaban.Kenkre@Sun.COM if (p->owner != ad) 7668040SBaban.Kenkre@Sun.COM continue; 7678040SBaban.Kenkre@Sun.COM 7688040SBaban.Kenkre@Sun.COM if (strcmp(host, p->host) == 0 && p->port == port) { 7698040SBaban.Kenkre@Sun.COM /* already added */ 7708040SBaban.Kenkre@Sun.COM rc = ADUTILS_SUCCESS; 7718040SBaban.Kenkre@Sun.COM goto err; 7728040SBaban.Kenkre@Sun.COM } 7738040SBaban.Kenkre@Sun.COM } 7748040SBaban.Kenkre@Sun.COM 7758040SBaban.Kenkre@Sun.COM rc = ADUTILS_ERR_MEMORY; 7768040SBaban.Kenkre@Sun.COM 7778040SBaban.Kenkre@Sun.COM /* add new entry */ 7788040SBaban.Kenkre@Sun.COM new = (adutils_host_t *)calloc(1, sizeof (*new)); 7798040SBaban.Kenkre@Sun.COM if (new == NULL) 7808040SBaban.Kenkre@Sun.COM goto err; 7818040SBaban.Kenkre@Sun.COM new->owner = ad; 7828040SBaban.Kenkre@Sun.COM new->port = port; 7838040SBaban.Kenkre@Sun.COM new->dead = 0; 7848040SBaban.Kenkre@Sun.COM new->max_requests = 80; 7858040SBaban.Kenkre@Sun.COM new->num_requests = 0; 7868040SBaban.Kenkre@Sun.COM if ((new->host = strdup(host)) == NULL) 7878040SBaban.Kenkre@Sun.COM goto err; 7888040SBaban.Kenkre@Sun.COM new->saslflags = LDAP_SASL_INTERACTIVE; 7898040SBaban.Kenkre@Sun.COM new->saslmech = "GSSAPI"; 7908040SBaban.Kenkre@Sun.COM 7918040SBaban.Kenkre@Sun.COM if ((ret = pthread_mutex_init(&new->lock, NULL)) != 0) { 7928040SBaban.Kenkre@Sun.COM free(new->host); 7938040SBaban.Kenkre@Sun.COM new->host = NULL; 7948040SBaban.Kenkre@Sun.COM errno = ret; 7958040SBaban.Kenkre@Sun.COM rc = ADUTILS_ERR_INTERNAL; 7968040SBaban.Kenkre@Sun.COM goto err; 7978040SBaban.Kenkre@Sun.COM } 7988040SBaban.Kenkre@Sun.COM 7998040SBaban.Kenkre@Sun.COM /* link in */ 8008040SBaban.Kenkre@Sun.COM rc = ADUTILS_SUCCESS; 8018040SBaban.Kenkre@Sun.COM new->next = host_head; 8028040SBaban.Kenkre@Sun.COM host_head = new; 8038040SBaban.Kenkre@Sun.COM 8048040SBaban.Kenkre@Sun.COM err: 8058040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adhostlock); 8068040SBaban.Kenkre@Sun.COM 8078040SBaban.Kenkre@Sun.COM if (rc != 0 && new != NULL) { 8088040SBaban.Kenkre@Sun.COM if (new->host != NULL) { 8098040SBaban.Kenkre@Sun.COM (void) pthread_mutex_destroy(&new->lock); 8108040SBaban.Kenkre@Sun.COM free(new->host); 8118040SBaban.Kenkre@Sun.COM } 8128040SBaban.Kenkre@Sun.COM free(new); 8138040SBaban.Kenkre@Sun.COM } 8148040SBaban.Kenkre@Sun.COM 8158040SBaban.Kenkre@Sun.COM return (rc); 8168040SBaban.Kenkre@Sun.COM } 8178040SBaban.Kenkre@Sun.COM 8188040SBaban.Kenkre@Sun.COM /* 8198040SBaban.Kenkre@Sun.COM * Free a DS configuration. 8208040SBaban.Kenkre@Sun.COM * Caller must lock the adhostlock mutex 8218040SBaban.Kenkre@Sun.COM */ 8228040SBaban.Kenkre@Sun.COM static 8238040SBaban.Kenkre@Sun.COM void 8248040SBaban.Kenkre@Sun.COM delete_ds(adutils_ad_t *ad, const char *host, int port) 8258040SBaban.Kenkre@Sun.COM { 8268040SBaban.Kenkre@Sun.COM adutils_host_t **p, *q; 8278040SBaban.Kenkre@Sun.COM 8288040SBaban.Kenkre@Sun.COM for (p = &host_head; *p != NULL; p = &((*p)->next)) { 8298040SBaban.Kenkre@Sun.COM if ((*p)->owner != ad || strcmp(host, (*p)->host) != 0 || 8308040SBaban.Kenkre@Sun.COM (*p)->port != port) 8318040SBaban.Kenkre@Sun.COM continue; 8328040SBaban.Kenkre@Sun.COM /* found */ 8338040SBaban.Kenkre@Sun.COM 8348040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&((*p)->lock)); 8358040SBaban.Kenkre@Sun.COM if ((*p)->ref > 0) { 8368040SBaban.Kenkre@Sun.COM /* 8378040SBaban.Kenkre@Sun.COM * Still in use. Set its owner to NULL so 8388040SBaban.Kenkre@Sun.COM * that it can be freed when its ref count 8398040SBaban.Kenkre@Sun.COM * becomes 0. 8408040SBaban.Kenkre@Sun.COM */ 8418040SBaban.Kenkre@Sun.COM (*p)->owner = NULL; 8428040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&((*p)->lock)); 8438040SBaban.Kenkre@Sun.COM break; 8448040SBaban.Kenkre@Sun.COM } 8458040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&((*p)->lock)); 8468040SBaban.Kenkre@Sun.COM 8478040SBaban.Kenkre@Sun.COM q = *p; 8488040SBaban.Kenkre@Sun.COM *p = (*p)->next; 8498040SBaban.Kenkre@Sun.COM 8508040SBaban.Kenkre@Sun.COM (void) pthread_mutex_destroy(&q->lock); 8518040SBaban.Kenkre@Sun.COM 8528040SBaban.Kenkre@Sun.COM if (q->ld) 8538040SBaban.Kenkre@Sun.COM (void) ldap_unbind(q->ld); 8548040SBaban.Kenkre@Sun.COM if (q->host) 8558040SBaban.Kenkre@Sun.COM free(q->host); 8568040SBaban.Kenkre@Sun.COM free(q); 8578040SBaban.Kenkre@Sun.COM break; 8588040SBaban.Kenkre@Sun.COM } 8598040SBaban.Kenkre@Sun.COM 8608040SBaban.Kenkre@Sun.COM } 8618361SJulian.Pullen@Sun.COM /* 8628361SJulian.Pullen@Sun.COM * Add known domain name and domain SID to AD configuration. 8638361SJulian.Pullen@Sun.COM */ 8648361SJulian.Pullen@Sun.COM 8658361SJulian.Pullen@Sun.COM adutils_rc 8668361SJulian.Pullen@Sun.COM adutils_add_domain(adutils_ad_t *ad, const char *domain, const char *sid) 8678361SJulian.Pullen@Sun.COM { 8688361SJulian.Pullen@Sun.COM struct known_domain *new; 8698361SJulian.Pullen@Sun.COM int num = ad->num_known_domains; 8708361SJulian.Pullen@Sun.COM 8718361SJulian.Pullen@Sun.COM ad->num_known_domains++; 8728361SJulian.Pullen@Sun.COM new = realloc(ad->known_domains, 8738361SJulian.Pullen@Sun.COM sizeof (struct known_domain) * ad->num_known_domains); 8748361SJulian.Pullen@Sun.COM if (new != NULL) { 8758361SJulian.Pullen@Sun.COM ad->known_domains = new; 8768361SJulian.Pullen@Sun.COM (void) strlcpy(ad->known_domains[num].name, domain, 8778361SJulian.Pullen@Sun.COM sizeof (ad->known_domains[num].name)); 8788361SJulian.Pullen@Sun.COM (void) strlcpy(ad->known_domains[num].sid, sid, 8798361SJulian.Pullen@Sun.COM sizeof (ad->known_domains[num].sid)); 8808361SJulian.Pullen@Sun.COM return (ADUTILS_SUCCESS); 8818361SJulian.Pullen@Sun.COM } else { 8828361SJulian.Pullen@Sun.COM if (ad->known_domains != NULL) { 8838361SJulian.Pullen@Sun.COM free(ad->known_domains); 8848361SJulian.Pullen@Sun.COM ad->known_domains = NULL; 8858361SJulian.Pullen@Sun.COM } 8868361SJulian.Pullen@Sun.COM ad->num_known_domains = 0; 8878361SJulian.Pullen@Sun.COM return (ADUTILS_ERR_MEMORY); 8888361SJulian.Pullen@Sun.COM } 8898361SJulian.Pullen@Sun.COM } 8908361SJulian.Pullen@Sun.COM 8918361SJulian.Pullen@Sun.COM 8928361SJulian.Pullen@Sun.COM /* 8938361SJulian.Pullen@Sun.COM * Check that this AD supports this domain. 8948361SJulian.Pullen@Sun.COM * If there are no known domains assume that the 8958361SJulian.Pullen@Sun.COM * domain is supported by this AD. 8968361SJulian.Pullen@Sun.COM * 8978361SJulian.Pullen@Sun.COM * Returns 1 if this domain is supported by this AD 8988361SJulian.Pullen@Sun.COM * else returns 0; 8998361SJulian.Pullen@Sun.COM */ 9008361SJulian.Pullen@Sun.COM 9018361SJulian.Pullen@Sun.COM int 9028361SJulian.Pullen@Sun.COM adutils_lookup_check_domain(adutils_query_state_t *qs, const char *domain) 9038361SJulian.Pullen@Sun.COM { 9048361SJulian.Pullen@Sun.COM adutils_ad_t *ad = qs->qadh->owner; 90510122SJordan.Brown@Sun.COM int i; 9068361SJulian.Pullen@Sun.COM 9078361SJulian.Pullen@Sun.COM for (i = 0; i < ad->num_known_domains; i++) { 90810122SJordan.Brown@Sun.COM if (domain_eq(domain, ad->known_domains[i].name)) 9098361SJulian.Pullen@Sun.COM return (1); 9108361SJulian.Pullen@Sun.COM } 9118361SJulian.Pullen@Sun.COM 9128361SJulian.Pullen@Sun.COM return ((i == 0) ? 1 : 0); 9138361SJulian.Pullen@Sun.COM } 9148361SJulian.Pullen@Sun.COM 9158361SJulian.Pullen@Sun.COM 9168361SJulian.Pullen@Sun.COM /* 9178361SJulian.Pullen@Sun.COM * Check that this AD supports the SID prefix. 9188361SJulian.Pullen@Sun.COM * The SID prefix should match the domain SID. 9198361SJulian.Pullen@Sun.COM * If there are no known domains assume that the 9208361SJulian.Pullen@Sun.COM * SID prefix is supported by this AD. 9218361SJulian.Pullen@Sun.COM * 9228361SJulian.Pullen@Sun.COM * Returns 1 if this sid prefix is supported by this AD 9238361SJulian.Pullen@Sun.COM * else returns 0; 9248361SJulian.Pullen@Sun.COM */ 9258361SJulian.Pullen@Sun.COM 9268361SJulian.Pullen@Sun.COM int 9278361SJulian.Pullen@Sun.COM adutils_lookup_check_sid_prefix(adutils_query_state_t *qs, const char *sid) 9288361SJulian.Pullen@Sun.COM { 9298361SJulian.Pullen@Sun.COM adutils_ad_t *ad = qs->qadh->owner; 9308361SJulian.Pullen@Sun.COM int i; 9318361SJulian.Pullen@Sun.COM 9328361SJulian.Pullen@Sun.COM 9338361SJulian.Pullen@Sun.COM for (i = 0; i < ad->num_known_domains; i++) { 9348361SJulian.Pullen@Sun.COM if (strcmp(sid, ad->known_domains[i].sid) == 0) 9358361SJulian.Pullen@Sun.COM return (1); 9368361SJulian.Pullen@Sun.COM } 9378361SJulian.Pullen@Sun.COM 9388361SJulian.Pullen@Sun.COM return ((i == 0) ? 1 : 0); 9398361SJulian.Pullen@Sun.COM } 9408361SJulian.Pullen@Sun.COM 9418040SBaban.Kenkre@Sun.COM 9428040SBaban.Kenkre@Sun.COM adutils_rc 9438040SBaban.Kenkre@Sun.COM adutils_lookup_batch_start(adutils_ad_t *ad, int nqueries, 9448040SBaban.Kenkre@Sun.COM adutils_ldap_res_search_cb ldap_res_search_cb, 9458040SBaban.Kenkre@Sun.COM void *ldap_res_search_argp, 9468040SBaban.Kenkre@Sun.COM adutils_query_state_t **state) 9478040SBaban.Kenkre@Sun.COM { 9488040SBaban.Kenkre@Sun.COM adutils_query_state_t *new_state; 9498040SBaban.Kenkre@Sun.COM adutils_host_t *adh = NULL; 9508040SBaban.Kenkre@Sun.COM 9518040SBaban.Kenkre@Sun.COM if (ad == NULL) 9528040SBaban.Kenkre@Sun.COM return (ADUTILS_ERR_INTERNAL); 9538040SBaban.Kenkre@Sun.COM 9548040SBaban.Kenkre@Sun.COM *state = NULL; 9558040SBaban.Kenkre@Sun.COM adh = get_conn(ad); 9568040SBaban.Kenkre@Sun.COM if (adh == NULL) 9578040SBaban.Kenkre@Sun.COM return (ADUTILS_ERR_RETRIABLE_NET_ERR); 9588040SBaban.Kenkre@Sun.COM 9598040SBaban.Kenkre@Sun.COM new_state = calloc(1, sizeof (adutils_query_state_t) + 9608040SBaban.Kenkre@Sun.COM (nqueries - 1) * sizeof (adutils_q_t)); 9618040SBaban.Kenkre@Sun.COM if (new_state == NULL) 9628040SBaban.Kenkre@Sun.COM return (ADUTILS_ERR_MEMORY); 9638040SBaban.Kenkre@Sun.COM 9648040SBaban.Kenkre@Sun.COM new_state->ref_cnt = 1; 9658040SBaban.Kenkre@Sun.COM new_state->qadh = adh; 9668361SJulian.Pullen@Sun.COM new_state->qsize = nqueries; 9678040SBaban.Kenkre@Sun.COM new_state->qadh_gen = adh->generation; 9688361SJulian.Pullen@Sun.COM new_state->qcount = 0; 9698040SBaban.Kenkre@Sun.COM new_state->ldap_res_search_cb = ldap_res_search_cb; 9708040SBaban.Kenkre@Sun.COM new_state->ldap_res_search_argp = ldap_res_search_argp; 9718040SBaban.Kenkre@Sun.COM (void) pthread_cond_init(&new_state->cv, NULL); 9728040SBaban.Kenkre@Sun.COM 9738040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&qstatelock); 9748040SBaban.Kenkre@Sun.COM new_state->next = qstatehead; 9758040SBaban.Kenkre@Sun.COM qstatehead = new_state; 9768040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&qstatelock); 9778040SBaban.Kenkre@Sun.COM *state = new_state; 9788040SBaban.Kenkre@Sun.COM 9798040SBaban.Kenkre@Sun.COM return (ADUTILS_SUCCESS); 9808040SBaban.Kenkre@Sun.COM } 9818040SBaban.Kenkre@Sun.COM 9828040SBaban.Kenkre@Sun.COM /* 9838040SBaban.Kenkre@Sun.COM * Find the adutils_query_state_t to which a given LDAP result msgid on a 9848040SBaban.Kenkre@Sun.COM * given connection belongs. This routine increaments the reference count 9858040SBaban.Kenkre@Sun.COM * so that the object can not be freed. adutils_lookup_batch_unlock() 9868040SBaban.Kenkre@Sun.COM * must be called to decreament the reference count. 9878040SBaban.Kenkre@Sun.COM */ 9888040SBaban.Kenkre@Sun.COM static 9898040SBaban.Kenkre@Sun.COM int 9908040SBaban.Kenkre@Sun.COM msgid2query(adutils_host_t *adh, int msgid, 9918040SBaban.Kenkre@Sun.COM adutils_query_state_t **state, int *qid) 9928040SBaban.Kenkre@Sun.COM { 9938040SBaban.Kenkre@Sun.COM adutils_query_state_t *p; 9948040SBaban.Kenkre@Sun.COM int i; 9958040SBaban.Kenkre@Sun.COM int ret; 9968040SBaban.Kenkre@Sun.COM 9978040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&qstatelock); 9988040SBaban.Kenkre@Sun.COM for (p = qstatehead; p != NULL; p = p->next) { 9998040SBaban.Kenkre@Sun.COM if (p->qadh != adh || adh->generation != p->qadh_gen) 10008040SBaban.Kenkre@Sun.COM continue; 10018040SBaban.Kenkre@Sun.COM for (i = 0; i < p->qcount; i++) { 10028040SBaban.Kenkre@Sun.COM if ((p->queries[i]).msgid == msgid) { 10038040SBaban.Kenkre@Sun.COM if (!p->qdead) { 10048040SBaban.Kenkre@Sun.COM p->ref_cnt++; 10058040SBaban.Kenkre@Sun.COM *state = p; 10068040SBaban.Kenkre@Sun.COM *qid = i; 10078040SBaban.Kenkre@Sun.COM ret = 1; 10088040SBaban.Kenkre@Sun.COM } else 10098040SBaban.Kenkre@Sun.COM ret = 0; 10108040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&qstatelock); 10118040SBaban.Kenkre@Sun.COM return (ret); 10128040SBaban.Kenkre@Sun.COM } 10138040SBaban.Kenkre@Sun.COM } 10148040SBaban.Kenkre@Sun.COM } 10158040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&qstatelock); 10168040SBaban.Kenkre@Sun.COM return (0); 10178040SBaban.Kenkre@Sun.COM } 10188040SBaban.Kenkre@Sun.COM 10198040SBaban.Kenkre@Sun.COM static 10208040SBaban.Kenkre@Sun.COM int 10218040SBaban.Kenkre@Sun.COM check_for_binary_attrs(const char *attr) 10228040SBaban.Kenkre@Sun.COM { 10238040SBaban.Kenkre@Sun.COM int i; 10248040SBaban.Kenkre@Sun.COM for (i = 0; binattrs[i].name != NULL; i++) { 10258040SBaban.Kenkre@Sun.COM if (strcasecmp(binattrs[i].name, attr) == 0) 10268040SBaban.Kenkre@Sun.COM return (i); 10278040SBaban.Kenkre@Sun.COM } 10288040SBaban.Kenkre@Sun.COM return (-1); 10298040SBaban.Kenkre@Sun.COM } 10308040SBaban.Kenkre@Sun.COM 10318040SBaban.Kenkre@Sun.COM static 10328040SBaban.Kenkre@Sun.COM void 10338040SBaban.Kenkre@Sun.COM free_entry(adutils_entry_t *entry) 10348040SBaban.Kenkre@Sun.COM { 10358040SBaban.Kenkre@Sun.COM int i, j; 10368040SBaban.Kenkre@Sun.COM adutils_attr_t *ap; 10378040SBaban.Kenkre@Sun.COM 10388040SBaban.Kenkre@Sun.COM if (entry == NULL) 10398040SBaban.Kenkre@Sun.COM return; 10408040SBaban.Kenkre@Sun.COM if (entry->attr_nvpairs == NULL) { 10418040SBaban.Kenkre@Sun.COM free(entry); 10428040SBaban.Kenkre@Sun.COM return; 10438040SBaban.Kenkre@Sun.COM } 10448040SBaban.Kenkre@Sun.COM for (i = 0; i < entry->num_nvpairs; i++) { 10458040SBaban.Kenkre@Sun.COM ap = &entry->attr_nvpairs[i]; 10468040SBaban.Kenkre@Sun.COM if (ap->attr_name == NULL) { 10478040SBaban.Kenkre@Sun.COM ldap_value_free(ap->attr_values); 10488040SBaban.Kenkre@Sun.COM continue; 10498040SBaban.Kenkre@Sun.COM } 10508040SBaban.Kenkre@Sun.COM if (check_for_binary_attrs(ap->attr_name) >= 0) { 10518040SBaban.Kenkre@Sun.COM free(ap->attr_name); 10528040SBaban.Kenkre@Sun.COM if (ap->attr_values == NULL) 10538040SBaban.Kenkre@Sun.COM continue; 10548040SBaban.Kenkre@Sun.COM for (j = 0; j < ap->num_values; j++) 10558040SBaban.Kenkre@Sun.COM free(ap->attr_values[j]); 10568040SBaban.Kenkre@Sun.COM free(ap->attr_values); 10578040SBaban.Kenkre@Sun.COM } else if (strcasecmp(ap->attr_name, "dn") == 0) { 10588040SBaban.Kenkre@Sun.COM free(ap->attr_name); 10598040SBaban.Kenkre@Sun.COM ldap_memfree(ap->attr_values[0]); 10608040SBaban.Kenkre@Sun.COM free(ap->attr_values); 10618040SBaban.Kenkre@Sun.COM } else { 10628040SBaban.Kenkre@Sun.COM free(ap->attr_name); 10638040SBaban.Kenkre@Sun.COM ldap_value_free(ap->attr_values); 10648040SBaban.Kenkre@Sun.COM } 10658040SBaban.Kenkre@Sun.COM } 10668040SBaban.Kenkre@Sun.COM free(entry->attr_nvpairs); 10678040SBaban.Kenkre@Sun.COM free(entry); 10688040SBaban.Kenkre@Sun.COM } 10698040SBaban.Kenkre@Sun.COM 10708040SBaban.Kenkre@Sun.COM void 10718040SBaban.Kenkre@Sun.COM adutils_freeresult(adutils_result_t **result) 10728040SBaban.Kenkre@Sun.COM { 10738040SBaban.Kenkre@Sun.COM adutils_entry_t *e, *next; 10748040SBaban.Kenkre@Sun.COM 10758040SBaban.Kenkre@Sun.COM if (result == NULL || *result == NULL) 10768040SBaban.Kenkre@Sun.COM return; 10778040SBaban.Kenkre@Sun.COM if ((*result)->entries == NULL) { 10788040SBaban.Kenkre@Sun.COM free(*result); 10798040SBaban.Kenkre@Sun.COM *result = NULL; 10808040SBaban.Kenkre@Sun.COM return; 10818040SBaban.Kenkre@Sun.COM } 10828040SBaban.Kenkre@Sun.COM for (e = (*result)->entries; e != NULL; e = next) { 10838040SBaban.Kenkre@Sun.COM next = e->next; 10848040SBaban.Kenkre@Sun.COM free_entry(e); 10858040SBaban.Kenkre@Sun.COM } 10868040SBaban.Kenkre@Sun.COM free(*result); 10878040SBaban.Kenkre@Sun.COM *result = NULL; 10888040SBaban.Kenkre@Sun.COM } 10898040SBaban.Kenkre@Sun.COM 10908040SBaban.Kenkre@Sun.COM const adutils_entry_t * 10918040SBaban.Kenkre@Sun.COM adutils_getfirstentry(adutils_result_t *result) 10928040SBaban.Kenkre@Sun.COM { 10938040SBaban.Kenkre@Sun.COM if (result != NULL) 10948040SBaban.Kenkre@Sun.COM return (result->entries); 10958040SBaban.Kenkre@Sun.COM return (NULL); 10968040SBaban.Kenkre@Sun.COM } 10978040SBaban.Kenkre@Sun.COM 10988040SBaban.Kenkre@Sun.COM 10998040SBaban.Kenkre@Sun.COM char ** 11008040SBaban.Kenkre@Sun.COM adutils_getattr(const adutils_entry_t *entry, const char *attrname) 11018040SBaban.Kenkre@Sun.COM { 11028040SBaban.Kenkre@Sun.COM int i; 11038040SBaban.Kenkre@Sun.COM adutils_attr_t *ap; 11048040SBaban.Kenkre@Sun.COM 11058040SBaban.Kenkre@Sun.COM if (entry == NULL || entry->attr_nvpairs == NULL) 11068040SBaban.Kenkre@Sun.COM return (NULL); 11078040SBaban.Kenkre@Sun.COM for (i = 0; i < entry->num_nvpairs; i++) { 11088040SBaban.Kenkre@Sun.COM ap = &entry->attr_nvpairs[i]; 11098040SBaban.Kenkre@Sun.COM if (ap->attr_name != NULL && 11108040SBaban.Kenkre@Sun.COM strcasecmp(ap->attr_name, attrname) == 0) 11118040SBaban.Kenkre@Sun.COM return (ap->attr_values); 11128040SBaban.Kenkre@Sun.COM } 11138040SBaban.Kenkre@Sun.COM return (NULL); 11148040SBaban.Kenkre@Sun.COM } 11158040SBaban.Kenkre@Sun.COM 11168040SBaban.Kenkre@Sun.COM 11178040SBaban.Kenkre@Sun.COM /* 11188040SBaban.Kenkre@Sun.COM * Queue LDAP result for the given query. 11198040SBaban.Kenkre@Sun.COM * 11208040SBaban.Kenkre@Sun.COM * Return values: 11218040SBaban.Kenkre@Sun.COM * 0 success 11228040SBaban.Kenkre@Sun.COM * -1 ignore result 11238040SBaban.Kenkre@Sun.COM * -2 error 11248040SBaban.Kenkre@Sun.COM */ 11258040SBaban.Kenkre@Sun.COM static 11268040SBaban.Kenkre@Sun.COM int 11278040SBaban.Kenkre@Sun.COM make_entry(adutils_q_t *q, adutils_host_t *adh, LDAPMessage *search_res, 11288040SBaban.Kenkre@Sun.COM adutils_entry_t **entry) 11298040SBaban.Kenkre@Sun.COM { 11308040SBaban.Kenkre@Sun.COM BerElement *ber = NULL; 11318040SBaban.Kenkre@Sun.COM BerValue **bvalues = NULL; 11328040SBaban.Kenkre@Sun.COM char **strvalues; 11338040SBaban.Kenkre@Sun.COM char *attr = NULL, *dn = NULL, *domain = NULL; 11348040SBaban.Kenkre@Sun.COM adutils_entry_t *ep; 11358040SBaban.Kenkre@Sun.COM adutils_attr_t *ap; 113610122SJordan.Brown@Sun.COM int i, j, b, ret = -2; 11378040SBaban.Kenkre@Sun.COM 11388040SBaban.Kenkre@Sun.COM *entry = NULL; 11398040SBaban.Kenkre@Sun.COM 11408040SBaban.Kenkre@Sun.COM /* Check that this is the domain that we were looking for */ 11418040SBaban.Kenkre@Sun.COM if ((dn = ldap_get_dn(adh->ld, search_res)) == NULL) 11428040SBaban.Kenkre@Sun.COM return (-2); 11438040SBaban.Kenkre@Sun.COM if ((domain = adutils_dn2dns(dn)) == NULL) { 11448040SBaban.Kenkre@Sun.COM ldap_memfree(dn); 11458040SBaban.Kenkre@Sun.COM return (-2); 11468040SBaban.Kenkre@Sun.COM } 11478040SBaban.Kenkre@Sun.COM if (q->edomain != NULL) { 114810122SJordan.Brown@Sun.COM if (!domain_eq(q->edomain, domain)) { 11498040SBaban.Kenkre@Sun.COM ldap_memfree(dn); 11508040SBaban.Kenkre@Sun.COM free(domain); 11518040SBaban.Kenkre@Sun.COM return (-1); 11528040SBaban.Kenkre@Sun.COM } 11538040SBaban.Kenkre@Sun.COM } 11548040SBaban.Kenkre@Sun.COM free(domain); 11558040SBaban.Kenkre@Sun.COM 11568040SBaban.Kenkre@Sun.COM /* Allocate memory for the entry */ 11578040SBaban.Kenkre@Sun.COM if ((ep = calloc(1, sizeof (*ep))) == NULL) 11588040SBaban.Kenkre@Sun.COM goto out; 11598040SBaban.Kenkre@Sun.COM 11608040SBaban.Kenkre@Sun.COM /* For 'dn' */ 11618040SBaban.Kenkre@Sun.COM ep->num_nvpairs = 1; 11628040SBaban.Kenkre@Sun.COM 11638040SBaban.Kenkre@Sun.COM /* Count the number of name-value pairs for this entry */ 11648040SBaban.Kenkre@Sun.COM for (attr = ldap_first_attribute(adh->ld, search_res, &ber); 11658040SBaban.Kenkre@Sun.COM attr != NULL; 11668040SBaban.Kenkre@Sun.COM attr = ldap_next_attribute(adh->ld, search_res, ber)) { 11678040SBaban.Kenkre@Sun.COM ep->num_nvpairs++; 11688040SBaban.Kenkre@Sun.COM ldap_memfree(attr); 11698040SBaban.Kenkre@Sun.COM } 11708040SBaban.Kenkre@Sun.COM ber_free(ber, 0); 11718040SBaban.Kenkre@Sun.COM ber = NULL; 11728040SBaban.Kenkre@Sun.COM 11738040SBaban.Kenkre@Sun.COM /* Allocate array for the attribute name-value pairs */ 11748040SBaban.Kenkre@Sun.COM ep->attr_nvpairs = calloc(ep->num_nvpairs, sizeof (*ep->attr_nvpairs)); 11758040SBaban.Kenkre@Sun.COM if (ep->attr_nvpairs == NULL) { 11768040SBaban.Kenkre@Sun.COM ep->num_nvpairs = 0; 11778040SBaban.Kenkre@Sun.COM goto out; 11788040SBaban.Kenkre@Sun.COM } 11798040SBaban.Kenkre@Sun.COM 11808040SBaban.Kenkre@Sun.COM /* For dn */ 11818040SBaban.Kenkre@Sun.COM ap = &ep->attr_nvpairs[0]; 11828040SBaban.Kenkre@Sun.COM if ((ap->attr_name = strdup("dn")) == NULL) 11838040SBaban.Kenkre@Sun.COM goto out; 11848040SBaban.Kenkre@Sun.COM ap->num_values = 1; 11858040SBaban.Kenkre@Sun.COM ap->attr_values = calloc(ap->num_values, sizeof (*ap->attr_values)); 11868040SBaban.Kenkre@Sun.COM if (ap->attr_values == NULL) { 11878040SBaban.Kenkre@Sun.COM ap->num_values = 0; 11888040SBaban.Kenkre@Sun.COM goto out; 11898040SBaban.Kenkre@Sun.COM } 11908040SBaban.Kenkre@Sun.COM ap->attr_values[0] = dn; 11918040SBaban.Kenkre@Sun.COM dn = NULL; 11928040SBaban.Kenkre@Sun.COM 11938040SBaban.Kenkre@Sun.COM for (attr = ldap_first_attribute(adh->ld, search_res, &ber), i = 1; 11948040SBaban.Kenkre@Sun.COM attr != NULL; 11958040SBaban.Kenkre@Sun.COM ldap_memfree(attr), i++, 11968040SBaban.Kenkre@Sun.COM attr = ldap_next_attribute(adh->ld, search_res, ber)) { 11978040SBaban.Kenkre@Sun.COM ap = &ep->attr_nvpairs[i]; 11988040SBaban.Kenkre@Sun.COM if ((ap->attr_name = strdup(attr)) == NULL) 11998040SBaban.Kenkre@Sun.COM goto out; 12008040SBaban.Kenkre@Sun.COM 12018040SBaban.Kenkre@Sun.COM if ((b = check_for_binary_attrs(attr)) >= 0) { 12028040SBaban.Kenkre@Sun.COM bvalues = 12038040SBaban.Kenkre@Sun.COM ldap_get_values_len(adh->ld, search_res, attr); 12048040SBaban.Kenkre@Sun.COM if (bvalues == NULL) 12058040SBaban.Kenkre@Sun.COM continue; 12068040SBaban.Kenkre@Sun.COM ap->num_values = ldap_count_values_len(bvalues); 12078040SBaban.Kenkre@Sun.COM if (ap->num_values == 0) { 12088040SBaban.Kenkre@Sun.COM ldap_value_free_len(bvalues); 12098040SBaban.Kenkre@Sun.COM bvalues = NULL; 12108040SBaban.Kenkre@Sun.COM continue; 12118040SBaban.Kenkre@Sun.COM } 12128040SBaban.Kenkre@Sun.COM ap->attr_values = calloc(ap->num_values, 12138040SBaban.Kenkre@Sun.COM sizeof (*ap->attr_values)); 12148040SBaban.Kenkre@Sun.COM if (ap->attr_values == NULL) { 12158040SBaban.Kenkre@Sun.COM ap->num_values = 0; 12168040SBaban.Kenkre@Sun.COM goto out; 12178040SBaban.Kenkre@Sun.COM } 12188040SBaban.Kenkre@Sun.COM for (j = 0; j < ap->num_values; j++) { 12198040SBaban.Kenkre@Sun.COM ap->attr_values[j] = 12208040SBaban.Kenkre@Sun.COM binattrs[b].ber2str(bvalues[j]); 12218040SBaban.Kenkre@Sun.COM if (ap->attr_values[j] == NULL) 12228040SBaban.Kenkre@Sun.COM goto out; 12238040SBaban.Kenkre@Sun.COM } 12248040SBaban.Kenkre@Sun.COM ldap_value_free_len(bvalues); 12258040SBaban.Kenkre@Sun.COM bvalues = NULL; 12268040SBaban.Kenkre@Sun.COM continue; 12278040SBaban.Kenkre@Sun.COM } 12288040SBaban.Kenkre@Sun.COM 12298040SBaban.Kenkre@Sun.COM strvalues = ldap_get_values(adh->ld, search_res, attr); 12308040SBaban.Kenkre@Sun.COM if (strvalues == NULL) 12318040SBaban.Kenkre@Sun.COM continue; 12328040SBaban.Kenkre@Sun.COM ap->num_values = ldap_count_values(strvalues); 12338040SBaban.Kenkre@Sun.COM if (ap->num_values == 0) { 12348040SBaban.Kenkre@Sun.COM ldap_value_free(strvalues); 12358040SBaban.Kenkre@Sun.COM continue; 12368040SBaban.Kenkre@Sun.COM } 12378040SBaban.Kenkre@Sun.COM ap->attr_values = strvalues; 12388040SBaban.Kenkre@Sun.COM } 12398040SBaban.Kenkre@Sun.COM 12408040SBaban.Kenkre@Sun.COM ret = 0; 12418040SBaban.Kenkre@Sun.COM out: 12428040SBaban.Kenkre@Sun.COM ldap_memfree(attr); 12438040SBaban.Kenkre@Sun.COM ldap_memfree(dn); 12448040SBaban.Kenkre@Sun.COM ber_free(ber, 0); 12458040SBaban.Kenkre@Sun.COM ldap_value_free_len(bvalues); 12468040SBaban.Kenkre@Sun.COM if (ret < 0) 12478040SBaban.Kenkre@Sun.COM free_entry(ep); 12488040SBaban.Kenkre@Sun.COM else 12498040SBaban.Kenkre@Sun.COM *entry = ep; 12508040SBaban.Kenkre@Sun.COM return (ret); 12518040SBaban.Kenkre@Sun.COM } 12528040SBaban.Kenkre@Sun.COM 12538040SBaban.Kenkre@Sun.COM /* 12548040SBaban.Kenkre@Sun.COM * Put the search result onto the given adutils_q_t. 12558040SBaban.Kenkre@Sun.COM * Returns: 0 success 12568040SBaban.Kenkre@Sun.COM * < 0 error 12578040SBaban.Kenkre@Sun.COM */ 12588040SBaban.Kenkre@Sun.COM static 12598040SBaban.Kenkre@Sun.COM int 12608040SBaban.Kenkre@Sun.COM add_entry(adutils_host_t *adh, adutils_q_t *q, LDAPMessage *search_res) 12618040SBaban.Kenkre@Sun.COM { 12628040SBaban.Kenkre@Sun.COM int ret = -1; 12638040SBaban.Kenkre@Sun.COM adutils_entry_t *entry = NULL; 12648040SBaban.Kenkre@Sun.COM adutils_result_t *res; 12658040SBaban.Kenkre@Sun.COM 12668040SBaban.Kenkre@Sun.COM ret = make_entry(q, adh, search_res, &entry); 12678040SBaban.Kenkre@Sun.COM if (ret < -1) { 12688040SBaban.Kenkre@Sun.COM *q->rc = ADUTILS_ERR_MEMORY; 12698040SBaban.Kenkre@Sun.COM goto out; 12708040SBaban.Kenkre@Sun.COM } else if (ret == -1) { 12718040SBaban.Kenkre@Sun.COM /* ignore result */ 12728040SBaban.Kenkre@Sun.COM goto out; 12738040SBaban.Kenkre@Sun.COM } 12748040SBaban.Kenkre@Sun.COM if (*q->result == NULL) { 12758040SBaban.Kenkre@Sun.COM res = calloc(1, sizeof (*res)); 12768040SBaban.Kenkre@Sun.COM if (res == NULL) { 12778040SBaban.Kenkre@Sun.COM *q->rc = ADUTILS_ERR_MEMORY; 12788040SBaban.Kenkre@Sun.COM goto out; 12798040SBaban.Kenkre@Sun.COM } 12808040SBaban.Kenkre@Sun.COM res->num_entries = 1; 12818040SBaban.Kenkre@Sun.COM res->entries = entry; 12828040SBaban.Kenkre@Sun.COM *q->result = res; 12838040SBaban.Kenkre@Sun.COM } else { 12848040SBaban.Kenkre@Sun.COM res = *q->result; 12858040SBaban.Kenkre@Sun.COM entry->next = res->entries; 12868040SBaban.Kenkre@Sun.COM res->entries = entry; 12878040SBaban.Kenkre@Sun.COM res->num_entries++; 12888040SBaban.Kenkre@Sun.COM } 12898040SBaban.Kenkre@Sun.COM *q->rc = ADUTILS_SUCCESS; 12908040SBaban.Kenkre@Sun.COM entry = NULL; 12918040SBaban.Kenkre@Sun.COM ret = 0; 12928040SBaban.Kenkre@Sun.COM 12938040SBaban.Kenkre@Sun.COM out: 12948040SBaban.Kenkre@Sun.COM free_entry(entry); 12958040SBaban.Kenkre@Sun.COM return (ret); 12968040SBaban.Kenkre@Sun.COM } 12978040SBaban.Kenkre@Sun.COM 12988040SBaban.Kenkre@Sun.COM /* 12998040SBaban.Kenkre@Sun.COM * Try to get a result; if there is one, find the corresponding 13008040SBaban.Kenkre@Sun.COM * adutils_q_t and process the result. 13018040SBaban.Kenkre@Sun.COM * 13028040SBaban.Kenkre@Sun.COM * Returns: 0 success 13038040SBaban.Kenkre@Sun.COM * -1 error 13048040SBaban.Kenkre@Sun.COM */ 13058040SBaban.Kenkre@Sun.COM static 13068040SBaban.Kenkre@Sun.COM int 13078040SBaban.Kenkre@Sun.COM get_adobject_batch(adutils_host_t *adh, struct timeval *timeout) 13088040SBaban.Kenkre@Sun.COM { 13098040SBaban.Kenkre@Sun.COM adutils_query_state_t *query_state; 13108040SBaban.Kenkre@Sun.COM LDAPMessage *res = NULL; 13118040SBaban.Kenkre@Sun.COM int rc, ret, msgid, qid; 13128040SBaban.Kenkre@Sun.COM adutils_q_t *que; 13138040SBaban.Kenkre@Sun.COM int num; 13148040SBaban.Kenkre@Sun.COM 13158040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&adh->lock); 13168040SBaban.Kenkre@Sun.COM if (adh->dead || adh->num_requests == 0) { 13178040SBaban.Kenkre@Sun.COM ret = (adh->dead) ? -1 : -2; 13188040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 13198040SBaban.Kenkre@Sun.COM return (ret); 13208040SBaban.Kenkre@Sun.COM } 13218040SBaban.Kenkre@Sun.COM 13228040SBaban.Kenkre@Sun.COM /* Get one result */ 13238040SBaban.Kenkre@Sun.COM rc = ldap_result(adh->ld, LDAP_RES_ANY, 0, timeout, &res); 13248040SBaban.Kenkre@Sun.COM if ((timeout != NULL && timeout->tv_sec > 0 && rc == LDAP_SUCCESS) || 13258040SBaban.Kenkre@Sun.COM rc < 0) 13268040SBaban.Kenkre@Sun.COM adh->dead = 1; 13278040SBaban.Kenkre@Sun.COM 13288040SBaban.Kenkre@Sun.COM if (rc == LDAP_RES_SEARCH_RESULT && adh->num_requests > 0) 13298040SBaban.Kenkre@Sun.COM adh->num_requests--; 13308040SBaban.Kenkre@Sun.COM if (adh->dead) { 13318040SBaban.Kenkre@Sun.COM num = adh->num_requests; 13328040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 13338671SJulian.Pullen@Sun.COM logger(LOG_DEBUG, 13348040SBaban.Kenkre@Sun.COM "AD ldap_result error - %d queued requests", num); 13358040SBaban.Kenkre@Sun.COM return (-1); 13368040SBaban.Kenkre@Sun.COM } 13378040SBaban.Kenkre@Sun.COM 13388040SBaban.Kenkre@Sun.COM switch (rc) { 13398040SBaban.Kenkre@Sun.COM case LDAP_RES_SEARCH_RESULT: 13408040SBaban.Kenkre@Sun.COM msgid = ldap_msgid(res); 13418040SBaban.Kenkre@Sun.COM if (msgid2query(adh, msgid, &query_state, &qid)) { 13428040SBaban.Kenkre@Sun.COM if (query_state->ldap_res_search_cb != NULL) { 13438040SBaban.Kenkre@Sun.COM /* 13448040SBaban.Kenkre@Sun.COM * We use the caller-provided callback 13458040SBaban.Kenkre@Sun.COM * to process the result. 13468040SBaban.Kenkre@Sun.COM */ 13478040SBaban.Kenkre@Sun.COM query_state->ldap_res_search_cb( 13488040SBaban.Kenkre@Sun.COM adh->ld, &res, rc, qid, 13498040SBaban.Kenkre@Sun.COM query_state->ldap_res_search_argp); 13508040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 13518040SBaban.Kenkre@Sun.COM } else { 13528040SBaban.Kenkre@Sun.COM /* 13538040SBaban.Kenkre@Sun.COM * No callback. We fallback to our 13548040SBaban.Kenkre@Sun.COM * default behaviour. All the entries 13558040SBaban.Kenkre@Sun.COM * gotten from this search have been 13568040SBaban.Kenkre@Sun.COM * added to the result list during 13578040SBaban.Kenkre@Sun.COM * LDAP_RES_SEARCH_ENTRY (see below). 13588040SBaban.Kenkre@Sun.COM * Here we set the return status to 13598040SBaban.Kenkre@Sun.COM * notfound if the result is still empty. 13608040SBaban.Kenkre@Sun.COM */ 13618040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 13628040SBaban.Kenkre@Sun.COM que = &(query_state->queries[qid]); 13638040SBaban.Kenkre@Sun.COM if (*que->result == NULL) 13648040SBaban.Kenkre@Sun.COM *que->rc = ADUTILS_ERR_NOTFOUND; 13658040SBaban.Kenkre@Sun.COM } 13668040SBaban.Kenkre@Sun.COM atomic_dec_32(&query_state->qinflight); 13678040SBaban.Kenkre@Sun.COM adutils_lookup_batch_unlock(&query_state); 13688040SBaban.Kenkre@Sun.COM } else { 13698040SBaban.Kenkre@Sun.COM num = adh->num_requests; 13708040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 13718671SJulian.Pullen@Sun.COM logger(LOG_DEBUG, 13728040SBaban.Kenkre@Sun.COM "AD cannot find message ID (%d) " 13738040SBaban.Kenkre@Sun.COM "- %d queued requests", 13748040SBaban.Kenkre@Sun.COM msgid, num); 13758040SBaban.Kenkre@Sun.COM } 13768040SBaban.Kenkre@Sun.COM (void) ldap_msgfree(res); 13778040SBaban.Kenkre@Sun.COM ret = 0; 13788040SBaban.Kenkre@Sun.COM break; 13798040SBaban.Kenkre@Sun.COM 13808040SBaban.Kenkre@Sun.COM case LDAP_RES_SEARCH_ENTRY: 13818040SBaban.Kenkre@Sun.COM msgid = ldap_msgid(res); 13828040SBaban.Kenkre@Sun.COM if (msgid2query(adh, msgid, &query_state, &qid)) { 13838040SBaban.Kenkre@Sun.COM if (query_state->ldap_res_search_cb != NULL) { 13848040SBaban.Kenkre@Sun.COM /* 13858040SBaban.Kenkre@Sun.COM * We use the caller-provided callback 13868040SBaban.Kenkre@Sun.COM * to process the entry. 13878040SBaban.Kenkre@Sun.COM */ 13888040SBaban.Kenkre@Sun.COM query_state->ldap_res_search_cb( 13898040SBaban.Kenkre@Sun.COM adh->ld, &res, rc, qid, 13908040SBaban.Kenkre@Sun.COM query_state->ldap_res_search_argp); 13918040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 13928040SBaban.Kenkre@Sun.COM } else { 13938040SBaban.Kenkre@Sun.COM /* 13948040SBaban.Kenkre@Sun.COM * No callback. We fallback to our 13958040SBaban.Kenkre@Sun.COM * default behaviour. This entry 13968040SBaban.Kenkre@Sun.COM * will be added to the result list. 13978040SBaban.Kenkre@Sun.COM */ 13988040SBaban.Kenkre@Sun.COM que = &(query_state->queries[qid]); 13998040SBaban.Kenkre@Sun.COM rc = add_entry(adh, que, res); 14008040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 14018040SBaban.Kenkre@Sun.COM if (rc < 0) { 14028671SJulian.Pullen@Sun.COM logger(LOG_DEBUG, 14038040SBaban.Kenkre@Sun.COM "Failed to queue entry by " 14048040SBaban.Kenkre@Sun.COM "message ID (%d) " 14058040SBaban.Kenkre@Sun.COM "- %d queued requests", 14068040SBaban.Kenkre@Sun.COM msgid, num); 14078040SBaban.Kenkre@Sun.COM } 14088040SBaban.Kenkre@Sun.COM } 14098040SBaban.Kenkre@Sun.COM adutils_lookup_batch_unlock(&query_state); 14108040SBaban.Kenkre@Sun.COM } else { 14118040SBaban.Kenkre@Sun.COM num = adh->num_requests; 14128040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 14138671SJulian.Pullen@Sun.COM logger(LOG_DEBUG, 14148040SBaban.Kenkre@Sun.COM "AD cannot find message ID (%d) " 14158040SBaban.Kenkre@Sun.COM "- %d queued requests", 14168040SBaban.Kenkre@Sun.COM msgid, num); 14178040SBaban.Kenkre@Sun.COM } 14188040SBaban.Kenkre@Sun.COM (void) ldap_msgfree(res); 14198040SBaban.Kenkre@Sun.COM ret = 0; 14208040SBaban.Kenkre@Sun.COM break; 14218040SBaban.Kenkre@Sun.COM 14228040SBaban.Kenkre@Sun.COM case LDAP_RES_SEARCH_REFERENCE: 14238040SBaban.Kenkre@Sun.COM /* 14248040SBaban.Kenkre@Sun.COM * We have no need for these at the moment. Eventually, 14258040SBaban.Kenkre@Sun.COM * when we query things that we can't expect to find in 14268040SBaban.Kenkre@Sun.COM * the Global Catalog then we'll need to learn to follow 14278040SBaban.Kenkre@Sun.COM * references. 14288040SBaban.Kenkre@Sun.COM */ 14298040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 14308040SBaban.Kenkre@Sun.COM (void) ldap_msgfree(res); 14318040SBaban.Kenkre@Sun.COM ret = 0; 14328040SBaban.Kenkre@Sun.COM break; 14338040SBaban.Kenkre@Sun.COM 14348040SBaban.Kenkre@Sun.COM default: 14358040SBaban.Kenkre@Sun.COM /* timeout or error; treat the same */ 14368040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 14378040SBaban.Kenkre@Sun.COM ret = -1; 14388040SBaban.Kenkre@Sun.COM break; 14398040SBaban.Kenkre@Sun.COM } 14408040SBaban.Kenkre@Sun.COM 14418040SBaban.Kenkre@Sun.COM return (ret); 14428040SBaban.Kenkre@Sun.COM } 14438040SBaban.Kenkre@Sun.COM 14448040SBaban.Kenkre@Sun.COM /* 14458040SBaban.Kenkre@Sun.COM * This routine decreament the reference count of the 14468040SBaban.Kenkre@Sun.COM * adutils_query_state_t 14478040SBaban.Kenkre@Sun.COM */ 14488040SBaban.Kenkre@Sun.COM static void 14498040SBaban.Kenkre@Sun.COM adutils_lookup_batch_unlock(adutils_query_state_t **state) 14508040SBaban.Kenkre@Sun.COM { 14518040SBaban.Kenkre@Sun.COM /* 14528040SBaban.Kenkre@Sun.COM * Decrement reference count with qstatelock locked 14538040SBaban.Kenkre@Sun.COM */ 14548040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&qstatelock); 14558040SBaban.Kenkre@Sun.COM (*state)->ref_cnt--; 14568040SBaban.Kenkre@Sun.COM /* 14578040SBaban.Kenkre@Sun.COM * If there are no references wakup the allocating thread 14588040SBaban.Kenkre@Sun.COM */ 14598040SBaban.Kenkre@Sun.COM if ((*state)->ref_cnt <= 1) 14608040SBaban.Kenkre@Sun.COM (void) pthread_cond_signal(&(*state)->cv); 14618040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&qstatelock); 14628040SBaban.Kenkre@Sun.COM *state = NULL; 14638040SBaban.Kenkre@Sun.COM } 14648040SBaban.Kenkre@Sun.COM 14658040SBaban.Kenkre@Sun.COM /* 14668040SBaban.Kenkre@Sun.COM * This routine frees the adutils_query_state_t structure 14678040SBaban.Kenkre@Sun.COM * If the reference count is greater than 1 it waits 14688040SBaban.Kenkre@Sun.COM * for the other threads to finish using it. 14698040SBaban.Kenkre@Sun.COM */ 14708040SBaban.Kenkre@Sun.COM void 14718040SBaban.Kenkre@Sun.COM adutils_lookup_batch_release(adutils_query_state_t **state) 14728040SBaban.Kenkre@Sun.COM { 14738040SBaban.Kenkre@Sun.COM adutils_query_state_t **p; 14748040SBaban.Kenkre@Sun.COM int i; 14758040SBaban.Kenkre@Sun.COM 14768040SBaban.Kenkre@Sun.COM if (state == NULL || *state == NULL) 14778040SBaban.Kenkre@Sun.COM return; 14788040SBaban.Kenkre@Sun.COM 14798040SBaban.Kenkre@Sun.COM /* 14808040SBaban.Kenkre@Sun.COM * Set state to dead to stop further operations. 14818040SBaban.Kenkre@Sun.COM * Wait for reference count with qstatelock locked 14828040SBaban.Kenkre@Sun.COM * to get to one. 14838040SBaban.Kenkre@Sun.COM */ 14848040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&qstatelock); 14858040SBaban.Kenkre@Sun.COM (*state)->qdead = 1; 14868040SBaban.Kenkre@Sun.COM while ((*state)->ref_cnt > 1) { 14878040SBaban.Kenkre@Sun.COM (void) pthread_cond_wait(&(*state)->cv, &qstatelock); 14888040SBaban.Kenkre@Sun.COM } 14898040SBaban.Kenkre@Sun.COM 14908040SBaban.Kenkre@Sun.COM /* Remove this state struct from the list of state structs */ 14918040SBaban.Kenkre@Sun.COM for (p = &qstatehead; *p != NULL; p = &(*p)->next) { 14928040SBaban.Kenkre@Sun.COM if (*p == (*state)) { 14938040SBaban.Kenkre@Sun.COM *p = (*state)->next; 14948040SBaban.Kenkre@Sun.COM break; 14958040SBaban.Kenkre@Sun.COM } 14968040SBaban.Kenkre@Sun.COM } 14978040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&qstatelock); 14988040SBaban.Kenkre@Sun.COM (void) pthread_cond_destroy(&(*state)->cv); 14998040SBaban.Kenkre@Sun.COM release_conn((*state)->qadh); 15008040SBaban.Kenkre@Sun.COM 15018040SBaban.Kenkre@Sun.COM /* Clear results for queries that failed */ 15028040SBaban.Kenkre@Sun.COM for (i = 0; i < (*state)->qcount; i++) { 15038040SBaban.Kenkre@Sun.COM if (*(*state)->queries[i].rc != ADUTILS_SUCCESS) { 15048040SBaban.Kenkre@Sun.COM adutils_freeresult((*state)->queries[i].result); 15058040SBaban.Kenkre@Sun.COM } 15068040SBaban.Kenkre@Sun.COM } 15078040SBaban.Kenkre@Sun.COM free(*state); 15088040SBaban.Kenkre@Sun.COM *state = NULL; 15098040SBaban.Kenkre@Sun.COM } 15108040SBaban.Kenkre@Sun.COM 15118040SBaban.Kenkre@Sun.COM 15128040SBaban.Kenkre@Sun.COM /* 15138040SBaban.Kenkre@Sun.COM * This routine waits for other threads using the 15148040SBaban.Kenkre@Sun.COM * adutils_query_state_t structure to finish. 15158040SBaban.Kenkre@Sun.COM * If the reference count is greater than 1 it waits 15168040SBaban.Kenkre@Sun.COM * for the other threads to finish using it. 15178040SBaban.Kenkre@Sun.COM */ 15188040SBaban.Kenkre@Sun.COM static 15198040SBaban.Kenkre@Sun.COM void 15208040SBaban.Kenkre@Sun.COM adutils_lookup_batch_wait(adutils_query_state_t *state) 15218040SBaban.Kenkre@Sun.COM { 15228040SBaban.Kenkre@Sun.COM /* 15238040SBaban.Kenkre@Sun.COM * Set state to dead to stop further operation. 15248040SBaban.Kenkre@Sun.COM * stating. 15258040SBaban.Kenkre@Sun.COM * Wait for reference count to get to one 15268040SBaban.Kenkre@Sun.COM * with qstatelock locked. 15278040SBaban.Kenkre@Sun.COM */ 15288040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&qstatelock); 15298040SBaban.Kenkre@Sun.COM state->qdead = 1; 15308040SBaban.Kenkre@Sun.COM while (state->ref_cnt > 1) { 15318040SBaban.Kenkre@Sun.COM (void) pthread_cond_wait(&state->cv, &qstatelock); 15328040SBaban.Kenkre@Sun.COM } 15338040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&qstatelock); 15348040SBaban.Kenkre@Sun.COM } 15358040SBaban.Kenkre@Sun.COM 15368040SBaban.Kenkre@Sun.COM /* 15378040SBaban.Kenkre@Sun.COM * Process active queries in the AD lookup batch and then finalize the 15388040SBaban.Kenkre@Sun.COM * result. 15398040SBaban.Kenkre@Sun.COM */ 15408040SBaban.Kenkre@Sun.COM adutils_rc 15418040SBaban.Kenkre@Sun.COM adutils_lookup_batch_end(adutils_query_state_t **state) 15428040SBaban.Kenkre@Sun.COM { 15438040SBaban.Kenkre@Sun.COM int rc = LDAP_SUCCESS; 15448040SBaban.Kenkre@Sun.COM adutils_rc ad_rc = ADUTILS_SUCCESS; 15458040SBaban.Kenkre@Sun.COM struct timeval tv; 15468040SBaban.Kenkre@Sun.COM 15478040SBaban.Kenkre@Sun.COM tv.tv_sec = ADUTILS_SEARCH_TIMEOUT; 15488040SBaban.Kenkre@Sun.COM tv.tv_usec = 0; 15498040SBaban.Kenkre@Sun.COM 15508040SBaban.Kenkre@Sun.COM /* Process results until done or until timeout, if given */ 15518040SBaban.Kenkre@Sun.COM while ((*state)->qinflight > 0) { 15528040SBaban.Kenkre@Sun.COM if ((rc = get_adobject_batch((*state)->qadh, 15538040SBaban.Kenkre@Sun.COM &tv)) != 0) 15548040SBaban.Kenkre@Sun.COM break; 15558040SBaban.Kenkre@Sun.COM } 15568040SBaban.Kenkre@Sun.COM (*state)->qdead = 1; 15578040SBaban.Kenkre@Sun.COM /* Wait for other threads processing search result to finish */ 15588040SBaban.Kenkre@Sun.COM adutils_lookup_batch_wait(*state); 15598040SBaban.Kenkre@Sun.COM if (rc == -1 || (*state)->qinflight != 0) 15608040SBaban.Kenkre@Sun.COM ad_rc = ADUTILS_ERR_RETRIABLE_NET_ERR; 15618040SBaban.Kenkre@Sun.COM adutils_lookup_batch_release(state); 15628040SBaban.Kenkre@Sun.COM return (ad_rc); 15638040SBaban.Kenkre@Sun.COM } 15648040SBaban.Kenkre@Sun.COM 15658040SBaban.Kenkre@Sun.COM /* 15668040SBaban.Kenkre@Sun.COM * Send one prepared search, queue up msgid, process what results are 15678040SBaban.Kenkre@Sun.COM * available 15688040SBaban.Kenkre@Sun.COM */ 15698040SBaban.Kenkre@Sun.COM adutils_rc 15708040SBaban.Kenkre@Sun.COM adutils_lookup_batch_add(adutils_query_state_t *state, 157110122SJordan.Brown@Sun.COM const char *filter, const char * const *attrs, const char *edomain, 15728040SBaban.Kenkre@Sun.COM adutils_result_t **result, adutils_rc *rc) 15738040SBaban.Kenkre@Sun.COM { 15748040SBaban.Kenkre@Sun.COM adutils_rc retcode = ADUTILS_SUCCESS; 15758040SBaban.Kenkre@Sun.COM int lrc, qid; 15768040SBaban.Kenkre@Sun.COM int num; 15778040SBaban.Kenkre@Sun.COM int dead; 15788040SBaban.Kenkre@Sun.COM struct timeval tv; 15798040SBaban.Kenkre@Sun.COM adutils_q_t *q; 15808040SBaban.Kenkre@Sun.COM 15818361SJulian.Pullen@Sun.COM qid = atomic_inc_32_nv(&state->qcount) - 1; 15828040SBaban.Kenkre@Sun.COM q = &(state->queries[qid]); 15838040SBaban.Kenkre@Sun.COM 15848361SJulian.Pullen@Sun.COM assert(qid < state->qsize); 15858361SJulian.Pullen@Sun.COM 15868040SBaban.Kenkre@Sun.COM /* 15878040SBaban.Kenkre@Sun.COM * Remember the expected domain so we can check the results 15888040SBaban.Kenkre@Sun.COM * against it 15898040SBaban.Kenkre@Sun.COM */ 15908040SBaban.Kenkre@Sun.COM q->edomain = edomain; 15918040SBaban.Kenkre@Sun.COM 15928040SBaban.Kenkre@Sun.COM /* Remember where to put the results */ 15938040SBaban.Kenkre@Sun.COM q->result = result; 15948040SBaban.Kenkre@Sun.COM q->rc = rc; 15958040SBaban.Kenkre@Sun.COM 15968040SBaban.Kenkre@Sun.COM /* 15978040SBaban.Kenkre@Sun.COM * Provide sane defaults for the results in case we never hear 15988040SBaban.Kenkre@Sun.COM * back from the DS before closing the connection. 15998040SBaban.Kenkre@Sun.COM */ 16008040SBaban.Kenkre@Sun.COM *rc = ADUTILS_ERR_RETRIABLE_NET_ERR; 16018040SBaban.Kenkre@Sun.COM if (result != NULL) 16028040SBaban.Kenkre@Sun.COM *result = NULL; 16038040SBaban.Kenkre@Sun.COM 16048040SBaban.Kenkre@Sun.COM /* Check the number of queued requests first */ 16058040SBaban.Kenkre@Sun.COM tv.tv_sec = ADUTILS_SEARCH_TIMEOUT; 16068040SBaban.Kenkre@Sun.COM tv.tv_usec = 0; 16078040SBaban.Kenkre@Sun.COM while (!state->qadh->dead && 16088040SBaban.Kenkre@Sun.COM state->qadh->num_requests > state->qadh->max_requests) { 16098040SBaban.Kenkre@Sun.COM if (get_adobject_batch(state->qadh, &tv) != 0) 16108040SBaban.Kenkre@Sun.COM break; 16118040SBaban.Kenkre@Sun.COM } 16128040SBaban.Kenkre@Sun.COM 16138040SBaban.Kenkre@Sun.COM /* Send this lookup, don't wait for a result here */ 16148040SBaban.Kenkre@Sun.COM lrc = LDAP_SUCCESS; 16158040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&state->qadh->lock); 16168040SBaban.Kenkre@Sun.COM 16178040SBaban.Kenkre@Sun.COM if (!state->qadh->dead) { 16188040SBaban.Kenkre@Sun.COM state->qadh->idletime = time(NULL); 1619*10504SKeyur.Desai@Sun.COM 1620*10504SKeyur.Desai@Sun.COM lrc = ldap_search_ext(state->qadh->ld, 1621*10504SKeyur.Desai@Sun.COM state->qadh->owner->basedn, 16228040SBaban.Kenkre@Sun.COM LDAP_SCOPE_SUBTREE, filter, (char **)attrs, 16238040SBaban.Kenkre@Sun.COM 0, NULL, NULL, NULL, -1, &q->msgid); 16248040SBaban.Kenkre@Sun.COM 16258040SBaban.Kenkre@Sun.COM if (lrc == LDAP_SUCCESS) { 16268040SBaban.Kenkre@Sun.COM state->qadh->num_requests++; 16278040SBaban.Kenkre@Sun.COM } else if (lrc == LDAP_BUSY || lrc == LDAP_UNAVAILABLE || 16288040SBaban.Kenkre@Sun.COM lrc == LDAP_CONNECT_ERROR || lrc == LDAP_SERVER_DOWN || 16298040SBaban.Kenkre@Sun.COM lrc == LDAP_UNWILLING_TO_PERFORM) { 16308040SBaban.Kenkre@Sun.COM retcode = ADUTILS_ERR_RETRIABLE_NET_ERR; 16318040SBaban.Kenkre@Sun.COM state->qadh->dead = 1; 16328040SBaban.Kenkre@Sun.COM } else { 16338040SBaban.Kenkre@Sun.COM retcode = ADUTILS_ERR_OTHER; 16348040SBaban.Kenkre@Sun.COM state->qadh->dead = 1; 16358040SBaban.Kenkre@Sun.COM } 16368040SBaban.Kenkre@Sun.COM } 16378040SBaban.Kenkre@Sun.COM dead = state->qadh->dead; 16388040SBaban.Kenkre@Sun.COM num = state->qadh->num_requests; 16398040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&state->qadh->lock); 16408040SBaban.Kenkre@Sun.COM 16418040SBaban.Kenkre@Sun.COM if (dead) { 16428040SBaban.Kenkre@Sun.COM if (lrc != LDAP_SUCCESS) 16438671SJulian.Pullen@Sun.COM logger(LOG_DEBUG, 16448040SBaban.Kenkre@Sun.COM "AD ldap_search_ext error (%s) " 16458040SBaban.Kenkre@Sun.COM "- %d queued requests", 16468040SBaban.Kenkre@Sun.COM ldap_err2string(lrc), num); 16478040SBaban.Kenkre@Sun.COM return (retcode); 16488040SBaban.Kenkre@Sun.COM } 16498040SBaban.Kenkre@Sun.COM 16508040SBaban.Kenkre@Sun.COM atomic_inc_32(&state->qinflight); 16518040SBaban.Kenkre@Sun.COM 16528040SBaban.Kenkre@Sun.COM /* 16538040SBaban.Kenkre@Sun.COM * Reap as many requests as we can _without_ waiting to prevent 16548040SBaban.Kenkre@Sun.COM * any possible TCP socket buffer starvation deadlocks. 16558040SBaban.Kenkre@Sun.COM */ 16568040SBaban.Kenkre@Sun.COM (void) memset(&tv, 0, sizeof (tv)); 16578040SBaban.Kenkre@Sun.COM while (get_adobject_batch(state->qadh, &tv) == 0) 16588040SBaban.Kenkre@Sun.COM ; 16598040SBaban.Kenkre@Sun.COM 16608040SBaban.Kenkre@Sun.COM return (ADUTILS_SUCCESS); 16618040SBaban.Kenkre@Sun.COM } 16628040SBaban.Kenkre@Sun.COM 16638040SBaban.Kenkre@Sun.COM /* 16648040SBaban.Kenkre@Sun.COM * Single AD lookup request implemented on top of the batch API. 16658040SBaban.Kenkre@Sun.COM */ 16668040SBaban.Kenkre@Sun.COM adutils_rc 16678040SBaban.Kenkre@Sun.COM adutils_lookup(adutils_ad_t *ad, const char *filter, const char **attrs, 16688040SBaban.Kenkre@Sun.COM const char *domain, adutils_result_t **result) 16698040SBaban.Kenkre@Sun.COM { 16708040SBaban.Kenkre@Sun.COM adutils_rc rc, brc; 16718040SBaban.Kenkre@Sun.COM adutils_query_state_t *qs; 16728040SBaban.Kenkre@Sun.COM 16738040SBaban.Kenkre@Sun.COM rc = adutils_lookup_batch_start(ad, 1, NULL, NULL, &qs); 16748040SBaban.Kenkre@Sun.COM if (rc != ADUTILS_SUCCESS) 16758040SBaban.Kenkre@Sun.COM return (rc); 16768040SBaban.Kenkre@Sun.COM 16778040SBaban.Kenkre@Sun.COM rc = adutils_lookup_batch_add(qs, filter, attrs, domain, result, &brc); 16788040SBaban.Kenkre@Sun.COM if (rc != ADUTILS_SUCCESS) { 16798040SBaban.Kenkre@Sun.COM adutils_lookup_batch_release(&qs); 16808040SBaban.Kenkre@Sun.COM return (rc); 16818040SBaban.Kenkre@Sun.COM } 16828040SBaban.Kenkre@Sun.COM 16838040SBaban.Kenkre@Sun.COM rc = adutils_lookup_batch_end(&qs); 16848040SBaban.Kenkre@Sun.COM if (rc != ADUTILS_SUCCESS) 16858040SBaban.Kenkre@Sun.COM return (rc); 16868040SBaban.Kenkre@Sun.COM return (brc); 16878040SBaban.Kenkre@Sun.COM } 168810122SJordan.Brown@Sun.COM 168910122SJordan.Brown@Sun.COM boolean_t 169010122SJordan.Brown@Sun.COM domain_eq(const char *a, const char *b) 169110122SJordan.Brown@Sun.COM { 169210122SJordan.Brown@Sun.COM int err; 169310122SJordan.Brown@Sun.COM 169410122SJordan.Brown@Sun.COM return (u8_strcmp(a, b, 0, U8_STRCMP_CI_LOWER, U8_UNICODE_LATEST, &err) 169510122SJordan.Brown@Sun.COM == 0 && err == 0); 169610122SJordan.Brown@Sun.COM } 1697