1*8040SBaban.Kenkre@Sun.COM /* 2*8040SBaban.Kenkre@Sun.COM * CDDL HEADER START 3*8040SBaban.Kenkre@Sun.COM * 4*8040SBaban.Kenkre@Sun.COM * The contents of this file are subject to the terms of the 5*8040SBaban.Kenkre@Sun.COM * Common Development and Distribution License (the "License"). 6*8040SBaban.Kenkre@Sun.COM * You may not use this file except in compliance with the License. 7*8040SBaban.Kenkre@Sun.COM * 8*8040SBaban.Kenkre@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*8040SBaban.Kenkre@Sun.COM * or http://www.opensolaris.org/os/licensing. 10*8040SBaban.Kenkre@Sun.COM * See the License for the specific language governing permissions 11*8040SBaban.Kenkre@Sun.COM * and limitations under the License. 12*8040SBaban.Kenkre@Sun.COM * 13*8040SBaban.Kenkre@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 14*8040SBaban.Kenkre@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*8040SBaban.Kenkre@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 16*8040SBaban.Kenkre@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 17*8040SBaban.Kenkre@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 18*8040SBaban.Kenkre@Sun.COM * 19*8040SBaban.Kenkre@Sun.COM * CDDL HEADER END 20*8040SBaban.Kenkre@Sun.COM */ 21*8040SBaban.Kenkre@Sun.COM /* 22*8040SBaban.Kenkre@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23*8040SBaban.Kenkre@Sun.COM * Use is subject to license terms. 24*8040SBaban.Kenkre@Sun.COM */ 25*8040SBaban.Kenkre@Sun.COM 26*8040SBaban.Kenkre@Sun.COM #include <alloca.h> 27*8040SBaban.Kenkre@Sun.COM #include <string.h> 28*8040SBaban.Kenkre@Sun.COM #include <strings.h> 29*8040SBaban.Kenkre@Sun.COM #include <lber.h> 30*8040SBaban.Kenkre@Sun.COM #include <sasl/sasl.h> 31*8040SBaban.Kenkre@Sun.COM #include <string.h> 32*8040SBaban.Kenkre@Sun.COM #include <ctype.h> 33*8040SBaban.Kenkre@Sun.COM #include <synch.h> 34*8040SBaban.Kenkre@Sun.COM #include <atomic.h> 35*8040SBaban.Kenkre@Sun.COM #include <errno.h> 36*8040SBaban.Kenkre@Sun.COM #include <assert.h> 37*8040SBaban.Kenkre@Sun.COM #include <limits.h> 38*8040SBaban.Kenkre@Sun.COM #include <sys/u8_textprep.h> 39*8040SBaban.Kenkre@Sun.COM #include <sys/varargs.h> 40*8040SBaban.Kenkre@Sun.COM #include "libadutils.h" 41*8040SBaban.Kenkre@Sun.COM #include "adutils_impl.h" 42*8040SBaban.Kenkre@Sun.COM 43*8040SBaban.Kenkre@Sun.COM /* List of DSs, needed by the idle connection reaper thread */ 44*8040SBaban.Kenkre@Sun.COM static pthread_mutex_t adhostlock = PTHREAD_MUTEX_INITIALIZER; 45*8040SBaban.Kenkre@Sun.COM static adutils_host_t *host_head = NULL; 46*8040SBaban.Kenkre@Sun.COM 47*8040SBaban.Kenkre@Sun.COM /* 48*8040SBaban.Kenkre@Sun.COM * List of query state structs -- needed so we can "route" LDAP results 49*8040SBaban.Kenkre@Sun.COM * to the right context if multiple threads should be using the same 50*8040SBaban.Kenkre@Sun.COM * connection concurrently 51*8040SBaban.Kenkre@Sun.COM */ 52*8040SBaban.Kenkre@Sun.COM static pthread_mutex_t qstatelock = PTHREAD_MUTEX_INITIALIZER; 53*8040SBaban.Kenkre@Sun.COM static adutils_query_state_t *qstatehead = NULL; 54*8040SBaban.Kenkre@Sun.COM 55*8040SBaban.Kenkre@Sun.COM static char *adutils_sid_ber2str(BerValue *bvalues); 56*8040SBaban.Kenkre@Sun.COM static void adutils_lookup_batch_unlock(adutils_query_state_t **state); 57*8040SBaban.Kenkre@Sun.COM static void delete_ds(adutils_ad_t *ad, const char *host, int port); 58*8040SBaban.Kenkre@Sun.COM 59*8040SBaban.Kenkre@Sun.COM typedef struct binary_attrs { 60*8040SBaban.Kenkre@Sun.COM const char *name; 61*8040SBaban.Kenkre@Sun.COM char *(*ber2str)(BerValue *bvalues); 62*8040SBaban.Kenkre@Sun.COM } binary_attrs_t; 63*8040SBaban.Kenkre@Sun.COM 64*8040SBaban.Kenkre@Sun.COM static binary_attrs_t binattrs[] = { 65*8040SBaban.Kenkre@Sun.COM {"objectSID", adutils_sid_ber2str}, 66*8040SBaban.Kenkre@Sun.COM {NULL, NULL} 67*8040SBaban.Kenkre@Sun.COM }; 68*8040SBaban.Kenkre@Sun.COM 69*8040SBaban.Kenkre@Sun.COM void 70*8040SBaban.Kenkre@Sun.COM adutils_set_log(int pri, bool_t syslog, bool_t degraded) 71*8040SBaban.Kenkre@Sun.COM { 72*8040SBaban.Kenkre@Sun.COM idmap_log_stderr(pri); 73*8040SBaban.Kenkre@Sun.COM idmap_log_syslog(syslog); 74*8040SBaban.Kenkre@Sun.COM idmap_log_degraded(degraded); 75*8040SBaban.Kenkre@Sun.COM } 76*8040SBaban.Kenkre@Sun.COM 77*8040SBaban.Kenkre@Sun.COM /* 78*8040SBaban.Kenkre@Sun.COM * Turn "foo.bar.com" into "dc=foo,dc=bar,dc=com" 79*8040SBaban.Kenkre@Sun.COM */ 80*8040SBaban.Kenkre@Sun.COM static 81*8040SBaban.Kenkre@Sun.COM char * 82*8040SBaban.Kenkre@Sun.COM adutils_dns2dn(const char *dns) 83*8040SBaban.Kenkre@Sun.COM { 84*8040SBaban.Kenkre@Sun.COM int nameparts; 85*8040SBaban.Kenkre@Sun.COM return (ldap_dns_to_dn((char *)dns, &nameparts)); 86*8040SBaban.Kenkre@Sun.COM } 87*8040SBaban.Kenkre@Sun.COM 88*8040SBaban.Kenkre@Sun.COM /* 89*8040SBaban.Kenkre@Sun.COM * Turn "dc=foo,dc=bar,dc=com" into "foo.bar.com"; ignores any other 90*8040SBaban.Kenkre@Sun.COM * attributes (CN, etc...). 91*8040SBaban.Kenkre@Sun.COM */ 92*8040SBaban.Kenkre@Sun.COM char * 93*8040SBaban.Kenkre@Sun.COM adutils_dn2dns(const char *dn) 94*8040SBaban.Kenkre@Sun.COM { 95*8040SBaban.Kenkre@Sun.COM char **rdns = NULL; 96*8040SBaban.Kenkre@Sun.COM char **attrs = NULL; 97*8040SBaban.Kenkre@Sun.COM char **labels = NULL; 98*8040SBaban.Kenkre@Sun.COM char *dns = NULL; 99*8040SBaban.Kenkre@Sun.COM char **rdn, **attr, **label; 100*8040SBaban.Kenkre@Sun.COM int maxlabels = 5; 101*8040SBaban.Kenkre@Sun.COM int nlabels = 0; 102*8040SBaban.Kenkre@Sun.COM int dnslen; 103*8040SBaban.Kenkre@Sun.COM 104*8040SBaban.Kenkre@Sun.COM /* 105*8040SBaban.Kenkre@Sun.COM * There is no reverse of ldap_dns_to_dn() in our libldap, so we 106*8040SBaban.Kenkre@Sun.COM * have to do the hard work here for now. 107*8040SBaban.Kenkre@Sun.COM */ 108*8040SBaban.Kenkre@Sun.COM 109*8040SBaban.Kenkre@Sun.COM /* 110*8040SBaban.Kenkre@Sun.COM * This code is much too liberal: it looks for "dc" attributes 111*8040SBaban.Kenkre@Sun.COM * in all RDNs of the DN. In theory this could cause problems 112*8040SBaban.Kenkre@Sun.COM * if people were to use "dc" in nodes other than the root of 113*8040SBaban.Kenkre@Sun.COM * the tree, but in practice noone, least of all Active 114*8040SBaban.Kenkre@Sun.COM * Directory, does that. 115*8040SBaban.Kenkre@Sun.COM * 116*8040SBaban.Kenkre@Sun.COM * On the other hand, this code is much too conservative: it 117*8040SBaban.Kenkre@Sun.COM * does not make assumptions about ldap_explode_dn(), and _that_ 118*8040SBaban.Kenkre@Sun.COM * is the true for looking at every attr of every RDN. 119*8040SBaban.Kenkre@Sun.COM * 120*8040SBaban.Kenkre@Sun.COM * Since we only ever look at dc and those must be DNS labels, 121*8040SBaban.Kenkre@Sun.COM * at least until we get around to supporting IDN here we 122*8040SBaban.Kenkre@Sun.COM * shouldn't see escaped labels from AD nor from libldap, though 123*8040SBaban.Kenkre@Sun.COM * the spec (RFC2253) does allow libldap to escape things that 124*8040SBaban.Kenkre@Sun.COM * don't need escaping -- if that should ever happen then 125*8040SBaban.Kenkre@Sun.COM * libldap will need a spanking, and we can take care of that. 126*8040SBaban.Kenkre@Sun.COM */ 127*8040SBaban.Kenkre@Sun.COM 128*8040SBaban.Kenkre@Sun.COM /* Explode a DN into RDNs */ 129*8040SBaban.Kenkre@Sun.COM if ((rdns = ldap_explode_dn(dn, 0)) == NULL) 130*8040SBaban.Kenkre@Sun.COM return (NULL); 131*8040SBaban.Kenkre@Sun.COM 132*8040SBaban.Kenkre@Sun.COM labels = calloc(maxlabels + 1, sizeof (char *)); 133*8040SBaban.Kenkre@Sun.COM label = labels; 134*8040SBaban.Kenkre@Sun.COM 135*8040SBaban.Kenkre@Sun.COM for (rdn = rdns; *rdn != NULL; rdn++) { 136*8040SBaban.Kenkre@Sun.COM if (attrs != NULL) 137*8040SBaban.Kenkre@Sun.COM ldap_value_free(attrs); 138*8040SBaban.Kenkre@Sun.COM 139*8040SBaban.Kenkre@Sun.COM /* Explode each RDN, look for DC attr, save val as DNS label */ 140*8040SBaban.Kenkre@Sun.COM if ((attrs = ldap_explode_rdn(rdn[0], 0)) == NULL) 141*8040SBaban.Kenkre@Sun.COM goto done; 142*8040SBaban.Kenkre@Sun.COM 143*8040SBaban.Kenkre@Sun.COM for (attr = attrs; *attr != NULL; attr++) { 144*8040SBaban.Kenkre@Sun.COM if (strncasecmp(*attr, "dc=", 3) != 0) 145*8040SBaban.Kenkre@Sun.COM continue; 146*8040SBaban.Kenkre@Sun.COM 147*8040SBaban.Kenkre@Sun.COM /* Found a DNS label */ 148*8040SBaban.Kenkre@Sun.COM labels[nlabels++] = strdup((*attr) + 3); 149*8040SBaban.Kenkre@Sun.COM 150*8040SBaban.Kenkre@Sun.COM if (nlabels == maxlabels) { 151*8040SBaban.Kenkre@Sun.COM char **tmp; 152*8040SBaban.Kenkre@Sun.COM tmp = realloc(labels, 153*8040SBaban.Kenkre@Sun.COM sizeof (char *) * (maxlabels + 1)); 154*8040SBaban.Kenkre@Sun.COM 155*8040SBaban.Kenkre@Sun.COM if (tmp == NULL) 156*8040SBaban.Kenkre@Sun.COM goto done; 157*8040SBaban.Kenkre@Sun.COM 158*8040SBaban.Kenkre@Sun.COM labels = tmp; 159*8040SBaban.Kenkre@Sun.COM labels[nlabels] = NULL; 160*8040SBaban.Kenkre@Sun.COM } 161*8040SBaban.Kenkre@Sun.COM 162*8040SBaban.Kenkre@Sun.COM /* There should be just one DC= attr per-RDN */ 163*8040SBaban.Kenkre@Sun.COM break; 164*8040SBaban.Kenkre@Sun.COM } 165*8040SBaban.Kenkre@Sun.COM } 166*8040SBaban.Kenkre@Sun.COM 167*8040SBaban.Kenkre@Sun.COM /* 168*8040SBaban.Kenkre@Sun.COM * Got all the labels, now join with '.' 169*8040SBaban.Kenkre@Sun.COM * 170*8040SBaban.Kenkre@Sun.COM * We need room for nlabels - 1 periods ('.'), one nul 171*8040SBaban.Kenkre@Sun.COM * terminator, and the strlen() of each label. 172*8040SBaban.Kenkre@Sun.COM */ 173*8040SBaban.Kenkre@Sun.COM dnslen = nlabels; 174*8040SBaban.Kenkre@Sun.COM for (label = labels; *label != NULL; label++) 175*8040SBaban.Kenkre@Sun.COM dnslen += strlen(*label); 176*8040SBaban.Kenkre@Sun.COM 177*8040SBaban.Kenkre@Sun.COM if ((dns = malloc(dnslen)) == NULL) 178*8040SBaban.Kenkre@Sun.COM goto done; 179*8040SBaban.Kenkre@Sun.COM 180*8040SBaban.Kenkre@Sun.COM *dns = '\0'; 181*8040SBaban.Kenkre@Sun.COM 182*8040SBaban.Kenkre@Sun.COM for (label = labels; *label != NULL; label++) { 183*8040SBaban.Kenkre@Sun.COM (void) strlcat(dns, *label, dnslen); 184*8040SBaban.Kenkre@Sun.COM /* 185*8040SBaban.Kenkre@Sun.COM * NOTE: the last '.' won't be appended -- there's no room 186*8040SBaban.Kenkre@Sun.COM * for it! 187*8040SBaban.Kenkre@Sun.COM */ 188*8040SBaban.Kenkre@Sun.COM (void) strlcat(dns, ".", dnslen); 189*8040SBaban.Kenkre@Sun.COM } 190*8040SBaban.Kenkre@Sun.COM 191*8040SBaban.Kenkre@Sun.COM done: 192*8040SBaban.Kenkre@Sun.COM if (labels != NULL) { 193*8040SBaban.Kenkre@Sun.COM for (label = labels; *label != NULL; label++) 194*8040SBaban.Kenkre@Sun.COM free(*label); 195*8040SBaban.Kenkre@Sun.COM free(labels); 196*8040SBaban.Kenkre@Sun.COM } 197*8040SBaban.Kenkre@Sun.COM if (attrs != NULL) 198*8040SBaban.Kenkre@Sun.COM ldap_value_free(attrs); 199*8040SBaban.Kenkre@Sun.COM if (rdns != NULL) 200*8040SBaban.Kenkre@Sun.COM ldap_value_free(rdns); 201*8040SBaban.Kenkre@Sun.COM 202*8040SBaban.Kenkre@Sun.COM return (dns); 203*8040SBaban.Kenkre@Sun.COM } 204*8040SBaban.Kenkre@Sun.COM 205*8040SBaban.Kenkre@Sun.COM /* 206*8040SBaban.Kenkre@Sun.COM * Convert a binary SID in a BerValue to a adutils_sid_t 207*8040SBaban.Kenkre@Sun.COM */ 208*8040SBaban.Kenkre@Sun.COM static 209*8040SBaban.Kenkre@Sun.COM int 210*8040SBaban.Kenkre@Sun.COM getsid(BerValue *bval, adutils_sid_t *sidp) 211*8040SBaban.Kenkre@Sun.COM { 212*8040SBaban.Kenkre@Sun.COM int i, j; 213*8040SBaban.Kenkre@Sun.COM uchar_t *v; 214*8040SBaban.Kenkre@Sun.COM uint32_t a; 215*8040SBaban.Kenkre@Sun.COM 216*8040SBaban.Kenkre@Sun.COM /* 217*8040SBaban.Kenkre@Sun.COM * The binary format of a SID is as follows: 218*8040SBaban.Kenkre@Sun.COM * 219*8040SBaban.Kenkre@Sun.COM * byte #0: version, always 0x01 220*8040SBaban.Kenkre@Sun.COM * byte #1: RID count, always <= 0x0f 221*8040SBaban.Kenkre@Sun.COM * bytes #2-#7: SID authority, big-endian 48-bit unsigned int 222*8040SBaban.Kenkre@Sun.COM * 223*8040SBaban.Kenkre@Sun.COM * followed by RID count RIDs, each a little-endian, unsigned 224*8040SBaban.Kenkre@Sun.COM * 32-bit int. 225*8040SBaban.Kenkre@Sun.COM */ 226*8040SBaban.Kenkre@Sun.COM /* 227*8040SBaban.Kenkre@Sun.COM * Sanity checks: must have at least one RID, version must be 228*8040SBaban.Kenkre@Sun.COM * 0x01, and the length must be 8 + rid count * 4 229*8040SBaban.Kenkre@Sun.COM */ 230*8040SBaban.Kenkre@Sun.COM if (bval->bv_len > 8 && bval->bv_val[0] == 0x01 && 231*8040SBaban.Kenkre@Sun.COM bval->bv_len == 1 + 1 + 6 + bval->bv_val[1] * 4) { 232*8040SBaban.Kenkre@Sun.COM v = (uchar_t *)bval->bv_val; 233*8040SBaban.Kenkre@Sun.COM sidp->version = v[0]; 234*8040SBaban.Kenkre@Sun.COM sidp->sub_authority_count = v[1]; 235*8040SBaban.Kenkre@Sun.COM sidp->authority = 236*8040SBaban.Kenkre@Sun.COM /* big endian -- so start from the left */ 237*8040SBaban.Kenkre@Sun.COM ((u_longlong_t)v[2] << 40) | 238*8040SBaban.Kenkre@Sun.COM ((u_longlong_t)v[3] << 32) | 239*8040SBaban.Kenkre@Sun.COM ((u_longlong_t)v[4] << 24) | 240*8040SBaban.Kenkre@Sun.COM ((u_longlong_t)v[5] << 16) | 241*8040SBaban.Kenkre@Sun.COM ((u_longlong_t)v[6] << 8) | 242*8040SBaban.Kenkre@Sun.COM (u_longlong_t)v[7]; 243*8040SBaban.Kenkre@Sun.COM for (i = 0; i < sidp->sub_authority_count; i++) { 244*8040SBaban.Kenkre@Sun.COM j = 8 + (i * 4); 245*8040SBaban.Kenkre@Sun.COM /* little endian -- so start from the right */ 246*8040SBaban.Kenkre@Sun.COM a = (v[j + 3] << 24) | (v[j + 2] << 16) | 247*8040SBaban.Kenkre@Sun.COM (v[j + 1] << 8) | (v[j]); 248*8040SBaban.Kenkre@Sun.COM sidp->sub_authorities[i] = a; 249*8040SBaban.Kenkre@Sun.COM } 250*8040SBaban.Kenkre@Sun.COM return (0); 251*8040SBaban.Kenkre@Sun.COM } 252*8040SBaban.Kenkre@Sun.COM return (-1); 253*8040SBaban.Kenkre@Sun.COM } 254*8040SBaban.Kenkre@Sun.COM 255*8040SBaban.Kenkre@Sun.COM /* 256*8040SBaban.Kenkre@Sun.COM * Convert a adutils_sid_t to S-1-... 257*8040SBaban.Kenkre@Sun.COM */ 258*8040SBaban.Kenkre@Sun.COM static 259*8040SBaban.Kenkre@Sun.COM char * 260*8040SBaban.Kenkre@Sun.COM sid2txt(adutils_sid_t *sidp) 261*8040SBaban.Kenkre@Sun.COM { 262*8040SBaban.Kenkre@Sun.COM int rlen, i, len; 263*8040SBaban.Kenkre@Sun.COM char *str, *cp; 264*8040SBaban.Kenkre@Sun.COM 265*8040SBaban.Kenkre@Sun.COM if (sidp->version != 1) 266*8040SBaban.Kenkre@Sun.COM return (NULL); 267*8040SBaban.Kenkre@Sun.COM 268*8040SBaban.Kenkre@Sun.COM len = sizeof ("S-1-") - 1; 269*8040SBaban.Kenkre@Sun.COM 270*8040SBaban.Kenkre@Sun.COM /* 271*8040SBaban.Kenkre@Sun.COM * We could optimize like so, but, why? 272*8040SBaban.Kenkre@Sun.COM * if (sidp->authority < 10) 273*8040SBaban.Kenkre@Sun.COM * len += 2; 274*8040SBaban.Kenkre@Sun.COM * else if (sidp->authority < 100) 275*8040SBaban.Kenkre@Sun.COM * len += 3; 276*8040SBaban.Kenkre@Sun.COM * else 277*8040SBaban.Kenkre@Sun.COM * len += snprintf(NULL, 0"%llu", sidp->authority); 278*8040SBaban.Kenkre@Sun.COM */ 279*8040SBaban.Kenkre@Sun.COM len += snprintf(NULL, 0, "%llu", sidp->authority); 280*8040SBaban.Kenkre@Sun.COM 281*8040SBaban.Kenkre@Sun.COM /* Max length of a uint32_t printed out in ASCII is 10 bytes */ 282*8040SBaban.Kenkre@Sun.COM len += 1 + (sidp->sub_authority_count + 1) * 10; 283*8040SBaban.Kenkre@Sun.COM 284*8040SBaban.Kenkre@Sun.COM if ((cp = str = malloc(len)) == NULL) 285*8040SBaban.Kenkre@Sun.COM return (NULL); 286*8040SBaban.Kenkre@Sun.COM 287*8040SBaban.Kenkre@Sun.COM rlen = snprintf(str, len, "S-1-%llu", sidp->authority); 288*8040SBaban.Kenkre@Sun.COM 289*8040SBaban.Kenkre@Sun.COM cp += rlen; 290*8040SBaban.Kenkre@Sun.COM len -= rlen; 291*8040SBaban.Kenkre@Sun.COM 292*8040SBaban.Kenkre@Sun.COM for (i = 0; i < sidp->sub_authority_count; i++) { 293*8040SBaban.Kenkre@Sun.COM assert(len > 0); 294*8040SBaban.Kenkre@Sun.COM rlen = snprintf(cp, len, "-%u", sidp->sub_authorities[i]); 295*8040SBaban.Kenkre@Sun.COM cp += rlen; 296*8040SBaban.Kenkre@Sun.COM len -= rlen; 297*8040SBaban.Kenkre@Sun.COM assert(len >= 0); 298*8040SBaban.Kenkre@Sun.COM } 299*8040SBaban.Kenkre@Sun.COM 300*8040SBaban.Kenkre@Sun.COM return (str); 301*8040SBaban.Kenkre@Sun.COM } 302*8040SBaban.Kenkre@Sun.COM 303*8040SBaban.Kenkre@Sun.COM /* 304*8040SBaban.Kenkre@Sun.COM * Convert a adutils_sid_t to on-the-wire encoding 305*8040SBaban.Kenkre@Sun.COM */ 306*8040SBaban.Kenkre@Sun.COM static 307*8040SBaban.Kenkre@Sun.COM int 308*8040SBaban.Kenkre@Sun.COM sid2binsid(adutils_sid_t *sid, uchar_t *binsid, int binsidlen) 309*8040SBaban.Kenkre@Sun.COM { 310*8040SBaban.Kenkre@Sun.COM uchar_t *p; 311*8040SBaban.Kenkre@Sun.COM int i; 312*8040SBaban.Kenkre@Sun.COM uint64_t a; 313*8040SBaban.Kenkre@Sun.COM uint32_t r; 314*8040SBaban.Kenkre@Sun.COM 315*8040SBaban.Kenkre@Sun.COM if (sid->version != 1 || 316*8040SBaban.Kenkre@Sun.COM binsidlen != (1 + 1 + 6 + sid->sub_authority_count * 4)) 317*8040SBaban.Kenkre@Sun.COM return (-1); 318*8040SBaban.Kenkre@Sun.COM 319*8040SBaban.Kenkre@Sun.COM p = binsid; 320*8040SBaban.Kenkre@Sun.COM *p++ = 0x01; /* version */ 321*8040SBaban.Kenkre@Sun.COM /* sub authority count */ 322*8040SBaban.Kenkre@Sun.COM *p++ = sid->sub_authority_count; 323*8040SBaban.Kenkre@Sun.COM /* Authority */ 324*8040SBaban.Kenkre@Sun.COM a = sid->authority; 325*8040SBaban.Kenkre@Sun.COM /* big-endian -- start from left */ 326*8040SBaban.Kenkre@Sun.COM *p++ = (a >> 40) & 0xFF; 327*8040SBaban.Kenkre@Sun.COM *p++ = (a >> 32) & 0xFF; 328*8040SBaban.Kenkre@Sun.COM *p++ = (a >> 24) & 0xFF; 329*8040SBaban.Kenkre@Sun.COM *p++ = (a >> 16) & 0xFF; 330*8040SBaban.Kenkre@Sun.COM *p++ = (a >> 8) & 0xFF; 331*8040SBaban.Kenkre@Sun.COM *p++ = a & 0xFF; 332*8040SBaban.Kenkre@Sun.COM 333*8040SBaban.Kenkre@Sun.COM /* sub-authorities */ 334*8040SBaban.Kenkre@Sun.COM for (i = 0; i < sid->sub_authority_count; i++) { 335*8040SBaban.Kenkre@Sun.COM r = sid->sub_authorities[i]; 336*8040SBaban.Kenkre@Sun.COM /* little-endian -- start from right */ 337*8040SBaban.Kenkre@Sun.COM *p++ = (r & 0x000000FF); 338*8040SBaban.Kenkre@Sun.COM *p++ = (r & 0x0000FF00) >> 8; 339*8040SBaban.Kenkre@Sun.COM *p++ = (r & 0x00FF0000) >> 16; 340*8040SBaban.Kenkre@Sun.COM *p++ = (r & 0xFF000000) >> 24; 341*8040SBaban.Kenkre@Sun.COM } 342*8040SBaban.Kenkre@Sun.COM 343*8040SBaban.Kenkre@Sun.COM return (0); 344*8040SBaban.Kenkre@Sun.COM } 345*8040SBaban.Kenkre@Sun.COM 346*8040SBaban.Kenkre@Sun.COM /* 347*8040SBaban.Kenkre@Sun.COM * Convert a stringified SID (S-1-...) into a hex-encoded version of the 348*8040SBaban.Kenkre@Sun.COM * on-the-wire encoding, but with each pair of hex digits pre-pended 349*8040SBaban.Kenkre@Sun.COM * with a '\', so we can pass this to libldap. 350*8040SBaban.Kenkre@Sun.COM */ 351*8040SBaban.Kenkre@Sun.COM int 352*8040SBaban.Kenkre@Sun.COM adutils_txtsid2hexbinsid(const char *txt, const uint32_t *rid, 353*8040SBaban.Kenkre@Sun.COM char *hexbinsid, int hexbinsidlen) 354*8040SBaban.Kenkre@Sun.COM { 355*8040SBaban.Kenkre@Sun.COM adutils_sid_t sid = { 0 }; 356*8040SBaban.Kenkre@Sun.COM int i, j; 357*8040SBaban.Kenkre@Sun.COM const char *cp; 358*8040SBaban.Kenkre@Sun.COM char *ecp; 359*8040SBaban.Kenkre@Sun.COM u_longlong_t a; 360*8040SBaban.Kenkre@Sun.COM unsigned long r; 361*8040SBaban.Kenkre@Sun.COM uchar_t *binsid, b, hb; 362*8040SBaban.Kenkre@Sun.COM 363*8040SBaban.Kenkre@Sun.COM /* Only version 1 SIDs please */ 364*8040SBaban.Kenkre@Sun.COM if (strncmp(txt, "S-1-", strlen("S-1-")) != 0) 365*8040SBaban.Kenkre@Sun.COM return (-1); 366*8040SBaban.Kenkre@Sun.COM 367*8040SBaban.Kenkre@Sun.COM if (strlen(txt) < (strlen("S-1-") + 1)) 368*8040SBaban.Kenkre@Sun.COM return (-1); 369*8040SBaban.Kenkre@Sun.COM 370*8040SBaban.Kenkre@Sun.COM /* count '-'s */ 371*8040SBaban.Kenkre@Sun.COM for (j = 0, cp = strchr(txt, '-'); 372*8040SBaban.Kenkre@Sun.COM cp != NULL && *cp != '\0'; 373*8040SBaban.Kenkre@Sun.COM j++, cp = strchr(cp + 1, '-')) { 374*8040SBaban.Kenkre@Sun.COM /* can't end on a '-' */ 375*8040SBaban.Kenkre@Sun.COM if (*(cp + 1) == '\0') 376*8040SBaban.Kenkre@Sun.COM return (-1); 377*8040SBaban.Kenkre@Sun.COM } 378*8040SBaban.Kenkre@Sun.COM 379*8040SBaban.Kenkre@Sun.COM /* Adjust count for version and authority */ 380*8040SBaban.Kenkre@Sun.COM j -= 2; 381*8040SBaban.Kenkre@Sun.COM 382*8040SBaban.Kenkre@Sun.COM /* we know the version number and RID count */ 383*8040SBaban.Kenkre@Sun.COM sid.version = 1; 384*8040SBaban.Kenkre@Sun.COM sid.sub_authority_count = (rid != NULL) ? j + 1 : j; 385*8040SBaban.Kenkre@Sun.COM 386*8040SBaban.Kenkre@Sun.COM /* must have at least one RID, but not too many */ 387*8040SBaban.Kenkre@Sun.COM if (sid.sub_authority_count < 1 || 388*8040SBaban.Kenkre@Sun.COM sid.sub_authority_count > ADUTILS_SID_MAX_SUB_AUTHORITIES) 389*8040SBaban.Kenkre@Sun.COM return (-1); 390*8040SBaban.Kenkre@Sun.COM 391*8040SBaban.Kenkre@Sun.COM /* check that we only have digits and '-' */ 392*8040SBaban.Kenkre@Sun.COM if (strspn(txt + 1, "0123456789-") < (strlen(txt) - 1)) 393*8040SBaban.Kenkre@Sun.COM return (-1); 394*8040SBaban.Kenkre@Sun.COM 395*8040SBaban.Kenkre@Sun.COM cp = txt + strlen("S-1-"); 396*8040SBaban.Kenkre@Sun.COM 397*8040SBaban.Kenkre@Sun.COM /* 64-bit safe parsing of unsigned 48-bit authority value */ 398*8040SBaban.Kenkre@Sun.COM errno = 0; 399*8040SBaban.Kenkre@Sun.COM a = strtoull(cp, &ecp, 10); 400*8040SBaban.Kenkre@Sun.COM 401*8040SBaban.Kenkre@Sun.COM /* errors parsing the authority or too many bits */ 402*8040SBaban.Kenkre@Sun.COM if (cp == ecp || (a == 0 && errno == EINVAL) || 403*8040SBaban.Kenkre@Sun.COM (a == ULLONG_MAX && errno == ERANGE) || 404*8040SBaban.Kenkre@Sun.COM (a & 0x0000ffffffffffffULL) != a) 405*8040SBaban.Kenkre@Sun.COM return (-1); 406*8040SBaban.Kenkre@Sun.COM 407*8040SBaban.Kenkre@Sun.COM cp = ecp; 408*8040SBaban.Kenkre@Sun.COM 409*8040SBaban.Kenkre@Sun.COM sid.authority = (uint64_t)a; 410*8040SBaban.Kenkre@Sun.COM 411*8040SBaban.Kenkre@Sun.COM for (i = 0; i < j; i++) { 412*8040SBaban.Kenkre@Sun.COM if (*cp++ != '-') 413*8040SBaban.Kenkre@Sun.COM return (-1); 414*8040SBaban.Kenkre@Sun.COM /* 64-bit safe parsing of unsigned 32-bit RID */ 415*8040SBaban.Kenkre@Sun.COM errno = 0; 416*8040SBaban.Kenkre@Sun.COM r = strtoul(cp, &ecp, 10); 417*8040SBaban.Kenkre@Sun.COM /* errors parsing the RID or too many bits */ 418*8040SBaban.Kenkre@Sun.COM if (cp == ecp || (r == 0 && errno == EINVAL) || 419*8040SBaban.Kenkre@Sun.COM (r == ULONG_MAX && errno == ERANGE) || 420*8040SBaban.Kenkre@Sun.COM (r & 0xffffffffUL) != r) 421*8040SBaban.Kenkre@Sun.COM return (-1); 422*8040SBaban.Kenkre@Sun.COM sid.sub_authorities[i] = (uint32_t)r; 423*8040SBaban.Kenkre@Sun.COM cp = ecp; 424*8040SBaban.Kenkre@Sun.COM } 425*8040SBaban.Kenkre@Sun.COM 426*8040SBaban.Kenkre@Sun.COM /* check that all of the string SID has been consumed */ 427*8040SBaban.Kenkre@Sun.COM if (*cp != '\0') 428*8040SBaban.Kenkre@Sun.COM return (-1); 429*8040SBaban.Kenkre@Sun.COM 430*8040SBaban.Kenkre@Sun.COM if (rid != NULL) 431*8040SBaban.Kenkre@Sun.COM sid.sub_authorities[j] = *rid; 432*8040SBaban.Kenkre@Sun.COM 433*8040SBaban.Kenkre@Sun.COM j = 1 + 1 + 6 + sid.sub_authority_count * 4; 434*8040SBaban.Kenkre@Sun.COM 435*8040SBaban.Kenkre@Sun.COM if (hexbinsidlen < (j * 3)) 436*8040SBaban.Kenkre@Sun.COM return (-2); 437*8040SBaban.Kenkre@Sun.COM 438*8040SBaban.Kenkre@Sun.COM /* binary encode the SID */ 439*8040SBaban.Kenkre@Sun.COM binsid = (uchar_t *)alloca(j); 440*8040SBaban.Kenkre@Sun.COM (void) sid2binsid(&sid, binsid, j); 441*8040SBaban.Kenkre@Sun.COM 442*8040SBaban.Kenkre@Sun.COM /* hex encode, with a backslash before each byte */ 443*8040SBaban.Kenkre@Sun.COM for (ecp = hexbinsid, i = 0; i < j; i++) { 444*8040SBaban.Kenkre@Sun.COM b = binsid[i]; 445*8040SBaban.Kenkre@Sun.COM *ecp++ = '\\'; 446*8040SBaban.Kenkre@Sun.COM hb = (b >> 4) & 0xF; 447*8040SBaban.Kenkre@Sun.COM *ecp++ = (hb <= 0x9 ? hb + '0' : hb - 10 + 'A'); 448*8040SBaban.Kenkre@Sun.COM hb = b & 0xF; 449*8040SBaban.Kenkre@Sun.COM *ecp++ = (hb <= 0x9 ? hb + '0' : hb - 10 + 'A'); 450*8040SBaban.Kenkre@Sun.COM } 451*8040SBaban.Kenkre@Sun.COM *ecp = '\0'; 452*8040SBaban.Kenkre@Sun.COM 453*8040SBaban.Kenkre@Sun.COM return (0); 454*8040SBaban.Kenkre@Sun.COM } 455*8040SBaban.Kenkre@Sun.COM 456*8040SBaban.Kenkre@Sun.COM static 457*8040SBaban.Kenkre@Sun.COM char * 458*8040SBaban.Kenkre@Sun.COM convert_bval2sid(BerValue *bval, uint32_t *rid) 459*8040SBaban.Kenkre@Sun.COM { 460*8040SBaban.Kenkre@Sun.COM adutils_sid_t sid; 461*8040SBaban.Kenkre@Sun.COM 462*8040SBaban.Kenkre@Sun.COM if (getsid(bval, &sid) < 0) 463*8040SBaban.Kenkre@Sun.COM return (NULL); 464*8040SBaban.Kenkre@Sun.COM 465*8040SBaban.Kenkre@Sun.COM /* 466*8040SBaban.Kenkre@Sun.COM * If desired and if the SID is what should be a domain/computer 467*8040SBaban.Kenkre@Sun.COM * user or group SID (i.e., S-1-5-w-x-y-z-<user/group RID>) then 468*8040SBaban.Kenkre@Sun.COM * save the last RID and truncate the SID 469*8040SBaban.Kenkre@Sun.COM */ 470*8040SBaban.Kenkre@Sun.COM if (rid != NULL && sid.authority == 5 && sid.sub_authority_count == 5) 471*8040SBaban.Kenkre@Sun.COM *rid = sid.sub_authorities[--sid.sub_authority_count]; 472*8040SBaban.Kenkre@Sun.COM return (sid2txt(&sid)); 473*8040SBaban.Kenkre@Sun.COM } 474*8040SBaban.Kenkre@Sun.COM 475*8040SBaban.Kenkre@Sun.COM 476*8040SBaban.Kenkre@Sun.COM /* 477*8040SBaban.Kenkre@Sun.COM * Return a NUL-terminated stringified SID from the value of an 478*8040SBaban.Kenkre@Sun.COM * objectSid attribute and put the last RID in *rid. 479*8040SBaban.Kenkre@Sun.COM */ 480*8040SBaban.Kenkre@Sun.COM char * 481*8040SBaban.Kenkre@Sun.COM adutils_bv_objsid2sidstr(BerValue *bval, uint32_t *rid) 482*8040SBaban.Kenkre@Sun.COM { 483*8040SBaban.Kenkre@Sun.COM char *sid; 484*8040SBaban.Kenkre@Sun.COM 485*8040SBaban.Kenkre@Sun.COM if (bval == NULL) 486*8040SBaban.Kenkre@Sun.COM return (NULL); 487*8040SBaban.Kenkre@Sun.COM /* objectSid is single valued */ 488*8040SBaban.Kenkre@Sun.COM if ((sid = convert_bval2sid(bval, rid)) == NULL) 489*8040SBaban.Kenkre@Sun.COM return (NULL); 490*8040SBaban.Kenkre@Sun.COM return (sid); 491*8040SBaban.Kenkre@Sun.COM } 492*8040SBaban.Kenkre@Sun.COM 493*8040SBaban.Kenkre@Sun.COM static 494*8040SBaban.Kenkre@Sun.COM char * 495*8040SBaban.Kenkre@Sun.COM adutils_sid_ber2str(BerValue *bval) 496*8040SBaban.Kenkre@Sun.COM { 497*8040SBaban.Kenkre@Sun.COM return (adutils_bv_objsid2sidstr(bval, NULL)); 498*8040SBaban.Kenkre@Sun.COM } 499*8040SBaban.Kenkre@Sun.COM 500*8040SBaban.Kenkre@Sun.COM 501*8040SBaban.Kenkre@Sun.COM /* Return a NUL-terminated string from the Ber value */ 502*8040SBaban.Kenkre@Sun.COM char * 503*8040SBaban.Kenkre@Sun.COM adutils_bv_name2str(BerValue *bval) 504*8040SBaban.Kenkre@Sun.COM { 505*8040SBaban.Kenkre@Sun.COM char *s; 506*8040SBaban.Kenkre@Sun.COM 507*8040SBaban.Kenkre@Sun.COM if (bval == NULL || bval->bv_val == NULL) 508*8040SBaban.Kenkre@Sun.COM return (NULL); 509*8040SBaban.Kenkre@Sun.COM if ((s = malloc(bval->bv_len + 1)) == NULL) 510*8040SBaban.Kenkre@Sun.COM return (NULL); 511*8040SBaban.Kenkre@Sun.COM (void) snprintf(s, bval->bv_len + 1, "%.*s", bval->bv_len, 512*8040SBaban.Kenkre@Sun.COM bval->bv_val); 513*8040SBaban.Kenkre@Sun.COM return (s); 514*8040SBaban.Kenkre@Sun.COM } 515*8040SBaban.Kenkre@Sun.COM 516*8040SBaban.Kenkre@Sun.COM /*ARGSUSED*/ 517*8040SBaban.Kenkre@Sun.COM static 518*8040SBaban.Kenkre@Sun.COM int 519*8040SBaban.Kenkre@Sun.COM saslcallback(LDAP *ld, unsigned flags, void *defaults, void *prompts) 520*8040SBaban.Kenkre@Sun.COM { 521*8040SBaban.Kenkre@Sun.COM sasl_interact_t *interact; 522*8040SBaban.Kenkre@Sun.COM 523*8040SBaban.Kenkre@Sun.COM if (prompts == NULL || flags != LDAP_SASL_INTERACTIVE) 524*8040SBaban.Kenkre@Sun.COM return (LDAP_PARAM_ERROR); 525*8040SBaban.Kenkre@Sun.COM 526*8040SBaban.Kenkre@Sun.COM /* There should be no extra arguemnts for SASL/GSSAPI authentication */ 527*8040SBaban.Kenkre@Sun.COM for (interact = prompts; interact->id != SASL_CB_LIST_END; 528*8040SBaban.Kenkre@Sun.COM interact++) { 529*8040SBaban.Kenkre@Sun.COM interact->result = NULL; 530*8040SBaban.Kenkre@Sun.COM interact->len = 0; 531*8040SBaban.Kenkre@Sun.COM } 532*8040SBaban.Kenkre@Sun.COM return (LDAP_SUCCESS); 533*8040SBaban.Kenkre@Sun.COM } 534*8040SBaban.Kenkre@Sun.COM 535*8040SBaban.Kenkre@Sun.COM 536*8040SBaban.Kenkre@Sun.COM #define ADCONN_TIME 300 537*8040SBaban.Kenkre@Sun.COM 538*8040SBaban.Kenkre@Sun.COM /* 539*8040SBaban.Kenkre@Sun.COM * Idle connection reaping side of connection management 540*8040SBaban.Kenkre@Sun.COM */ 541*8040SBaban.Kenkre@Sun.COM void 542*8040SBaban.Kenkre@Sun.COM adutils_reap_idle_connections() 543*8040SBaban.Kenkre@Sun.COM { 544*8040SBaban.Kenkre@Sun.COM adutils_host_t *adh; 545*8040SBaban.Kenkre@Sun.COM time_t now; 546*8040SBaban.Kenkre@Sun.COM 547*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&adhostlock); 548*8040SBaban.Kenkre@Sun.COM now = time(NULL); 549*8040SBaban.Kenkre@Sun.COM for (adh = host_head; adh != NULL; adh = adh->next) { 550*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&adh->lock); 551*8040SBaban.Kenkre@Sun.COM if (adh->ref == 0 && adh->idletime != 0 && 552*8040SBaban.Kenkre@Sun.COM adh->idletime + ADCONN_TIME < now) { 553*8040SBaban.Kenkre@Sun.COM if (adh->ld) { 554*8040SBaban.Kenkre@Sun.COM (void) ldap_unbind(adh->ld); 555*8040SBaban.Kenkre@Sun.COM adh->ld = NULL; 556*8040SBaban.Kenkre@Sun.COM adh->idletime = 0; 557*8040SBaban.Kenkre@Sun.COM adh->ref = 0; 558*8040SBaban.Kenkre@Sun.COM } 559*8040SBaban.Kenkre@Sun.COM } 560*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 561*8040SBaban.Kenkre@Sun.COM } 562*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adhostlock); 563*8040SBaban.Kenkre@Sun.COM } 564*8040SBaban.Kenkre@Sun.COM 565*8040SBaban.Kenkre@Sun.COM 566*8040SBaban.Kenkre@Sun.COM adutils_rc 567*8040SBaban.Kenkre@Sun.COM adutils_ad_alloc(adutils_ad_t **new_ad, const char *default_domain, 568*8040SBaban.Kenkre@Sun.COM adutils_ad_partition_t part) 569*8040SBaban.Kenkre@Sun.COM { 570*8040SBaban.Kenkre@Sun.COM adutils_ad_t *ad; 571*8040SBaban.Kenkre@Sun.COM 572*8040SBaban.Kenkre@Sun.COM *new_ad = NULL; 573*8040SBaban.Kenkre@Sun.COM 574*8040SBaban.Kenkre@Sun.COM if ((default_domain == NULL || *default_domain == '\0') && 575*8040SBaban.Kenkre@Sun.COM part != ADUTILS_AD_GLOBAL_CATALOG) 576*8040SBaban.Kenkre@Sun.COM return (ADUTILS_ERR_DOMAIN); 577*8040SBaban.Kenkre@Sun.COM if ((ad = calloc(1, sizeof (*ad))) == NULL) 578*8040SBaban.Kenkre@Sun.COM return (ADUTILS_ERR_MEMORY); 579*8040SBaban.Kenkre@Sun.COM ad->ref = 1; 580*8040SBaban.Kenkre@Sun.COM ad->partition = part; 581*8040SBaban.Kenkre@Sun.COM if (default_domain == NULL) 582*8040SBaban.Kenkre@Sun.COM default_domain = ""; 583*8040SBaban.Kenkre@Sun.COM if ((ad->dflt_w2k_dom = strdup(default_domain)) == NULL) 584*8040SBaban.Kenkre@Sun.COM goto err; 585*8040SBaban.Kenkre@Sun.COM if (pthread_mutex_init(&ad->lock, NULL) != 0) 586*8040SBaban.Kenkre@Sun.COM goto err; 587*8040SBaban.Kenkre@Sun.COM *new_ad = ad; 588*8040SBaban.Kenkre@Sun.COM return (ADUTILS_SUCCESS); 589*8040SBaban.Kenkre@Sun.COM 590*8040SBaban.Kenkre@Sun.COM err: 591*8040SBaban.Kenkre@Sun.COM if (ad->dflt_w2k_dom != NULL) 592*8040SBaban.Kenkre@Sun.COM free(ad->dflt_w2k_dom); 593*8040SBaban.Kenkre@Sun.COM free(ad); 594*8040SBaban.Kenkre@Sun.COM return (ADUTILS_ERR_MEMORY); 595*8040SBaban.Kenkre@Sun.COM } 596*8040SBaban.Kenkre@Sun.COM 597*8040SBaban.Kenkre@Sun.COM void 598*8040SBaban.Kenkre@Sun.COM adutils_ad_free(adutils_ad_t **ad) 599*8040SBaban.Kenkre@Sun.COM { 600*8040SBaban.Kenkre@Sun.COM adutils_host_t *p; 601*8040SBaban.Kenkre@Sun.COM adutils_host_t *prev; 602*8040SBaban.Kenkre@Sun.COM 603*8040SBaban.Kenkre@Sun.COM if (ad == NULL || *ad == NULL) 604*8040SBaban.Kenkre@Sun.COM return; 605*8040SBaban.Kenkre@Sun.COM 606*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&(*ad)->lock); 607*8040SBaban.Kenkre@Sun.COM 608*8040SBaban.Kenkre@Sun.COM if (atomic_dec_32_nv(&(*ad)->ref) > 0) { 609*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&(*ad)->lock); 610*8040SBaban.Kenkre@Sun.COM *ad = NULL; 611*8040SBaban.Kenkre@Sun.COM return; 612*8040SBaban.Kenkre@Sun.COM } 613*8040SBaban.Kenkre@Sun.COM 614*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&adhostlock); 615*8040SBaban.Kenkre@Sun.COM prev = NULL; 616*8040SBaban.Kenkre@Sun.COM p = host_head; 617*8040SBaban.Kenkre@Sun.COM while (p != NULL) { 618*8040SBaban.Kenkre@Sun.COM if (p->owner != (*ad)) { 619*8040SBaban.Kenkre@Sun.COM prev = p; 620*8040SBaban.Kenkre@Sun.COM p = p->next; 621*8040SBaban.Kenkre@Sun.COM continue; 622*8040SBaban.Kenkre@Sun.COM } else { 623*8040SBaban.Kenkre@Sun.COM delete_ds((*ad), p->host, p->port); 624*8040SBaban.Kenkre@Sun.COM if (prev == NULL) 625*8040SBaban.Kenkre@Sun.COM p = host_head; 626*8040SBaban.Kenkre@Sun.COM else 627*8040SBaban.Kenkre@Sun.COM p = prev->next; 628*8040SBaban.Kenkre@Sun.COM } 629*8040SBaban.Kenkre@Sun.COM } 630*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adhostlock); 631*8040SBaban.Kenkre@Sun.COM 632*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&(*ad)->lock); 633*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_destroy(&(*ad)->lock); 634*8040SBaban.Kenkre@Sun.COM 635*8040SBaban.Kenkre@Sun.COM free((*ad)->dflt_w2k_dom); 636*8040SBaban.Kenkre@Sun.COM free(*ad); 637*8040SBaban.Kenkre@Sun.COM 638*8040SBaban.Kenkre@Sun.COM *ad = NULL; 639*8040SBaban.Kenkre@Sun.COM } 640*8040SBaban.Kenkre@Sun.COM 641*8040SBaban.Kenkre@Sun.COM static 642*8040SBaban.Kenkre@Sun.COM int 643*8040SBaban.Kenkre@Sun.COM open_conn(adutils_host_t *adh, int timeoutsecs) 644*8040SBaban.Kenkre@Sun.COM { 645*8040SBaban.Kenkre@Sun.COM int zero = 0; 646*8040SBaban.Kenkre@Sun.COM int ldversion, rc; 647*8040SBaban.Kenkre@Sun.COM int timeoutms = timeoutsecs * 1000; 648*8040SBaban.Kenkre@Sun.COM 649*8040SBaban.Kenkre@Sun.COM if (adh == NULL) 650*8040SBaban.Kenkre@Sun.COM return (0); 651*8040SBaban.Kenkre@Sun.COM 652*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&adh->lock); 653*8040SBaban.Kenkre@Sun.COM 654*8040SBaban.Kenkre@Sun.COM if (!adh->dead && adh->ld != NULL) 655*8040SBaban.Kenkre@Sun.COM /* done! */ 656*8040SBaban.Kenkre@Sun.COM goto out; 657*8040SBaban.Kenkre@Sun.COM 658*8040SBaban.Kenkre@Sun.COM if (adh->ld != NULL) { 659*8040SBaban.Kenkre@Sun.COM (void) ldap_unbind(adh->ld); 660*8040SBaban.Kenkre@Sun.COM adh->ld = NULL; 661*8040SBaban.Kenkre@Sun.COM } 662*8040SBaban.Kenkre@Sun.COM adh->num_requests = 0; 663*8040SBaban.Kenkre@Sun.COM 664*8040SBaban.Kenkre@Sun.COM atomic_inc_64(&adh->generation); 665*8040SBaban.Kenkre@Sun.COM 666*8040SBaban.Kenkre@Sun.COM /* Open and bind an LDAP connection */ 667*8040SBaban.Kenkre@Sun.COM adh->ld = ldap_init(adh->host, adh->port); 668*8040SBaban.Kenkre@Sun.COM if (adh->ld == NULL) { 669*8040SBaban.Kenkre@Sun.COM idmapdlog(LOG_INFO, "ldap_init() to server " 670*8040SBaban.Kenkre@Sun.COM "%s port %d failed. (%s)", adh->host, 671*8040SBaban.Kenkre@Sun.COM adh->port, strerror(errno)); 672*8040SBaban.Kenkre@Sun.COM goto out; 673*8040SBaban.Kenkre@Sun.COM } 674*8040SBaban.Kenkre@Sun.COM ldversion = LDAP_VERSION3; 675*8040SBaban.Kenkre@Sun.COM (void) ldap_set_option(adh->ld, LDAP_OPT_PROTOCOL_VERSION, &ldversion); 676*8040SBaban.Kenkre@Sun.COM (void) ldap_set_option(adh->ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); 677*8040SBaban.Kenkre@Sun.COM (void) ldap_set_option(adh->ld, LDAP_OPT_TIMELIMIT, &zero); 678*8040SBaban.Kenkre@Sun.COM (void) ldap_set_option(adh->ld, LDAP_OPT_SIZELIMIT, &zero); 679*8040SBaban.Kenkre@Sun.COM (void) ldap_set_option(adh->ld, LDAP_X_OPT_CONNECT_TIMEOUT, &timeoutms); 680*8040SBaban.Kenkre@Sun.COM (void) ldap_set_option(adh->ld, LDAP_OPT_RESTART, LDAP_OPT_ON); 681*8040SBaban.Kenkre@Sun.COM rc = ldap_sasl_interactive_bind_s(adh->ld, "" /* binddn */, 682*8040SBaban.Kenkre@Sun.COM adh->saslmech, NULL, NULL, adh->saslflags, &saslcallback, 683*8040SBaban.Kenkre@Sun.COM NULL); 684*8040SBaban.Kenkre@Sun.COM 685*8040SBaban.Kenkre@Sun.COM if (rc != LDAP_SUCCESS) { 686*8040SBaban.Kenkre@Sun.COM (void) ldap_unbind(adh->ld); 687*8040SBaban.Kenkre@Sun.COM adh->ld = NULL; 688*8040SBaban.Kenkre@Sun.COM idmapdlog(LOG_INFO, "ldap_sasl_interactive_bind_s() to server " 689*8040SBaban.Kenkre@Sun.COM "%s port %d failed. (%s)", adh->host, adh->port, 690*8040SBaban.Kenkre@Sun.COM ldap_err2string(rc)); 691*8040SBaban.Kenkre@Sun.COM } 692*8040SBaban.Kenkre@Sun.COM 693*8040SBaban.Kenkre@Sun.COM idmapdlog(LOG_DEBUG, "Using global catalog server %s:%d", 694*8040SBaban.Kenkre@Sun.COM adh->host, adh->port); 695*8040SBaban.Kenkre@Sun.COM 696*8040SBaban.Kenkre@Sun.COM out: 697*8040SBaban.Kenkre@Sun.COM if (adh->ld != NULL) { 698*8040SBaban.Kenkre@Sun.COM atomic_inc_32(&adh->ref); 699*8040SBaban.Kenkre@Sun.COM adh->idletime = time(NULL); 700*8040SBaban.Kenkre@Sun.COM adh->dead = 0; 701*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 702*8040SBaban.Kenkre@Sun.COM return (1); 703*8040SBaban.Kenkre@Sun.COM } 704*8040SBaban.Kenkre@Sun.COM 705*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 706*8040SBaban.Kenkre@Sun.COM return (0); 707*8040SBaban.Kenkre@Sun.COM } 708*8040SBaban.Kenkre@Sun.COM 709*8040SBaban.Kenkre@Sun.COM 710*8040SBaban.Kenkre@Sun.COM /* 711*8040SBaban.Kenkre@Sun.COM * Connection management: find an open connection or open one 712*8040SBaban.Kenkre@Sun.COM */ 713*8040SBaban.Kenkre@Sun.COM static 714*8040SBaban.Kenkre@Sun.COM adutils_host_t * 715*8040SBaban.Kenkre@Sun.COM get_conn(adutils_ad_t *ad) 716*8040SBaban.Kenkre@Sun.COM { 717*8040SBaban.Kenkre@Sun.COM adutils_host_t *adh = NULL; 718*8040SBaban.Kenkre@Sun.COM int tries; 719*8040SBaban.Kenkre@Sun.COM int dscount = 0; 720*8040SBaban.Kenkre@Sun.COM int timeoutsecs = ADUTILS_LDAP_OPEN_TIMEOUT; 721*8040SBaban.Kenkre@Sun.COM 722*8040SBaban.Kenkre@Sun.COM retry: 723*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&adhostlock); 724*8040SBaban.Kenkre@Sun.COM 725*8040SBaban.Kenkre@Sun.COM if (host_head == NULL) { 726*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adhostlock); 727*8040SBaban.Kenkre@Sun.COM goto out; 728*8040SBaban.Kenkre@Sun.COM } 729*8040SBaban.Kenkre@Sun.COM 730*8040SBaban.Kenkre@Sun.COM if (dscount == 0) { 731*8040SBaban.Kenkre@Sun.COM /* 732*8040SBaban.Kenkre@Sun.COM * First try: count the number of DSes. 733*8040SBaban.Kenkre@Sun.COM * 734*8040SBaban.Kenkre@Sun.COM * Integer overflow is not an issue -- we can't have so many 735*8040SBaban.Kenkre@Sun.COM * DSes because they won't fit even DNS over TCP, and SMF 736*8040SBaban.Kenkre@Sun.COM * shouldn't let you set so many. 737*8040SBaban.Kenkre@Sun.COM */ 738*8040SBaban.Kenkre@Sun.COM for (adh = host_head, tries = 0; adh != NULL; adh = adh->next) { 739*8040SBaban.Kenkre@Sun.COM if (adh->owner == ad) 740*8040SBaban.Kenkre@Sun.COM dscount++; 741*8040SBaban.Kenkre@Sun.COM } 742*8040SBaban.Kenkre@Sun.COM 743*8040SBaban.Kenkre@Sun.COM if (dscount == 0) { 744*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adhostlock); 745*8040SBaban.Kenkre@Sun.COM goto out; 746*8040SBaban.Kenkre@Sun.COM } 747*8040SBaban.Kenkre@Sun.COM 748*8040SBaban.Kenkre@Sun.COM tries = dscount * 3; /* three tries per-ds */ 749*8040SBaban.Kenkre@Sun.COM 750*8040SBaban.Kenkre@Sun.COM /* 751*8040SBaban.Kenkre@Sun.COM * Begin round-robin at the next DS in the list after the last 752*8040SBaban.Kenkre@Sun.COM * one that we had a connection to, else start with the first 753*8040SBaban.Kenkre@Sun.COM * DS in the list. 754*8040SBaban.Kenkre@Sun.COM */ 755*8040SBaban.Kenkre@Sun.COM adh = ad->last_adh; 756*8040SBaban.Kenkre@Sun.COM } 757*8040SBaban.Kenkre@Sun.COM 758*8040SBaban.Kenkre@Sun.COM /* 759*8040SBaban.Kenkre@Sun.COM * Round-robin -- pick the next one on the list; if the list 760*8040SBaban.Kenkre@Sun.COM * changes on us, no big deal, we'll just potentially go 761*8040SBaban.Kenkre@Sun.COM * around the wrong number of times. 762*8040SBaban.Kenkre@Sun.COM */ 763*8040SBaban.Kenkre@Sun.COM for (;;) { 764*8040SBaban.Kenkre@Sun.COM if (adh != NULL && adh->ld != NULL && !adh->dead) 765*8040SBaban.Kenkre@Sun.COM break; 766*8040SBaban.Kenkre@Sun.COM if (adh == NULL || (adh = adh->next) == NULL) 767*8040SBaban.Kenkre@Sun.COM adh = host_head; 768*8040SBaban.Kenkre@Sun.COM if (adh->owner == ad) 769*8040SBaban.Kenkre@Sun.COM break; 770*8040SBaban.Kenkre@Sun.COM } 771*8040SBaban.Kenkre@Sun.COM 772*8040SBaban.Kenkre@Sun.COM ad->last_adh = adh; 773*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adhostlock); 774*8040SBaban.Kenkre@Sun.COM 775*8040SBaban.Kenkre@Sun.COM /* Found suitable DS, open it if not already opened */ 776*8040SBaban.Kenkre@Sun.COM if (open_conn(adh, timeoutsecs)) 777*8040SBaban.Kenkre@Sun.COM return (adh); 778*8040SBaban.Kenkre@Sun.COM 779*8040SBaban.Kenkre@Sun.COM tries--; 780*8040SBaban.Kenkre@Sun.COM if ((tries % dscount) == 0) 781*8040SBaban.Kenkre@Sun.COM timeoutsecs *= 2; 782*8040SBaban.Kenkre@Sun.COM if (tries > 0) 783*8040SBaban.Kenkre@Sun.COM goto retry; 784*8040SBaban.Kenkre@Sun.COM 785*8040SBaban.Kenkre@Sun.COM out: 786*8040SBaban.Kenkre@Sun.COM idmapdlog(LOG_NOTICE, "Couldn't open an LDAP connection to any global " 787*8040SBaban.Kenkre@Sun.COM "catalog server!"); 788*8040SBaban.Kenkre@Sun.COM return (NULL); 789*8040SBaban.Kenkre@Sun.COM } 790*8040SBaban.Kenkre@Sun.COM 791*8040SBaban.Kenkre@Sun.COM static 792*8040SBaban.Kenkre@Sun.COM void 793*8040SBaban.Kenkre@Sun.COM release_conn(adutils_host_t *adh) 794*8040SBaban.Kenkre@Sun.COM { 795*8040SBaban.Kenkre@Sun.COM int delete = 0; 796*8040SBaban.Kenkre@Sun.COM 797*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&adh->lock); 798*8040SBaban.Kenkre@Sun.COM if (atomic_dec_32_nv(&adh->ref) == 0) { 799*8040SBaban.Kenkre@Sun.COM if (adh->owner == NULL) 800*8040SBaban.Kenkre@Sun.COM delete = 1; 801*8040SBaban.Kenkre@Sun.COM adh->idletime = time(NULL); 802*8040SBaban.Kenkre@Sun.COM } 803*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 804*8040SBaban.Kenkre@Sun.COM 805*8040SBaban.Kenkre@Sun.COM /* Free this host if its owner no longer exists. */ 806*8040SBaban.Kenkre@Sun.COM if (delete) { 807*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&adhostlock); 808*8040SBaban.Kenkre@Sun.COM delete_ds(NULL, adh->host, adh->port); 809*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adhostlock); 810*8040SBaban.Kenkre@Sun.COM } 811*8040SBaban.Kenkre@Sun.COM } 812*8040SBaban.Kenkre@Sun.COM 813*8040SBaban.Kenkre@Sun.COM /* 814*8040SBaban.Kenkre@Sun.COM * Create a adutils_host_t, populate it and add it to the list of hosts. 815*8040SBaban.Kenkre@Sun.COM */ 816*8040SBaban.Kenkre@Sun.COM adutils_rc 817*8040SBaban.Kenkre@Sun.COM adutils_add_ds(adutils_ad_t *ad, const char *host, int port) 818*8040SBaban.Kenkre@Sun.COM { 819*8040SBaban.Kenkre@Sun.COM adutils_host_t *p; 820*8040SBaban.Kenkre@Sun.COM adutils_host_t *new = NULL; 821*8040SBaban.Kenkre@Sun.COM int ret; 822*8040SBaban.Kenkre@Sun.COM adutils_rc rc; 823*8040SBaban.Kenkre@Sun.COM 824*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&adhostlock); 825*8040SBaban.Kenkre@Sun.COM for (p = host_head; p != NULL; p = p->next) { 826*8040SBaban.Kenkre@Sun.COM if (p->owner != ad) 827*8040SBaban.Kenkre@Sun.COM continue; 828*8040SBaban.Kenkre@Sun.COM 829*8040SBaban.Kenkre@Sun.COM if (strcmp(host, p->host) == 0 && p->port == port) { 830*8040SBaban.Kenkre@Sun.COM /* already added */ 831*8040SBaban.Kenkre@Sun.COM rc = ADUTILS_SUCCESS; 832*8040SBaban.Kenkre@Sun.COM goto err; 833*8040SBaban.Kenkre@Sun.COM } 834*8040SBaban.Kenkre@Sun.COM } 835*8040SBaban.Kenkre@Sun.COM 836*8040SBaban.Kenkre@Sun.COM rc = ADUTILS_ERR_MEMORY; 837*8040SBaban.Kenkre@Sun.COM 838*8040SBaban.Kenkre@Sun.COM /* add new entry */ 839*8040SBaban.Kenkre@Sun.COM new = (adutils_host_t *)calloc(1, sizeof (*new)); 840*8040SBaban.Kenkre@Sun.COM if (new == NULL) 841*8040SBaban.Kenkre@Sun.COM goto err; 842*8040SBaban.Kenkre@Sun.COM new->owner = ad; 843*8040SBaban.Kenkre@Sun.COM new->port = port; 844*8040SBaban.Kenkre@Sun.COM new->dead = 0; 845*8040SBaban.Kenkre@Sun.COM new->max_requests = 80; 846*8040SBaban.Kenkre@Sun.COM new->num_requests = 0; 847*8040SBaban.Kenkre@Sun.COM if ((new->host = strdup(host)) == NULL) 848*8040SBaban.Kenkre@Sun.COM goto err; 849*8040SBaban.Kenkre@Sun.COM new->saslflags = LDAP_SASL_INTERACTIVE; 850*8040SBaban.Kenkre@Sun.COM new->saslmech = "GSSAPI"; 851*8040SBaban.Kenkre@Sun.COM 852*8040SBaban.Kenkre@Sun.COM if ((ret = pthread_mutex_init(&new->lock, NULL)) != 0) { 853*8040SBaban.Kenkre@Sun.COM free(new->host); 854*8040SBaban.Kenkre@Sun.COM new->host = NULL; 855*8040SBaban.Kenkre@Sun.COM errno = ret; 856*8040SBaban.Kenkre@Sun.COM rc = ADUTILS_ERR_INTERNAL; 857*8040SBaban.Kenkre@Sun.COM goto err; 858*8040SBaban.Kenkre@Sun.COM } 859*8040SBaban.Kenkre@Sun.COM 860*8040SBaban.Kenkre@Sun.COM /* link in */ 861*8040SBaban.Kenkre@Sun.COM rc = ADUTILS_SUCCESS; 862*8040SBaban.Kenkre@Sun.COM new->next = host_head; 863*8040SBaban.Kenkre@Sun.COM host_head = new; 864*8040SBaban.Kenkre@Sun.COM 865*8040SBaban.Kenkre@Sun.COM err: 866*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adhostlock); 867*8040SBaban.Kenkre@Sun.COM 868*8040SBaban.Kenkre@Sun.COM if (rc != 0 && new != NULL) { 869*8040SBaban.Kenkre@Sun.COM if (new->host != NULL) { 870*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_destroy(&new->lock); 871*8040SBaban.Kenkre@Sun.COM free(new->host); 872*8040SBaban.Kenkre@Sun.COM } 873*8040SBaban.Kenkre@Sun.COM free(new); 874*8040SBaban.Kenkre@Sun.COM } 875*8040SBaban.Kenkre@Sun.COM 876*8040SBaban.Kenkre@Sun.COM return (rc); 877*8040SBaban.Kenkre@Sun.COM } 878*8040SBaban.Kenkre@Sun.COM 879*8040SBaban.Kenkre@Sun.COM /* 880*8040SBaban.Kenkre@Sun.COM * Free a DS configuration. 881*8040SBaban.Kenkre@Sun.COM * Caller must lock the adhostlock mutex 882*8040SBaban.Kenkre@Sun.COM */ 883*8040SBaban.Kenkre@Sun.COM static 884*8040SBaban.Kenkre@Sun.COM void 885*8040SBaban.Kenkre@Sun.COM delete_ds(adutils_ad_t *ad, const char *host, int port) 886*8040SBaban.Kenkre@Sun.COM { 887*8040SBaban.Kenkre@Sun.COM adutils_host_t **p, *q; 888*8040SBaban.Kenkre@Sun.COM 889*8040SBaban.Kenkre@Sun.COM for (p = &host_head; *p != NULL; p = &((*p)->next)) { 890*8040SBaban.Kenkre@Sun.COM if ((*p)->owner != ad || strcmp(host, (*p)->host) != 0 || 891*8040SBaban.Kenkre@Sun.COM (*p)->port != port) 892*8040SBaban.Kenkre@Sun.COM continue; 893*8040SBaban.Kenkre@Sun.COM /* found */ 894*8040SBaban.Kenkre@Sun.COM 895*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&((*p)->lock)); 896*8040SBaban.Kenkre@Sun.COM if ((*p)->ref > 0) { 897*8040SBaban.Kenkre@Sun.COM /* 898*8040SBaban.Kenkre@Sun.COM * Still in use. Set its owner to NULL so 899*8040SBaban.Kenkre@Sun.COM * that it can be freed when its ref count 900*8040SBaban.Kenkre@Sun.COM * becomes 0. 901*8040SBaban.Kenkre@Sun.COM */ 902*8040SBaban.Kenkre@Sun.COM (*p)->owner = NULL; 903*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&((*p)->lock)); 904*8040SBaban.Kenkre@Sun.COM break; 905*8040SBaban.Kenkre@Sun.COM } 906*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&((*p)->lock)); 907*8040SBaban.Kenkre@Sun.COM 908*8040SBaban.Kenkre@Sun.COM q = *p; 909*8040SBaban.Kenkre@Sun.COM *p = (*p)->next; 910*8040SBaban.Kenkre@Sun.COM 911*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_destroy(&q->lock); 912*8040SBaban.Kenkre@Sun.COM 913*8040SBaban.Kenkre@Sun.COM if (q->ld) 914*8040SBaban.Kenkre@Sun.COM (void) ldap_unbind(q->ld); 915*8040SBaban.Kenkre@Sun.COM if (q->host) 916*8040SBaban.Kenkre@Sun.COM free(q->host); 917*8040SBaban.Kenkre@Sun.COM free(q); 918*8040SBaban.Kenkre@Sun.COM break; 919*8040SBaban.Kenkre@Sun.COM } 920*8040SBaban.Kenkre@Sun.COM 921*8040SBaban.Kenkre@Sun.COM } 922*8040SBaban.Kenkre@Sun.COM 923*8040SBaban.Kenkre@Sun.COM adutils_rc 924*8040SBaban.Kenkre@Sun.COM adutils_lookup_batch_start(adutils_ad_t *ad, int nqueries, 925*8040SBaban.Kenkre@Sun.COM adutils_ldap_res_search_cb ldap_res_search_cb, 926*8040SBaban.Kenkre@Sun.COM void *ldap_res_search_argp, 927*8040SBaban.Kenkre@Sun.COM adutils_query_state_t **state) 928*8040SBaban.Kenkre@Sun.COM { 929*8040SBaban.Kenkre@Sun.COM adutils_query_state_t *new_state; 930*8040SBaban.Kenkre@Sun.COM adutils_host_t *adh = NULL; 931*8040SBaban.Kenkre@Sun.COM 932*8040SBaban.Kenkre@Sun.COM if (ad == NULL) 933*8040SBaban.Kenkre@Sun.COM return (ADUTILS_ERR_INTERNAL); 934*8040SBaban.Kenkre@Sun.COM 935*8040SBaban.Kenkre@Sun.COM *state = NULL; 936*8040SBaban.Kenkre@Sun.COM adh = get_conn(ad); 937*8040SBaban.Kenkre@Sun.COM if (adh == NULL) 938*8040SBaban.Kenkre@Sun.COM return (ADUTILS_ERR_RETRIABLE_NET_ERR); 939*8040SBaban.Kenkre@Sun.COM 940*8040SBaban.Kenkre@Sun.COM new_state = calloc(1, sizeof (adutils_query_state_t) + 941*8040SBaban.Kenkre@Sun.COM (nqueries - 1) * sizeof (adutils_q_t)); 942*8040SBaban.Kenkre@Sun.COM if (new_state == NULL) 943*8040SBaban.Kenkre@Sun.COM return (ADUTILS_ERR_MEMORY); 944*8040SBaban.Kenkre@Sun.COM 945*8040SBaban.Kenkre@Sun.COM /* 946*8040SBaban.Kenkre@Sun.COM * Save default domain from the ad object so that we don't 947*8040SBaban.Kenkre@Sun.COM * have to access the 'ad' object later. 948*8040SBaban.Kenkre@Sun.COM */ 949*8040SBaban.Kenkre@Sun.COM new_state->default_domain = strdup(adh->owner->dflt_w2k_dom); 950*8040SBaban.Kenkre@Sun.COM if (new_state->default_domain == NULL) { 951*8040SBaban.Kenkre@Sun.COM free(new_state); 952*8040SBaban.Kenkre@Sun.COM return (ADUTILS_ERR_MEMORY); 953*8040SBaban.Kenkre@Sun.COM } 954*8040SBaban.Kenkre@Sun.COM 955*8040SBaban.Kenkre@Sun.COM if (ad->partition == ADUTILS_AD_DATA) 956*8040SBaban.Kenkre@Sun.COM new_state->basedn = adutils_dns2dn(new_state->default_domain); 957*8040SBaban.Kenkre@Sun.COM else 958*8040SBaban.Kenkre@Sun.COM new_state->basedn = strdup(""); 959*8040SBaban.Kenkre@Sun.COM if (new_state->basedn == NULL) { 960*8040SBaban.Kenkre@Sun.COM free(new_state->default_domain); 961*8040SBaban.Kenkre@Sun.COM free(new_state); 962*8040SBaban.Kenkre@Sun.COM return (ADUTILS_ERR_MEMORY); 963*8040SBaban.Kenkre@Sun.COM } 964*8040SBaban.Kenkre@Sun.COM 965*8040SBaban.Kenkre@Sun.COM new_state->ref_cnt = 1; 966*8040SBaban.Kenkre@Sun.COM new_state->qadh = adh; 967*8040SBaban.Kenkre@Sun.COM new_state->qcount = nqueries; 968*8040SBaban.Kenkre@Sun.COM new_state->qadh_gen = adh->generation; 969*8040SBaban.Kenkre@Sun.COM new_state->qlastsent = 0; 970*8040SBaban.Kenkre@Sun.COM new_state->ldap_res_search_cb = ldap_res_search_cb; 971*8040SBaban.Kenkre@Sun.COM new_state->ldap_res_search_argp = ldap_res_search_argp; 972*8040SBaban.Kenkre@Sun.COM (void) pthread_cond_init(&new_state->cv, NULL); 973*8040SBaban.Kenkre@Sun.COM 974*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&qstatelock); 975*8040SBaban.Kenkre@Sun.COM new_state->next = qstatehead; 976*8040SBaban.Kenkre@Sun.COM qstatehead = new_state; 977*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&qstatelock); 978*8040SBaban.Kenkre@Sun.COM *state = new_state; 979*8040SBaban.Kenkre@Sun.COM 980*8040SBaban.Kenkre@Sun.COM return (ADUTILS_SUCCESS); 981*8040SBaban.Kenkre@Sun.COM } 982*8040SBaban.Kenkre@Sun.COM 983*8040SBaban.Kenkre@Sun.COM /* 984*8040SBaban.Kenkre@Sun.COM * Find the adutils_query_state_t to which a given LDAP result msgid on a 985*8040SBaban.Kenkre@Sun.COM * given connection belongs. This routine increaments the reference count 986*8040SBaban.Kenkre@Sun.COM * so that the object can not be freed. adutils_lookup_batch_unlock() 987*8040SBaban.Kenkre@Sun.COM * must be called to decreament the reference count. 988*8040SBaban.Kenkre@Sun.COM */ 989*8040SBaban.Kenkre@Sun.COM static 990*8040SBaban.Kenkre@Sun.COM int 991*8040SBaban.Kenkre@Sun.COM msgid2query(adutils_host_t *adh, int msgid, 992*8040SBaban.Kenkre@Sun.COM adutils_query_state_t **state, int *qid) 993*8040SBaban.Kenkre@Sun.COM { 994*8040SBaban.Kenkre@Sun.COM adutils_query_state_t *p; 995*8040SBaban.Kenkre@Sun.COM int i; 996*8040SBaban.Kenkre@Sun.COM int ret; 997*8040SBaban.Kenkre@Sun.COM 998*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&qstatelock); 999*8040SBaban.Kenkre@Sun.COM for (p = qstatehead; p != NULL; p = p->next) { 1000*8040SBaban.Kenkre@Sun.COM if (p->qadh != adh || adh->generation != p->qadh_gen) 1001*8040SBaban.Kenkre@Sun.COM continue; 1002*8040SBaban.Kenkre@Sun.COM for (i = 0; i < p->qcount; i++) { 1003*8040SBaban.Kenkre@Sun.COM if ((p->queries[i]).msgid == msgid) { 1004*8040SBaban.Kenkre@Sun.COM if (!p->qdead) { 1005*8040SBaban.Kenkre@Sun.COM p->ref_cnt++; 1006*8040SBaban.Kenkre@Sun.COM *state = p; 1007*8040SBaban.Kenkre@Sun.COM *qid = i; 1008*8040SBaban.Kenkre@Sun.COM ret = 1; 1009*8040SBaban.Kenkre@Sun.COM } else 1010*8040SBaban.Kenkre@Sun.COM ret = 0; 1011*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&qstatelock); 1012*8040SBaban.Kenkre@Sun.COM return (ret); 1013*8040SBaban.Kenkre@Sun.COM } 1014*8040SBaban.Kenkre@Sun.COM } 1015*8040SBaban.Kenkre@Sun.COM } 1016*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&qstatelock); 1017*8040SBaban.Kenkre@Sun.COM return (0); 1018*8040SBaban.Kenkre@Sun.COM } 1019*8040SBaban.Kenkre@Sun.COM 1020*8040SBaban.Kenkre@Sun.COM static 1021*8040SBaban.Kenkre@Sun.COM int 1022*8040SBaban.Kenkre@Sun.COM check_for_binary_attrs(const char *attr) 1023*8040SBaban.Kenkre@Sun.COM { 1024*8040SBaban.Kenkre@Sun.COM int i; 1025*8040SBaban.Kenkre@Sun.COM for (i = 0; binattrs[i].name != NULL; i++) { 1026*8040SBaban.Kenkre@Sun.COM if (strcasecmp(binattrs[i].name, attr) == 0) 1027*8040SBaban.Kenkre@Sun.COM return (i); 1028*8040SBaban.Kenkre@Sun.COM } 1029*8040SBaban.Kenkre@Sun.COM return (-1); 1030*8040SBaban.Kenkre@Sun.COM } 1031*8040SBaban.Kenkre@Sun.COM 1032*8040SBaban.Kenkre@Sun.COM static 1033*8040SBaban.Kenkre@Sun.COM void 1034*8040SBaban.Kenkre@Sun.COM free_entry(adutils_entry_t *entry) 1035*8040SBaban.Kenkre@Sun.COM { 1036*8040SBaban.Kenkre@Sun.COM int i, j; 1037*8040SBaban.Kenkre@Sun.COM adutils_attr_t *ap; 1038*8040SBaban.Kenkre@Sun.COM 1039*8040SBaban.Kenkre@Sun.COM if (entry == NULL) 1040*8040SBaban.Kenkre@Sun.COM return; 1041*8040SBaban.Kenkre@Sun.COM if (entry->attr_nvpairs == NULL) { 1042*8040SBaban.Kenkre@Sun.COM free(entry); 1043*8040SBaban.Kenkre@Sun.COM return; 1044*8040SBaban.Kenkre@Sun.COM } 1045*8040SBaban.Kenkre@Sun.COM for (i = 0; i < entry->num_nvpairs; i++) { 1046*8040SBaban.Kenkre@Sun.COM ap = &entry->attr_nvpairs[i]; 1047*8040SBaban.Kenkre@Sun.COM if (ap->attr_name == NULL) { 1048*8040SBaban.Kenkre@Sun.COM ldap_value_free(ap->attr_values); 1049*8040SBaban.Kenkre@Sun.COM continue; 1050*8040SBaban.Kenkre@Sun.COM } 1051*8040SBaban.Kenkre@Sun.COM if (check_for_binary_attrs(ap->attr_name) >= 0) { 1052*8040SBaban.Kenkre@Sun.COM free(ap->attr_name); 1053*8040SBaban.Kenkre@Sun.COM if (ap->attr_values == NULL) 1054*8040SBaban.Kenkre@Sun.COM continue; 1055*8040SBaban.Kenkre@Sun.COM for (j = 0; j < ap->num_values; j++) 1056*8040SBaban.Kenkre@Sun.COM free(ap->attr_values[j]); 1057*8040SBaban.Kenkre@Sun.COM free(ap->attr_values); 1058*8040SBaban.Kenkre@Sun.COM } else if (strcasecmp(ap->attr_name, "dn") == 0) { 1059*8040SBaban.Kenkre@Sun.COM free(ap->attr_name); 1060*8040SBaban.Kenkre@Sun.COM ldap_memfree(ap->attr_values[0]); 1061*8040SBaban.Kenkre@Sun.COM free(ap->attr_values); 1062*8040SBaban.Kenkre@Sun.COM } else { 1063*8040SBaban.Kenkre@Sun.COM free(ap->attr_name); 1064*8040SBaban.Kenkre@Sun.COM ldap_value_free(ap->attr_values); 1065*8040SBaban.Kenkre@Sun.COM } 1066*8040SBaban.Kenkre@Sun.COM } 1067*8040SBaban.Kenkre@Sun.COM free(entry->attr_nvpairs); 1068*8040SBaban.Kenkre@Sun.COM free(entry); 1069*8040SBaban.Kenkre@Sun.COM } 1070*8040SBaban.Kenkre@Sun.COM 1071*8040SBaban.Kenkre@Sun.COM void 1072*8040SBaban.Kenkre@Sun.COM adutils_freeresult(adutils_result_t **result) 1073*8040SBaban.Kenkre@Sun.COM { 1074*8040SBaban.Kenkre@Sun.COM adutils_entry_t *e, *next; 1075*8040SBaban.Kenkre@Sun.COM 1076*8040SBaban.Kenkre@Sun.COM if (result == NULL || *result == NULL) 1077*8040SBaban.Kenkre@Sun.COM return; 1078*8040SBaban.Kenkre@Sun.COM if ((*result)->entries == NULL) { 1079*8040SBaban.Kenkre@Sun.COM free(*result); 1080*8040SBaban.Kenkre@Sun.COM *result = NULL; 1081*8040SBaban.Kenkre@Sun.COM return; 1082*8040SBaban.Kenkre@Sun.COM } 1083*8040SBaban.Kenkre@Sun.COM for (e = (*result)->entries; e != NULL; e = next) { 1084*8040SBaban.Kenkre@Sun.COM next = e->next; 1085*8040SBaban.Kenkre@Sun.COM free_entry(e); 1086*8040SBaban.Kenkre@Sun.COM } 1087*8040SBaban.Kenkre@Sun.COM free(*result); 1088*8040SBaban.Kenkre@Sun.COM *result = NULL; 1089*8040SBaban.Kenkre@Sun.COM } 1090*8040SBaban.Kenkre@Sun.COM 1091*8040SBaban.Kenkre@Sun.COM const adutils_entry_t * 1092*8040SBaban.Kenkre@Sun.COM adutils_getfirstentry(adutils_result_t *result) 1093*8040SBaban.Kenkre@Sun.COM { 1094*8040SBaban.Kenkre@Sun.COM if (result != NULL) 1095*8040SBaban.Kenkre@Sun.COM return (result->entries); 1096*8040SBaban.Kenkre@Sun.COM return (NULL); 1097*8040SBaban.Kenkre@Sun.COM } 1098*8040SBaban.Kenkre@Sun.COM 1099*8040SBaban.Kenkre@Sun.COM 1100*8040SBaban.Kenkre@Sun.COM char ** 1101*8040SBaban.Kenkre@Sun.COM adutils_getattr(const adutils_entry_t *entry, const char *attrname) 1102*8040SBaban.Kenkre@Sun.COM { 1103*8040SBaban.Kenkre@Sun.COM int i; 1104*8040SBaban.Kenkre@Sun.COM adutils_attr_t *ap; 1105*8040SBaban.Kenkre@Sun.COM 1106*8040SBaban.Kenkre@Sun.COM if (entry == NULL || entry->attr_nvpairs == NULL) 1107*8040SBaban.Kenkre@Sun.COM return (NULL); 1108*8040SBaban.Kenkre@Sun.COM for (i = 0; i < entry->num_nvpairs; i++) { 1109*8040SBaban.Kenkre@Sun.COM ap = &entry->attr_nvpairs[i]; 1110*8040SBaban.Kenkre@Sun.COM if (ap->attr_name != NULL && 1111*8040SBaban.Kenkre@Sun.COM strcasecmp(ap->attr_name, attrname) == 0) 1112*8040SBaban.Kenkre@Sun.COM return (ap->attr_values); 1113*8040SBaban.Kenkre@Sun.COM } 1114*8040SBaban.Kenkre@Sun.COM return (NULL); 1115*8040SBaban.Kenkre@Sun.COM } 1116*8040SBaban.Kenkre@Sun.COM 1117*8040SBaban.Kenkre@Sun.COM 1118*8040SBaban.Kenkre@Sun.COM /* 1119*8040SBaban.Kenkre@Sun.COM * Queue LDAP result for the given query. 1120*8040SBaban.Kenkre@Sun.COM * 1121*8040SBaban.Kenkre@Sun.COM * Return values: 1122*8040SBaban.Kenkre@Sun.COM * 0 success 1123*8040SBaban.Kenkre@Sun.COM * -1 ignore result 1124*8040SBaban.Kenkre@Sun.COM * -2 error 1125*8040SBaban.Kenkre@Sun.COM */ 1126*8040SBaban.Kenkre@Sun.COM static 1127*8040SBaban.Kenkre@Sun.COM int 1128*8040SBaban.Kenkre@Sun.COM make_entry(adutils_q_t *q, adutils_host_t *adh, LDAPMessage *search_res, 1129*8040SBaban.Kenkre@Sun.COM adutils_entry_t **entry) 1130*8040SBaban.Kenkre@Sun.COM { 1131*8040SBaban.Kenkre@Sun.COM BerElement *ber = NULL; 1132*8040SBaban.Kenkre@Sun.COM BerValue **bvalues = NULL; 1133*8040SBaban.Kenkre@Sun.COM char **strvalues; 1134*8040SBaban.Kenkre@Sun.COM char *attr = NULL, *dn = NULL, *domain = NULL; 1135*8040SBaban.Kenkre@Sun.COM adutils_entry_t *ep; 1136*8040SBaban.Kenkre@Sun.COM adutils_attr_t *ap; 1137*8040SBaban.Kenkre@Sun.COM int i, j, b, err = 0, ret = -2; 1138*8040SBaban.Kenkre@Sun.COM 1139*8040SBaban.Kenkre@Sun.COM *entry = NULL; 1140*8040SBaban.Kenkre@Sun.COM 1141*8040SBaban.Kenkre@Sun.COM /* Check that this is the domain that we were looking for */ 1142*8040SBaban.Kenkre@Sun.COM if ((dn = ldap_get_dn(adh->ld, search_res)) == NULL) 1143*8040SBaban.Kenkre@Sun.COM return (-2); 1144*8040SBaban.Kenkre@Sun.COM if ((domain = adutils_dn2dns(dn)) == NULL) { 1145*8040SBaban.Kenkre@Sun.COM ldap_memfree(dn); 1146*8040SBaban.Kenkre@Sun.COM return (-2); 1147*8040SBaban.Kenkre@Sun.COM } 1148*8040SBaban.Kenkre@Sun.COM if (q->edomain != NULL) { 1149*8040SBaban.Kenkre@Sun.COM if (u8_strcmp(q->edomain, domain, 0, U8_STRCMP_CI_LOWER, 1150*8040SBaban.Kenkre@Sun.COM U8_UNICODE_LATEST, &err) != 0 || err != 0) { 1151*8040SBaban.Kenkre@Sun.COM ldap_memfree(dn); 1152*8040SBaban.Kenkre@Sun.COM free(domain); 1153*8040SBaban.Kenkre@Sun.COM return (-1); 1154*8040SBaban.Kenkre@Sun.COM } 1155*8040SBaban.Kenkre@Sun.COM } 1156*8040SBaban.Kenkre@Sun.COM free(domain); 1157*8040SBaban.Kenkre@Sun.COM 1158*8040SBaban.Kenkre@Sun.COM /* Allocate memory for the entry */ 1159*8040SBaban.Kenkre@Sun.COM if ((ep = calloc(1, sizeof (*ep))) == NULL) 1160*8040SBaban.Kenkre@Sun.COM goto out; 1161*8040SBaban.Kenkre@Sun.COM 1162*8040SBaban.Kenkre@Sun.COM /* For 'dn' */ 1163*8040SBaban.Kenkre@Sun.COM ep->num_nvpairs = 1; 1164*8040SBaban.Kenkre@Sun.COM 1165*8040SBaban.Kenkre@Sun.COM /* Count the number of name-value pairs for this entry */ 1166*8040SBaban.Kenkre@Sun.COM for (attr = ldap_first_attribute(adh->ld, search_res, &ber); 1167*8040SBaban.Kenkre@Sun.COM attr != NULL; 1168*8040SBaban.Kenkre@Sun.COM attr = ldap_next_attribute(adh->ld, search_res, ber)) { 1169*8040SBaban.Kenkre@Sun.COM ep->num_nvpairs++; 1170*8040SBaban.Kenkre@Sun.COM ldap_memfree(attr); 1171*8040SBaban.Kenkre@Sun.COM } 1172*8040SBaban.Kenkre@Sun.COM ber_free(ber, 0); 1173*8040SBaban.Kenkre@Sun.COM ber = NULL; 1174*8040SBaban.Kenkre@Sun.COM 1175*8040SBaban.Kenkre@Sun.COM /* Allocate array for the attribute name-value pairs */ 1176*8040SBaban.Kenkre@Sun.COM ep->attr_nvpairs = calloc(ep->num_nvpairs, sizeof (*ep->attr_nvpairs)); 1177*8040SBaban.Kenkre@Sun.COM if (ep->attr_nvpairs == NULL) { 1178*8040SBaban.Kenkre@Sun.COM ep->num_nvpairs = 0; 1179*8040SBaban.Kenkre@Sun.COM goto out; 1180*8040SBaban.Kenkre@Sun.COM } 1181*8040SBaban.Kenkre@Sun.COM 1182*8040SBaban.Kenkre@Sun.COM /* For dn */ 1183*8040SBaban.Kenkre@Sun.COM ap = &ep->attr_nvpairs[0]; 1184*8040SBaban.Kenkre@Sun.COM if ((ap->attr_name = strdup("dn")) == NULL) 1185*8040SBaban.Kenkre@Sun.COM goto out; 1186*8040SBaban.Kenkre@Sun.COM ap->num_values = 1; 1187*8040SBaban.Kenkre@Sun.COM ap->attr_values = calloc(ap->num_values, sizeof (*ap->attr_values)); 1188*8040SBaban.Kenkre@Sun.COM if (ap->attr_values == NULL) { 1189*8040SBaban.Kenkre@Sun.COM ap->num_values = 0; 1190*8040SBaban.Kenkre@Sun.COM goto out; 1191*8040SBaban.Kenkre@Sun.COM } 1192*8040SBaban.Kenkre@Sun.COM ap->attr_values[0] = dn; 1193*8040SBaban.Kenkre@Sun.COM dn = NULL; 1194*8040SBaban.Kenkre@Sun.COM 1195*8040SBaban.Kenkre@Sun.COM for (attr = ldap_first_attribute(adh->ld, search_res, &ber), i = 1; 1196*8040SBaban.Kenkre@Sun.COM attr != NULL; 1197*8040SBaban.Kenkre@Sun.COM ldap_memfree(attr), i++, 1198*8040SBaban.Kenkre@Sun.COM attr = ldap_next_attribute(adh->ld, search_res, ber)) { 1199*8040SBaban.Kenkre@Sun.COM ap = &ep->attr_nvpairs[i]; 1200*8040SBaban.Kenkre@Sun.COM if ((ap->attr_name = strdup(attr)) == NULL) 1201*8040SBaban.Kenkre@Sun.COM goto out; 1202*8040SBaban.Kenkre@Sun.COM 1203*8040SBaban.Kenkre@Sun.COM if ((b = check_for_binary_attrs(attr)) >= 0) { 1204*8040SBaban.Kenkre@Sun.COM bvalues = 1205*8040SBaban.Kenkre@Sun.COM ldap_get_values_len(adh->ld, search_res, attr); 1206*8040SBaban.Kenkre@Sun.COM if (bvalues == NULL) 1207*8040SBaban.Kenkre@Sun.COM continue; 1208*8040SBaban.Kenkre@Sun.COM ap->num_values = ldap_count_values_len(bvalues); 1209*8040SBaban.Kenkre@Sun.COM if (ap->num_values == 0) { 1210*8040SBaban.Kenkre@Sun.COM ldap_value_free_len(bvalues); 1211*8040SBaban.Kenkre@Sun.COM bvalues = NULL; 1212*8040SBaban.Kenkre@Sun.COM continue; 1213*8040SBaban.Kenkre@Sun.COM } 1214*8040SBaban.Kenkre@Sun.COM ap->attr_values = calloc(ap->num_values, 1215*8040SBaban.Kenkre@Sun.COM sizeof (*ap->attr_values)); 1216*8040SBaban.Kenkre@Sun.COM if (ap->attr_values == NULL) { 1217*8040SBaban.Kenkre@Sun.COM ap->num_values = 0; 1218*8040SBaban.Kenkre@Sun.COM goto out; 1219*8040SBaban.Kenkre@Sun.COM } 1220*8040SBaban.Kenkre@Sun.COM for (j = 0; j < ap->num_values; j++) { 1221*8040SBaban.Kenkre@Sun.COM ap->attr_values[j] = 1222*8040SBaban.Kenkre@Sun.COM binattrs[b].ber2str(bvalues[j]); 1223*8040SBaban.Kenkre@Sun.COM if (ap->attr_values[j] == NULL) 1224*8040SBaban.Kenkre@Sun.COM goto out; 1225*8040SBaban.Kenkre@Sun.COM } 1226*8040SBaban.Kenkre@Sun.COM ldap_value_free_len(bvalues); 1227*8040SBaban.Kenkre@Sun.COM bvalues = NULL; 1228*8040SBaban.Kenkre@Sun.COM continue; 1229*8040SBaban.Kenkre@Sun.COM } 1230*8040SBaban.Kenkre@Sun.COM 1231*8040SBaban.Kenkre@Sun.COM strvalues = ldap_get_values(adh->ld, search_res, attr); 1232*8040SBaban.Kenkre@Sun.COM if (strvalues == NULL) 1233*8040SBaban.Kenkre@Sun.COM continue; 1234*8040SBaban.Kenkre@Sun.COM ap->num_values = ldap_count_values(strvalues); 1235*8040SBaban.Kenkre@Sun.COM if (ap->num_values == 0) { 1236*8040SBaban.Kenkre@Sun.COM ldap_value_free(strvalues); 1237*8040SBaban.Kenkre@Sun.COM continue; 1238*8040SBaban.Kenkre@Sun.COM } 1239*8040SBaban.Kenkre@Sun.COM ap->attr_values = strvalues; 1240*8040SBaban.Kenkre@Sun.COM } 1241*8040SBaban.Kenkre@Sun.COM 1242*8040SBaban.Kenkre@Sun.COM ret = 0; 1243*8040SBaban.Kenkre@Sun.COM out: 1244*8040SBaban.Kenkre@Sun.COM ldap_memfree(attr); 1245*8040SBaban.Kenkre@Sun.COM ldap_memfree(dn); 1246*8040SBaban.Kenkre@Sun.COM ber_free(ber, 0); 1247*8040SBaban.Kenkre@Sun.COM ldap_value_free_len(bvalues); 1248*8040SBaban.Kenkre@Sun.COM if (ret < 0) 1249*8040SBaban.Kenkre@Sun.COM free_entry(ep); 1250*8040SBaban.Kenkre@Sun.COM else 1251*8040SBaban.Kenkre@Sun.COM *entry = ep; 1252*8040SBaban.Kenkre@Sun.COM return (ret); 1253*8040SBaban.Kenkre@Sun.COM } 1254*8040SBaban.Kenkre@Sun.COM 1255*8040SBaban.Kenkre@Sun.COM /* 1256*8040SBaban.Kenkre@Sun.COM * Put the search result onto the given adutils_q_t. 1257*8040SBaban.Kenkre@Sun.COM * Returns: 0 success 1258*8040SBaban.Kenkre@Sun.COM * < 0 error 1259*8040SBaban.Kenkre@Sun.COM */ 1260*8040SBaban.Kenkre@Sun.COM static 1261*8040SBaban.Kenkre@Sun.COM int 1262*8040SBaban.Kenkre@Sun.COM add_entry(adutils_host_t *adh, adutils_q_t *q, LDAPMessage *search_res) 1263*8040SBaban.Kenkre@Sun.COM { 1264*8040SBaban.Kenkre@Sun.COM int ret = -1; 1265*8040SBaban.Kenkre@Sun.COM adutils_entry_t *entry = NULL; 1266*8040SBaban.Kenkre@Sun.COM adutils_result_t *res; 1267*8040SBaban.Kenkre@Sun.COM 1268*8040SBaban.Kenkre@Sun.COM ret = make_entry(q, adh, search_res, &entry); 1269*8040SBaban.Kenkre@Sun.COM if (ret < -1) { 1270*8040SBaban.Kenkre@Sun.COM *q->rc = ADUTILS_ERR_MEMORY; 1271*8040SBaban.Kenkre@Sun.COM goto out; 1272*8040SBaban.Kenkre@Sun.COM } else if (ret == -1) { 1273*8040SBaban.Kenkre@Sun.COM /* ignore result */ 1274*8040SBaban.Kenkre@Sun.COM goto out; 1275*8040SBaban.Kenkre@Sun.COM } 1276*8040SBaban.Kenkre@Sun.COM if (*q->result == NULL) { 1277*8040SBaban.Kenkre@Sun.COM res = calloc(1, sizeof (*res)); 1278*8040SBaban.Kenkre@Sun.COM if (res == NULL) { 1279*8040SBaban.Kenkre@Sun.COM *q->rc = ADUTILS_ERR_MEMORY; 1280*8040SBaban.Kenkre@Sun.COM goto out; 1281*8040SBaban.Kenkre@Sun.COM } 1282*8040SBaban.Kenkre@Sun.COM res->num_entries = 1; 1283*8040SBaban.Kenkre@Sun.COM res->entries = entry; 1284*8040SBaban.Kenkre@Sun.COM *q->result = res; 1285*8040SBaban.Kenkre@Sun.COM } else { 1286*8040SBaban.Kenkre@Sun.COM res = *q->result; 1287*8040SBaban.Kenkre@Sun.COM entry->next = res->entries; 1288*8040SBaban.Kenkre@Sun.COM res->entries = entry; 1289*8040SBaban.Kenkre@Sun.COM res->num_entries++; 1290*8040SBaban.Kenkre@Sun.COM } 1291*8040SBaban.Kenkre@Sun.COM *q->rc = ADUTILS_SUCCESS; 1292*8040SBaban.Kenkre@Sun.COM entry = NULL; 1293*8040SBaban.Kenkre@Sun.COM ret = 0; 1294*8040SBaban.Kenkre@Sun.COM 1295*8040SBaban.Kenkre@Sun.COM out: 1296*8040SBaban.Kenkre@Sun.COM free_entry(entry); 1297*8040SBaban.Kenkre@Sun.COM return (ret); 1298*8040SBaban.Kenkre@Sun.COM } 1299*8040SBaban.Kenkre@Sun.COM 1300*8040SBaban.Kenkre@Sun.COM /* 1301*8040SBaban.Kenkre@Sun.COM * Try to get a result; if there is one, find the corresponding 1302*8040SBaban.Kenkre@Sun.COM * adutils_q_t and process the result. 1303*8040SBaban.Kenkre@Sun.COM * 1304*8040SBaban.Kenkre@Sun.COM * Returns: 0 success 1305*8040SBaban.Kenkre@Sun.COM * -1 error 1306*8040SBaban.Kenkre@Sun.COM */ 1307*8040SBaban.Kenkre@Sun.COM static 1308*8040SBaban.Kenkre@Sun.COM int 1309*8040SBaban.Kenkre@Sun.COM get_adobject_batch(adutils_host_t *adh, struct timeval *timeout) 1310*8040SBaban.Kenkre@Sun.COM { 1311*8040SBaban.Kenkre@Sun.COM adutils_query_state_t *query_state; 1312*8040SBaban.Kenkre@Sun.COM LDAPMessage *res = NULL; 1313*8040SBaban.Kenkre@Sun.COM int rc, ret, msgid, qid; 1314*8040SBaban.Kenkre@Sun.COM adutils_q_t *que; 1315*8040SBaban.Kenkre@Sun.COM int num; 1316*8040SBaban.Kenkre@Sun.COM 1317*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&adh->lock); 1318*8040SBaban.Kenkre@Sun.COM if (adh->dead || adh->num_requests == 0) { 1319*8040SBaban.Kenkre@Sun.COM ret = (adh->dead) ? -1 : -2; 1320*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 1321*8040SBaban.Kenkre@Sun.COM return (ret); 1322*8040SBaban.Kenkre@Sun.COM } 1323*8040SBaban.Kenkre@Sun.COM 1324*8040SBaban.Kenkre@Sun.COM /* Get one result */ 1325*8040SBaban.Kenkre@Sun.COM rc = ldap_result(adh->ld, LDAP_RES_ANY, 0, timeout, &res); 1326*8040SBaban.Kenkre@Sun.COM if ((timeout != NULL && timeout->tv_sec > 0 && rc == LDAP_SUCCESS) || 1327*8040SBaban.Kenkre@Sun.COM rc < 0) 1328*8040SBaban.Kenkre@Sun.COM adh->dead = 1; 1329*8040SBaban.Kenkre@Sun.COM 1330*8040SBaban.Kenkre@Sun.COM if (rc == LDAP_RES_SEARCH_RESULT && adh->num_requests > 0) 1331*8040SBaban.Kenkre@Sun.COM adh->num_requests--; 1332*8040SBaban.Kenkre@Sun.COM if (adh->dead) { 1333*8040SBaban.Kenkre@Sun.COM num = adh->num_requests; 1334*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 1335*8040SBaban.Kenkre@Sun.COM idmapdlog(LOG_DEBUG, 1336*8040SBaban.Kenkre@Sun.COM "AD ldap_result error - %d queued requests", num); 1337*8040SBaban.Kenkre@Sun.COM return (-1); 1338*8040SBaban.Kenkre@Sun.COM } 1339*8040SBaban.Kenkre@Sun.COM 1340*8040SBaban.Kenkre@Sun.COM switch (rc) { 1341*8040SBaban.Kenkre@Sun.COM case LDAP_RES_SEARCH_RESULT: 1342*8040SBaban.Kenkre@Sun.COM msgid = ldap_msgid(res); 1343*8040SBaban.Kenkre@Sun.COM if (msgid2query(adh, msgid, &query_state, &qid)) { 1344*8040SBaban.Kenkre@Sun.COM if (query_state->ldap_res_search_cb != NULL) { 1345*8040SBaban.Kenkre@Sun.COM /* 1346*8040SBaban.Kenkre@Sun.COM * We use the caller-provided callback 1347*8040SBaban.Kenkre@Sun.COM * to process the result. 1348*8040SBaban.Kenkre@Sun.COM */ 1349*8040SBaban.Kenkre@Sun.COM query_state->ldap_res_search_cb( 1350*8040SBaban.Kenkre@Sun.COM adh->ld, &res, rc, qid, 1351*8040SBaban.Kenkre@Sun.COM query_state->ldap_res_search_argp); 1352*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 1353*8040SBaban.Kenkre@Sun.COM } else { 1354*8040SBaban.Kenkre@Sun.COM /* 1355*8040SBaban.Kenkre@Sun.COM * No callback. We fallback to our 1356*8040SBaban.Kenkre@Sun.COM * default behaviour. All the entries 1357*8040SBaban.Kenkre@Sun.COM * gotten from this search have been 1358*8040SBaban.Kenkre@Sun.COM * added to the result list during 1359*8040SBaban.Kenkre@Sun.COM * LDAP_RES_SEARCH_ENTRY (see below). 1360*8040SBaban.Kenkre@Sun.COM * Here we set the return status to 1361*8040SBaban.Kenkre@Sun.COM * notfound if the result is still empty. 1362*8040SBaban.Kenkre@Sun.COM */ 1363*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 1364*8040SBaban.Kenkre@Sun.COM que = &(query_state->queries[qid]); 1365*8040SBaban.Kenkre@Sun.COM if (*que->result == NULL) 1366*8040SBaban.Kenkre@Sun.COM *que->rc = ADUTILS_ERR_NOTFOUND; 1367*8040SBaban.Kenkre@Sun.COM } 1368*8040SBaban.Kenkre@Sun.COM atomic_dec_32(&query_state->qinflight); 1369*8040SBaban.Kenkre@Sun.COM adutils_lookup_batch_unlock(&query_state); 1370*8040SBaban.Kenkre@Sun.COM } else { 1371*8040SBaban.Kenkre@Sun.COM num = adh->num_requests; 1372*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 1373*8040SBaban.Kenkre@Sun.COM idmapdlog(LOG_DEBUG, 1374*8040SBaban.Kenkre@Sun.COM "AD cannot find message ID (%d) " 1375*8040SBaban.Kenkre@Sun.COM "- %d queued requests", 1376*8040SBaban.Kenkre@Sun.COM msgid, num); 1377*8040SBaban.Kenkre@Sun.COM } 1378*8040SBaban.Kenkre@Sun.COM (void) ldap_msgfree(res); 1379*8040SBaban.Kenkre@Sun.COM ret = 0; 1380*8040SBaban.Kenkre@Sun.COM break; 1381*8040SBaban.Kenkre@Sun.COM 1382*8040SBaban.Kenkre@Sun.COM case LDAP_RES_SEARCH_ENTRY: 1383*8040SBaban.Kenkre@Sun.COM msgid = ldap_msgid(res); 1384*8040SBaban.Kenkre@Sun.COM if (msgid2query(adh, msgid, &query_state, &qid)) { 1385*8040SBaban.Kenkre@Sun.COM if (query_state->ldap_res_search_cb != NULL) { 1386*8040SBaban.Kenkre@Sun.COM /* 1387*8040SBaban.Kenkre@Sun.COM * We use the caller-provided callback 1388*8040SBaban.Kenkre@Sun.COM * to process the entry. 1389*8040SBaban.Kenkre@Sun.COM */ 1390*8040SBaban.Kenkre@Sun.COM query_state->ldap_res_search_cb( 1391*8040SBaban.Kenkre@Sun.COM adh->ld, &res, rc, qid, 1392*8040SBaban.Kenkre@Sun.COM query_state->ldap_res_search_argp); 1393*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 1394*8040SBaban.Kenkre@Sun.COM } else { 1395*8040SBaban.Kenkre@Sun.COM /* 1396*8040SBaban.Kenkre@Sun.COM * No callback. We fallback to our 1397*8040SBaban.Kenkre@Sun.COM * default behaviour. This entry 1398*8040SBaban.Kenkre@Sun.COM * will be added to the result list. 1399*8040SBaban.Kenkre@Sun.COM */ 1400*8040SBaban.Kenkre@Sun.COM que = &(query_state->queries[qid]); 1401*8040SBaban.Kenkre@Sun.COM rc = add_entry(adh, que, res); 1402*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 1403*8040SBaban.Kenkre@Sun.COM if (rc < 0) { 1404*8040SBaban.Kenkre@Sun.COM idmapdlog(LOG_DEBUG, 1405*8040SBaban.Kenkre@Sun.COM "Failed to queue entry by " 1406*8040SBaban.Kenkre@Sun.COM "message ID (%d) " 1407*8040SBaban.Kenkre@Sun.COM "- %d queued requests", 1408*8040SBaban.Kenkre@Sun.COM msgid, num); 1409*8040SBaban.Kenkre@Sun.COM } 1410*8040SBaban.Kenkre@Sun.COM } 1411*8040SBaban.Kenkre@Sun.COM adutils_lookup_batch_unlock(&query_state); 1412*8040SBaban.Kenkre@Sun.COM } else { 1413*8040SBaban.Kenkre@Sun.COM num = adh->num_requests; 1414*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 1415*8040SBaban.Kenkre@Sun.COM idmapdlog(LOG_DEBUG, 1416*8040SBaban.Kenkre@Sun.COM "AD cannot find message ID (%d) " 1417*8040SBaban.Kenkre@Sun.COM "- %d queued requests", 1418*8040SBaban.Kenkre@Sun.COM msgid, num); 1419*8040SBaban.Kenkre@Sun.COM } 1420*8040SBaban.Kenkre@Sun.COM (void) ldap_msgfree(res); 1421*8040SBaban.Kenkre@Sun.COM ret = 0; 1422*8040SBaban.Kenkre@Sun.COM break; 1423*8040SBaban.Kenkre@Sun.COM 1424*8040SBaban.Kenkre@Sun.COM case LDAP_RES_SEARCH_REFERENCE: 1425*8040SBaban.Kenkre@Sun.COM /* 1426*8040SBaban.Kenkre@Sun.COM * We have no need for these at the moment. Eventually, 1427*8040SBaban.Kenkre@Sun.COM * when we query things that we can't expect to find in 1428*8040SBaban.Kenkre@Sun.COM * the Global Catalog then we'll need to learn to follow 1429*8040SBaban.Kenkre@Sun.COM * references. 1430*8040SBaban.Kenkre@Sun.COM */ 1431*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 1432*8040SBaban.Kenkre@Sun.COM (void) ldap_msgfree(res); 1433*8040SBaban.Kenkre@Sun.COM ret = 0; 1434*8040SBaban.Kenkre@Sun.COM break; 1435*8040SBaban.Kenkre@Sun.COM 1436*8040SBaban.Kenkre@Sun.COM default: 1437*8040SBaban.Kenkre@Sun.COM /* timeout or error; treat the same */ 1438*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&adh->lock); 1439*8040SBaban.Kenkre@Sun.COM ret = -1; 1440*8040SBaban.Kenkre@Sun.COM break; 1441*8040SBaban.Kenkre@Sun.COM } 1442*8040SBaban.Kenkre@Sun.COM 1443*8040SBaban.Kenkre@Sun.COM return (ret); 1444*8040SBaban.Kenkre@Sun.COM } 1445*8040SBaban.Kenkre@Sun.COM 1446*8040SBaban.Kenkre@Sun.COM /* 1447*8040SBaban.Kenkre@Sun.COM * This routine decreament the reference count of the 1448*8040SBaban.Kenkre@Sun.COM * adutils_query_state_t 1449*8040SBaban.Kenkre@Sun.COM */ 1450*8040SBaban.Kenkre@Sun.COM static void 1451*8040SBaban.Kenkre@Sun.COM adutils_lookup_batch_unlock(adutils_query_state_t **state) 1452*8040SBaban.Kenkre@Sun.COM { 1453*8040SBaban.Kenkre@Sun.COM /* 1454*8040SBaban.Kenkre@Sun.COM * Decrement reference count with qstatelock locked 1455*8040SBaban.Kenkre@Sun.COM */ 1456*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&qstatelock); 1457*8040SBaban.Kenkre@Sun.COM (*state)->ref_cnt--; 1458*8040SBaban.Kenkre@Sun.COM /* 1459*8040SBaban.Kenkre@Sun.COM * If there are no references wakup the allocating thread 1460*8040SBaban.Kenkre@Sun.COM */ 1461*8040SBaban.Kenkre@Sun.COM if ((*state)->ref_cnt <= 1) 1462*8040SBaban.Kenkre@Sun.COM (void) pthread_cond_signal(&(*state)->cv); 1463*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&qstatelock); 1464*8040SBaban.Kenkre@Sun.COM *state = NULL; 1465*8040SBaban.Kenkre@Sun.COM } 1466*8040SBaban.Kenkre@Sun.COM 1467*8040SBaban.Kenkre@Sun.COM /* 1468*8040SBaban.Kenkre@Sun.COM * This routine frees the adutils_query_state_t structure 1469*8040SBaban.Kenkre@Sun.COM * If the reference count is greater than 1 it waits 1470*8040SBaban.Kenkre@Sun.COM * for the other threads to finish using it. 1471*8040SBaban.Kenkre@Sun.COM */ 1472*8040SBaban.Kenkre@Sun.COM void 1473*8040SBaban.Kenkre@Sun.COM adutils_lookup_batch_release(adutils_query_state_t **state) 1474*8040SBaban.Kenkre@Sun.COM { 1475*8040SBaban.Kenkre@Sun.COM adutils_query_state_t **p; 1476*8040SBaban.Kenkre@Sun.COM int i; 1477*8040SBaban.Kenkre@Sun.COM 1478*8040SBaban.Kenkre@Sun.COM if (state == NULL || *state == NULL) 1479*8040SBaban.Kenkre@Sun.COM return; 1480*8040SBaban.Kenkre@Sun.COM 1481*8040SBaban.Kenkre@Sun.COM /* 1482*8040SBaban.Kenkre@Sun.COM * Set state to dead to stop further operations. 1483*8040SBaban.Kenkre@Sun.COM * Wait for reference count with qstatelock locked 1484*8040SBaban.Kenkre@Sun.COM * to get to one. 1485*8040SBaban.Kenkre@Sun.COM */ 1486*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&qstatelock); 1487*8040SBaban.Kenkre@Sun.COM (*state)->qdead = 1; 1488*8040SBaban.Kenkre@Sun.COM while ((*state)->ref_cnt > 1) { 1489*8040SBaban.Kenkre@Sun.COM (void) pthread_cond_wait(&(*state)->cv, &qstatelock); 1490*8040SBaban.Kenkre@Sun.COM } 1491*8040SBaban.Kenkre@Sun.COM 1492*8040SBaban.Kenkre@Sun.COM /* Remove this state struct from the list of state structs */ 1493*8040SBaban.Kenkre@Sun.COM for (p = &qstatehead; *p != NULL; p = &(*p)->next) { 1494*8040SBaban.Kenkre@Sun.COM if (*p == (*state)) { 1495*8040SBaban.Kenkre@Sun.COM *p = (*state)->next; 1496*8040SBaban.Kenkre@Sun.COM break; 1497*8040SBaban.Kenkre@Sun.COM } 1498*8040SBaban.Kenkre@Sun.COM } 1499*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&qstatelock); 1500*8040SBaban.Kenkre@Sun.COM (void) pthread_cond_destroy(&(*state)->cv); 1501*8040SBaban.Kenkre@Sun.COM release_conn((*state)->qadh); 1502*8040SBaban.Kenkre@Sun.COM 1503*8040SBaban.Kenkre@Sun.COM /* Clear results for queries that failed */ 1504*8040SBaban.Kenkre@Sun.COM for (i = 0; i < (*state)->qcount; i++) { 1505*8040SBaban.Kenkre@Sun.COM if (*(*state)->queries[i].rc != ADUTILS_SUCCESS) { 1506*8040SBaban.Kenkre@Sun.COM adutils_freeresult((*state)->queries[i].result); 1507*8040SBaban.Kenkre@Sun.COM } 1508*8040SBaban.Kenkre@Sun.COM } 1509*8040SBaban.Kenkre@Sun.COM free((*state)->default_domain); 1510*8040SBaban.Kenkre@Sun.COM free((*state)->basedn); 1511*8040SBaban.Kenkre@Sun.COM free(*state); 1512*8040SBaban.Kenkre@Sun.COM *state = NULL; 1513*8040SBaban.Kenkre@Sun.COM } 1514*8040SBaban.Kenkre@Sun.COM 1515*8040SBaban.Kenkre@Sun.COM 1516*8040SBaban.Kenkre@Sun.COM /* 1517*8040SBaban.Kenkre@Sun.COM * This routine waits for other threads using the 1518*8040SBaban.Kenkre@Sun.COM * adutils_query_state_t structure to finish. 1519*8040SBaban.Kenkre@Sun.COM * If the reference count is greater than 1 it waits 1520*8040SBaban.Kenkre@Sun.COM * for the other threads to finish using it. 1521*8040SBaban.Kenkre@Sun.COM */ 1522*8040SBaban.Kenkre@Sun.COM static 1523*8040SBaban.Kenkre@Sun.COM void 1524*8040SBaban.Kenkre@Sun.COM adutils_lookup_batch_wait(adutils_query_state_t *state) 1525*8040SBaban.Kenkre@Sun.COM { 1526*8040SBaban.Kenkre@Sun.COM /* 1527*8040SBaban.Kenkre@Sun.COM * Set state to dead to stop further operation. 1528*8040SBaban.Kenkre@Sun.COM * stating. 1529*8040SBaban.Kenkre@Sun.COM * Wait for reference count to get to one 1530*8040SBaban.Kenkre@Sun.COM * with qstatelock locked. 1531*8040SBaban.Kenkre@Sun.COM */ 1532*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&qstatelock); 1533*8040SBaban.Kenkre@Sun.COM state->qdead = 1; 1534*8040SBaban.Kenkre@Sun.COM while (state->ref_cnt > 1) { 1535*8040SBaban.Kenkre@Sun.COM (void) pthread_cond_wait(&state->cv, &qstatelock); 1536*8040SBaban.Kenkre@Sun.COM } 1537*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&qstatelock); 1538*8040SBaban.Kenkre@Sun.COM } 1539*8040SBaban.Kenkre@Sun.COM 1540*8040SBaban.Kenkre@Sun.COM /* 1541*8040SBaban.Kenkre@Sun.COM * Process active queries in the AD lookup batch and then finalize the 1542*8040SBaban.Kenkre@Sun.COM * result. 1543*8040SBaban.Kenkre@Sun.COM */ 1544*8040SBaban.Kenkre@Sun.COM adutils_rc 1545*8040SBaban.Kenkre@Sun.COM adutils_lookup_batch_end(adutils_query_state_t **state) 1546*8040SBaban.Kenkre@Sun.COM { 1547*8040SBaban.Kenkre@Sun.COM int rc = LDAP_SUCCESS; 1548*8040SBaban.Kenkre@Sun.COM adutils_rc ad_rc = ADUTILS_SUCCESS; 1549*8040SBaban.Kenkre@Sun.COM struct timeval tv; 1550*8040SBaban.Kenkre@Sun.COM 1551*8040SBaban.Kenkre@Sun.COM tv.tv_sec = ADUTILS_SEARCH_TIMEOUT; 1552*8040SBaban.Kenkre@Sun.COM tv.tv_usec = 0; 1553*8040SBaban.Kenkre@Sun.COM 1554*8040SBaban.Kenkre@Sun.COM /* Process results until done or until timeout, if given */ 1555*8040SBaban.Kenkre@Sun.COM while ((*state)->qinflight > 0) { 1556*8040SBaban.Kenkre@Sun.COM if ((rc = get_adobject_batch((*state)->qadh, 1557*8040SBaban.Kenkre@Sun.COM &tv)) != 0) 1558*8040SBaban.Kenkre@Sun.COM break; 1559*8040SBaban.Kenkre@Sun.COM } 1560*8040SBaban.Kenkre@Sun.COM (*state)->qdead = 1; 1561*8040SBaban.Kenkre@Sun.COM /* Wait for other threads processing search result to finish */ 1562*8040SBaban.Kenkre@Sun.COM adutils_lookup_batch_wait(*state); 1563*8040SBaban.Kenkre@Sun.COM if (rc == -1 || (*state)->qinflight != 0) 1564*8040SBaban.Kenkre@Sun.COM ad_rc = ADUTILS_ERR_RETRIABLE_NET_ERR; 1565*8040SBaban.Kenkre@Sun.COM adutils_lookup_batch_release(state); 1566*8040SBaban.Kenkre@Sun.COM return (ad_rc); 1567*8040SBaban.Kenkre@Sun.COM } 1568*8040SBaban.Kenkre@Sun.COM 1569*8040SBaban.Kenkre@Sun.COM const char * 1570*8040SBaban.Kenkre@Sun.COM adutils_lookup_batch_getdefdomain(adutils_query_state_t *state) 1571*8040SBaban.Kenkre@Sun.COM { 1572*8040SBaban.Kenkre@Sun.COM return (state->default_domain); 1573*8040SBaban.Kenkre@Sun.COM } 1574*8040SBaban.Kenkre@Sun.COM 1575*8040SBaban.Kenkre@Sun.COM /* 1576*8040SBaban.Kenkre@Sun.COM * Send one prepared search, queue up msgid, process what results are 1577*8040SBaban.Kenkre@Sun.COM * available 1578*8040SBaban.Kenkre@Sun.COM */ 1579*8040SBaban.Kenkre@Sun.COM adutils_rc 1580*8040SBaban.Kenkre@Sun.COM adutils_lookup_batch_add(adutils_query_state_t *state, 1581*8040SBaban.Kenkre@Sun.COM const char *filter, const char **attrs, const char *edomain, 1582*8040SBaban.Kenkre@Sun.COM adutils_result_t **result, adutils_rc *rc) 1583*8040SBaban.Kenkre@Sun.COM { 1584*8040SBaban.Kenkre@Sun.COM adutils_rc retcode = ADUTILS_SUCCESS; 1585*8040SBaban.Kenkre@Sun.COM int lrc, qid; 1586*8040SBaban.Kenkre@Sun.COM int num; 1587*8040SBaban.Kenkre@Sun.COM int dead; 1588*8040SBaban.Kenkre@Sun.COM struct timeval tv; 1589*8040SBaban.Kenkre@Sun.COM adutils_q_t *q; 1590*8040SBaban.Kenkre@Sun.COM 1591*8040SBaban.Kenkre@Sun.COM qid = atomic_inc_32_nv(&state->qlastsent) - 1; 1592*8040SBaban.Kenkre@Sun.COM q = &(state->queries[qid]); 1593*8040SBaban.Kenkre@Sun.COM 1594*8040SBaban.Kenkre@Sun.COM /* 1595*8040SBaban.Kenkre@Sun.COM * Remember the expected domain so we can check the results 1596*8040SBaban.Kenkre@Sun.COM * against it 1597*8040SBaban.Kenkre@Sun.COM */ 1598*8040SBaban.Kenkre@Sun.COM q->edomain = edomain; 1599*8040SBaban.Kenkre@Sun.COM 1600*8040SBaban.Kenkre@Sun.COM /* Remember where to put the results */ 1601*8040SBaban.Kenkre@Sun.COM q->result = result; 1602*8040SBaban.Kenkre@Sun.COM q->rc = rc; 1603*8040SBaban.Kenkre@Sun.COM 1604*8040SBaban.Kenkre@Sun.COM /* 1605*8040SBaban.Kenkre@Sun.COM * Provide sane defaults for the results in case we never hear 1606*8040SBaban.Kenkre@Sun.COM * back from the DS before closing the connection. 1607*8040SBaban.Kenkre@Sun.COM */ 1608*8040SBaban.Kenkre@Sun.COM *rc = ADUTILS_ERR_RETRIABLE_NET_ERR; 1609*8040SBaban.Kenkre@Sun.COM if (result != NULL) 1610*8040SBaban.Kenkre@Sun.COM *result = NULL; 1611*8040SBaban.Kenkre@Sun.COM 1612*8040SBaban.Kenkre@Sun.COM /* Check the number of queued requests first */ 1613*8040SBaban.Kenkre@Sun.COM tv.tv_sec = ADUTILS_SEARCH_TIMEOUT; 1614*8040SBaban.Kenkre@Sun.COM tv.tv_usec = 0; 1615*8040SBaban.Kenkre@Sun.COM while (!state->qadh->dead && 1616*8040SBaban.Kenkre@Sun.COM state->qadh->num_requests > state->qadh->max_requests) { 1617*8040SBaban.Kenkre@Sun.COM if (get_adobject_batch(state->qadh, &tv) != 0) 1618*8040SBaban.Kenkre@Sun.COM break; 1619*8040SBaban.Kenkre@Sun.COM } 1620*8040SBaban.Kenkre@Sun.COM 1621*8040SBaban.Kenkre@Sun.COM /* Send this lookup, don't wait for a result here */ 1622*8040SBaban.Kenkre@Sun.COM lrc = LDAP_SUCCESS; 1623*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&state->qadh->lock); 1624*8040SBaban.Kenkre@Sun.COM 1625*8040SBaban.Kenkre@Sun.COM if (!state->qadh->dead) { 1626*8040SBaban.Kenkre@Sun.COM state->qadh->idletime = time(NULL); 1627*8040SBaban.Kenkre@Sun.COM lrc = ldap_search_ext(state->qadh->ld, state->basedn, 1628*8040SBaban.Kenkre@Sun.COM LDAP_SCOPE_SUBTREE, filter, (char **)attrs, 1629*8040SBaban.Kenkre@Sun.COM 0, NULL, NULL, NULL, -1, &q->msgid); 1630*8040SBaban.Kenkre@Sun.COM 1631*8040SBaban.Kenkre@Sun.COM if (lrc == LDAP_SUCCESS) { 1632*8040SBaban.Kenkre@Sun.COM state->qadh->num_requests++; 1633*8040SBaban.Kenkre@Sun.COM } else if (lrc == LDAP_BUSY || lrc == LDAP_UNAVAILABLE || 1634*8040SBaban.Kenkre@Sun.COM lrc == LDAP_CONNECT_ERROR || lrc == LDAP_SERVER_DOWN || 1635*8040SBaban.Kenkre@Sun.COM lrc == LDAP_UNWILLING_TO_PERFORM) { 1636*8040SBaban.Kenkre@Sun.COM retcode = ADUTILS_ERR_RETRIABLE_NET_ERR; 1637*8040SBaban.Kenkre@Sun.COM state->qadh->dead = 1; 1638*8040SBaban.Kenkre@Sun.COM } else { 1639*8040SBaban.Kenkre@Sun.COM retcode = ADUTILS_ERR_OTHER; 1640*8040SBaban.Kenkre@Sun.COM state->qadh->dead = 1; 1641*8040SBaban.Kenkre@Sun.COM } 1642*8040SBaban.Kenkre@Sun.COM } 1643*8040SBaban.Kenkre@Sun.COM dead = state->qadh->dead; 1644*8040SBaban.Kenkre@Sun.COM num = state->qadh->num_requests; 1645*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&state->qadh->lock); 1646*8040SBaban.Kenkre@Sun.COM 1647*8040SBaban.Kenkre@Sun.COM if (dead) { 1648*8040SBaban.Kenkre@Sun.COM if (lrc != LDAP_SUCCESS) 1649*8040SBaban.Kenkre@Sun.COM idmapdlog(LOG_DEBUG, 1650*8040SBaban.Kenkre@Sun.COM "AD ldap_search_ext error (%s) " 1651*8040SBaban.Kenkre@Sun.COM "- %d queued requests", 1652*8040SBaban.Kenkre@Sun.COM ldap_err2string(lrc), num); 1653*8040SBaban.Kenkre@Sun.COM return (retcode); 1654*8040SBaban.Kenkre@Sun.COM } 1655*8040SBaban.Kenkre@Sun.COM 1656*8040SBaban.Kenkre@Sun.COM atomic_inc_32(&state->qinflight); 1657*8040SBaban.Kenkre@Sun.COM 1658*8040SBaban.Kenkre@Sun.COM /* 1659*8040SBaban.Kenkre@Sun.COM * Reap as many requests as we can _without_ waiting to prevent 1660*8040SBaban.Kenkre@Sun.COM * any possible TCP socket buffer starvation deadlocks. 1661*8040SBaban.Kenkre@Sun.COM */ 1662*8040SBaban.Kenkre@Sun.COM (void) memset(&tv, 0, sizeof (tv)); 1663*8040SBaban.Kenkre@Sun.COM while (get_adobject_batch(state->qadh, &tv) == 0) 1664*8040SBaban.Kenkre@Sun.COM ; 1665*8040SBaban.Kenkre@Sun.COM 1666*8040SBaban.Kenkre@Sun.COM return (ADUTILS_SUCCESS); 1667*8040SBaban.Kenkre@Sun.COM } 1668*8040SBaban.Kenkre@Sun.COM 1669*8040SBaban.Kenkre@Sun.COM /* 1670*8040SBaban.Kenkre@Sun.COM * Single AD lookup request implemented on top of the batch API. 1671*8040SBaban.Kenkre@Sun.COM */ 1672*8040SBaban.Kenkre@Sun.COM adutils_rc 1673*8040SBaban.Kenkre@Sun.COM adutils_lookup(adutils_ad_t *ad, const char *filter, const char **attrs, 1674*8040SBaban.Kenkre@Sun.COM const char *domain, adutils_result_t **result) 1675*8040SBaban.Kenkre@Sun.COM { 1676*8040SBaban.Kenkre@Sun.COM adutils_rc rc, brc; 1677*8040SBaban.Kenkre@Sun.COM adutils_query_state_t *qs; 1678*8040SBaban.Kenkre@Sun.COM 1679*8040SBaban.Kenkre@Sun.COM rc = adutils_lookup_batch_start(ad, 1, NULL, NULL, &qs); 1680*8040SBaban.Kenkre@Sun.COM if (rc != ADUTILS_SUCCESS) 1681*8040SBaban.Kenkre@Sun.COM return (rc); 1682*8040SBaban.Kenkre@Sun.COM 1683*8040SBaban.Kenkre@Sun.COM rc = adutils_lookup_batch_add(qs, filter, attrs, domain, result, &brc); 1684*8040SBaban.Kenkre@Sun.COM if (rc != ADUTILS_SUCCESS) { 1685*8040SBaban.Kenkre@Sun.COM adutils_lookup_batch_release(&qs); 1686*8040SBaban.Kenkre@Sun.COM return (rc); 1687*8040SBaban.Kenkre@Sun.COM } 1688*8040SBaban.Kenkre@Sun.COM 1689*8040SBaban.Kenkre@Sun.COM rc = adutils_lookup_batch_end(&qs); 1690*8040SBaban.Kenkre@Sun.COM if (rc != ADUTILS_SUCCESS) 1691*8040SBaban.Kenkre@Sun.COM return (rc); 1692*8040SBaban.Kenkre@Sun.COM return (brc); 1693*8040SBaban.Kenkre@Sun.COM } 1694