1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * 3*0Sstevel@tonic-gate * Copyright (c) 1998-2001 by Sun Microsystems, Inc. 4*0Sstevel@tonic-gate * All rights reserved. 5*0Sstevel@tonic-gate * 6*0Sstevel@tonic-gate */ 7*0Sstevel@tonic-gate 8*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 9*0Sstevel@tonic-gate 10*0Sstevel@tonic-gate /* 11*0Sstevel@tonic-gate * Copyright (c) 1990 Regents of the University of Michigan. 12*0Sstevel@tonic-gate * All rights reserved. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * search.c 15*0Sstevel@tonic-gate */ 16*0Sstevel@tonic-gate 17*0Sstevel@tonic-gate #ifndef lint 18*0Sstevel@tonic-gate static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; 19*0Sstevel@tonic-gate #endif 20*0Sstevel@tonic-gate 21*0Sstevel@tonic-gate #include <stdio.h> 22*0Sstevel@tonic-gate #include <string.h> 23*0Sstevel@tonic-gate #include <ctype.h> 24*0Sstevel@tonic-gate #include <stdlib.h> /* free() for Solaris */ 25*0Sstevel@tonic-gate 26*0Sstevel@tonic-gate #ifdef MACOS 27*0Sstevel@tonic-gate #include <stdlib.h> 28*0Sstevel@tonic-gate #include "macos.h" 29*0Sstevel@tonic-gate #endif /* MACOS */ 30*0Sstevel@tonic-gate 31*0Sstevel@tonic-gate #if defined(DOS) || defined(_WIN32) 32*0Sstevel@tonic-gate #include "msdos.h" 33*0Sstevel@tonic-gate #endif /* DOS */ 34*0Sstevel@tonic-gate 35*0Sstevel@tonic-gate #if !defined(MACOS) && !defined(DOS) && !defined(_WIN32) 36*0Sstevel@tonic-gate #include <sys/time.h> 37*0Sstevel@tonic-gate #include <sys/types.h> 38*0Sstevel@tonic-gate #include <sys/socket.h> 39*0Sstevel@tonic-gate #endif 40*0Sstevel@tonic-gate #include "lber.h" 41*0Sstevel@tonic-gate #include "ldap.h" 42*0Sstevel@tonic-gate #include "ldap-private.h" 43*0Sstevel@tonic-gate #include "ldap-int.h" 44*0Sstevel@tonic-gate 45*0Sstevel@tonic-gate #ifdef NEEDPROTOS 46*0Sstevel@tonic-gate static char *find_right_paren(char *s); 47*0Sstevel@tonic-gate static char *put_complex_filter(BerElement *ber, char *str, 48*0Sstevel@tonic-gate unsigned int tag, int not); 49*0Sstevel@tonic-gate static int put_filter(BerElement *ber, char *str); 50*0Sstevel@tonic-gate static int put_simple_filter(BerElement *ber, char *str); 51*0Sstevel@tonic-gate static int put_substring_filter(BerElement *ber, char *type, char *str); 52*0Sstevel@tonic-gate static int put_filter_list(BerElement *ber, char *str); 53*0Sstevel@tonic-gate static char *star_search(char *str); 54*0Sstevel@tonic-gate static int hex_char2int(char c); 55*0Sstevel@tonic-gate static int decode_value(char *str); 56*0Sstevel@tonic-gate #else 57*0Sstevel@tonic-gate static char *find_right_paren(); 58*0Sstevel@tonic-gate static char *put_complex_filter(); 59*0Sstevel@tonic-gate static int put_filter(); 60*0Sstevel@tonic-gate static int put_simple_filter(); 61*0Sstevel@tonic-gate static int put_substring_filter(); 62*0Sstevel@tonic-gate static int put_filter_list(); 63*0Sstevel@tonic-gate static char *star_search(); 64*0Sstevel@tonic-gate static int hex_char2int(); 65*0Sstevel@tonic-gate static int decode_value(); 66*0Sstevel@tonic-gate #endif /* NEEDPROTOS */ 67*0Sstevel@tonic-gate 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate BerElement * 70*0Sstevel@tonic-gate ldap_build_search_req(LDAP *ld, char *base, int scope, char *filter, 71*0Sstevel@tonic-gate char **attrs, int attrsonly, LDAPControl ** serverctrls, 72*0Sstevel@tonic-gate struct timeval *timeoutp, int sizelimit) 73*0Sstevel@tonic-gate { 74*0Sstevel@tonic-gate BerElement *ber; 75*0Sstevel@tonic-gate int err; 76*0Sstevel@tonic-gate int theSizeLimit, theTimeLimit; 77*0Sstevel@tonic-gate char *theFilter; 78*0Sstevel@tonic-gate 79*0Sstevel@tonic-gate /* 80*0Sstevel@tonic-gate * Create the search request. It looks like this: 81*0Sstevel@tonic-gate * SearchRequest := [APPLICATION 3] SEQUENCE { 82*0Sstevel@tonic-gate * baseObject DistinguishedName, 83*0Sstevel@tonic-gate * scope ENUMERATED { 84*0Sstevel@tonic-gate * baseObject (0), 85*0Sstevel@tonic-gate * singleLevel (1), 86*0Sstevel@tonic-gate * wholeSubtree (2) 87*0Sstevel@tonic-gate * }, 88*0Sstevel@tonic-gate * derefAliases ENUMERATED { 89*0Sstevel@tonic-gate * neverDerefaliases (0), 90*0Sstevel@tonic-gate * derefInSearching (1), 91*0Sstevel@tonic-gate * derefFindingBaseObj (2), 92*0Sstevel@tonic-gate * alwaysDerefAliases (3) 93*0Sstevel@tonic-gate * }, 94*0Sstevel@tonic-gate * sizelimit INTEGER (0 .. 65535), 95*0Sstevel@tonic-gate * timelimit INTEGER (0 .. 65535), 96*0Sstevel@tonic-gate * attrsOnly BOOLEAN, 97*0Sstevel@tonic-gate * filter Filter, 98*0Sstevel@tonic-gate * attributes SEQUENCE OF AttributeType 99*0Sstevel@tonic-gate * } 100*0Sstevel@tonic-gate * wrapped in an ldap message. 101*0Sstevel@tonic-gate */ 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gate if (filter == NULL || *filter == '\0') { 104*0Sstevel@tonic-gate ld->ld_errno = LDAP_PARAM_ERROR; 105*0Sstevel@tonic-gate return (NULLBER); 106*0Sstevel@tonic-gate } 107*0Sstevel@tonic-gate 108*0Sstevel@tonic-gate /* create a message to send */ 109*0Sstevel@tonic-gate if ((ber = alloc_ber_with_options(ld)) == NULLBER) { 110*0Sstevel@tonic-gate return (NULLBER); 111*0Sstevel@tonic-gate } 112*0Sstevel@tonic-gate 113*0Sstevel@tonic-gate if (base == NULL) { 114*0Sstevel@tonic-gate base = ""; 115*0Sstevel@tonic-gate } 116*0Sstevel@tonic-gate 117*0Sstevel@tonic-gate if (timeoutp != NULL) { 118*0Sstevel@tonic-gate if (timeoutp->tv_sec > 0) { 119*0Sstevel@tonic-gate theTimeLimit = (int)(timeoutp->tv_sec + 120*0Sstevel@tonic-gate (timeoutp->tv_usec / 1000000)); 121*0Sstevel@tonic-gate } else if (timeoutp->tv_usec > 0) { 122*0Sstevel@tonic-gate theTimeLimit = 1; /* minimum we can express in LDAP */ 123*0Sstevel@tonic-gate } else { 124*0Sstevel@tonic-gate theTimeLimit = 0; /* no limit */ 125*0Sstevel@tonic-gate } 126*0Sstevel@tonic-gate } else { 127*0Sstevel@tonic-gate theTimeLimit = ld->ld_timelimit; 128*0Sstevel@tonic-gate } 129*0Sstevel@tonic-gate 130*0Sstevel@tonic-gate #ifdef CLDAP 131*0Sstevel@tonic-gate if (ld->ld_sb.sb_naddr > 0) { 132*0Sstevel@tonic-gate err = ber_printf(ber, "{ist{seeiib", ++ld->ld_msgid, 133*0Sstevel@tonic-gate ld->ld_cldapdn, LDAP_REQ_SEARCH, base, scope, ld->ld_deref, 134*0Sstevel@tonic-gate sizelimit == -1 ? ld->ld_sizelimit : sizelimit, theTimeLimit, 135*0Sstevel@tonic-gate attrsonly); 136*0Sstevel@tonic-gate } else { 137*0Sstevel@tonic-gate #endif /* CLDAP */ 138*0Sstevel@tonic-gate err = ber_printf(ber, "{it{seeiib", ++ld->ld_msgid, 139*0Sstevel@tonic-gate LDAP_REQ_SEARCH, base, scope, ld->ld_deref, 140*0Sstevel@tonic-gate sizelimit == -1 ? ld->ld_sizelimit : sizelimit, 141*0Sstevel@tonic-gate theTimeLimit, attrsonly); 142*0Sstevel@tonic-gate #ifdef CLDAP 143*0Sstevel@tonic-gate } 144*0Sstevel@tonic-gate #endif /* CLDAP */ 145*0Sstevel@tonic-gate 146*0Sstevel@tonic-gate if (err == -1) { 147*0Sstevel@tonic-gate ld->ld_errno = LDAP_ENCODING_ERROR; 148*0Sstevel@tonic-gate ber_free(ber, 1); 149*0Sstevel@tonic-gate return (NULLBER); 150*0Sstevel@tonic-gate } 151*0Sstevel@tonic-gate 152*0Sstevel@tonic-gate theFilter = filter; 153*0Sstevel@tonic-gate while (*theFilter == ' ') theFilter++; 154*0Sstevel@tonic-gate if ((*theFilter == '&') || (*theFilter == '|') || (*theFilter == '!')) { 155*0Sstevel@tonic-gate char *ptr = theFilter; 156*0Sstevel@tonic-gate theFilter = (char *)calloc(1, strlen(ptr) + 3); 157*0Sstevel@tonic-gate sprintf(theFilter, "(%s)", ptr); 158*0Sstevel@tonic-gate } else { 159*0Sstevel@tonic-gate theFilter = strdup(filter); 160*0Sstevel@tonic-gate } 161*0Sstevel@tonic-gate err = put_filter(ber, theFilter); 162*0Sstevel@tonic-gate free(theFilter); 163*0Sstevel@tonic-gate 164*0Sstevel@tonic-gate if (err == -1) { 165*0Sstevel@tonic-gate ld->ld_errno = LDAP_FILTER_ERROR; 166*0Sstevel@tonic-gate ber_free(ber, 1); 167*0Sstevel@tonic-gate return (NULLBER); 168*0Sstevel@tonic-gate } 169*0Sstevel@tonic-gate 170*0Sstevel@tonic-gate if (ber_printf(ber, "{v}}", attrs) == -1) { 171*0Sstevel@tonic-gate ld->ld_errno = LDAP_ENCODING_ERROR; 172*0Sstevel@tonic-gate ber_free(ber, 1); 173*0Sstevel@tonic-gate return (NULLBER); 174*0Sstevel@tonic-gate } 175*0Sstevel@tonic-gate 176*0Sstevel@tonic-gate /* LDAPv3 */ 177*0Sstevel@tonic-gate /* Code controls if any */ 178*0Sstevel@tonic-gate if (serverctrls && serverctrls[0]) { 179*0Sstevel@tonic-gate if (ldap_controls_code(ber, serverctrls) != LDAP_SUCCESS) { 180*0Sstevel@tonic-gate ld->ld_errno = LDAP_ENCODING_ERROR; 181*0Sstevel@tonic-gate ber_free(ber, 1); 182*0Sstevel@tonic-gate return (NULLBER); 183*0Sstevel@tonic-gate } 184*0Sstevel@tonic-gate } else if (ld->ld_srvctrls && ld->ld_srvctrls[0]) { 185*0Sstevel@tonic-gate /* Otherwise, is there any global server ctrls ? */ 186*0Sstevel@tonic-gate if (ldap_controls_code(ber, ld->ld_srvctrls) != LDAP_SUCCESS) { 187*0Sstevel@tonic-gate ld->ld_errno = LDAP_ENCODING_ERROR; 188*0Sstevel@tonic-gate ber_free(ber, 1); 189*0Sstevel@tonic-gate return (NULLBER); 190*0Sstevel@tonic-gate } 191*0Sstevel@tonic-gate } 192*0Sstevel@tonic-gate 193*0Sstevel@tonic-gate if (ber_printf(ber, "}") == -1) { 194*0Sstevel@tonic-gate ld->ld_errno = LDAP_ENCODING_ERROR; 195*0Sstevel@tonic-gate ber_free(ber, 1); 196*0Sstevel@tonic-gate return (NULLBER); 197*0Sstevel@tonic-gate } 198*0Sstevel@tonic-gate 199*0Sstevel@tonic-gate return (ber); 200*0Sstevel@tonic-gate } 201*0Sstevel@tonic-gate 202*0Sstevel@tonic-gate /* 203*0Sstevel@tonic-gate * ldap_search - initiate an ldap (and X.500) search operation. Parameters: 204*0Sstevel@tonic-gate * 205*0Sstevel@tonic-gate * ld LDAP descriptor 206*0Sstevel@tonic-gate * base DN of the base object 207*0Sstevel@tonic-gate * scope the search scope - one of LDAP_SCOPE_BASE, 208*0Sstevel@tonic-gate * LDAP_SCOPE_ONELEVEL, LDAP_SCOPE_SUBTREE 209*0Sstevel@tonic-gate * filter a string containing the search filter 210*0Sstevel@tonic-gate * (e.g., "(|(cn=bob)(sn=bob))") 211*0Sstevel@tonic-gate * attrs list of attribute types to return for matches 212*0Sstevel@tonic-gate * attrsonly 1 => attributes only 0 => attributes and values 213*0Sstevel@tonic-gate * 214*0Sstevel@tonic-gate * Example: 215*0Sstevel@tonic-gate * char *attrs[] = { "mail", "title", 0 }; 216*0Sstevel@tonic-gate * msgid = ldap_search( ld, "c=us@o=UM", LDAP_SCOPE_SUBTREE, "cn~=bob", 217*0Sstevel@tonic-gate * attrs, attrsonly ); 218*0Sstevel@tonic-gate */ 219*0Sstevel@tonic-gate int 220*0Sstevel@tonic-gate ldap_search(LDAP *ld, char *base, int scope, char *filter, 221*0Sstevel@tonic-gate char **attrs, int attrsonly) 222*0Sstevel@tonic-gate { 223*0Sstevel@tonic-gate BerElement *ber; 224*0Sstevel@tonic-gate 225*0Sstevel@tonic-gate #if defined(SUN) && defined(_REENTRANT) 226*0Sstevel@tonic-gate int rv; 227*0Sstevel@tonic-gate 228*0Sstevel@tonic-gate LOCK_LDAP(ld); 229*0Sstevel@tonic-gate #endif 230*0Sstevel@tonic-gate Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 242, "ldap_search\n"), 231*0Sstevel@tonic-gate 0, 0, 0); 232*0Sstevel@tonic-gate 233*0Sstevel@tonic-gate if ((ber = ldap_build_search_req(ld, base, scope, filter, attrs, 234*0Sstevel@tonic-gate attrsonly, NULL, NULL, -1)) == NULLBER) { 235*0Sstevel@tonic-gate #if defined(SUN) && defined(_REENTRANT) 236*0Sstevel@tonic-gate UNLOCK_LDAP(ld); 237*0Sstevel@tonic-gate #endif 238*0Sstevel@tonic-gate return (-1); 239*0Sstevel@tonic-gate } 240*0Sstevel@tonic-gate 241*0Sstevel@tonic-gate #ifndef NO_CACHE 242*0Sstevel@tonic-gate if (ld->ld_cache != NULL) { 243*0Sstevel@tonic-gate if (check_cache(ld, LDAP_REQ_SEARCH, ber) == 0) { 244*0Sstevel@tonic-gate ber_free(ber, 1); 245*0Sstevel@tonic-gate ld->ld_errno = LDAP_SUCCESS; 246*0Sstevel@tonic-gate rv = ld->ld_msgid; 247*0Sstevel@tonic-gate #ifdef _REENTRANT 248*0Sstevel@tonic-gate UNLOCK_LDAP(ld); 249*0Sstevel@tonic-gate #endif 250*0Sstevel@tonic-gate return (rv); 251*0Sstevel@tonic-gate } 252*0Sstevel@tonic-gate add_request_to_cache(ld, LDAP_REQ_SEARCH, ber); 253*0Sstevel@tonic-gate } 254*0Sstevel@tonic-gate #endif /* NO_CACHE */ 255*0Sstevel@tonic-gate 256*0Sstevel@tonic-gate /* send the message */ 257*0Sstevel@tonic-gate rv = send_initial_request(ld, LDAP_REQ_SEARCH, base, ber); 258*0Sstevel@tonic-gate #ifdef _REENTRANT 259*0Sstevel@tonic-gate UNLOCK_LDAP(ld); 260*0Sstevel@tonic-gate #endif 261*0Sstevel@tonic-gate return (rv); 262*0Sstevel@tonic-gate } 263*0Sstevel@tonic-gate 264*0Sstevel@tonic-gate 265*0Sstevel@tonic-gate static char * 266*0Sstevel@tonic-gate find_right_paren(char *s) 267*0Sstevel@tonic-gate { 268*0Sstevel@tonic-gate int balance, escape; 269*0Sstevel@tonic-gate 270*0Sstevel@tonic-gate balance = 1; 271*0Sstevel@tonic-gate escape = 0; 272*0Sstevel@tonic-gate while (*s && balance) { 273*0Sstevel@tonic-gate if (escape == 0) { 274*0Sstevel@tonic-gate if (*s == '(') 275*0Sstevel@tonic-gate balance++; 276*0Sstevel@tonic-gate else if (*s == ')') 277*0Sstevel@tonic-gate balance--; 278*0Sstevel@tonic-gate } 279*0Sstevel@tonic-gate if (*s == '\\' && ! escape) 280*0Sstevel@tonic-gate escape = 1; 281*0Sstevel@tonic-gate else 282*0Sstevel@tonic-gate escape = 0; 283*0Sstevel@tonic-gate if (balance) 284*0Sstevel@tonic-gate s++; 285*0Sstevel@tonic-gate } 286*0Sstevel@tonic-gate 287*0Sstevel@tonic-gate return (*s ? s : NULL); 288*0Sstevel@tonic-gate } 289*0Sstevel@tonic-gate 290*0Sstevel@tonic-gate static char * 291*0Sstevel@tonic-gate put_complex_filter(BerElement *ber, char *str, unsigned int tag, int not) 292*0Sstevel@tonic-gate { 293*0Sstevel@tonic-gate char *next; 294*0Sstevel@tonic-gate 295*0Sstevel@tonic-gate /* 296*0Sstevel@tonic-gate * We have (x(filter)...) with str sitting on 297*0Sstevel@tonic-gate * the x. We have to find the paren matching 298*0Sstevel@tonic-gate * the one before the x and put the intervening 299*0Sstevel@tonic-gate * filters by calling put_filter_list(). 300*0Sstevel@tonic-gate */ 301*0Sstevel@tonic-gate 302*0Sstevel@tonic-gate /* put explicit tag */ 303*0Sstevel@tonic-gate if (ber_printf(ber, "t{", tag) == -1) 304*0Sstevel@tonic-gate return (NULL); 305*0Sstevel@tonic-gate /* 306*0Sstevel@tonic-gate if (!not && ber_printf(ber, "{") == -1) 307*0Sstevel@tonic-gate return (NULL); 308*0Sstevel@tonic-gate */ 309*0Sstevel@tonic-gate 310*0Sstevel@tonic-gate str++; 311*0Sstevel@tonic-gate if ((next = find_right_paren(str)) == NULL) 312*0Sstevel@tonic-gate return (NULL); 313*0Sstevel@tonic-gate 314*0Sstevel@tonic-gate *next = '\0'; 315*0Sstevel@tonic-gate if (put_filter_list(ber, str) == -1) 316*0Sstevel@tonic-gate return (NULL); 317*0Sstevel@tonic-gate *next++ = ')'; 318*0Sstevel@tonic-gate 319*0Sstevel@tonic-gate /* flush explicit tagged thang */ 320*0Sstevel@tonic-gate if (ber_printf(ber, "}") == -1) 321*0Sstevel@tonic-gate return (NULL); 322*0Sstevel@tonic-gate /* 323*0Sstevel@tonic-gate if (!not && ber_printf(ber, "}") == -1) 324*0Sstevel@tonic-gate return (NULL); 325*0Sstevel@tonic-gate */ 326*0Sstevel@tonic-gate 327*0Sstevel@tonic-gate return (next); 328*0Sstevel@tonic-gate } 329*0Sstevel@tonic-gate 330*0Sstevel@tonic-gate static int 331*0Sstevel@tonic-gate put_filter(BerElement *ber, char *str) 332*0Sstevel@tonic-gate { 333*0Sstevel@tonic-gate char *next, *tmp, *s, *d; 334*0Sstevel@tonic-gate int parens, balance, escape; 335*0Sstevel@tonic-gate int multipleparen = 0; 336*0Sstevel@tonic-gate 337*0Sstevel@tonic-gate /* 338*0Sstevel@tonic-gate * A Filter looks like this: 339*0Sstevel@tonic-gate * Filter ::= CHOICE { 340*0Sstevel@tonic-gate * and [0] SET OF Filter, 341*0Sstevel@tonic-gate * or [1] SET OF Filter, 342*0Sstevel@tonic-gate * not [2] Filter, 343*0Sstevel@tonic-gate * equalityMatch [3] AttributeValueAssertion, 344*0Sstevel@tonic-gate * substrings [4] SubstringFilter, 345*0Sstevel@tonic-gate * greaterOrEqual [5] AttributeValueAssertion, 346*0Sstevel@tonic-gate * lessOrEqual [6] AttributeValueAssertion, 347*0Sstevel@tonic-gate * present [7] AttributeType, 348*0Sstevel@tonic-gate * approxMatch [8] AttributeValueAssertion, 349*0Sstevel@tonic-gate * extensibleMatch [9] MatchingRuleAssertion 350*0Sstevel@tonic-gate * } 351*0Sstevel@tonic-gate * 352*0Sstevel@tonic-gate * SubstringFilter ::= SEQUENCE { 353*0Sstevel@tonic-gate * type AttributeType, 354*0Sstevel@tonic-gate * SEQUENCE OF CHOICE { 355*0Sstevel@tonic-gate * initial [0] IA5String, 356*0Sstevel@tonic-gate * any [1] IA5String, 357*0Sstevel@tonic-gate * final [2] IA5String 358*0Sstevel@tonic-gate * } 359*0Sstevel@tonic-gate * } 360*0Sstevel@tonic-gate * MatchingRuleAssertion ::= SEQUENCE { 361*0Sstevel@tonic-gate * matchingRule [1] MatchingRuleId OPTIONAL, 362*0Sstevel@tonic-gate * type [2] AttributeDescription OPTIONAL, 363*0Sstevel@tonic-gate * matchValue [3] AssertionValue, 364*0Sstevel@tonic-gate * dnAttributes [4] BOOLEAN DEFAULT FALSE 365*0Sstevel@tonic-gate * } 366*0Sstevel@tonic-gate * 367*0Sstevel@tonic-gate * Note: tags in a choice are always explicit 368*0Sstevel@tonic-gate */ 369*0Sstevel@tonic-gate 370*0Sstevel@tonic-gate Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 243, 371*0Sstevel@tonic-gate "put_filter \"%s\"\n"), str, 0, 0); 372*0Sstevel@tonic-gate 373*0Sstevel@tonic-gate parens = 0; 374*0Sstevel@tonic-gate while (*str) { 375*0Sstevel@tonic-gate switch (*str) { 376*0Sstevel@tonic-gate case '(': 377*0Sstevel@tonic-gate str++; 378*0Sstevel@tonic-gate parens++; 379*0Sstevel@tonic-gate switch (*str) { 380*0Sstevel@tonic-gate case '&': 381*0Sstevel@tonic-gate Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 382*0Sstevel@tonic-gate 244, "put_filter: AND\n"), 0, 0, 0); 383*0Sstevel@tonic-gate 384*0Sstevel@tonic-gate if ((str = put_complex_filter(ber, str, 385*0Sstevel@tonic-gate LDAP_FILTER_AND, 0)) == NULL) 386*0Sstevel@tonic-gate return (-1); 387*0Sstevel@tonic-gate 388*0Sstevel@tonic-gate parens--; 389*0Sstevel@tonic-gate break; 390*0Sstevel@tonic-gate 391*0Sstevel@tonic-gate case '|': 392*0Sstevel@tonic-gate Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 393*0Sstevel@tonic-gate 245, "put_filter: OR\n"), 0, 0, 0); 394*0Sstevel@tonic-gate 395*0Sstevel@tonic-gate if ((str = put_complex_filter(ber, str, 396*0Sstevel@tonic-gate LDAP_FILTER_OR, 0)) == NULL) 397*0Sstevel@tonic-gate return (-1); 398*0Sstevel@tonic-gate 399*0Sstevel@tonic-gate parens--; 400*0Sstevel@tonic-gate break; 401*0Sstevel@tonic-gate 402*0Sstevel@tonic-gate case '!': 403*0Sstevel@tonic-gate Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 404*0Sstevel@tonic-gate 246, "put_filter: NOT\n"), 0, 0, 0); 405*0Sstevel@tonic-gate 406*0Sstevel@tonic-gate if ((str = put_complex_filter(ber, str, 407*0Sstevel@tonic-gate LDAP_FILTER_NOT, 1)) == NULL) 408*0Sstevel@tonic-gate return (-1); 409*0Sstevel@tonic-gate 410*0Sstevel@tonic-gate parens--; 411*0Sstevel@tonic-gate break; 412*0Sstevel@tonic-gate 413*0Sstevel@tonic-gate case '(': 414*0Sstevel@tonic-gate Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 415*0Sstevel@tonic-gate 402, "put_filter: Double Parentheses\n"), 416*0Sstevel@tonic-gate 0, 0, 0); 417*0Sstevel@tonic-gate multipleparen++; 418*0Sstevel@tonic-gate continue; 419*0Sstevel@tonic-gate 420*0Sstevel@tonic-gate default: 421*0Sstevel@tonic-gate Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 422*0Sstevel@tonic-gate 247, "put_filter: simple\n"), 0, 0, 0); 423*0Sstevel@tonic-gate 424*0Sstevel@tonic-gate balance = 1; 425*0Sstevel@tonic-gate escape = 0; 426*0Sstevel@tonic-gate next = str; 427*0Sstevel@tonic-gate while (*next && balance) { 428*0Sstevel@tonic-gate if (escape == 0) { 429*0Sstevel@tonic-gate if (*next == '(') 430*0Sstevel@tonic-gate balance++; 431*0Sstevel@tonic-gate else if (*next == ')') 432*0Sstevel@tonic-gate balance--; 433*0Sstevel@tonic-gate } 434*0Sstevel@tonic-gate if (*next == '\\' && ! escape) 435*0Sstevel@tonic-gate escape = 1; 436*0Sstevel@tonic-gate else 437*0Sstevel@tonic-gate escape = 0; 438*0Sstevel@tonic-gate if (balance) 439*0Sstevel@tonic-gate next++; 440*0Sstevel@tonic-gate } 441*0Sstevel@tonic-gate if (balance != 0) 442*0Sstevel@tonic-gate return (-1); 443*0Sstevel@tonic-gate 444*0Sstevel@tonic-gate *next = '\0'; 445*0Sstevel@tonic-gate if (put_simple_filter(ber, str) == -1) 446*0Sstevel@tonic-gate return (-1); 447*0Sstevel@tonic-gate *next++ = ')'; 448*0Sstevel@tonic-gate str = next; 449*0Sstevel@tonic-gate parens--; 450*0Sstevel@tonic-gate break; 451*0Sstevel@tonic-gate } 452*0Sstevel@tonic-gate break; 453*0Sstevel@tonic-gate 454*0Sstevel@tonic-gate case ')': 455*0Sstevel@tonic-gate Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 248, 456*0Sstevel@tonic-gate "put_filter: end\n"), 0, 0, 0); 457*0Sstevel@tonic-gate if (multipleparen) { 458*0Sstevel@tonic-gate multipleparen--; 459*0Sstevel@tonic-gate } else { 460*0Sstevel@tonic-gate if (ber_printf(ber, "]") == -1) 461*0Sstevel@tonic-gate return (-1); 462*0Sstevel@tonic-gate } 463*0Sstevel@tonic-gate 464*0Sstevel@tonic-gate str++; 465*0Sstevel@tonic-gate parens--; 466*0Sstevel@tonic-gate break; 467*0Sstevel@tonic-gate 468*0Sstevel@tonic-gate case ' ': 469*0Sstevel@tonic-gate str++; 470*0Sstevel@tonic-gate break; 471*0Sstevel@tonic-gate 472*0Sstevel@tonic-gate default: /* assume it's a simple type=value filter */ 473*0Sstevel@tonic-gate Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 249, 474*0Sstevel@tonic-gate "put_filter: default\n"), 0, 0, 0); 475*0Sstevel@tonic-gate next = strchr(str, '\0'); 476*0Sstevel@tonic-gate if (put_simple_filter(ber, str) == -1) { 477*0Sstevel@tonic-gate return (-1); 478*0Sstevel@tonic-gate } 479*0Sstevel@tonic-gate str = next; 480*0Sstevel@tonic-gate break; 481*0Sstevel@tonic-gate } 482*0Sstevel@tonic-gate } 483*0Sstevel@tonic-gate 484*0Sstevel@tonic-gate return (parens ? -1 : 0); 485*0Sstevel@tonic-gate } 486*0Sstevel@tonic-gate 487*0Sstevel@tonic-gate /* 488*0Sstevel@tonic-gate * Put a list of filters like this "(filter1)(filter2)..." 489*0Sstevel@tonic-gate */ 490*0Sstevel@tonic-gate 491*0Sstevel@tonic-gate static int 492*0Sstevel@tonic-gate put_filter_list(BerElement *ber, char *str) 493*0Sstevel@tonic-gate { 494*0Sstevel@tonic-gate char *next; 495*0Sstevel@tonic-gate char save; 496*0Sstevel@tonic-gate 497*0Sstevel@tonic-gate Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 250, 498*0Sstevel@tonic-gate "put_filter_list \"%s\"\n"), str, 0, 0); 499*0Sstevel@tonic-gate 500*0Sstevel@tonic-gate while (*str) { 501*0Sstevel@tonic-gate while (*str && isspace(*str)) 502*0Sstevel@tonic-gate str++; 503*0Sstevel@tonic-gate if (*str == '\0') 504*0Sstevel@tonic-gate break; 505*0Sstevel@tonic-gate 506*0Sstevel@tonic-gate if ((next = find_right_paren(str + 1)) == NULL) 507*0Sstevel@tonic-gate return (-1); 508*0Sstevel@tonic-gate save = *++next; 509*0Sstevel@tonic-gate 510*0Sstevel@tonic-gate /* now we have "(filter)" with str pointing to it */ 511*0Sstevel@tonic-gate *next = '\0'; 512*0Sstevel@tonic-gate if (put_filter(ber, str) == -1) 513*0Sstevel@tonic-gate return (-1); 514*0Sstevel@tonic-gate *next = save; 515*0Sstevel@tonic-gate 516*0Sstevel@tonic-gate str = next; 517*0Sstevel@tonic-gate } 518*0Sstevel@tonic-gate 519*0Sstevel@tonic-gate return (0); 520*0Sstevel@tonic-gate } 521*0Sstevel@tonic-gate 522*0Sstevel@tonic-gate static int 523*0Sstevel@tonic-gate put_simple_filter(BerElement *ber, char *str) 524*0Sstevel@tonic-gate { 525*0Sstevel@tonic-gate char *s; 526*0Sstevel@tonic-gate char *value, savechar; 527*0Sstevel@tonic-gate unsigned int ftype; 528*0Sstevel@tonic-gate int rc; 529*0Sstevel@tonic-gate int len; 530*0Sstevel@tonic-gate 531*0Sstevel@tonic-gate Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 251, 532*0Sstevel@tonic-gate "put_simple_filter \"%s\"\n"), str, 0, 0); 533*0Sstevel@tonic-gate 534*0Sstevel@tonic-gate if ((s = strchr(str, '=')) == NULL) 535*0Sstevel@tonic-gate return (-1); 536*0Sstevel@tonic-gate value = s + 1; 537*0Sstevel@tonic-gate *s-- = '\0'; 538*0Sstevel@tonic-gate savechar = *s; 539*0Sstevel@tonic-gate 540*0Sstevel@tonic-gate switch (*s) { 541*0Sstevel@tonic-gate case '<': 542*0Sstevel@tonic-gate ftype = LDAP_FILTER_LE; 543*0Sstevel@tonic-gate *s = '\0'; 544*0Sstevel@tonic-gate break; 545*0Sstevel@tonic-gate case '>': 546*0Sstevel@tonic-gate ftype = LDAP_FILTER_GE; 547*0Sstevel@tonic-gate *s = '\0'; 548*0Sstevel@tonic-gate break; 549*0Sstevel@tonic-gate case '~': 550*0Sstevel@tonic-gate ftype = LDAP_FILTER_APPROX; 551*0Sstevel@tonic-gate *s = '\0'; 552*0Sstevel@tonic-gate break; 553*0Sstevel@tonic-gate /* LDAP V3 : New extensible matching */ 554*0Sstevel@tonic-gate case ':': 555*0Sstevel@tonic-gate rc = put_extensible_filter(ber, str, value); 556*0Sstevel@tonic-gate *(value -1) = '='; 557*0Sstevel@tonic-gate return (rc); 558*0Sstevel@tonic-gate default: 559*0Sstevel@tonic-gate if (star_search(value) == NULL) { 560*0Sstevel@tonic-gate ftype = LDAP_FILTER_EQUALITY; 561*0Sstevel@tonic-gate } else if (strcmp(value, "*") == 0) { 562*0Sstevel@tonic-gate ftype = LDAP_FILTER_PRESENT; 563*0Sstevel@tonic-gate } else { 564*0Sstevel@tonic-gate rc = put_substring_filter(ber, str, value); 565*0Sstevel@tonic-gate *(value-1) = '='; 566*0Sstevel@tonic-gate return (rc); 567*0Sstevel@tonic-gate } 568*0Sstevel@tonic-gate break; 569*0Sstevel@tonic-gate } 570*0Sstevel@tonic-gate 571*0Sstevel@tonic-gate if (*(value -1) == '=') 572*0Sstevel@tonic-gate return (rc); 573*0Sstevel@tonic-gate if (ftype == LDAP_FILTER_PRESENT) { 574*0Sstevel@tonic-gate rc = ber_printf(ber, "ts", ftype, str); 575*0Sstevel@tonic-gate } else { 576*0Sstevel@tonic-gate if ((len = decode_value(value)) >= 0) 577*0Sstevel@tonic-gate rc = ber_printf(ber, "t{so}", ftype, str, value, len); 578*0Sstevel@tonic-gate } 579*0Sstevel@tonic-gate 580*0Sstevel@tonic-gate *s = savechar; 581*0Sstevel@tonic-gate *(value-1) = '='; 582*0Sstevel@tonic-gate return (rc == -1 ? rc : 0); 583*0Sstevel@tonic-gate } 584*0Sstevel@tonic-gate 585*0Sstevel@tonic-gate static int 586*0Sstevel@tonic-gate put_substring_filter(BerElement *ber, char *type, char *val) 587*0Sstevel@tonic-gate { 588*0Sstevel@tonic-gate char *nextstar, gotstar = 0; 589*0Sstevel@tonic-gate unsigned int ftype; 590*0Sstevel@tonic-gate int len; 591*0Sstevel@tonic-gate 592*0Sstevel@tonic-gate Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 252, 593*0Sstevel@tonic-gate "put_substring_filter \"%1$s=%2$s\"\n"), type, val, 0); 594*0Sstevel@tonic-gate 595*0Sstevel@tonic-gate if (ber_printf(ber, "t{s{", LDAP_FILTER_SUBSTRINGS, type) == -1) 596*0Sstevel@tonic-gate return (-1); 597*0Sstevel@tonic-gate 598*0Sstevel@tonic-gate while (val != NULL) { 599*0Sstevel@tonic-gate if ((nextstar = star_search(val)) != NULL) 600*0Sstevel@tonic-gate *nextstar++ = '\0'; 601*0Sstevel@tonic-gate 602*0Sstevel@tonic-gate if (gotstar == 0) { 603*0Sstevel@tonic-gate ftype = LDAP_SUBSTRING_INITIAL; 604*0Sstevel@tonic-gate } else if (nextstar == NULL) { 605*0Sstevel@tonic-gate ftype = LDAP_SUBSTRING_FINAL; 606*0Sstevel@tonic-gate } else { 607*0Sstevel@tonic-gate ftype = LDAP_SUBSTRING_ANY; 608*0Sstevel@tonic-gate } 609*0Sstevel@tonic-gate if (*val != '\0') { 610*0Sstevel@tonic-gate if ((len = decode_value(val)) == -1 || 611*0Sstevel@tonic-gate ber_printf(ber, "to", ftype, val, len) == -1) 612*0Sstevel@tonic-gate return (-1); 613*0Sstevel@tonic-gate } 614*0Sstevel@tonic-gate 615*0Sstevel@tonic-gate gotstar = 1; 616*0Sstevel@tonic-gate if (nextstar != NULL) 617*0Sstevel@tonic-gate *(nextstar-1) = '*'; 618*0Sstevel@tonic-gate val = nextstar; 619*0Sstevel@tonic-gate } 620*0Sstevel@tonic-gate 621*0Sstevel@tonic-gate if (ber_printf(ber, "}}") == -1) 622*0Sstevel@tonic-gate return (-1); 623*0Sstevel@tonic-gate 624*0Sstevel@tonic-gate return (0); 625*0Sstevel@tonic-gate } 626*0Sstevel@tonic-gate 627*0Sstevel@tonic-gate static int 628*0Sstevel@tonic-gate put_extensible_filter(BerElement *ber, char *type, char *val) 629*0Sstevel@tonic-gate { 630*0Sstevel@tonic-gate char *ptr, *ptype; 631*0Sstevel@tonic-gate char *dn, *rule; 632*0Sstevel@tonic-gate int len; 633*0Sstevel@tonic-gate 634*0Sstevel@tonic-gate Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 252, 635*0Sstevel@tonic-gate "put_extensible_filter \"%1$s=%2$s\"\n"), type, val, 0); 636*0Sstevel@tonic-gate 637*0Sstevel@tonic-gate /* type is off form : attr:dn:matchingrule: or :dn:matchingrule: */ 638*0Sstevel@tonic-gate /* type ends with ':', suppress it */ 639*0Sstevel@tonic-gate ptr = strdup(type); 640*0Sstevel@tonic-gate ptype = ptr; 641*0Sstevel@tonic-gate while (*ptype) { 642*0Sstevel@tonic-gate *ptype = tolower(*ptype); 643*0Sstevel@tonic-gate ptype++; 644*0Sstevel@tonic-gate } 645*0Sstevel@tonic-gate 646*0Sstevel@tonic-gate len = strlen(ptr); 647*0Sstevel@tonic-gate if (len > 0 && ptr[len -1] == ':') 648*0Sstevel@tonic-gate ptr [len - 1] = '\0'; 649*0Sstevel@tonic-gate else { 650*0Sstevel@tonic-gate return (-1); 651*0Sstevel@tonic-gate } 652*0Sstevel@tonic-gate 653*0Sstevel@tonic-gate ptype = ptr; 654*0Sstevel@tonic-gate /* Search first ':dn' */ 655*0Sstevel@tonic-gate if ((dn = strstr(ptype, ":dn")) == NULL) { 656*0Sstevel@tonic-gate /* No dn */ 657*0Sstevel@tonic-gate /* if there's a : its separating type and matching rule */ 658*0Sstevel@tonic-gate rule = strchr(ptype, ':'); 659*0Sstevel@tonic-gate if (rule == ptype) { 660*0Sstevel@tonic-gate ptype = NULL; 661*0Sstevel@tonic-gate } 662*0Sstevel@tonic-gate } else { 663*0Sstevel@tonic-gate if (dn == ptype) { 664*0Sstevel@tonic-gate ptype = NULL; 665*0Sstevel@tonic-gate } else { 666*0Sstevel@tonic-gate *dn = '\0'; 667*0Sstevel@tonic-gate } 668*0Sstevel@tonic-gate 669*0Sstevel@tonic-gate rule = dn + 3; 670*0Sstevel@tonic-gate } 671*0Sstevel@tonic-gate 672*0Sstevel@tonic-gate if (rule && rule[0] == ':') { 673*0Sstevel@tonic-gate rule[0] = '\0'; 674*0Sstevel@tonic-gate rule++; 675*0Sstevel@tonic-gate } else { 676*0Sstevel@tonic-gate rule = NULL; 677*0Sstevel@tonic-gate } 678*0Sstevel@tonic-gate 679*0Sstevel@tonic-gate if ((ptype == NULL || *ptype == '\0') && rule == NULL) { 680*0Sstevel@tonic-gate free(ptr); 681*0Sstevel@tonic-gate return (-1); 682*0Sstevel@tonic-gate } 683*0Sstevel@tonic-gate 684*0Sstevel@tonic-gate if (ber_printf(ber, "t{", LDAP_FILTER_EXTENSIBLE) == -1) { 685*0Sstevel@tonic-gate free(ptr); 686*0Sstevel@tonic-gate return (-1); 687*0Sstevel@tonic-gate } 688*0Sstevel@tonic-gate 689*0Sstevel@tonic-gate if (rule && *rule && (ber_printf(ber, "ts", 690*0Sstevel@tonic-gate LDAP_TAG_FEXT_RULE, rule) == -1)) { 691*0Sstevel@tonic-gate free(ptr); 692*0Sstevel@tonic-gate return (-1); 693*0Sstevel@tonic-gate } 694*0Sstevel@tonic-gate 695*0Sstevel@tonic-gate if (ptype && *ptype && (ber_printf(ber, "ts", 696*0Sstevel@tonic-gate LDAP_TAG_FEXT_TYPE, ptype) == -1)) { 697*0Sstevel@tonic-gate free(ptr); 698*0Sstevel@tonic-gate return (-1); 699*0Sstevel@tonic-gate } 700*0Sstevel@tonic-gate 701*0Sstevel@tonic-gate /* Code value */ 702*0Sstevel@tonic-gate if ((len = decode_value(val)) == -1 || 703*0Sstevel@tonic-gate ber_printf(ber, "to", LDAP_TAG_FEXT_VAL, val, len) == -1) { 704*0Sstevel@tonic-gate free(ptr); 705*0Sstevel@tonic-gate return (-1); 706*0Sstevel@tonic-gate } 707*0Sstevel@tonic-gate 708*0Sstevel@tonic-gate if (dn && (ber_printf(ber, "tb", LDAP_TAG_FEXT_DN, 1) == -1)) { 709*0Sstevel@tonic-gate free(ptr); 710*0Sstevel@tonic-gate return (-1); 711*0Sstevel@tonic-gate } 712*0Sstevel@tonic-gate 713*0Sstevel@tonic-gate free(ptr); 714*0Sstevel@tonic-gate 715*0Sstevel@tonic-gate if (ber_printf(ber, "}") == -1) 716*0Sstevel@tonic-gate return (-1); 717*0Sstevel@tonic-gate 718*0Sstevel@tonic-gate return (0); 719*0Sstevel@tonic-gate } 720*0Sstevel@tonic-gate 721*0Sstevel@tonic-gate int 722*0Sstevel@tonic-gate ldap_search_st(LDAP *ld, char *base, int scope, char *filter, char **attrs, 723*0Sstevel@tonic-gate int attrsonly, struct timeval *timeout, LDAPMessage **res) 724*0Sstevel@tonic-gate { 725*0Sstevel@tonic-gate int msgid; 726*0Sstevel@tonic-gate 727*0Sstevel@tonic-gate if ((msgid = ldap_search(ld, base, scope, filter, attrs, attrsonly)) 728*0Sstevel@tonic-gate == -1) 729*0Sstevel@tonic-gate return (ld->ld_errno); 730*0Sstevel@tonic-gate 731*0Sstevel@tonic-gate if (ldap_result(ld, msgid, 1, timeout, res) == -1) 732*0Sstevel@tonic-gate return (ld->ld_errno); 733*0Sstevel@tonic-gate 734*0Sstevel@tonic-gate if (ld->ld_errno == LDAP_TIMEOUT) { 735*0Sstevel@tonic-gate (void) ldap_abandon(ld, msgid); 736*0Sstevel@tonic-gate ld->ld_errno = LDAP_TIMEOUT; 737*0Sstevel@tonic-gate return (ld->ld_errno); 738*0Sstevel@tonic-gate } 739*0Sstevel@tonic-gate 740*0Sstevel@tonic-gate return (ldap_result2error(ld, *res, 0)); 741*0Sstevel@tonic-gate } 742*0Sstevel@tonic-gate 743*0Sstevel@tonic-gate int 744*0Sstevel@tonic-gate ldap_search_s(LDAP *ld, char *base, int scope, char *filter, char **attrs, 745*0Sstevel@tonic-gate int attrsonly, LDAPMessage **res) 746*0Sstevel@tonic-gate { 747*0Sstevel@tonic-gate int msgid; 748*0Sstevel@tonic-gate 749*0Sstevel@tonic-gate if ((msgid = ldap_search(ld, base, scope, filter, attrs, attrsonly)) 750*0Sstevel@tonic-gate == -1) 751*0Sstevel@tonic-gate return (ld->ld_errno); 752*0Sstevel@tonic-gate 753*0Sstevel@tonic-gate if (ldap_result(ld, msgid, 1, (struct timeval *)NULL, res) == -1) 754*0Sstevel@tonic-gate return (ld->ld_errno); 755*0Sstevel@tonic-gate 756*0Sstevel@tonic-gate return (ldap_result2error(ld, *res, 0)); 757*0Sstevel@tonic-gate } 758*0Sstevel@tonic-gate 759*0Sstevel@tonic-gate /* LDAPv3 API EXTENSIONS */ 760*0Sstevel@tonic-gate int ldap_search_ext(LDAP *ld, char *base, int scope, char *filter, 761*0Sstevel@tonic-gate char **attrs, int attrsonly, LDAPControl **serverctrls, 762*0Sstevel@tonic-gate LDAPControl **clientctrls, struct timeval *timeoutp, int sizelimit, 763*0Sstevel@tonic-gate int *msgidp) 764*0Sstevel@tonic-gate { 765*0Sstevel@tonic-gate BerElement *ber; 766*0Sstevel@tonic-gate int rv; 767*0Sstevel@tonic-gate 768*0Sstevel@tonic-gate if (timeoutp != NULL && timeoutp->tv_sec == 0 && 769*0Sstevel@tonic-gate timeoutp->tv_usec == 0) { 770*0Sstevel@tonic-gate timeoutp = NULL; 771*0Sstevel@tonic-gate } 772*0Sstevel@tonic-gate 773*0Sstevel@tonic-gate #ifdef _REENTRANT 774*0Sstevel@tonic-gate LOCK_LDAP(ld); 775*0Sstevel@tonic-gate #endif 776*0Sstevel@tonic-gate Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 242, 777*0Sstevel@tonic-gate "ldap_search\n"), 0, 0, 0); 778*0Sstevel@tonic-gate 779*0Sstevel@tonic-gate if ((ber = ldap_build_search_req(ld, base, scope, filter, attrs, 780*0Sstevel@tonic-gate attrsonly, serverctrls, timeoutp, sizelimit)) == NULLBER) { 781*0Sstevel@tonic-gate rv = ld->ld_errno; 782*0Sstevel@tonic-gate if (rv == LDAP_SUCCESS) 783*0Sstevel@tonic-gate rv = LDAP_OTHER; 784*0Sstevel@tonic-gate #ifdef _REENTRANT 785*0Sstevel@tonic-gate UNLOCK_LDAP(ld); 786*0Sstevel@tonic-gate #endif 787*0Sstevel@tonic-gate return (rv); 788*0Sstevel@tonic-gate } 789*0Sstevel@tonic-gate 790*0Sstevel@tonic-gate #ifndef NO_CACHE 791*0Sstevel@tonic-gate if (ld->ld_cache != NULL) { 792*0Sstevel@tonic-gate if (check_cache(ld, LDAP_REQ_SEARCH, ber) == 0) { 793*0Sstevel@tonic-gate ber_free(ber, 1); 794*0Sstevel@tonic-gate ld->ld_errno = LDAP_SUCCESS; 795*0Sstevel@tonic-gate *msgidp = ld->ld_msgid; 796*0Sstevel@tonic-gate #ifdef _REENTRANT 797*0Sstevel@tonic-gate UNLOCK_LDAP(ld); 798*0Sstevel@tonic-gate #endif 799*0Sstevel@tonic-gate return (LDAP_SUCCESS); 800*0Sstevel@tonic-gate } 801*0Sstevel@tonic-gate add_request_to_cache(ld, LDAP_REQ_SEARCH, ber); 802*0Sstevel@tonic-gate } 803*0Sstevel@tonic-gate #endif /* NO_CACHE */ 804*0Sstevel@tonic-gate 805*0Sstevel@tonic-gate /* send the message */ 806*0Sstevel@tonic-gate rv = send_initial_request(ld, LDAP_REQ_SEARCH, base, ber); 807*0Sstevel@tonic-gate if (rv == -1) { 808*0Sstevel@tonic-gate rv = ld->ld_errno; 809*0Sstevel@tonic-gate if (rv == LDAP_SUCCESS) { 810*0Sstevel@tonic-gate rv = LDAP_OTHER; 811*0Sstevel@tonic-gate } 812*0Sstevel@tonic-gate #ifdef _REENTRANT 813*0Sstevel@tonic-gate UNLOCK_LDAP(ld); 814*0Sstevel@tonic-gate #endif 815*0Sstevel@tonic-gate return (rv); 816*0Sstevel@tonic-gate } 817*0Sstevel@tonic-gate 818*0Sstevel@tonic-gate *msgidp = rv; 819*0Sstevel@tonic-gate #if _REENTRANT 820*0Sstevel@tonic-gate UNLOCK_LDAP(ld); 821*0Sstevel@tonic-gate #endif 822*0Sstevel@tonic-gate return (LDAP_SUCCESS); 823*0Sstevel@tonic-gate } 824*0Sstevel@tonic-gate 825*0Sstevel@tonic-gate 826*0Sstevel@tonic-gate int ldap_search_ext_s(LDAP *ld, char *base, int scope, char *filter, 827*0Sstevel@tonic-gate char **attrs, int attrsonly, LDAPControl **serverctrls, 828*0Sstevel@tonic-gate LDAPControl **clientctrls, struct timeval *timeoutp, int sizelimit, 829*0Sstevel@tonic-gate LDAPMessage **res) 830*0Sstevel@tonic-gate { 831*0Sstevel@tonic-gate int msgid; 832*0Sstevel@tonic-gate int retcode = LDAP_SUCCESS; 833*0Sstevel@tonic-gate 834*0Sstevel@tonic-gate if ((retcode = ldap_search_ext(ld, base, scope, filter, attrs, 835*0Sstevel@tonic-gate attrsonly, serverctrls, clientctrls, timeoutp, sizelimit, 836*0Sstevel@tonic-gate &msgid)) != LDAP_SUCCESS) 837*0Sstevel@tonic-gate return (retcode); 838*0Sstevel@tonic-gate if (ldap_result(ld, msgid, 1, timeoutp, res) == -1) 839*0Sstevel@tonic-gate return (ld->ld_errno); 840*0Sstevel@tonic-gate 841*0Sstevel@tonic-gate 842*0Sstevel@tonic-gate #if _REENTRANT 843*0Sstevel@tonic-gate LOCK_LDAP(ld); 844*0Sstevel@tonic-gate #endif 845*0Sstevel@tonic-gate retcode = ldap_parse_result(ld, *res, &ld->ld_errno, &ld->ld_matched, 846*0Sstevel@tonic-gate &ld->ld_error, &ld->ld_referrals, &ld->ld_ret_ctrls, 0); 847*0Sstevel@tonic-gate if (retcode == LDAP_SUCCESS) 848*0Sstevel@tonic-gate retcode = ld->ld_errno; 849*0Sstevel@tonic-gate #if _REENTRANT 850*0Sstevel@tonic-gate UNLOCK_LDAP(ld); 851*0Sstevel@tonic-gate #endif 852*0Sstevel@tonic-gate return (retcode); 853*0Sstevel@tonic-gate } 854*0Sstevel@tonic-gate 855*0Sstevel@tonic-gate /* 856*0Sstevel@tonic-gate * Search string for ascii '*' (asterisk) character. 857*0Sstevel@tonic-gate * RFC 1960 permits an escaped asterisk to pass through. 858*0Sstevel@tonic-gate * RFC 2254 adds the definition of encoded characters: 859*0Sstevel@tonic-gate * 860*0Sstevel@tonic-gate * Character ASCII value 861*0Sstevel@tonic-gate * --------------------------- 862*0Sstevel@tonic-gate * * 0x2a 863*0Sstevel@tonic-gate * ( 0x28 864*0Sstevel@tonic-gate * ) 0x29 865*0Sstevel@tonic-gate * \ 0x5c 866*0Sstevel@tonic-gate * NUL 0x00 867*0Sstevel@tonic-gate * 868*0Sstevel@tonic-gate * No distinction of escaped characters is made here. 869*0Sstevel@tonic-gate */ 870*0Sstevel@tonic-gate static char * 871*0Sstevel@tonic-gate star_search(char *str) 872*0Sstevel@tonic-gate { 873*0Sstevel@tonic-gate for (; *str; str++) { 874*0Sstevel@tonic-gate switch (*str) { 875*0Sstevel@tonic-gate case '*': 876*0Sstevel@tonic-gate return (str); 877*0Sstevel@tonic-gate case '\\': 878*0Sstevel@tonic-gate if (str[1] == '\0') 879*0Sstevel@tonic-gate break; /* input string exahausted */ 880*0Sstevel@tonic-gate ++str; /* Assume RFC 1960 escaped character */ 881*0Sstevel@tonic-gate /* Check for RFC 2254 hex encoding */ 882*0Sstevel@tonic-gate if (hex_char2int(str[0]) >= 0 && 883*0Sstevel@tonic-gate hex_char2int(str[1]) >= 0) { 884*0Sstevel@tonic-gate str++; /* skip over RFC 2254 hex encoding */ 885*0Sstevel@tonic-gate } 886*0Sstevel@tonic-gate default: 887*0Sstevel@tonic-gate break; 888*0Sstevel@tonic-gate } 889*0Sstevel@tonic-gate } 890*0Sstevel@tonic-gate return (NULL); 891*0Sstevel@tonic-gate } 892*0Sstevel@tonic-gate 893*0Sstevel@tonic-gate /* 894*0Sstevel@tonic-gate * Return integer value of hexadecimal character or (-1) if character is 895*0Sstevel@tonic-gate * not a hexadecimal digit [0-9A-Fa-f]. 896*0Sstevel@tonic-gate */ 897*0Sstevel@tonic-gate static int 898*0Sstevel@tonic-gate hex_char2int(char c) 899*0Sstevel@tonic-gate { 900*0Sstevel@tonic-gate if (c >= '0' && c <= '9') { 901*0Sstevel@tonic-gate return (c-'0'); 902*0Sstevel@tonic-gate } else if (c >= 'A' && c <= 'F') { 903*0Sstevel@tonic-gate return (c-'A'+10); 904*0Sstevel@tonic-gate } else if (c >= 'a' && c <= 'f') { 905*0Sstevel@tonic-gate return (c-'a'+10); 906*0Sstevel@tonic-gate } 907*0Sstevel@tonic-gate return (-1); 908*0Sstevel@tonic-gate } 909*0Sstevel@tonic-gate 910*0Sstevel@tonic-gate /* 911*0Sstevel@tonic-gate * Modifys passed string converting escaped hexadecimal characters as 912*0Sstevel@tonic-gate * per RFC 2254 and un-escapes escaped characters. Returns length of 913*0Sstevel@tonic-gate * modified string as it may contain null characters as per RFC 2254. 914*0Sstevel@tonic-gate */ 915*0Sstevel@tonic-gate static int 916*0Sstevel@tonic-gate decode_value(char *start) 917*0Sstevel@tonic-gate { 918*0Sstevel@tonic-gate char *read, *write; 919*0Sstevel@tonic-gate int hn, ln; 920*0Sstevel@tonic-gate 921*0Sstevel@tonic-gate for (read = write = start; *read; *write++ = *read++) { 922*0Sstevel@tonic-gate if (*read == '\\') { 923*0Sstevel@tonic-gate if (*++read == '\0') 924*0Sstevel@tonic-gate break; /* input string exahausted */ 925*0Sstevel@tonic-gate /* 926*0Sstevel@tonic-gate * Assume *read is simple RFC 1960 escaped character. 927*0Sstevel@tonic-gate * However check for RFC 2254 hex encoding. 928*0Sstevel@tonic-gate */ 929*0Sstevel@tonic-gate if ((hn = hex_char2int(read[0])) >= 0 && 930*0Sstevel@tonic-gate (ln = hex_char2int(read[1])) >= 0) { 931*0Sstevel@tonic-gate read++; 932*0Sstevel@tonic-gate *read = (hn<<4)+ln; 933*0Sstevel@tonic-gate } 934*0Sstevel@tonic-gate } 935*0Sstevel@tonic-gate } 936*0Sstevel@tonic-gate *write = '\0'; 937*0Sstevel@tonic-gate return (write-start); 938*0Sstevel@tonic-gate } 939*0Sstevel@tonic-gate 940