12b4a7802SBaban Kenkre /* 22b4a7802SBaban Kenkre * CDDL HEADER START 32b4a7802SBaban Kenkre * 42b4a7802SBaban Kenkre * The contents of this file are subject to the terms of the 52b4a7802SBaban Kenkre * Common Development and Distribution License (the "License"). 62b4a7802SBaban Kenkre * You may not use this file except in compliance with the License. 72b4a7802SBaban Kenkre * 82b4a7802SBaban Kenkre * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 92b4a7802SBaban Kenkre * or http://www.opensolaris.org/os/licensing. 102b4a7802SBaban Kenkre * See the License for the specific language governing permissions 112b4a7802SBaban Kenkre * and limitations under the License. 122b4a7802SBaban Kenkre * 132b4a7802SBaban Kenkre * When distributing Covered Code, include this CDDL HEADER in each 142b4a7802SBaban Kenkre * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 152b4a7802SBaban Kenkre * If applicable, add the following below this CDDL HEADER, with the 162b4a7802SBaban Kenkre * fields enclosed by brackets "[]" replaced with your own identifying 172b4a7802SBaban Kenkre * information: Portions Copyright [yyyy] [name of copyright owner] 182b4a7802SBaban Kenkre * 192b4a7802SBaban Kenkre * CDDL HEADER END 202b4a7802SBaban Kenkre */ 212b4a7802SBaban Kenkre /* 22*148c5f43SAlan Wright * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 232b4a7802SBaban Kenkre */ 242b4a7802SBaban Kenkre 252b4a7802SBaban Kenkre #include <alloca.h> 262b4a7802SBaban Kenkre #include <string.h> 272b4a7802SBaban Kenkre #include <strings.h> 282b4a7802SBaban Kenkre #include <lber.h> 292b4a7802SBaban Kenkre #include <sasl/sasl.h> 302b4a7802SBaban Kenkre #include <string.h> 312b4a7802SBaban Kenkre #include <ctype.h> 322b4a7802SBaban Kenkre #include <synch.h> 332b4a7802SBaban Kenkre #include <atomic.h> 342b4a7802SBaban Kenkre #include <errno.h> 352b4a7802SBaban Kenkre #include <assert.h> 362b4a7802SBaban Kenkre #include <limits.h> 377a8a68f5SJulian Pullen #include <syslog.h> 382b4a7802SBaban Kenkre #include <sys/u8_textprep.h> 392b4a7802SBaban Kenkre #include <sys/varargs.h> 402b4a7802SBaban Kenkre #include "libadutils.h" 412b4a7802SBaban Kenkre #include "adutils_impl.h" 422b4a7802SBaban Kenkre 432b4a7802SBaban Kenkre /* List of DSs, needed by the idle connection reaper thread */ 442b4a7802SBaban Kenkre static pthread_mutex_t adhostlock = PTHREAD_MUTEX_INITIALIZER; 452b4a7802SBaban Kenkre static adutils_host_t *host_head = NULL; 462b4a7802SBaban Kenkre 472b4a7802SBaban Kenkre /* 482b4a7802SBaban Kenkre * List of query state structs -- needed so we can "route" LDAP results 492b4a7802SBaban Kenkre * to the right context if multiple threads should be using the same 502b4a7802SBaban Kenkre * connection concurrently 512b4a7802SBaban Kenkre */ 522b4a7802SBaban Kenkre static pthread_mutex_t qstatelock = PTHREAD_MUTEX_INITIALIZER; 532b4a7802SBaban Kenkre static adutils_query_state_t *qstatehead = NULL; 542b4a7802SBaban Kenkre 552b4a7802SBaban Kenkre static char *adutils_sid_ber2str(BerValue *bvalues); 562b4a7802SBaban Kenkre static void adutils_lookup_batch_unlock(adutils_query_state_t **state); 572b4a7802SBaban Kenkre static void delete_ds(adutils_ad_t *ad, const char *host, int port); 582b4a7802SBaban Kenkre 59*148c5f43SAlan Wright int ad_debug[AD_DEBUG_MAX+1] = {0}; 60*148c5f43SAlan Wright 612b4a7802SBaban Kenkre typedef struct binary_attrs { 622b4a7802SBaban Kenkre const char *name; 632b4a7802SBaban Kenkre char *(*ber2str)(BerValue *bvalues); 642b4a7802SBaban Kenkre } binary_attrs_t; 652b4a7802SBaban Kenkre 662b4a7802SBaban Kenkre static binary_attrs_t binattrs[] = { 672b4a7802SBaban Kenkre {"objectSID", adutils_sid_ber2str}, 682b4a7802SBaban Kenkre {NULL, NULL} 692b4a7802SBaban Kenkre }; 702b4a7802SBaban Kenkre 714d61c878SJulian Pullen 727a8a68f5SJulian Pullen adutils_logger logger = syslog; 737a8a68f5SJulian Pullen 747a8a68f5SJulian Pullen 752b4a7802SBaban Kenkre void 767a8a68f5SJulian Pullen adutils_set_logger(adutils_logger funct) 772b4a7802SBaban Kenkre { 787a8a68f5SJulian Pullen logger = funct; 792b4a7802SBaban Kenkre } 802b4a7802SBaban Kenkre 814d61c878SJulian Pullen 822b4a7802SBaban Kenkre /* 832b4a7802SBaban Kenkre * Turn "foo.bar.com" into "dc=foo,dc=bar,dc=com" 842b4a7802SBaban Kenkre */ 852b4a7802SBaban Kenkre static 862b4a7802SBaban Kenkre char * 872b4a7802SBaban Kenkre adutils_dns2dn(const char *dns) 882b4a7802SBaban Kenkre { 897a8a68f5SJulian Pullen int num_parts; 907a8a68f5SJulian Pullen 917a8a68f5SJulian Pullen return (ldap_dns_to_dn((char *)dns, &num_parts)); 922b4a7802SBaban Kenkre } 932b4a7802SBaban Kenkre 944d61c878SJulian Pullen 952b4a7802SBaban Kenkre /* 962b4a7802SBaban Kenkre * Turn "dc=foo,dc=bar,dc=com" into "foo.bar.com"; ignores any other 972b4a7802SBaban Kenkre * attributes (CN, etc...). 982b4a7802SBaban Kenkre */ 992b4a7802SBaban Kenkre char * 1002b4a7802SBaban Kenkre adutils_dn2dns(const char *dn) 1012b4a7802SBaban Kenkre { 1027a8a68f5SJulian Pullen return (DN_to_DNS(dn)); 1032b4a7802SBaban Kenkre } 1042b4a7802SBaban Kenkre 1052b4a7802SBaban Kenkre 1062b4a7802SBaban Kenkre /* 1072b4a7802SBaban Kenkre * Convert a binary SID in a BerValue to a adutils_sid_t 1082b4a7802SBaban Kenkre */ 1092b4a7802SBaban Kenkre int 1107a8a68f5SJulian Pullen adutils_getsid(BerValue *bval, adutils_sid_t *sidp) 1112b4a7802SBaban Kenkre { 1122b4a7802SBaban Kenkre int i, j; 1132b4a7802SBaban Kenkre uchar_t *v; 1142b4a7802SBaban Kenkre uint32_t a; 1152b4a7802SBaban Kenkre 1162b4a7802SBaban Kenkre /* 1172b4a7802SBaban Kenkre * The binary format of a SID is as follows: 1182b4a7802SBaban Kenkre * 1192b4a7802SBaban Kenkre * byte #0: version, always 0x01 1202b4a7802SBaban Kenkre * byte #1: RID count, always <= 0x0f 1212b4a7802SBaban Kenkre * bytes #2-#7: SID authority, big-endian 48-bit unsigned int 1222b4a7802SBaban Kenkre * 1232b4a7802SBaban Kenkre * followed by RID count RIDs, each a little-endian, unsigned 1242b4a7802SBaban Kenkre * 32-bit int. 1252b4a7802SBaban Kenkre */ 1262b4a7802SBaban Kenkre /* 1272b4a7802SBaban Kenkre * Sanity checks: must have at least one RID, version must be 1282b4a7802SBaban Kenkre * 0x01, and the length must be 8 + rid count * 4 1292b4a7802SBaban Kenkre */ 1302b4a7802SBaban Kenkre if (bval->bv_len > 8 && bval->bv_val[0] == 0x01 && 1312b4a7802SBaban Kenkre bval->bv_len == 1 + 1 + 6 + bval->bv_val[1] * 4) { 1322b4a7802SBaban Kenkre v = (uchar_t *)bval->bv_val; 1332b4a7802SBaban Kenkre sidp->version = v[0]; 1342b4a7802SBaban Kenkre sidp->sub_authority_count = v[1]; 1352b4a7802SBaban Kenkre sidp->authority = 1362b4a7802SBaban Kenkre /* big endian -- so start from the left */ 1372b4a7802SBaban Kenkre ((u_longlong_t)v[2] << 40) | 1382b4a7802SBaban Kenkre ((u_longlong_t)v[3] << 32) | 1392b4a7802SBaban Kenkre ((u_longlong_t)v[4] << 24) | 1402b4a7802SBaban Kenkre ((u_longlong_t)v[5] << 16) | 1412b4a7802SBaban Kenkre ((u_longlong_t)v[6] << 8) | 1422b4a7802SBaban Kenkre (u_longlong_t)v[7]; 1432b4a7802SBaban Kenkre for (i = 0; i < sidp->sub_authority_count; i++) { 1442b4a7802SBaban Kenkre j = 8 + (i * 4); 1452b4a7802SBaban Kenkre /* little endian -- so start from the right */ 1462b4a7802SBaban Kenkre a = (v[j + 3] << 24) | (v[j + 2] << 16) | 1472b4a7802SBaban Kenkre (v[j + 1] << 8) | (v[j]); 1482b4a7802SBaban Kenkre sidp->sub_authorities[i] = a; 1492b4a7802SBaban Kenkre } 1502b4a7802SBaban Kenkre return (0); 1512b4a7802SBaban Kenkre } 1522b4a7802SBaban Kenkre return (-1); 1532b4a7802SBaban Kenkre } 1542b4a7802SBaban Kenkre 1552b4a7802SBaban Kenkre /* 1562b4a7802SBaban Kenkre * Convert a adutils_sid_t to S-1-... 1572b4a7802SBaban Kenkre */ 1582b4a7802SBaban Kenkre char * 1597a8a68f5SJulian Pullen adutils_sid2txt(adutils_sid_t *sidp) 1602b4a7802SBaban Kenkre { 1612b4a7802SBaban Kenkre int rlen, i, len; 1622b4a7802SBaban Kenkre char *str, *cp; 1632b4a7802SBaban Kenkre 1642b4a7802SBaban Kenkre if (sidp->version != 1) 1652b4a7802SBaban Kenkre return (NULL); 1662b4a7802SBaban Kenkre 1672b4a7802SBaban Kenkre len = sizeof ("S-1-") - 1; 1682b4a7802SBaban Kenkre 1692b4a7802SBaban Kenkre /* 1702b4a7802SBaban Kenkre * We could optimize like so, but, why? 1712b4a7802SBaban Kenkre * if (sidp->authority < 10) 1722b4a7802SBaban Kenkre * len += 2; 1732b4a7802SBaban Kenkre * else if (sidp->authority < 100) 1742b4a7802SBaban Kenkre * len += 3; 1752b4a7802SBaban Kenkre * else 1762b4a7802SBaban Kenkre * len += snprintf(NULL, 0"%llu", sidp->authority); 1772b4a7802SBaban Kenkre */ 1782b4a7802SBaban Kenkre len += snprintf(NULL, 0, "%llu", sidp->authority); 1792b4a7802SBaban Kenkre 1802b4a7802SBaban Kenkre /* Max length of a uint32_t printed out in ASCII is 10 bytes */ 1812b4a7802SBaban Kenkre len += 1 + (sidp->sub_authority_count + 1) * 10; 1822b4a7802SBaban Kenkre 1832b4a7802SBaban Kenkre if ((cp = str = malloc(len)) == NULL) 1842b4a7802SBaban Kenkre return (NULL); 1852b4a7802SBaban Kenkre 1862b4a7802SBaban Kenkre rlen = snprintf(str, len, "S-1-%llu", sidp->authority); 1872b4a7802SBaban Kenkre 1882b4a7802SBaban Kenkre cp += rlen; 1892b4a7802SBaban Kenkre len -= rlen; 1902b4a7802SBaban Kenkre 1912b4a7802SBaban Kenkre for (i = 0; i < sidp->sub_authority_count; i++) { 1922b4a7802SBaban Kenkre assert(len > 0); 1932b4a7802SBaban Kenkre rlen = snprintf(cp, len, "-%u", sidp->sub_authorities[i]); 1942b4a7802SBaban Kenkre cp += rlen; 1952b4a7802SBaban Kenkre len -= rlen; 1962b4a7802SBaban Kenkre assert(len >= 0); 1972b4a7802SBaban Kenkre } 1982b4a7802SBaban Kenkre 1992b4a7802SBaban Kenkre return (str); 2002b4a7802SBaban Kenkre } 2012b4a7802SBaban Kenkre 2022b4a7802SBaban Kenkre /* 2032b4a7802SBaban Kenkre * Convert a adutils_sid_t to on-the-wire encoding 2042b4a7802SBaban Kenkre */ 2052b4a7802SBaban Kenkre static 2062b4a7802SBaban Kenkre int 2072b4a7802SBaban Kenkre sid2binsid(adutils_sid_t *sid, uchar_t *binsid, int binsidlen) 2082b4a7802SBaban Kenkre { 2092b4a7802SBaban Kenkre uchar_t *p; 2102b4a7802SBaban Kenkre int i; 2112b4a7802SBaban Kenkre uint64_t a; 2122b4a7802SBaban Kenkre uint32_t r; 2132b4a7802SBaban Kenkre 2142b4a7802SBaban Kenkre if (sid->version != 1 || 2152b4a7802SBaban Kenkre binsidlen != (1 + 1 + 6 + sid->sub_authority_count * 4)) 2162b4a7802SBaban Kenkre return (-1); 2172b4a7802SBaban Kenkre 2182b4a7802SBaban Kenkre p = binsid; 2192b4a7802SBaban Kenkre *p++ = 0x01; /* version */ 2202b4a7802SBaban Kenkre /* sub authority count */ 2212b4a7802SBaban Kenkre *p++ = sid->sub_authority_count; 2222b4a7802SBaban Kenkre /* Authority */ 2232b4a7802SBaban Kenkre a = sid->authority; 2242b4a7802SBaban Kenkre /* big-endian -- start from left */ 2252b4a7802SBaban Kenkre *p++ = (a >> 40) & 0xFF; 2262b4a7802SBaban Kenkre *p++ = (a >> 32) & 0xFF; 2272b4a7802SBaban Kenkre *p++ = (a >> 24) & 0xFF; 2282b4a7802SBaban Kenkre *p++ = (a >> 16) & 0xFF; 2292b4a7802SBaban Kenkre *p++ = (a >> 8) & 0xFF; 2302b4a7802SBaban Kenkre *p++ = a & 0xFF; 2312b4a7802SBaban Kenkre 2322b4a7802SBaban Kenkre /* sub-authorities */ 2332b4a7802SBaban Kenkre for (i = 0; i < sid->sub_authority_count; i++) { 2342b4a7802SBaban Kenkre r = sid->sub_authorities[i]; 2352b4a7802SBaban Kenkre /* little-endian -- start from right */ 2362b4a7802SBaban Kenkre *p++ = (r & 0x000000FF); 2372b4a7802SBaban Kenkre *p++ = (r & 0x0000FF00) >> 8; 2382b4a7802SBaban Kenkre *p++ = (r & 0x00FF0000) >> 16; 2392b4a7802SBaban Kenkre *p++ = (r & 0xFF000000) >> 24; 2402b4a7802SBaban Kenkre } 2412b4a7802SBaban Kenkre 2422b4a7802SBaban Kenkre return (0); 2432b4a7802SBaban Kenkre } 2442b4a7802SBaban Kenkre 2452b4a7802SBaban Kenkre /* 2462b4a7802SBaban Kenkre * Convert a stringified SID (S-1-...) into a hex-encoded version of the 2472b4a7802SBaban Kenkre * on-the-wire encoding, but with each pair of hex digits pre-pended 2482b4a7802SBaban Kenkre * with a '\', so we can pass this to libldap. 2492b4a7802SBaban Kenkre */ 2502b4a7802SBaban Kenkre int 2512b4a7802SBaban Kenkre adutils_txtsid2hexbinsid(const char *txt, const uint32_t *rid, 2522b4a7802SBaban Kenkre char *hexbinsid, int hexbinsidlen) 2532b4a7802SBaban Kenkre { 2542b4a7802SBaban Kenkre adutils_sid_t sid = { 0 }; 2552b4a7802SBaban Kenkre int i, j; 2562b4a7802SBaban Kenkre const char *cp; 2572b4a7802SBaban Kenkre char *ecp; 2582b4a7802SBaban Kenkre u_longlong_t a; 2592b4a7802SBaban Kenkre unsigned long r; 2602b4a7802SBaban Kenkre uchar_t *binsid, b, hb; 2612b4a7802SBaban Kenkre 2622b4a7802SBaban Kenkre /* Only version 1 SIDs please */ 2632b4a7802SBaban Kenkre if (strncmp(txt, "S-1-", strlen("S-1-")) != 0) 2642b4a7802SBaban Kenkre return (-1); 2652b4a7802SBaban Kenkre 2662b4a7802SBaban Kenkre if (strlen(txt) < (strlen("S-1-") + 1)) 2672b4a7802SBaban Kenkre return (-1); 2682b4a7802SBaban Kenkre 2692b4a7802SBaban Kenkre /* count '-'s */ 2702b4a7802SBaban Kenkre for (j = 0, cp = strchr(txt, '-'); 2712b4a7802SBaban Kenkre cp != NULL && *cp != '\0'; 2722b4a7802SBaban Kenkre j++, cp = strchr(cp + 1, '-')) { 2732b4a7802SBaban Kenkre /* can't end on a '-' */ 2742b4a7802SBaban Kenkre if (*(cp + 1) == '\0') 2752b4a7802SBaban Kenkre return (-1); 2762b4a7802SBaban Kenkre } 2772b4a7802SBaban Kenkre 2782b4a7802SBaban Kenkre /* Adjust count for version and authority */ 2792b4a7802SBaban Kenkre j -= 2; 2802b4a7802SBaban Kenkre 2812b4a7802SBaban Kenkre /* we know the version number and RID count */ 2822b4a7802SBaban Kenkre sid.version = 1; 2832b4a7802SBaban Kenkre sid.sub_authority_count = (rid != NULL) ? j + 1 : j; 2842b4a7802SBaban Kenkre 2852b4a7802SBaban Kenkre /* must have at least one RID, but not too many */ 2862b4a7802SBaban Kenkre if (sid.sub_authority_count < 1 || 2872b4a7802SBaban Kenkre sid.sub_authority_count > ADUTILS_SID_MAX_SUB_AUTHORITIES) 2882b4a7802SBaban Kenkre return (-1); 2892b4a7802SBaban Kenkre 2902b4a7802SBaban Kenkre /* check that we only have digits and '-' */ 2912b4a7802SBaban Kenkre if (strspn(txt + 1, "0123456789-") < (strlen(txt) - 1)) 2922b4a7802SBaban Kenkre return (-1); 2932b4a7802SBaban Kenkre 2942b4a7802SBaban Kenkre cp = txt + strlen("S-1-"); 2952b4a7802SBaban Kenkre 2962b4a7802SBaban Kenkre /* 64-bit safe parsing of unsigned 48-bit authority value */ 2972b4a7802SBaban Kenkre errno = 0; 2982b4a7802SBaban Kenkre a = strtoull(cp, &ecp, 10); 2992b4a7802SBaban Kenkre 3002b4a7802SBaban Kenkre /* errors parsing the authority or too many bits */ 3012b4a7802SBaban Kenkre if (cp == ecp || (a == 0 && errno == EINVAL) || 3022b4a7802SBaban Kenkre (a == ULLONG_MAX && errno == ERANGE) || 3032b4a7802SBaban Kenkre (a & 0x0000ffffffffffffULL) != a) 3042b4a7802SBaban Kenkre return (-1); 3052b4a7802SBaban Kenkre 3062b4a7802SBaban Kenkre cp = ecp; 3072b4a7802SBaban Kenkre 3082b4a7802SBaban Kenkre sid.authority = (uint64_t)a; 3092b4a7802SBaban Kenkre 3102b4a7802SBaban Kenkre for (i = 0; i < j; i++) { 3112b4a7802SBaban Kenkre if (*cp++ != '-') 3122b4a7802SBaban Kenkre return (-1); 3132b4a7802SBaban Kenkre /* 64-bit safe parsing of unsigned 32-bit RID */ 3142b4a7802SBaban Kenkre errno = 0; 3152b4a7802SBaban Kenkre r = strtoul(cp, &ecp, 10); 3162b4a7802SBaban Kenkre /* errors parsing the RID or too many bits */ 3172b4a7802SBaban Kenkre if (cp == ecp || (r == 0 && errno == EINVAL) || 3182b4a7802SBaban Kenkre (r == ULONG_MAX && errno == ERANGE) || 3192b4a7802SBaban Kenkre (r & 0xffffffffUL) != r) 3202b4a7802SBaban Kenkre return (-1); 3212b4a7802SBaban Kenkre sid.sub_authorities[i] = (uint32_t)r; 3222b4a7802SBaban Kenkre cp = ecp; 3232b4a7802SBaban Kenkre } 3242b4a7802SBaban Kenkre 3252b4a7802SBaban Kenkre /* check that all of the string SID has been consumed */ 3262b4a7802SBaban Kenkre if (*cp != '\0') 3272b4a7802SBaban Kenkre return (-1); 3282b4a7802SBaban Kenkre 3292b4a7802SBaban Kenkre if (rid != NULL) 3302b4a7802SBaban Kenkre sid.sub_authorities[j] = *rid; 3312b4a7802SBaban Kenkre 3322b4a7802SBaban Kenkre j = 1 + 1 + 6 + sid.sub_authority_count * 4; 3332b4a7802SBaban Kenkre 3342b4a7802SBaban Kenkre if (hexbinsidlen < (j * 3)) 3352b4a7802SBaban Kenkre return (-2); 3362b4a7802SBaban Kenkre 3372b4a7802SBaban Kenkre /* binary encode the SID */ 3382b4a7802SBaban Kenkre binsid = (uchar_t *)alloca(j); 3392b4a7802SBaban Kenkre (void) sid2binsid(&sid, binsid, j); 3402b4a7802SBaban Kenkre 3412b4a7802SBaban Kenkre /* hex encode, with a backslash before each byte */ 3422b4a7802SBaban Kenkre for (ecp = hexbinsid, i = 0; i < j; i++) { 3432b4a7802SBaban Kenkre b = binsid[i]; 3442b4a7802SBaban Kenkre *ecp++ = '\\'; 3452b4a7802SBaban Kenkre hb = (b >> 4) & 0xF; 3462b4a7802SBaban Kenkre *ecp++ = (hb <= 0x9 ? hb + '0' : hb - 10 + 'A'); 3472b4a7802SBaban Kenkre hb = b & 0xF; 3482b4a7802SBaban Kenkre *ecp++ = (hb <= 0x9 ? hb + '0' : hb - 10 + 'A'); 3492b4a7802SBaban Kenkre } 3502b4a7802SBaban Kenkre *ecp = '\0'; 3512b4a7802SBaban Kenkre 3522b4a7802SBaban Kenkre return (0); 3532b4a7802SBaban Kenkre } 3542b4a7802SBaban Kenkre 3552b4a7802SBaban Kenkre static 3562b4a7802SBaban Kenkre char * 3572b4a7802SBaban Kenkre convert_bval2sid(BerValue *bval, uint32_t *rid) 3582b4a7802SBaban Kenkre { 3592b4a7802SBaban Kenkre adutils_sid_t sid; 3602b4a7802SBaban Kenkre 3617a8a68f5SJulian Pullen if (adutils_getsid(bval, &sid) < 0) 3622b4a7802SBaban Kenkre return (NULL); 3632b4a7802SBaban Kenkre 3642b4a7802SBaban Kenkre /* 3652b4a7802SBaban Kenkre * If desired and if the SID is what should be a domain/computer 3662b4a7802SBaban Kenkre * user or group SID (i.e., S-1-5-w-x-y-z-<user/group RID>) then 3672b4a7802SBaban Kenkre * save the last RID and truncate the SID 3682b4a7802SBaban Kenkre */ 3692b4a7802SBaban Kenkre if (rid != NULL && sid.authority == 5 && sid.sub_authority_count == 5) 3702b4a7802SBaban Kenkre *rid = sid.sub_authorities[--sid.sub_authority_count]; 3717a8a68f5SJulian Pullen return (adutils_sid2txt(&sid)); 3722b4a7802SBaban Kenkre } 3732b4a7802SBaban Kenkre 3742b4a7802SBaban Kenkre 3752b4a7802SBaban Kenkre /* 3762b4a7802SBaban Kenkre * Return a NUL-terminated stringified SID from the value of an 3772b4a7802SBaban Kenkre * objectSid attribute and put the last RID in *rid. 3782b4a7802SBaban Kenkre */ 3792b4a7802SBaban Kenkre char * 3802b4a7802SBaban Kenkre adutils_bv_objsid2sidstr(BerValue *bval, uint32_t *rid) 3812b4a7802SBaban Kenkre { 3822b4a7802SBaban Kenkre char *sid; 3832b4a7802SBaban Kenkre 3842b4a7802SBaban Kenkre if (bval == NULL) 3852b4a7802SBaban Kenkre return (NULL); 3862b4a7802SBaban Kenkre /* objectSid is single valued */ 3872b4a7802SBaban Kenkre if ((sid = convert_bval2sid(bval, rid)) == NULL) 3882b4a7802SBaban Kenkre return (NULL); 3892b4a7802SBaban Kenkre return (sid); 3902b4a7802SBaban Kenkre } 3912b4a7802SBaban Kenkre 3922b4a7802SBaban Kenkre static 3932b4a7802SBaban Kenkre char * 3942b4a7802SBaban Kenkre adutils_sid_ber2str(BerValue *bval) 3952b4a7802SBaban Kenkre { 3962b4a7802SBaban Kenkre return (adutils_bv_objsid2sidstr(bval, NULL)); 3972b4a7802SBaban Kenkre } 3982b4a7802SBaban Kenkre 3992b4a7802SBaban Kenkre 400e3f2c991SKeyur Desai /* 401e3f2c991SKeyur Desai * Extract an int from the Ber value 402e3f2c991SKeyur Desai * Return B_TRUE if a valid integer was found, B_FALSE if not. 403e3f2c991SKeyur Desai */ 404e3f2c991SKeyur Desai boolean_t 405e3f2c991SKeyur Desai adutils_bv_uint(BerValue *bval, unsigned int *result) 406e3f2c991SKeyur Desai { 407e3f2c991SKeyur Desai char buf[40]; /* big enough for any int */ 408e3f2c991SKeyur Desai unsigned int tmp; 409e3f2c991SKeyur Desai char *p; 410e3f2c991SKeyur Desai 411e3f2c991SKeyur Desai *result = 0; /* for error cases */ 412e3f2c991SKeyur Desai 413e3f2c991SKeyur Desai if (bval == NULL || bval->bv_val == NULL) 414e3f2c991SKeyur Desai return (B_FALSE); 415e3f2c991SKeyur Desai if (bval->bv_len >= sizeof (buf)) 416e3f2c991SKeyur Desai return (B_FALSE); 417e3f2c991SKeyur Desai 418e3f2c991SKeyur Desai (void) memcpy(buf, bval->bv_val, bval->bv_len); 419e3f2c991SKeyur Desai buf[bval->bv_len] = '\0'; 420e3f2c991SKeyur Desai 421e3f2c991SKeyur Desai tmp = strtoul(buf, &p, 10); 422e3f2c991SKeyur Desai 423e3f2c991SKeyur Desai /* Junk after the number? */ 424e3f2c991SKeyur Desai if (*p != '\0') 425e3f2c991SKeyur Desai return (B_FALSE); 426e3f2c991SKeyur Desai 427e3f2c991SKeyur Desai *result = tmp; 428e3f2c991SKeyur Desai 429e3f2c991SKeyur Desai return (B_TRUE); 430e3f2c991SKeyur Desai } 431e3f2c991SKeyur Desai 4322b4a7802SBaban Kenkre /* Return a NUL-terminated string from the Ber value */ 4332b4a7802SBaban Kenkre char * 434e3f2c991SKeyur Desai adutils_bv_str(BerValue *bval) 4352b4a7802SBaban Kenkre { 4362b4a7802SBaban Kenkre char *s; 4372b4a7802SBaban Kenkre 4382b4a7802SBaban Kenkre if (bval == NULL || bval->bv_val == NULL) 4392b4a7802SBaban Kenkre return (NULL); 4402b4a7802SBaban Kenkre if ((s = malloc(bval->bv_len + 1)) == NULL) 4412b4a7802SBaban Kenkre return (NULL); 4422b4a7802SBaban Kenkre (void) snprintf(s, bval->bv_len + 1, "%.*s", bval->bv_len, 4432b4a7802SBaban Kenkre bval->bv_val); 4442b4a7802SBaban Kenkre return (s); 4452b4a7802SBaban Kenkre } 4462b4a7802SBaban Kenkre 4472b4a7802SBaban Kenkre /*ARGSUSED*/ 4482b4a7802SBaban Kenkre int 4492b4a7802SBaban Kenkre saslcallback(LDAP *ld, unsigned flags, void *defaults, void *prompts) 4502b4a7802SBaban Kenkre { 4512b4a7802SBaban Kenkre sasl_interact_t *interact; 4522b4a7802SBaban Kenkre 4532b4a7802SBaban Kenkre if (prompts == NULL || flags != LDAP_SASL_INTERACTIVE) 4542b4a7802SBaban Kenkre return (LDAP_PARAM_ERROR); 4552b4a7802SBaban Kenkre 4562b4a7802SBaban Kenkre /* There should be no extra arguemnts for SASL/GSSAPI authentication */ 4572b4a7802SBaban Kenkre for (interact = prompts; interact->id != SASL_CB_LIST_END; 4582b4a7802SBaban Kenkre interact++) { 4592b4a7802SBaban Kenkre interact->result = NULL; 4602b4a7802SBaban Kenkre interact->len = 0; 4612b4a7802SBaban Kenkre } 4622b4a7802SBaban Kenkre return (LDAP_SUCCESS); 4632b4a7802SBaban Kenkre } 4642b4a7802SBaban Kenkre 4652b4a7802SBaban Kenkre 4662b4a7802SBaban Kenkre #define ADCONN_TIME 300 4672b4a7802SBaban Kenkre 4682b4a7802SBaban Kenkre /* 4692b4a7802SBaban Kenkre * Idle connection reaping side of connection management 4702b4a7802SBaban Kenkre */ 4712b4a7802SBaban Kenkre void 4722b4a7802SBaban Kenkre adutils_reap_idle_connections() 4732b4a7802SBaban Kenkre { 4742b4a7802SBaban Kenkre adutils_host_t *adh; 4752b4a7802SBaban Kenkre time_t now; 4762b4a7802SBaban Kenkre 4772b4a7802SBaban Kenkre (void) pthread_mutex_lock(&adhostlock); 4782b4a7802SBaban Kenkre now = time(NULL); 4792b4a7802SBaban Kenkre for (adh = host_head; adh != NULL; adh = adh->next) { 4802b4a7802SBaban Kenkre (void) pthread_mutex_lock(&adh->lock); 4812b4a7802SBaban Kenkre if (adh->ref == 0 && adh->idletime != 0 && 4822b4a7802SBaban Kenkre adh->idletime + ADCONN_TIME < now) { 4832b4a7802SBaban Kenkre if (adh->ld) { 4842b4a7802SBaban Kenkre (void) ldap_unbind(adh->ld); 4852b4a7802SBaban Kenkre adh->ld = NULL; 4862b4a7802SBaban Kenkre adh->idletime = 0; 4872b4a7802SBaban Kenkre adh->ref = 0; 4882b4a7802SBaban Kenkre } 4892b4a7802SBaban Kenkre } 4902b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&adh->lock); 4912b4a7802SBaban Kenkre } 4922b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&adhostlock); 4932b4a7802SBaban Kenkre } 4942b4a7802SBaban Kenkre 4952b4a7802SBaban Kenkre 4962b4a7802SBaban Kenkre adutils_rc 497e3f2c991SKeyur Desai adutils_ad_alloc(adutils_ad_t **new_ad, const char *domain_name, 4982b4a7802SBaban Kenkre adutils_ad_partition_t part) 4992b4a7802SBaban Kenkre { 5002b4a7802SBaban Kenkre adutils_ad_t *ad; 5012b4a7802SBaban Kenkre 5022b4a7802SBaban Kenkre *new_ad = NULL; 5032b4a7802SBaban Kenkre 5042b4a7802SBaban Kenkre if ((ad = calloc(1, sizeof (*ad))) == NULL) 5052b4a7802SBaban Kenkre return (ADUTILS_ERR_MEMORY); 5062b4a7802SBaban Kenkre ad->ref = 1; 5072b4a7802SBaban Kenkre ad->partition = part; 508e3f2c991SKeyur Desai 509e3f2c991SKeyur Desai /* domain_name is required iff we are talking directly to a DC */ 510e3f2c991SKeyur Desai if (part == ADUTILS_AD_DATA) { 511e3f2c991SKeyur Desai assert(domain_name != NULL); 512e3f2c991SKeyur Desai assert(*domain_name != '\0'); 513e3f2c991SKeyur Desai 514e3f2c991SKeyur Desai ad->basedn = adutils_dns2dn(domain_name); 515e3f2c991SKeyur Desai } else { 516e3f2c991SKeyur Desai assert(domain_name == NULL); 517e3f2c991SKeyur Desai ad->basedn = strdup(""); 518e3f2c991SKeyur Desai } 519e3f2c991SKeyur Desai if (ad->basedn == NULL) 5202b4a7802SBaban Kenkre goto err; 521e3f2c991SKeyur Desai 5222b4a7802SBaban Kenkre if (pthread_mutex_init(&ad->lock, NULL) != 0) 5232b4a7802SBaban Kenkre goto err; 5242b4a7802SBaban Kenkre *new_ad = ad; 5252b4a7802SBaban Kenkre return (ADUTILS_SUCCESS); 5262b4a7802SBaban Kenkre 5272b4a7802SBaban Kenkre err: 528e3f2c991SKeyur Desai free(ad->basedn); 5292b4a7802SBaban Kenkre free(ad); 5302b4a7802SBaban Kenkre return (ADUTILS_ERR_MEMORY); 5312b4a7802SBaban Kenkre } 5322b4a7802SBaban Kenkre 5332b4a7802SBaban Kenkre void 5342b4a7802SBaban Kenkre adutils_ad_free(adutils_ad_t **ad) 5352b4a7802SBaban Kenkre { 5362b4a7802SBaban Kenkre adutils_host_t *p; 5372b4a7802SBaban Kenkre adutils_host_t *prev; 5382b4a7802SBaban Kenkre 5392b4a7802SBaban Kenkre if (ad == NULL || *ad == NULL) 5402b4a7802SBaban Kenkre return; 5412b4a7802SBaban Kenkre 5422b4a7802SBaban Kenkre (void) pthread_mutex_lock(&(*ad)->lock); 5432b4a7802SBaban Kenkre 5442b4a7802SBaban Kenkre if (atomic_dec_32_nv(&(*ad)->ref) > 0) { 5452b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&(*ad)->lock); 5462b4a7802SBaban Kenkre *ad = NULL; 5472b4a7802SBaban Kenkre return; 5482b4a7802SBaban Kenkre } 5492b4a7802SBaban Kenkre 5502b4a7802SBaban Kenkre (void) pthread_mutex_lock(&adhostlock); 5512b4a7802SBaban Kenkre prev = NULL; 5522b4a7802SBaban Kenkre p = host_head; 5532b4a7802SBaban Kenkre while (p != NULL) { 5542b4a7802SBaban Kenkre if (p->owner != (*ad)) { 5552b4a7802SBaban Kenkre prev = p; 5562b4a7802SBaban Kenkre p = p->next; 5572b4a7802SBaban Kenkre continue; 5582b4a7802SBaban Kenkre } else { 5592b4a7802SBaban Kenkre delete_ds((*ad), p->host, p->port); 5602b4a7802SBaban Kenkre if (prev == NULL) 5612b4a7802SBaban Kenkre p = host_head; 5622b4a7802SBaban Kenkre else 5632b4a7802SBaban Kenkre p = prev->next; 5642b4a7802SBaban Kenkre } 5652b4a7802SBaban Kenkre } 5662b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&adhostlock); 5672b4a7802SBaban Kenkre 5682b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&(*ad)->lock); 5692b4a7802SBaban Kenkre (void) pthread_mutex_destroy(&(*ad)->lock); 5702b4a7802SBaban Kenkre 5714d61c878SJulian Pullen if ((*ad)->known_domains) 5724d61c878SJulian Pullen free((*ad)->known_domains); 573e3f2c991SKeyur Desai free((*ad)->basedn); 5742b4a7802SBaban Kenkre free(*ad); 5752b4a7802SBaban Kenkre 5762b4a7802SBaban Kenkre *ad = NULL; 5772b4a7802SBaban Kenkre } 5782b4a7802SBaban Kenkre 5792b4a7802SBaban Kenkre static 5802b4a7802SBaban Kenkre int 5812b4a7802SBaban Kenkre open_conn(adutils_host_t *adh, int timeoutsecs) 5822b4a7802SBaban Kenkre { 5832b4a7802SBaban Kenkre int zero = 0; 5842b4a7802SBaban Kenkre int ldversion, rc; 5852b4a7802SBaban Kenkre int timeoutms = timeoutsecs * 1000; 5862b4a7802SBaban Kenkre 5872b4a7802SBaban Kenkre if (adh == NULL) 5882b4a7802SBaban Kenkre return (0); 5892b4a7802SBaban Kenkre 5902b4a7802SBaban Kenkre (void) pthread_mutex_lock(&adh->lock); 5912b4a7802SBaban Kenkre 5922b4a7802SBaban Kenkre if (!adh->dead && adh->ld != NULL) 5932b4a7802SBaban Kenkre /* done! */ 5942b4a7802SBaban Kenkre goto out; 5952b4a7802SBaban Kenkre 5962b4a7802SBaban Kenkre if (adh->ld != NULL) { 5972b4a7802SBaban Kenkre (void) ldap_unbind(adh->ld); 5982b4a7802SBaban Kenkre adh->ld = NULL; 5992b4a7802SBaban Kenkre } 6002b4a7802SBaban Kenkre adh->num_requests = 0; 6012b4a7802SBaban Kenkre 6022b4a7802SBaban Kenkre atomic_inc_64(&adh->generation); 6032b4a7802SBaban Kenkre 6042b4a7802SBaban Kenkre /* Open and bind an LDAP connection */ 6052b4a7802SBaban Kenkre adh->ld = ldap_init(adh->host, adh->port); 6062b4a7802SBaban Kenkre if (adh->ld == NULL) { 6077a8a68f5SJulian Pullen logger(LOG_INFO, "ldap_init() to server " 6082b4a7802SBaban Kenkre "%s port %d failed. (%s)", adh->host, 6092b4a7802SBaban Kenkre adh->port, strerror(errno)); 6102b4a7802SBaban Kenkre goto out; 6112b4a7802SBaban Kenkre } 6122b4a7802SBaban Kenkre ldversion = LDAP_VERSION3; 6132b4a7802SBaban Kenkre (void) ldap_set_option(adh->ld, LDAP_OPT_PROTOCOL_VERSION, &ldversion); 6142b4a7802SBaban Kenkre (void) ldap_set_option(adh->ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); 6152b4a7802SBaban Kenkre (void) ldap_set_option(adh->ld, LDAP_OPT_TIMELIMIT, &zero); 6162b4a7802SBaban Kenkre (void) ldap_set_option(adh->ld, LDAP_OPT_SIZELIMIT, &zero); 6172b4a7802SBaban Kenkre (void) ldap_set_option(adh->ld, LDAP_X_OPT_CONNECT_TIMEOUT, &timeoutms); 6182b4a7802SBaban Kenkre (void) ldap_set_option(adh->ld, LDAP_OPT_RESTART, LDAP_OPT_ON); 619bd428526SJulian Pullen 620bd428526SJulian Pullen rc = adutils_set_thread_functions(adh->ld); 621bd428526SJulian Pullen if (rc != LDAP_SUCCESS) { 622bd428526SJulian Pullen /* Error has already been logged */ 623bd428526SJulian Pullen (void) ldap_unbind(adh->ld); 624bd428526SJulian Pullen adh->ld = NULL; 625bd428526SJulian Pullen goto out; 626bd428526SJulian Pullen } 627bd428526SJulian Pullen 6282b4a7802SBaban Kenkre rc = ldap_sasl_interactive_bind_s(adh->ld, "" /* binddn */, 6292b4a7802SBaban Kenkre adh->saslmech, NULL, NULL, adh->saslflags, &saslcallback, 6302b4a7802SBaban Kenkre NULL); 6312b4a7802SBaban Kenkre 6322b4a7802SBaban Kenkre if (rc != LDAP_SUCCESS) { 6332b4a7802SBaban Kenkre (void) ldap_unbind(adh->ld); 6342b4a7802SBaban Kenkre adh->ld = NULL; 6357a8a68f5SJulian Pullen logger(LOG_INFO, "ldap_sasl_interactive_bind_s() to server " 6362b4a7802SBaban Kenkre "%s port %d failed. (%s)", adh->host, adh->port, 6372b4a7802SBaban Kenkre ldap_err2string(rc)); 638e3f2c991SKeyur Desai goto out; 6392b4a7802SBaban Kenkre } 6402b4a7802SBaban Kenkre 641e3f2c991SKeyur Desai logger(LOG_DEBUG, "Using server %s:%d", 6422b4a7802SBaban Kenkre adh->host, adh->port); 6432b4a7802SBaban Kenkre 6442b4a7802SBaban Kenkre out: 6452b4a7802SBaban Kenkre if (adh->ld != NULL) { 6462b4a7802SBaban Kenkre atomic_inc_32(&adh->ref); 6472b4a7802SBaban Kenkre adh->idletime = time(NULL); 6482b4a7802SBaban Kenkre adh->dead = 0; 6492b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&adh->lock); 6502b4a7802SBaban Kenkre return (1); 6512b4a7802SBaban Kenkre } 6522b4a7802SBaban Kenkre 6532b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&adh->lock); 6542b4a7802SBaban Kenkre return (0); 6552b4a7802SBaban Kenkre } 6562b4a7802SBaban Kenkre 6572b4a7802SBaban Kenkre 6582b4a7802SBaban Kenkre /* 6592b4a7802SBaban Kenkre * Connection management: find an open connection or open one 6602b4a7802SBaban Kenkre */ 6612b4a7802SBaban Kenkre static 6622b4a7802SBaban Kenkre adutils_host_t * 6632b4a7802SBaban Kenkre get_conn(adutils_ad_t *ad) 6642b4a7802SBaban Kenkre { 6652b4a7802SBaban Kenkre adutils_host_t *adh = NULL; 6662b4a7802SBaban Kenkre int tries; 6672b4a7802SBaban Kenkre int dscount = 0; 6682b4a7802SBaban Kenkre int timeoutsecs = ADUTILS_LDAP_OPEN_TIMEOUT; 6692b4a7802SBaban Kenkre 6702b4a7802SBaban Kenkre retry: 6712b4a7802SBaban Kenkre (void) pthread_mutex_lock(&adhostlock); 6722b4a7802SBaban Kenkre 6732b4a7802SBaban Kenkre if (host_head == NULL) { 6742b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&adhostlock); 6752b4a7802SBaban Kenkre goto out; 6762b4a7802SBaban Kenkre } 6772b4a7802SBaban Kenkre 6782b4a7802SBaban Kenkre if (dscount == 0) { 6792b4a7802SBaban Kenkre /* 6802b4a7802SBaban Kenkre * First try: count the number of DSes. 6812b4a7802SBaban Kenkre * 6822b4a7802SBaban Kenkre * Integer overflow is not an issue -- we can't have so many 6832b4a7802SBaban Kenkre * DSes because they won't fit even DNS over TCP, and SMF 6842b4a7802SBaban Kenkre * shouldn't let you set so many. 6852b4a7802SBaban Kenkre */ 6862b4a7802SBaban Kenkre for (adh = host_head, tries = 0; adh != NULL; adh = adh->next) { 6872b4a7802SBaban Kenkre if (adh->owner == ad) 6882b4a7802SBaban Kenkre dscount++; 6892b4a7802SBaban Kenkre } 6902b4a7802SBaban Kenkre 6912b4a7802SBaban Kenkre if (dscount == 0) { 6922b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&adhostlock); 6932b4a7802SBaban Kenkre goto out; 6942b4a7802SBaban Kenkre } 6952b4a7802SBaban Kenkre 6962b4a7802SBaban Kenkre tries = dscount * 3; /* three tries per-ds */ 6972b4a7802SBaban Kenkre 6982b4a7802SBaban Kenkre /* 6992b4a7802SBaban Kenkre * Begin round-robin at the next DS in the list after the last 7002b4a7802SBaban Kenkre * one that we had a connection to, else start with the first 7012b4a7802SBaban Kenkre * DS in the list. 7022b4a7802SBaban Kenkre */ 7032b4a7802SBaban Kenkre adh = ad->last_adh; 7042b4a7802SBaban Kenkre } 7052b4a7802SBaban Kenkre 7062b4a7802SBaban Kenkre /* 7072b4a7802SBaban Kenkre * Round-robin -- pick the next one on the list; if the list 7082b4a7802SBaban Kenkre * changes on us, no big deal, we'll just potentially go 7092b4a7802SBaban Kenkre * around the wrong number of times. 7102b4a7802SBaban Kenkre */ 7112b4a7802SBaban Kenkre for (;;) { 7124d61c878SJulian Pullen if (adh != NULL && adh->owner == ad && adh->ld != NULL && 7134d61c878SJulian Pullen !adh->dead) 7142b4a7802SBaban Kenkre break; 7152b4a7802SBaban Kenkre if (adh == NULL || (adh = adh->next) == NULL) 7162b4a7802SBaban Kenkre adh = host_head; 7172b4a7802SBaban Kenkre if (adh->owner == ad) 7182b4a7802SBaban Kenkre break; 7192b4a7802SBaban Kenkre } 7202b4a7802SBaban Kenkre 7212b4a7802SBaban Kenkre ad->last_adh = adh; 7222b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&adhostlock); 7232b4a7802SBaban Kenkre 7242b4a7802SBaban Kenkre /* Found suitable DS, open it if not already opened */ 7252b4a7802SBaban Kenkre if (open_conn(adh, timeoutsecs)) 7262b4a7802SBaban Kenkre return (adh); 7272b4a7802SBaban Kenkre 7282b4a7802SBaban Kenkre tries--; 7292b4a7802SBaban Kenkre if ((tries % dscount) == 0) 7302b4a7802SBaban Kenkre timeoutsecs *= 2; 7312b4a7802SBaban Kenkre if (tries > 0) 7322b4a7802SBaban Kenkre goto retry; 7332b4a7802SBaban Kenkre 7342b4a7802SBaban Kenkre out: 7357a8a68f5SJulian Pullen logger(LOG_NOTICE, "Couldn't open an LDAP connection to any global " 7362b4a7802SBaban Kenkre "catalog server!"); 7372b4a7802SBaban Kenkre return (NULL); 7382b4a7802SBaban Kenkre } 7392b4a7802SBaban Kenkre 7402b4a7802SBaban Kenkre static 7412b4a7802SBaban Kenkre void 7422b4a7802SBaban Kenkre release_conn(adutils_host_t *adh) 7432b4a7802SBaban Kenkre { 7442b4a7802SBaban Kenkre int delete = 0; 7452b4a7802SBaban Kenkre 7462b4a7802SBaban Kenkre (void) pthread_mutex_lock(&adh->lock); 7472b4a7802SBaban Kenkre if (atomic_dec_32_nv(&adh->ref) == 0) { 7482b4a7802SBaban Kenkre if (adh->owner == NULL) 7492b4a7802SBaban Kenkre delete = 1; 7502b4a7802SBaban Kenkre adh->idletime = time(NULL); 7512b4a7802SBaban Kenkre } 7522b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&adh->lock); 7532b4a7802SBaban Kenkre 7542b4a7802SBaban Kenkre /* Free this host if its owner no longer exists. */ 7552b4a7802SBaban Kenkre if (delete) { 7562b4a7802SBaban Kenkre (void) pthread_mutex_lock(&adhostlock); 7572b4a7802SBaban Kenkre delete_ds(NULL, adh->host, adh->port); 7582b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&adhostlock); 7592b4a7802SBaban Kenkre } 7602b4a7802SBaban Kenkre } 7612b4a7802SBaban Kenkre 7622b4a7802SBaban Kenkre /* 7632b4a7802SBaban Kenkre * Create a adutils_host_t, populate it and add it to the list of hosts. 7642b4a7802SBaban Kenkre */ 7652b4a7802SBaban Kenkre adutils_rc 7662b4a7802SBaban Kenkre adutils_add_ds(adutils_ad_t *ad, const char *host, int port) 7672b4a7802SBaban Kenkre { 7682b4a7802SBaban Kenkre adutils_host_t *p; 7692b4a7802SBaban Kenkre adutils_host_t *new = NULL; 7702b4a7802SBaban Kenkre int ret; 7712b4a7802SBaban Kenkre adutils_rc rc; 7722b4a7802SBaban Kenkre 7732b4a7802SBaban Kenkre (void) pthread_mutex_lock(&adhostlock); 7742b4a7802SBaban Kenkre for (p = host_head; p != NULL; p = p->next) { 7752b4a7802SBaban Kenkre if (p->owner != ad) 7762b4a7802SBaban Kenkre continue; 7772b4a7802SBaban Kenkre 7782b4a7802SBaban Kenkre if (strcmp(host, p->host) == 0 && p->port == port) { 7792b4a7802SBaban Kenkre /* already added */ 7802b4a7802SBaban Kenkre rc = ADUTILS_SUCCESS; 7812b4a7802SBaban Kenkre goto err; 7822b4a7802SBaban Kenkre } 7832b4a7802SBaban Kenkre } 7842b4a7802SBaban Kenkre 7852b4a7802SBaban Kenkre rc = ADUTILS_ERR_MEMORY; 7862b4a7802SBaban Kenkre 7872b4a7802SBaban Kenkre /* add new entry */ 7882b4a7802SBaban Kenkre new = (adutils_host_t *)calloc(1, sizeof (*new)); 7892b4a7802SBaban Kenkre if (new == NULL) 7902b4a7802SBaban Kenkre goto err; 7912b4a7802SBaban Kenkre new->owner = ad; 7922b4a7802SBaban Kenkre new->port = port; 7932b4a7802SBaban Kenkre new->dead = 0; 7942b4a7802SBaban Kenkre new->max_requests = 80; 7952b4a7802SBaban Kenkre new->num_requests = 0; 7962b4a7802SBaban Kenkre if ((new->host = strdup(host)) == NULL) 7972b4a7802SBaban Kenkre goto err; 7982b4a7802SBaban Kenkre new->saslflags = LDAP_SASL_INTERACTIVE; 7992b4a7802SBaban Kenkre new->saslmech = "GSSAPI"; 8002b4a7802SBaban Kenkre 8012b4a7802SBaban Kenkre if ((ret = pthread_mutex_init(&new->lock, NULL)) != 0) { 8022b4a7802SBaban Kenkre free(new->host); 8032b4a7802SBaban Kenkre new->host = NULL; 8042b4a7802SBaban Kenkre errno = ret; 8052b4a7802SBaban Kenkre rc = ADUTILS_ERR_INTERNAL; 8062b4a7802SBaban Kenkre goto err; 8072b4a7802SBaban Kenkre } 8082b4a7802SBaban Kenkre 8092b4a7802SBaban Kenkre /* link in */ 8102b4a7802SBaban Kenkre rc = ADUTILS_SUCCESS; 8112b4a7802SBaban Kenkre new->next = host_head; 8122b4a7802SBaban Kenkre host_head = new; 8132b4a7802SBaban Kenkre 8142b4a7802SBaban Kenkre err: 8152b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&adhostlock); 8162b4a7802SBaban Kenkre 8172b4a7802SBaban Kenkre if (rc != 0 && new != NULL) { 8182b4a7802SBaban Kenkre if (new->host != NULL) { 8192b4a7802SBaban Kenkre (void) pthread_mutex_destroy(&new->lock); 8202b4a7802SBaban Kenkre free(new->host); 8212b4a7802SBaban Kenkre } 8222b4a7802SBaban Kenkre free(new); 8232b4a7802SBaban Kenkre } 8242b4a7802SBaban Kenkre 8252b4a7802SBaban Kenkre return (rc); 8262b4a7802SBaban Kenkre } 8272b4a7802SBaban Kenkre 8282b4a7802SBaban Kenkre /* 8292b4a7802SBaban Kenkre * Free a DS configuration. 8302b4a7802SBaban Kenkre * Caller must lock the adhostlock mutex 8312b4a7802SBaban Kenkre */ 8322b4a7802SBaban Kenkre static 8332b4a7802SBaban Kenkre void 8342b4a7802SBaban Kenkre delete_ds(adutils_ad_t *ad, const char *host, int port) 8352b4a7802SBaban Kenkre { 8362b4a7802SBaban Kenkre adutils_host_t **p, *q; 8372b4a7802SBaban Kenkre 8382b4a7802SBaban Kenkre for (p = &host_head; *p != NULL; p = &((*p)->next)) { 8392b4a7802SBaban Kenkre if ((*p)->owner != ad || strcmp(host, (*p)->host) != 0 || 8402b4a7802SBaban Kenkre (*p)->port != port) 8412b4a7802SBaban Kenkre continue; 8422b4a7802SBaban Kenkre /* found */ 8432b4a7802SBaban Kenkre 8442b4a7802SBaban Kenkre (void) pthread_mutex_lock(&((*p)->lock)); 8452b4a7802SBaban Kenkre if ((*p)->ref > 0) { 8462b4a7802SBaban Kenkre /* 8472b4a7802SBaban Kenkre * Still in use. Set its owner to NULL so 8482b4a7802SBaban Kenkre * that it can be freed when its ref count 8492b4a7802SBaban Kenkre * becomes 0. 8502b4a7802SBaban Kenkre */ 8512b4a7802SBaban Kenkre (*p)->owner = NULL; 8522b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&((*p)->lock)); 8532b4a7802SBaban Kenkre break; 8542b4a7802SBaban Kenkre } 8552b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&((*p)->lock)); 8562b4a7802SBaban Kenkre 8572b4a7802SBaban Kenkre q = *p; 8582b4a7802SBaban Kenkre *p = (*p)->next; 8592b4a7802SBaban Kenkre 8602b4a7802SBaban Kenkre (void) pthread_mutex_destroy(&q->lock); 8612b4a7802SBaban Kenkre 8622b4a7802SBaban Kenkre if (q->ld) 8632b4a7802SBaban Kenkre (void) ldap_unbind(q->ld); 8642b4a7802SBaban Kenkre if (q->host) 8652b4a7802SBaban Kenkre free(q->host); 8662b4a7802SBaban Kenkre free(q); 8672b4a7802SBaban Kenkre break; 8682b4a7802SBaban Kenkre } 8692b4a7802SBaban Kenkre 8702b4a7802SBaban Kenkre } 8714d61c878SJulian Pullen /* 8724d61c878SJulian Pullen * Add known domain name and domain SID to AD configuration. 8734d61c878SJulian Pullen */ 8744d61c878SJulian Pullen 8754d61c878SJulian Pullen adutils_rc 8764d61c878SJulian Pullen adutils_add_domain(adutils_ad_t *ad, const char *domain, const char *sid) 8774d61c878SJulian Pullen { 8784d61c878SJulian Pullen struct known_domain *new; 8794d61c878SJulian Pullen int num = ad->num_known_domains; 8804d61c878SJulian Pullen 8814d61c878SJulian Pullen ad->num_known_domains++; 8824d61c878SJulian Pullen new = realloc(ad->known_domains, 8834d61c878SJulian Pullen sizeof (struct known_domain) * ad->num_known_domains); 8844d61c878SJulian Pullen if (new != NULL) { 8854d61c878SJulian Pullen ad->known_domains = new; 8864d61c878SJulian Pullen (void) strlcpy(ad->known_domains[num].name, domain, 8874d61c878SJulian Pullen sizeof (ad->known_domains[num].name)); 8884d61c878SJulian Pullen (void) strlcpy(ad->known_domains[num].sid, sid, 8894d61c878SJulian Pullen sizeof (ad->known_domains[num].sid)); 8904d61c878SJulian Pullen return (ADUTILS_SUCCESS); 8914d61c878SJulian Pullen } else { 8924d61c878SJulian Pullen if (ad->known_domains != NULL) { 8934d61c878SJulian Pullen free(ad->known_domains); 8944d61c878SJulian Pullen ad->known_domains = NULL; 8954d61c878SJulian Pullen } 8964d61c878SJulian Pullen ad->num_known_domains = 0; 8974d61c878SJulian Pullen return (ADUTILS_ERR_MEMORY); 8984d61c878SJulian Pullen } 8994d61c878SJulian Pullen } 9004d61c878SJulian Pullen 9014d61c878SJulian Pullen 9024d61c878SJulian Pullen /* 9034d61c878SJulian Pullen * Check that this AD supports this domain. 9044d61c878SJulian Pullen * If there are no known domains assume that the 9054d61c878SJulian Pullen * domain is supported by this AD. 9064d61c878SJulian Pullen * 9074d61c878SJulian Pullen * Returns 1 if this domain is supported by this AD 9084d61c878SJulian Pullen * else returns 0; 9094d61c878SJulian Pullen */ 9104d61c878SJulian Pullen 9114d61c878SJulian Pullen int 9124d61c878SJulian Pullen adutils_lookup_check_domain(adutils_query_state_t *qs, const char *domain) 9134d61c878SJulian Pullen { 9144d61c878SJulian Pullen adutils_ad_t *ad = qs->qadh->owner; 9151fcced4cSJordan Brown int i; 9164d61c878SJulian Pullen 9174d61c878SJulian Pullen for (i = 0; i < ad->num_known_domains; i++) { 9181fcced4cSJordan Brown if (domain_eq(domain, ad->known_domains[i].name)) 9194d61c878SJulian Pullen return (1); 9204d61c878SJulian Pullen } 9214d61c878SJulian Pullen 9224d61c878SJulian Pullen return ((i == 0) ? 1 : 0); 9234d61c878SJulian Pullen } 9244d61c878SJulian Pullen 9254d61c878SJulian Pullen 9264d61c878SJulian Pullen /* 9274d61c878SJulian Pullen * Check that this AD supports the SID prefix. 9284d61c878SJulian Pullen * The SID prefix should match the domain SID. 9294d61c878SJulian Pullen * If there are no known domains assume that the 9304d61c878SJulian Pullen * SID prefix is supported by this AD. 9314d61c878SJulian Pullen * 9324d61c878SJulian Pullen * Returns 1 if this sid prefix is supported by this AD 9334d61c878SJulian Pullen * else returns 0; 9344d61c878SJulian Pullen */ 9354d61c878SJulian Pullen 9364d61c878SJulian Pullen int 9374d61c878SJulian Pullen adutils_lookup_check_sid_prefix(adutils_query_state_t *qs, const char *sid) 9384d61c878SJulian Pullen { 9394d61c878SJulian Pullen adutils_ad_t *ad = qs->qadh->owner; 9404d61c878SJulian Pullen int i; 9414d61c878SJulian Pullen 9424d61c878SJulian Pullen 9434d61c878SJulian Pullen for (i = 0; i < ad->num_known_domains; i++) { 9444d61c878SJulian Pullen if (strcmp(sid, ad->known_domains[i].sid) == 0) 9454d61c878SJulian Pullen return (1); 9464d61c878SJulian Pullen } 9474d61c878SJulian Pullen 9484d61c878SJulian Pullen return ((i == 0) ? 1 : 0); 9494d61c878SJulian Pullen } 9504d61c878SJulian Pullen 9512b4a7802SBaban Kenkre 9522b4a7802SBaban Kenkre adutils_rc 9532b4a7802SBaban Kenkre adutils_lookup_batch_start(adutils_ad_t *ad, int nqueries, 9542b4a7802SBaban Kenkre adutils_ldap_res_search_cb ldap_res_search_cb, 9552b4a7802SBaban Kenkre void *ldap_res_search_argp, 9562b4a7802SBaban Kenkre adutils_query_state_t **state) 9572b4a7802SBaban Kenkre { 9582b4a7802SBaban Kenkre adutils_query_state_t *new_state; 9592b4a7802SBaban Kenkre adutils_host_t *adh = NULL; 9602b4a7802SBaban Kenkre 9612b4a7802SBaban Kenkre if (ad == NULL) 9622b4a7802SBaban Kenkre return (ADUTILS_ERR_INTERNAL); 9632b4a7802SBaban Kenkre 9642b4a7802SBaban Kenkre *state = NULL; 9652b4a7802SBaban Kenkre adh = get_conn(ad); 9662b4a7802SBaban Kenkre if (adh == NULL) 9672b4a7802SBaban Kenkre return (ADUTILS_ERR_RETRIABLE_NET_ERR); 9682b4a7802SBaban Kenkre 9692b4a7802SBaban Kenkre new_state = calloc(1, sizeof (adutils_query_state_t) + 9702b4a7802SBaban Kenkre (nqueries - 1) * sizeof (adutils_q_t)); 9712b4a7802SBaban Kenkre if (new_state == NULL) 9722b4a7802SBaban Kenkre return (ADUTILS_ERR_MEMORY); 9732b4a7802SBaban Kenkre 9742b4a7802SBaban Kenkre new_state->ref_cnt = 1; 9752b4a7802SBaban Kenkre new_state->qadh = adh; 9764d61c878SJulian Pullen new_state->qsize = nqueries; 9772b4a7802SBaban Kenkre new_state->qadh_gen = adh->generation; 9784d61c878SJulian Pullen new_state->qcount = 0; 9792b4a7802SBaban Kenkre new_state->ldap_res_search_cb = ldap_res_search_cb; 9802b4a7802SBaban Kenkre new_state->ldap_res_search_argp = ldap_res_search_argp; 9812b4a7802SBaban Kenkre (void) pthread_cond_init(&new_state->cv, NULL); 9822b4a7802SBaban Kenkre 9832b4a7802SBaban Kenkre (void) pthread_mutex_lock(&qstatelock); 9842b4a7802SBaban Kenkre new_state->next = qstatehead; 9852b4a7802SBaban Kenkre qstatehead = new_state; 9862b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&qstatelock); 9872b4a7802SBaban Kenkre *state = new_state; 9882b4a7802SBaban Kenkre 9892b4a7802SBaban Kenkre return (ADUTILS_SUCCESS); 9902b4a7802SBaban Kenkre } 9912b4a7802SBaban Kenkre 9922b4a7802SBaban Kenkre /* 9932b4a7802SBaban Kenkre * Find the adutils_query_state_t to which a given LDAP result msgid on a 9942b4a7802SBaban Kenkre * given connection belongs. This routine increaments the reference count 9952b4a7802SBaban Kenkre * so that the object can not be freed. adutils_lookup_batch_unlock() 9962b4a7802SBaban Kenkre * must be called to decreament the reference count. 9972b4a7802SBaban Kenkre */ 9982b4a7802SBaban Kenkre static 9992b4a7802SBaban Kenkre int 10002b4a7802SBaban Kenkre msgid2query(adutils_host_t *adh, int msgid, 10012b4a7802SBaban Kenkre adutils_query_state_t **state, int *qid) 10022b4a7802SBaban Kenkre { 10032b4a7802SBaban Kenkre adutils_query_state_t *p; 10042b4a7802SBaban Kenkre int i; 10052b4a7802SBaban Kenkre int ret; 10062b4a7802SBaban Kenkre 10072b4a7802SBaban Kenkre (void) pthread_mutex_lock(&qstatelock); 10082b4a7802SBaban Kenkre for (p = qstatehead; p != NULL; p = p->next) { 10092b4a7802SBaban Kenkre if (p->qadh != adh || adh->generation != p->qadh_gen) 10102b4a7802SBaban Kenkre continue; 10112b4a7802SBaban Kenkre for (i = 0; i < p->qcount; i++) { 10122b4a7802SBaban Kenkre if ((p->queries[i]).msgid == msgid) { 10132b4a7802SBaban Kenkre if (!p->qdead) { 10142b4a7802SBaban Kenkre p->ref_cnt++; 10152b4a7802SBaban Kenkre *state = p; 10162b4a7802SBaban Kenkre *qid = i; 10172b4a7802SBaban Kenkre ret = 1; 10182b4a7802SBaban Kenkre } else 10192b4a7802SBaban Kenkre ret = 0; 10202b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&qstatelock); 10212b4a7802SBaban Kenkre return (ret); 10222b4a7802SBaban Kenkre } 10232b4a7802SBaban Kenkre } 10242b4a7802SBaban Kenkre } 10252b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&qstatelock); 10262b4a7802SBaban Kenkre return (0); 10272b4a7802SBaban Kenkre } 10282b4a7802SBaban Kenkre 10292b4a7802SBaban Kenkre static 10302b4a7802SBaban Kenkre int 10312b4a7802SBaban Kenkre check_for_binary_attrs(const char *attr) 10322b4a7802SBaban Kenkre { 10332b4a7802SBaban Kenkre int i; 10342b4a7802SBaban Kenkre for (i = 0; binattrs[i].name != NULL; i++) { 10352b4a7802SBaban Kenkre if (strcasecmp(binattrs[i].name, attr) == 0) 10362b4a7802SBaban Kenkre return (i); 10372b4a7802SBaban Kenkre } 10382b4a7802SBaban Kenkre return (-1); 10392b4a7802SBaban Kenkre } 10402b4a7802SBaban Kenkre 10412b4a7802SBaban Kenkre static 10422b4a7802SBaban Kenkre void 10432b4a7802SBaban Kenkre free_entry(adutils_entry_t *entry) 10442b4a7802SBaban Kenkre { 10452b4a7802SBaban Kenkre int i, j; 10462b4a7802SBaban Kenkre adutils_attr_t *ap; 10472b4a7802SBaban Kenkre 10482b4a7802SBaban Kenkre if (entry == NULL) 10492b4a7802SBaban Kenkre return; 10502b4a7802SBaban Kenkre if (entry->attr_nvpairs == NULL) { 10512b4a7802SBaban Kenkre free(entry); 10522b4a7802SBaban Kenkre return; 10532b4a7802SBaban Kenkre } 10542b4a7802SBaban Kenkre for (i = 0; i < entry->num_nvpairs; i++) { 10552b4a7802SBaban Kenkre ap = &entry->attr_nvpairs[i]; 10562b4a7802SBaban Kenkre if (ap->attr_name == NULL) { 10572b4a7802SBaban Kenkre ldap_value_free(ap->attr_values); 10582b4a7802SBaban Kenkre continue; 10592b4a7802SBaban Kenkre } 10602b4a7802SBaban Kenkre if (check_for_binary_attrs(ap->attr_name) >= 0) { 10612b4a7802SBaban Kenkre free(ap->attr_name); 10622b4a7802SBaban Kenkre if (ap->attr_values == NULL) 10632b4a7802SBaban Kenkre continue; 10642b4a7802SBaban Kenkre for (j = 0; j < ap->num_values; j++) 10652b4a7802SBaban Kenkre free(ap->attr_values[j]); 10662b4a7802SBaban Kenkre free(ap->attr_values); 10672b4a7802SBaban Kenkre } else if (strcasecmp(ap->attr_name, "dn") == 0) { 10682b4a7802SBaban Kenkre free(ap->attr_name); 10692b4a7802SBaban Kenkre ldap_memfree(ap->attr_values[0]); 10702b4a7802SBaban Kenkre free(ap->attr_values); 10712b4a7802SBaban Kenkre } else { 10722b4a7802SBaban Kenkre free(ap->attr_name); 10732b4a7802SBaban Kenkre ldap_value_free(ap->attr_values); 10742b4a7802SBaban Kenkre } 10752b4a7802SBaban Kenkre } 10762b4a7802SBaban Kenkre free(entry->attr_nvpairs); 10772b4a7802SBaban Kenkre free(entry); 10782b4a7802SBaban Kenkre } 10792b4a7802SBaban Kenkre 10802b4a7802SBaban Kenkre void 10812b4a7802SBaban Kenkre adutils_freeresult(adutils_result_t **result) 10822b4a7802SBaban Kenkre { 10832b4a7802SBaban Kenkre adutils_entry_t *e, *next; 10842b4a7802SBaban Kenkre 10852b4a7802SBaban Kenkre if (result == NULL || *result == NULL) 10862b4a7802SBaban Kenkre return; 10872b4a7802SBaban Kenkre if ((*result)->entries == NULL) { 10882b4a7802SBaban Kenkre free(*result); 10892b4a7802SBaban Kenkre *result = NULL; 10902b4a7802SBaban Kenkre return; 10912b4a7802SBaban Kenkre } 10922b4a7802SBaban Kenkre for (e = (*result)->entries; e != NULL; e = next) { 10932b4a7802SBaban Kenkre next = e->next; 10942b4a7802SBaban Kenkre free_entry(e); 10952b4a7802SBaban Kenkre } 10962b4a7802SBaban Kenkre free(*result); 10972b4a7802SBaban Kenkre *result = NULL; 10982b4a7802SBaban Kenkre } 10992b4a7802SBaban Kenkre 11002b4a7802SBaban Kenkre const adutils_entry_t * 11012b4a7802SBaban Kenkre adutils_getfirstentry(adutils_result_t *result) 11022b4a7802SBaban Kenkre { 11032b4a7802SBaban Kenkre if (result != NULL) 11042b4a7802SBaban Kenkre return (result->entries); 11052b4a7802SBaban Kenkre return (NULL); 11062b4a7802SBaban Kenkre } 11072b4a7802SBaban Kenkre 11082b4a7802SBaban Kenkre 11092b4a7802SBaban Kenkre char ** 11102b4a7802SBaban Kenkre adutils_getattr(const adutils_entry_t *entry, const char *attrname) 11112b4a7802SBaban Kenkre { 11122b4a7802SBaban Kenkre int i; 11132b4a7802SBaban Kenkre adutils_attr_t *ap; 11142b4a7802SBaban Kenkre 11152b4a7802SBaban Kenkre if (entry == NULL || entry->attr_nvpairs == NULL) 11162b4a7802SBaban Kenkre return (NULL); 11172b4a7802SBaban Kenkre for (i = 0; i < entry->num_nvpairs; i++) { 11182b4a7802SBaban Kenkre ap = &entry->attr_nvpairs[i]; 11192b4a7802SBaban Kenkre if (ap->attr_name != NULL && 11202b4a7802SBaban Kenkre strcasecmp(ap->attr_name, attrname) == 0) 11212b4a7802SBaban Kenkre return (ap->attr_values); 11222b4a7802SBaban Kenkre } 11232b4a7802SBaban Kenkre return (NULL); 11242b4a7802SBaban Kenkre } 11252b4a7802SBaban Kenkre 11262b4a7802SBaban Kenkre 11272b4a7802SBaban Kenkre /* 11282b4a7802SBaban Kenkre * Queue LDAP result for the given query. 11292b4a7802SBaban Kenkre * 11302b4a7802SBaban Kenkre * Return values: 11312b4a7802SBaban Kenkre * 0 success 11322b4a7802SBaban Kenkre * -1 ignore result 11332b4a7802SBaban Kenkre * -2 error 11342b4a7802SBaban Kenkre */ 11352b4a7802SBaban Kenkre static 11362b4a7802SBaban Kenkre int 11372b4a7802SBaban Kenkre make_entry(adutils_q_t *q, adutils_host_t *adh, LDAPMessage *search_res, 11382b4a7802SBaban Kenkre adutils_entry_t **entry) 11392b4a7802SBaban Kenkre { 11402b4a7802SBaban Kenkre BerElement *ber = NULL; 11412b4a7802SBaban Kenkre BerValue **bvalues = NULL; 11422b4a7802SBaban Kenkre char **strvalues; 11432b4a7802SBaban Kenkre char *attr = NULL, *dn = NULL, *domain = NULL; 11442b4a7802SBaban Kenkre adutils_entry_t *ep; 11452b4a7802SBaban Kenkre adutils_attr_t *ap; 11461fcced4cSJordan Brown int i, j, b, ret = -2; 11472b4a7802SBaban Kenkre 11482b4a7802SBaban Kenkre *entry = NULL; 11492b4a7802SBaban Kenkre 11502b4a7802SBaban Kenkre /* Check that this is the domain that we were looking for */ 11512b4a7802SBaban Kenkre if ((dn = ldap_get_dn(adh->ld, search_res)) == NULL) 11522b4a7802SBaban Kenkre return (-2); 11532b4a7802SBaban Kenkre if ((domain = adutils_dn2dns(dn)) == NULL) { 11542b4a7802SBaban Kenkre ldap_memfree(dn); 11552b4a7802SBaban Kenkre return (-2); 11562b4a7802SBaban Kenkre } 11572b4a7802SBaban Kenkre if (q->edomain != NULL) { 11581fcced4cSJordan Brown if (!domain_eq(q->edomain, domain)) { 11592b4a7802SBaban Kenkre ldap_memfree(dn); 11602b4a7802SBaban Kenkre free(domain); 11612b4a7802SBaban Kenkre return (-1); 11622b4a7802SBaban Kenkre } 11632b4a7802SBaban Kenkre } 11642b4a7802SBaban Kenkre free(domain); 11652b4a7802SBaban Kenkre 11662b4a7802SBaban Kenkre /* Allocate memory for the entry */ 11672b4a7802SBaban Kenkre if ((ep = calloc(1, sizeof (*ep))) == NULL) 11682b4a7802SBaban Kenkre goto out; 11692b4a7802SBaban Kenkre 11702b4a7802SBaban Kenkre /* For 'dn' */ 11712b4a7802SBaban Kenkre ep->num_nvpairs = 1; 11722b4a7802SBaban Kenkre 11732b4a7802SBaban Kenkre /* Count the number of name-value pairs for this entry */ 11742b4a7802SBaban Kenkre for (attr = ldap_first_attribute(adh->ld, search_res, &ber); 11752b4a7802SBaban Kenkre attr != NULL; 11762b4a7802SBaban Kenkre attr = ldap_next_attribute(adh->ld, search_res, ber)) { 11772b4a7802SBaban Kenkre ep->num_nvpairs++; 11782b4a7802SBaban Kenkre ldap_memfree(attr); 11792b4a7802SBaban Kenkre } 11802b4a7802SBaban Kenkre ber_free(ber, 0); 11812b4a7802SBaban Kenkre ber = NULL; 11822b4a7802SBaban Kenkre 11832b4a7802SBaban Kenkre /* Allocate array for the attribute name-value pairs */ 11842b4a7802SBaban Kenkre ep->attr_nvpairs = calloc(ep->num_nvpairs, sizeof (*ep->attr_nvpairs)); 11852b4a7802SBaban Kenkre if (ep->attr_nvpairs == NULL) { 11862b4a7802SBaban Kenkre ep->num_nvpairs = 0; 11872b4a7802SBaban Kenkre goto out; 11882b4a7802SBaban Kenkre } 11892b4a7802SBaban Kenkre 11902b4a7802SBaban Kenkre /* For dn */ 11912b4a7802SBaban Kenkre ap = &ep->attr_nvpairs[0]; 11922b4a7802SBaban Kenkre if ((ap->attr_name = strdup("dn")) == NULL) 11932b4a7802SBaban Kenkre goto out; 11942b4a7802SBaban Kenkre ap->num_values = 1; 11952b4a7802SBaban Kenkre ap->attr_values = calloc(ap->num_values, sizeof (*ap->attr_values)); 11962b4a7802SBaban Kenkre if (ap->attr_values == NULL) { 11972b4a7802SBaban Kenkre ap->num_values = 0; 11982b4a7802SBaban Kenkre goto out; 11992b4a7802SBaban Kenkre } 12002b4a7802SBaban Kenkre ap->attr_values[0] = dn; 12012b4a7802SBaban Kenkre dn = NULL; 12022b4a7802SBaban Kenkre 12032b4a7802SBaban Kenkre for (attr = ldap_first_attribute(adh->ld, search_res, &ber), i = 1; 12042b4a7802SBaban Kenkre attr != NULL; 12052b4a7802SBaban Kenkre ldap_memfree(attr), i++, 12062b4a7802SBaban Kenkre attr = ldap_next_attribute(adh->ld, search_res, ber)) { 12072b4a7802SBaban Kenkre ap = &ep->attr_nvpairs[i]; 12082b4a7802SBaban Kenkre if ((ap->attr_name = strdup(attr)) == NULL) 12092b4a7802SBaban Kenkre goto out; 12102b4a7802SBaban Kenkre 12112b4a7802SBaban Kenkre if ((b = check_for_binary_attrs(attr)) >= 0) { 12122b4a7802SBaban Kenkre bvalues = 12132b4a7802SBaban Kenkre ldap_get_values_len(adh->ld, search_res, attr); 12142b4a7802SBaban Kenkre if (bvalues == NULL) 12152b4a7802SBaban Kenkre continue; 12162b4a7802SBaban Kenkre ap->num_values = ldap_count_values_len(bvalues); 12172b4a7802SBaban Kenkre if (ap->num_values == 0) { 12182b4a7802SBaban Kenkre ldap_value_free_len(bvalues); 12192b4a7802SBaban Kenkre bvalues = NULL; 12202b4a7802SBaban Kenkre continue; 12212b4a7802SBaban Kenkre } 12222b4a7802SBaban Kenkre ap->attr_values = calloc(ap->num_values, 12232b4a7802SBaban Kenkre sizeof (*ap->attr_values)); 12242b4a7802SBaban Kenkre if (ap->attr_values == NULL) { 12252b4a7802SBaban Kenkre ap->num_values = 0; 12262b4a7802SBaban Kenkre goto out; 12272b4a7802SBaban Kenkre } 12282b4a7802SBaban Kenkre for (j = 0; j < ap->num_values; j++) { 12292b4a7802SBaban Kenkre ap->attr_values[j] = 12302b4a7802SBaban Kenkre binattrs[b].ber2str(bvalues[j]); 12312b4a7802SBaban Kenkre if (ap->attr_values[j] == NULL) 12322b4a7802SBaban Kenkre goto out; 12332b4a7802SBaban Kenkre } 12342b4a7802SBaban Kenkre ldap_value_free_len(bvalues); 12352b4a7802SBaban Kenkre bvalues = NULL; 12362b4a7802SBaban Kenkre continue; 12372b4a7802SBaban Kenkre } 12382b4a7802SBaban Kenkre 12392b4a7802SBaban Kenkre strvalues = ldap_get_values(adh->ld, search_res, attr); 12402b4a7802SBaban Kenkre if (strvalues == NULL) 12412b4a7802SBaban Kenkre continue; 12422b4a7802SBaban Kenkre ap->num_values = ldap_count_values(strvalues); 12432b4a7802SBaban Kenkre if (ap->num_values == 0) { 12442b4a7802SBaban Kenkre ldap_value_free(strvalues); 12452b4a7802SBaban Kenkre continue; 12462b4a7802SBaban Kenkre } 12472b4a7802SBaban Kenkre ap->attr_values = strvalues; 12482b4a7802SBaban Kenkre } 12492b4a7802SBaban Kenkre 12502b4a7802SBaban Kenkre ret = 0; 12512b4a7802SBaban Kenkre out: 12522b4a7802SBaban Kenkre ldap_memfree(attr); 12532b4a7802SBaban Kenkre ldap_memfree(dn); 12542b4a7802SBaban Kenkre ber_free(ber, 0); 12552b4a7802SBaban Kenkre ldap_value_free_len(bvalues); 12562b4a7802SBaban Kenkre if (ret < 0) 12572b4a7802SBaban Kenkre free_entry(ep); 12582b4a7802SBaban Kenkre else 12592b4a7802SBaban Kenkre *entry = ep; 12602b4a7802SBaban Kenkre return (ret); 12612b4a7802SBaban Kenkre } 12622b4a7802SBaban Kenkre 12632b4a7802SBaban Kenkre /* 12642b4a7802SBaban Kenkre * Put the search result onto the given adutils_q_t. 12652b4a7802SBaban Kenkre * Returns: 0 success 12662b4a7802SBaban Kenkre * < 0 error 12672b4a7802SBaban Kenkre */ 12682b4a7802SBaban Kenkre static 12692b4a7802SBaban Kenkre int 12702b4a7802SBaban Kenkre add_entry(adutils_host_t *adh, adutils_q_t *q, LDAPMessage *search_res) 12712b4a7802SBaban Kenkre { 12722b4a7802SBaban Kenkre int ret = -1; 12732b4a7802SBaban Kenkre adutils_entry_t *entry = NULL; 12742b4a7802SBaban Kenkre adutils_result_t *res; 12752b4a7802SBaban Kenkre 12762b4a7802SBaban Kenkre ret = make_entry(q, adh, search_res, &entry); 12772b4a7802SBaban Kenkre if (ret < -1) { 12782b4a7802SBaban Kenkre *q->rc = ADUTILS_ERR_MEMORY; 12792b4a7802SBaban Kenkre goto out; 12802b4a7802SBaban Kenkre } else if (ret == -1) { 12812b4a7802SBaban Kenkre /* ignore result */ 12822b4a7802SBaban Kenkre goto out; 12832b4a7802SBaban Kenkre } 12842b4a7802SBaban Kenkre if (*q->result == NULL) { 12852b4a7802SBaban Kenkre res = calloc(1, sizeof (*res)); 12862b4a7802SBaban Kenkre if (res == NULL) { 12872b4a7802SBaban Kenkre *q->rc = ADUTILS_ERR_MEMORY; 12882b4a7802SBaban Kenkre goto out; 12892b4a7802SBaban Kenkre } 12902b4a7802SBaban Kenkre res->num_entries = 1; 12912b4a7802SBaban Kenkre res->entries = entry; 12922b4a7802SBaban Kenkre *q->result = res; 12932b4a7802SBaban Kenkre } else { 12942b4a7802SBaban Kenkre res = *q->result; 12952b4a7802SBaban Kenkre entry->next = res->entries; 12962b4a7802SBaban Kenkre res->entries = entry; 12972b4a7802SBaban Kenkre res->num_entries++; 12982b4a7802SBaban Kenkre } 12992b4a7802SBaban Kenkre *q->rc = ADUTILS_SUCCESS; 13002b4a7802SBaban Kenkre entry = NULL; 13012b4a7802SBaban Kenkre ret = 0; 13022b4a7802SBaban Kenkre 13032b4a7802SBaban Kenkre out: 13042b4a7802SBaban Kenkre free_entry(entry); 13052b4a7802SBaban Kenkre return (ret); 13062b4a7802SBaban Kenkre } 13072b4a7802SBaban Kenkre 13082b4a7802SBaban Kenkre /* 13092b4a7802SBaban Kenkre * Try to get a result; if there is one, find the corresponding 13102b4a7802SBaban Kenkre * adutils_q_t and process the result. 13112b4a7802SBaban Kenkre * 13122b4a7802SBaban Kenkre * Returns: 0 success 13132b4a7802SBaban Kenkre * -1 error 13142b4a7802SBaban Kenkre */ 13152b4a7802SBaban Kenkre static 13162b4a7802SBaban Kenkre int 13172b4a7802SBaban Kenkre get_adobject_batch(adutils_host_t *adh, struct timeval *timeout) 13182b4a7802SBaban Kenkre { 13192b4a7802SBaban Kenkre adutils_query_state_t *query_state; 13202b4a7802SBaban Kenkre LDAPMessage *res = NULL; 13212b4a7802SBaban Kenkre int rc, ret, msgid, qid; 13222b4a7802SBaban Kenkre adutils_q_t *que; 13232b4a7802SBaban Kenkre int num; 13242b4a7802SBaban Kenkre 13252b4a7802SBaban Kenkre (void) pthread_mutex_lock(&adh->lock); 13262b4a7802SBaban Kenkre if (adh->dead || adh->num_requests == 0) { 13272b4a7802SBaban Kenkre ret = (adh->dead) ? -1 : -2; 13282b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&adh->lock); 13292b4a7802SBaban Kenkre return (ret); 13302b4a7802SBaban Kenkre } 13312b4a7802SBaban Kenkre 13322b4a7802SBaban Kenkre /* Get one result */ 13332b4a7802SBaban Kenkre rc = ldap_result(adh->ld, LDAP_RES_ANY, 0, timeout, &res); 13342b4a7802SBaban Kenkre if ((timeout != NULL && timeout->tv_sec > 0 && rc == LDAP_SUCCESS) || 13352b4a7802SBaban Kenkre rc < 0) 13362b4a7802SBaban Kenkre adh->dead = 1; 13372b4a7802SBaban Kenkre 13382b4a7802SBaban Kenkre if (rc == LDAP_RES_SEARCH_RESULT && adh->num_requests > 0) 13392b4a7802SBaban Kenkre adh->num_requests--; 13402b4a7802SBaban Kenkre if (adh->dead) { 13412b4a7802SBaban Kenkre num = adh->num_requests; 13422b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&adh->lock); 13437a8a68f5SJulian Pullen logger(LOG_DEBUG, 13442b4a7802SBaban Kenkre "AD ldap_result error - %d queued requests", num); 13452b4a7802SBaban Kenkre return (-1); 13462b4a7802SBaban Kenkre } 13472b4a7802SBaban Kenkre 13482b4a7802SBaban Kenkre switch (rc) { 13492b4a7802SBaban Kenkre case LDAP_RES_SEARCH_RESULT: 13502b4a7802SBaban Kenkre msgid = ldap_msgid(res); 13512b4a7802SBaban Kenkre if (msgid2query(adh, msgid, &query_state, &qid)) { 13522b4a7802SBaban Kenkre if (query_state->ldap_res_search_cb != NULL) { 13532b4a7802SBaban Kenkre /* 13542b4a7802SBaban Kenkre * We use the caller-provided callback 13552b4a7802SBaban Kenkre * to process the result. 13562b4a7802SBaban Kenkre */ 13572b4a7802SBaban Kenkre query_state->ldap_res_search_cb( 13582b4a7802SBaban Kenkre adh->ld, &res, rc, qid, 13592b4a7802SBaban Kenkre query_state->ldap_res_search_argp); 13602b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&adh->lock); 13612b4a7802SBaban Kenkre } else { 13622b4a7802SBaban Kenkre /* 13632b4a7802SBaban Kenkre * No callback. We fallback to our 13642b4a7802SBaban Kenkre * default behaviour. All the entries 13652b4a7802SBaban Kenkre * gotten from this search have been 13662b4a7802SBaban Kenkre * added to the result list during 13672b4a7802SBaban Kenkre * LDAP_RES_SEARCH_ENTRY (see below). 13682b4a7802SBaban Kenkre * Here we set the return status to 13692b4a7802SBaban Kenkre * notfound if the result is still empty. 13702b4a7802SBaban Kenkre */ 13712b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&adh->lock); 13722b4a7802SBaban Kenkre que = &(query_state->queries[qid]); 13732b4a7802SBaban Kenkre if (*que->result == NULL) 13742b4a7802SBaban Kenkre *que->rc = ADUTILS_ERR_NOTFOUND; 13752b4a7802SBaban Kenkre } 13762b4a7802SBaban Kenkre atomic_dec_32(&query_state->qinflight); 13772b4a7802SBaban Kenkre adutils_lookup_batch_unlock(&query_state); 13782b4a7802SBaban Kenkre } else { 13792b4a7802SBaban Kenkre num = adh->num_requests; 13802b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&adh->lock); 13817a8a68f5SJulian Pullen logger(LOG_DEBUG, 13822b4a7802SBaban Kenkre "AD cannot find message ID (%d) " 13832b4a7802SBaban Kenkre "- %d queued requests", 13842b4a7802SBaban Kenkre msgid, num); 13852b4a7802SBaban Kenkre } 13862b4a7802SBaban Kenkre (void) ldap_msgfree(res); 13872b4a7802SBaban Kenkre ret = 0; 13882b4a7802SBaban Kenkre break; 13892b4a7802SBaban Kenkre 13902b4a7802SBaban Kenkre case LDAP_RES_SEARCH_ENTRY: 13912b4a7802SBaban Kenkre msgid = ldap_msgid(res); 13922b4a7802SBaban Kenkre if (msgid2query(adh, msgid, &query_state, &qid)) { 13932b4a7802SBaban Kenkre if (query_state->ldap_res_search_cb != NULL) { 13942b4a7802SBaban Kenkre /* 13952b4a7802SBaban Kenkre * We use the caller-provided callback 13962b4a7802SBaban Kenkre * to process the entry. 13972b4a7802SBaban Kenkre */ 13982b4a7802SBaban Kenkre query_state->ldap_res_search_cb( 13992b4a7802SBaban Kenkre adh->ld, &res, rc, qid, 14002b4a7802SBaban Kenkre query_state->ldap_res_search_argp); 14012b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&adh->lock); 14022b4a7802SBaban Kenkre } else { 14032b4a7802SBaban Kenkre /* 14042b4a7802SBaban Kenkre * No callback. We fallback to our 14052b4a7802SBaban Kenkre * default behaviour. This entry 14062b4a7802SBaban Kenkre * will be added to the result list. 14072b4a7802SBaban Kenkre */ 14082b4a7802SBaban Kenkre que = &(query_state->queries[qid]); 14092b4a7802SBaban Kenkre rc = add_entry(adh, que, res); 14102b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&adh->lock); 14112b4a7802SBaban Kenkre if (rc < 0) { 14127a8a68f5SJulian Pullen logger(LOG_DEBUG, 14132b4a7802SBaban Kenkre "Failed to queue entry by " 14142b4a7802SBaban Kenkre "message ID (%d) " 14152b4a7802SBaban Kenkre "- %d queued requests", 14162b4a7802SBaban Kenkre msgid, num); 14172b4a7802SBaban Kenkre } 14182b4a7802SBaban Kenkre } 14192b4a7802SBaban Kenkre adutils_lookup_batch_unlock(&query_state); 14202b4a7802SBaban Kenkre } else { 14212b4a7802SBaban Kenkre num = adh->num_requests; 14222b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&adh->lock); 14237a8a68f5SJulian Pullen logger(LOG_DEBUG, 14242b4a7802SBaban Kenkre "AD cannot find message ID (%d) " 14252b4a7802SBaban Kenkre "- %d queued requests", 14262b4a7802SBaban Kenkre msgid, num); 14272b4a7802SBaban Kenkre } 14282b4a7802SBaban Kenkre (void) ldap_msgfree(res); 14292b4a7802SBaban Kenkre ret = 0; 14302b4a7802SBaban Kenkre break; 14312b4a7802SBaban Kenkre 14322b4a7802SBaban Kenkre case LDAP_RES_SEARCH_REFERENCE: 14332b4a7802SBaban Kenkre /* 14342b4a7802SBaban Kenkre * We have no need for these at the moment. Eventually, 14352b4a7802SBaban Kenkre * when we query things that we can't expect to find in 14362b4a7802SBaban Kenkre * the Global Catalog then we'll need to learn to follow 14372b4a7802SBaban Kenkre * references. 14382b4a7802SBaban Kenkre */ 14392b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&adh->lock); 14402b4a7802SBaban Kenkre (void) ldap_msgfree(res); 14412b4a7802SBaban Kenkre ret = 0; 14422b4a7802SBaban Kenkre break; 14432b4a7802SBaban Kenkre 14442b4a7802SBaban Kenkre default: 14452b4a7802SBaban Kenkre /* timeout or error; treat the same */ 14462b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&adh->lock); 14472b4a7802SBaban Kenkre ret = -1; 14482b4a7802SBaban Kenkre break; 14492b4a7802SBaban Kenkre } 14502b4a7802SBaban Kenkre 14512b4a7802SBaban Kenkre return (ret); 14522b4a7802SBaban Kenkre } 14532b4a7802SBaban Kenkre 14542b4a7802SBaban Kenkre /* 14552b4a7802SBaban Kenkre * This routine decreament the reference count of the 14562b4a7802SBaban Kenkre * adutils_query_state_t 14572b4a7802SBaban Kenkre */ 14582b4a7802SBaban Kenkre static void 14592b4a7802SBaban Kenkre adutils_lookup_batch_unlock(adutils_query_state_t **state) 14602b4a7802SBaban Kenkre { 14612b4a7802SBaban Kenkre /* 14622b4a7802SBaban Kenkre * Decrement reference count with qstatelock locked 14632b4a7802SBaban Kenkre */ 14642b4a7802SBaban Kenkre (void) pthread_mutex_lock(&qstatelock); 14652b4a7802SBaban Kenkre (*state)->ref_cnt--; 14662b4a7802SBaban Kenkre /* 14672b4a7802SBaban Kenkre * If there are no references wakup the allocating thread 14682b4a7802SBaban Kenkre */ 14692b4a7802SBaban Kenkre if ((*state)->ref_cnt <= 1) 14702b4a7802SBaban Kenkre (void) pthread_cond_signal(&(*state)->cv); 14712b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&qstatelock); 14722b4a7802SBaban Kenkre *state = NULL; 14732b4a7802SBaban Kenkre } 14742b4a7802SBaban Kenkre 14752b4a7802SBaban Kenkre /* 14762b4a7802SBaban Kenkre * This routine frees the adutils_query_state_t structure 14772b4a7802SBaban Kenkre * If the reference count is greater than 1 it waits 14782b4a7802SBaban Kenkre * for the other threads to finish using it. 14792b4a7802SBaban Kenkre */ 14802b4a7802SBaban Kenkre void 14812b4a7802SBaban Kenkre adutils_lookup_batch_release(adutils_query_state_t **state) 14822b4a7802SBaban Kenkre { 14832b4a7802SBaban Kenkre adutils_query_state_t **p; 14842b4a7802SBaban Kenkre int i; 14852b4a7802SBaban Kenkre 14862b4a7802SBaban Kenkre if (state == NULL || *state == NULL) 14872b4a7802SBaban Kenkre return; 14882b4a7802SBaban Kenkre 14892b4a7802SBaban Kenkre /* 14902b4a7802SBaban Kenkre * Set state to dead to stop further operations. 14912b4a7802SBaban Kenkre * Wait for reference count with qstatelock locked 14922b4a7802SBaban Kenkre * to get to one. 14932b4a7802SBaban Kenkre */ 14942b4a7802SBaban Kenkre (void) pthread_mutex_lock(&qstatelock); 14952b4a7802SBaban Kenkre (*state)->qdead = 1; 14962b4a7802SBaban Kenkre while ((*state)->ref_cnt > 1) { 14972b4a7802SBaban Kenkre (void) pthread_cond_wait(&(*state)->cv, &qstatelock); 14982b4a7802SBaban Kenkre } 14992b4a7802SBaban Kenkre 15002b4a7802SBaban Kenkre /* Remove this state struct from the list of state structs */ 15012b4a7802SBaban Kenkre for (p = &qstatehead; *p != NULL; p = &(*p)->next) { 15022b4a7802SBaban Kenkre if (*p == (*state)) { 15032b4a7802SBaban Kenkre *p = (*state)->next; 15042b4a7802SBaban Kenkre break; 15052b4a7802SBaban Kenkre } 15062b4a7802SBaban Kenkre } 15072b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&qstatelock); 15082b4a7802SBaban Kenkre (void) pthread_cond_destroy(&(*state)->cv); 15092b4a7802SBaban Kenkre release_conn((*state)->qadh); 15102b4a7802SBaban Kenkre 15112b4a7802SBaban Kenkre /* Clear results for queries that failed */ 15122b4a7802SBaban Kenkre for (i = 0; i < (*state)->qcount; i++) { 15132b4a7802SBaban Kenkre if (*(*state)->queries[i].rc != ADUTILS_SUCCESS) { 15142b4a7802SBaban Kenkre adutils_freeresult((*state)->queries[i].result); 15152b4a7802SBaban Kenkre } 15162b4a7802SBaban Kenkre } 15172b4a7802SBaban Kenkre free(*state); 15182b4a7802SBaban Kenkre *state = NULL; 15192b4a7802SBaban Kenkre } 15202b4a7802SBaban Kenkre 15212b4a7802SBaban Kenkre 15222b4a7802SBaban Kenkre /* 15232b4a7802SBaban Kenkre * This routine waits for other threads using the 15242b4a7802SBaban Kenkre * adutils_query_state_t structure to finish. 15252b4a7802SBaban Kenkre * If the reference count is greater than 1 it waits 15262b4a7802SBaban Kenkre * for the other threads to finish using it. 15272b4a7802SBaban Kenkre */ 15282b4a7802SBaban Kenkre static 15292b4a7802SBaban Kenkre void 15302b4a7802SBaban Kenkre adutils_lookup_batch_wait(adutils_query_state_t *state) 15312b4a7802SBaban Kenkre { 15322b4a7802SBaban Kenkre /* 15332b4a7802SBaban Kenkre * Set state to dead to stop further operation. 15342b4a7802SBaban Kenkre * stating. 15352b4a7802SBaban Kenkre * Wait for reference count to get to one 15362b4a7802SBaban Kenkre * with qstatelock locked. 15372b4a7802SBaban Kenkre */ 15382b4a7802SBaban Kenkre (void) pthread_mutex_lock(&qstatelock); 15392b4a7802SBaban Kenkre state->qdead = 1; 15402b4a7802SBaban Kenkre while (state->ref_cnt > 1) { 15412b4a7802SBaban Kenkre (void) pthread_cond_wait(&state->cv, &qstatelock); 15422b4a7802SBaban Kenkre } 15432b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&qstatelock); 15442b4a7802SBaban Kenkre } 15452b4a7802SBaban Kenkre 15462b4a7802SBaban Kenkre /* 15472b4a7802SBaban Kenkre * Process active queries in the AD lookup batch and then finalize the 15482b4a7802SBaban Kenkre * result. 15492b4a7802SBaban Kenkre */ 15502b4a7802SBaban Kenkre adutils_rc 15512b4a7802SBaban Kenkre adutils_lookup_batch_end(adutils_query_state_t **state) 15522b4a7802SBaban Kenkre { 15532b4a7802SBaban Kenkre int rc = LDAP_SUCCESS; 15542b4a7802SBaban Kenkre adutils_rc ad_rc = ADUTILS_SUCCESS; 15552b4a7802SBaban Kenkre struct timeval tv; 15562b4a7802SBaban Kenkre 15572b4a7802SBaban Kenkre tv.tv_sec = ADUTILS_SEARCH_TIMEOUT; 15582b4a7802SBaban Kenkre tv.tv_usec = 0; 15592b4a7802SBaban Kenkre 15602b4a7802SBaban Kenkre /* Process results until done or until timeout, if given */ 15612b4a7802SBaban Kenkre while ((*state)->qinflight > 0) { 15622b4a7802SBaban Kenkre if ((rc = get_adobject_batch((*state)->qadh, 15632b4a7802SBaban Kenkre &tv)) != 0) 15642b4a7802SBaban Kenkre break; 15652b4a7802SBaban Kenkre } 15662b4a7802SBaban Kenkre (*state)->qdead = 1; 15672b4a7802SBaban Kenkre /* Wait for other threads processing search result to finish */ 15682b4a7802SBaban Kenkre adutils_lookup_batch_wait(*state); 15692b4a7802SBaban Kenkre if (rc == -1 || (*state)->qinflight != 0) 15702b4a7802SBaban Kenkre ad_rc = ADUTILS_ERR_RETRIABLE_NET_ERR; 15712b4a7802SBaban Kenkre adutils_lookup_batch_release(state); 15722b4a7802SBaban Kenkre return (ad_rc); 15732b4a7802SBaban Kenkre } 15742b4a7802SBaban Kenkre 15752b4a7802SBaban Kenkre /* 15762b4a7802SBaban Kenkre * Send one prepared search, queue up msgid, process what results are 15772b4a7802SBaban Kenkre * available 15782b4a7802SBaban Kenkre */ 15792b4a7802SBaban Kenkre adutils_rc 15802b4a7802SBaban Kenkre adutils_lookup_batch_add(adutils_query_state_t *state, 15811fcced4cSJordan Brown const char *filter, const char * const *attrs, const char *edomain, 15822b4a7802SBaban Kenkre adutils_result_t **result, adutils_rc *rc) 15832b4a7802SBaban Kenkre { 15842b4a7802SBaban Kenkre adutils_rc retcode = ADUTILS_SUCCESS; 15852b4a7802SBaban Kenkre int lrc, qid; 15862b4a7802SBaban Kenkre int num; 15872b4a7802SBaban Kenkre int dead; 15882b4a7802SBaban Kenkre struct timeval tv; 15892b4a7802SBaban Kenkre adutils_q_t *q; 15902b4a7802SBaban Kenkre 15914d61c878SJulian Pullen qid = atomic_inc_32_nv(&state->qcount) - 1; 15922b4a7802SBaban Kenkre q = &(state->queries[qid]); 15932b4a7802SBaban Kenkre 15944d61c878SJulian Pullen assert(qid < state->qsize); 15954d61c878SJulian Pullen 15962b4a7802SBaban Kenkre /* 15972b4a7802SBaban Kenkre * Remember the expected domain so we can check the results 15982b4a7802SBaban Kenkre * against it 15992b4a7802SBaban Kenkre */ 16002b4a7802SBaban Kenkre q->edomain = edomain; 16012b4a7802SBaban Kenkre 16022b4a7802SBaban Kenkre /* Remember where to put the results */ 16032b4a7802SBaban Kenkre q->result = result; 16042b4a7802SBaban Kenkre q->rc = rc; 16052b4a7802SBaban Kenkre 16062b4a7802SBaban Kenkre /* 16072b4a7802SBaban Kenkre * Provide sane defaults for the results in case we never hear 16082b4a7802SBaban Kenkre * back from the DS before closing the connection. 16092b4a7802SBaban Kenkre */ 16102b4a7802SBaban Kenkre *rc = ADUTILS_ERR_RETRIABLE_NET_ERR; 16112b4a7802SBaban Kenkre if (result != NULL) 16122b4a7802SBaban Kenkre *result = NULL; 16132b4a7802SBaban Kenkre 16142b4a7802SBaban Kenkre /* Check the number of queued requests first */ 16152b4a7802SBaban Kenkre tv.tv_sec = ADUTILS_SEARCH_TIMEOUT; 16162b4a7802SBaban Kenkre tv.tv_usec = 0; 16172b4a7802SBaban Kenkre while (!state->qadh->dead && 16182b4a7802SBaban Kenkre state->qadh->num_requests > state->qadh->max_requests) { 16192b4a7802SBaban Kenkre if (get_adobject_batch(state->qadh, &tv) != 0) 16202b4a7802SBaban Kenkre break; 16212b4a7802SBaban Kenkre } 16222b4a7802SBaban Kenkre 16232b4a7802SBaban Kenkre /* Send this lookup, don't wait for a result here */ 16242b4a7802SBaban Kenkre lrc = LDAP_SUCCESS; 16252b4a7802SBaban Kenkre (void) pthread_mutex_lock(&state->qadh->lock); 16262b4a7802SBaban Kenkre 16272b4a7802SBaban Kenkre if (!state->qadh->dead) { 16282b4a7802SBaban Kenkre state->qadh->idletime = time(NULL); 1629e3f2c991SKeyur Desai 1630e3f2c991SKeyur Desai lrc = ldap_search_ext(state->qadh->ld, 1631e3f2c991SKeyur Desai state->qadh->owner->basedn, 16322b4a7802SBaban Kenkre LDAP_SCOPE_SUBTREE, filter, (char **)attrs, 16332b4a7802SBaban Kenkre 0, NULL, NULL, NULL, -1, &q->msgid); 16342b4a7802SBaban Kenkre 16352b4a7802SBaban Kenkre if (lrc == LDAP_SUCCESS) { 16362b4a7802SBaban Kenkre state->qadh->num_requests++; 16372b4a7802SBaban Kenkre } else if (lrc == LDAP_BUSY || lrc == LDAP_UNAVAILABLE || 16382b4a7802SBaban Kenkre lrc == LDAP_CONNECT_ERROR || lrc == LDAP_SERVER_DOWN || 16392b4a7802SBaban Kenkre lrc == LDAP_UNWILLING_TO_PERFORM) { 16402b4a7802SBaban Kenkre retcode = ADUTILS_ERR_RETRIABLE_NET_ERR; 16412b4a7802SBaban Kenkre state->qadh->dead = 1; 16422b4a7802SBaban Kenkre } else { 16432b4a7802SBaban Kenkre retcode = ADUTILS_ERR_OTHER; 16442b4a7802SBaban Kenkre state->qadh->dead = 1; 16452b4a7802SBaban Kenkre } 16462b4a7802SBaban Kenkre } 16472b4a7802SBaban Kenkre dead = state->qadh->dead; 16482b4a7802SBaban Kenkre num = state->qadh->num_requests; 16492b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&state->qadh->lock); 16502b4a7802SBaban Kenkre 16512b4a7802SBaban Kenkre if (dead) { 16522b4a7802SBaban Kenkre if (lrc != LDAP_SUCCESS) 16537a8a68f5SJulian Pullen logger(LOG_DEBUG, 16542b4a7802SBaban Kenkre "AD ldap_search_ext error (%s) " 16552b4a7802SBaban Kenkre "- %d queued requests", 16562b4a7802SBaban Kenkre ldap_err2string(lrc), num); 16572b4a7802SBaban Kenkre return (retcode); 16582b4a7802SBaban Kenkre } 16592b4a7802SBaban Kenkre 16602b4a7802SBaban Kenkre atomic_inc_32(&state->qinflight); 16612b4a7802SBaban Kenkre 16622b4a7802SBaban Kenkre /* 16632b4a7802SBaban Kenkre * Reap as many requests as we can _without_ waiting to prevent 16642b4a7802SBaban Kenkre * any possible TCP socket buffer starvation deadlocks. 16652b4a7802SBaban Kenkre */ 16662b4a7802SBaban Kenkre (void) memset(&tv, 0, sizeof (tv)); 16672b4a7802SBaban Kenkre while (get_adobject_batch(state->qadh, &tv) == 0) 16682b4a7802SBaban Kenkre ; 16692b4a7802SBaban Kenkre 16702b4a7802SBaban Kenkre return (ADUTILS_SUCCESS); 16712b4a7802SBaban Kenkre } 16722b4a7802SBaban Kenkre 16732b4a7802SBaban Kenkre /* 16742b4a7802SBaban Kenkre * Single AD lookup request implemented on top of the batch API. 16752b4a7802SBaban Kenkre */ 16762b4a7802SBaban Kenkre adutils_rc 16772b4a7802SBaban Kenkre adutils_lookup(adutils_ad_t *ad, const char *filter, const char **attrs, 16782b4a7802SBaban Kenkre const char *domain, adutils_result_t **result) 16792b4a7802SBaban Kenkre { 16802b4a7802SBaban Kenkre adutils_rc rc, brc; 16812b4a7802SBaban Kenkre adutils_query_state_t *qs; 16822b4a7802SBaban Kenkre 16832b4a7802SBaban Kenkre rc = adutils_lookup_batch_start(ad, 1, NULL, NULL, &qs); 16842b4a7802SBaban Kenkre if (rc != ADUTILS_SUCCESS) 16852b4a7802SBaban Kenkre return (rc); 16862b4a7802SBaban Kenkre 16872b4a7802SBaban Kenkre rc = adutils_lookup_batch_add(qs, filter, attrs, domain, result, &brc); 16882b4a7802SBaban Kenkre if (rc != ADUTILS_SUCCESS) { 16892b4a7802SBaban Kenkre adutils_lookup_batch_release(&qs); 16902b4a7802SBaban Kenkre return (rc); 16912b4a7802SBaban Kenkre } 16922b4a7802SBaban Kenkre 16932b4a7802SBaban Kenkre rc = adutils_lookup_batch_end(&qs); 16942b4a7802SBaban Kenkre if (rc != ADUTILS_SUCCESS) 16952b4a7802SBaban Kenkre return (rc); 16962b4a7802SBaban Kenkre return (brc); 16972b4a7802SBaban Kenkre } 16981fcced4cSJordan Brown 16991fcced4cSJordan Brown boolean_t 17001fcced4cSJordan Brown domain_eq(const char *a, const char *b) 17011fcced4cSJordan Brown { 17021fcced4cSJordan Brown int err; 17031fcced4cSJordan Brown 17041fcced4cSJordan Brown return (u8_strcmp(a, b, 0, U8_STRCMP_CI_LOWER, U8_UNICODE_LATEST, &err) 17051fcced4cSJordan Brown == 0 && err == 0); 17061fcced4cSJordan Brown } 1707*148c5f43SAlan Wright 1708*148c5f43SAlan Wright void 1709*148c5f43SAlan Wright adutils_set_debug(enum ad_debug item, int value) 1710*148c5f43SAlan Wright { 1711*148c5f43SAlan Wright if (item >= 0 && item <= AD_DEBUG_MAX) 1712*148c5f43SAlan Wright ad_debug[item] = value; 1713*148c5f43SAlan Wright } 1714