search.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
*
* Copyright (c) 1998-2001 by Sun Microsystems, Inc.
* All rights reserved.
*
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Copyright (c) 1990 Regents of the University of Michigan.
* All rights reserved.
*
* search.c
*/
#ifndef lint
static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
#endif
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h> /* free() for Solaris */
#ifdef MACOS
#include <stdlib.h>
#include "macos.h"
#endif /* MACOS */
#include "msdos.h"
#endif /* DOS */
#endif
#include "lber.h"
#include "ldap.h"
#include "ldap-private.h"
#include "ldap-int.h"
#ifdef NEEDPROTOS
static char *find_right_paren(char *s);
static char *star_search(char *str);
static int hex_char2int(char c);
static int decode_value(char *str);
#else
static char *find_right_paren();
static char *put_complex_filter();
static int put_filter();
static int put_simple_filter();
static int put_substring_filter();
static int put_filter_list();
static char *star_search();
static int hex_char2int();
static int decode_value();
#endif /* NEEDPROTOS */
{
int err;
int theSizeLimit, theTimeLimit;
char *theFilter;
/*
* Create the search request. It looks like this:
* SearchRequest := [APPLICATION 3] SEQUENCE {
* baseObject DistinguishedName,
* scope ENUMERATED {
* baseObject (0),
* singleLevel (1),
* wholeSubtree (2)
* },
* derefAliases ENUMERATED {
* neverDerefaliases (0),
* derefInSearching (1),
* derefFindingBaseObj (2),
* alwaysDerefAliases (3)
* },
* sizelimit INTEGER (0 .. 65535),
* timelimit INTEGER (0 .. 65535),
* attrsOnly BOOLEAN,
* filter Filter,
* attributes SEQUENCE OF AttributeType
* }
* wrapped in an ldap message.
*/
return (NULLBER);
}
/* create a message to send */
return (NULLBER);
}
base = "";
}
} else {
theTimeLimit = 0; /* no limit */
}
} else {
}
#ifdef CLDAP
} else {
#endif /* CLDAP */
#ifdef CLDAP
}
#endif /* CLDAP */
if (err == -1) {
return (NULLBER);
}
} else {
}
if (err == -1) {
return (NULLBER);
}
return (NULLBER);
}
/* LDAPv3 */
/* Code controls if any */
if (serverctrls && serverctrls[0]) {
return (NULLBER);
}
/* Otherwise, is there any global server ctrls ? */
return (NULLBER);
}
}
return (NULLBER);
}
return (ber);
}
/*
* ldap_search - initiate an ldap (and X.500) search operation. Parameters:
*
* ld LDAP descriptor
* base DN of the base object
* scope the search scope - one of LDAP_SCOPE_BASE,
* LDAP_SCOPE_ONELEVEL, LDAP_SCOPE_SUBTREE
* filter a string containing the search filter
* (e.g., "(|(cn=bob)(sn=bob))")
* attrs list of attribute types to return for matches
* attrsonly 1 => attributes only 0 => attributes and values
*
* Example:
* char *attrs[] = { "mail", "title", 0 };
* msgid = ldap_search( ld, "c=us@o=UM", LDAP_SCOPE_SUBTREE, "cn~=bob",
* attrs, attrsonly );
*/
int
{
#if defined(SUN) && defined(_REENTRANT)
int rv;
#endif
0, 0, 0);
#if defined(SUN) && defined(_REENTRANT)
#endif
return (-1);
}
#ifndef NO_CACHE
#ifdef _REENTRANT
#endif
return (rv);
}
}
#endif /* NO_CACHE */
/* send the message */
#ifdef _REENTRANT
#endif
return (rv);
}
static char *
find_right_paren(char *s)
{
balance = 1;
escape = 0;
while (*s && balance) {
if (escape == 0) {
if (*s == '(')
balance++;
else if (*s == ')')
balance--;
}
if (*s == '\\' && ! escape)
escape = 1;
else
escape = 0;
if (balance)
s++;
}
return (*s ? s : NULL);
}
static char *
{
char *next;
/*
* We have (x(filter)...) with str sitting on
* the x. We have to find the paren matching
* the one before the x and put the intervening
* filters by calling put_filter_list().
*/
/* put explicit tag */
return (NULL);
/*
if (!not && ber_printf(ber, "{") == -1)
return (NULL);
*/
str++;
return (NULL);
*next = '\0';
return (NULL);
*next++ = ')';
/* flush explicit tagged thang */
return (NULL);
/*
if (!not && ber_printf(ber, "}") == -1)
return (NULL);
*/
return (next);
}
static int
{
int multipleparen = 0;
/*
* A Filter looks like this:
* Filter ::= CHOICE {
* and [0] SET OF Filter,
* or [1] SET OF Filter,
* not [2] Filter,
* equalityMatch [3] AttributeValueAssertion,
* substrings [4] SubstringFilter,
* greaterOrEqual [5] AttributeValueAssertion,
* lessOrEqual [6] AttributeValueAssertion,
* present [7] AttributeType,
* approxMatch [8] AttributeValueAssertion,
* extensibleMatch [9] MatchingRuleAssertion
* }
*
* SubstringFilter ::= SEQUENCE {
* type AttributeType,
* SEQUENCE OF CHOICE {
* initial [0] IA5String,
* any [1] IA5String,
* final [2] IA5String
* }
* }
* MatchingRuleAssertion ::= SEQUENCE {
* matchingRule [1] MatchingRuleId OPTIONAL,
* type [2] AttributeDescription OPTIONAL,
* matchValue [3] AssertionValue,
* dnAttributes [4] BOOLEAN DEFAULT FALSE
* }
*
* Note: tags in a choice are always explicit
*/
"put_filter \"%s\"\n"), str, 0, 0);
parens = 0;
while (*str) {
switch (*str) {
case '(':
str++;
parens++;
switch (*str) {
case '&':
244, "put_filter: AND\n"), 0, 0, 0);
LDAP_FILTER_AND, 0)) == NULL)
return (-1);
parens--;
break;
case '|':
245, "put_filter: OR\n"), 0, 0, 0);
LDAP_FILTER_OR, 0)) == NULL)
return (-1);
parens--;
break;
case '!':
246, "put_filter: NOT\n"), 0, 0, 0);
return (-1);
parens--;
break;
case '(':
402, "put_filter: Double Parentheses\n"),
0, 0, 0);
continue;
default:
247, "put_filter: simple\n"), 0, 0, 0);
balance = 1;
escape = 0;
if (escape == 0) {
if (*next == '(')
balance++;
else if (*next == ')')
balance--;
}
escape = 1;
else
escape = 0;
if (balance)
next++;
}
if (balance != 0)
return (-1);
*next = '\0';
return (-1);
*next++ = ')';
parens--;
break;
}
break;
case ')':
"put_filter: end\n"), 0, 0, 0);
if (multipleparen) {
} else {
return (-1);
}
str++;
parens--;
break;
case ' ':
str++;
break;
default: /* assume it's a simple type=value filter */
"put_filter: default\n"), 0, 0, 0);
return (-1);
}
break;
}
}
return (parens ? -1 : 0);
}
/*
* Put a list of filters like this "(filter1)(filter2)..."
*/
static int
{
char *next;
char save;
"put_filter_list \"%s\"\n"), str, 0, 0);
while (*str) {
str++;
if (*str == '\0')
break;
return (-1);
/* now we have "(filter)" with str pointing to it */
*next = '\0';
return (-1);
}
return (0);
}
static int
{
char *s;
unsigned int ftype;
int rc;
int len;
"put_simple_filter \"%s\"\n"), str, 0, 0);
return (-1);
value = s + 1;
*s-- = '\0';
savechar = *s;
switch (*s) {
case '<':
*s = '\0';
break;
case '>':
*s = '\0';
break;
case '~':
*s = '\0';
break;
/* LDAP V3 : New extensible matching */
case ':':
return (rc);
default:
} else {
return (rc);
}
break;
}
return (rc);
if (ftype == LDAP_FILTER_PRESENT) {
} else {
}
*s = savechar;
}
static int
{
unsigned int ftype;
int len;
return (-1);
*nextstar++ = '\0';
if (gotstar == 0) {
} else {
}
if (*val != '\0') {
return (-1);
}
gotstar = 1;
}
return (-1);
return (0);
}
static int
{
int len;
/* type is off form : attr:dn:matchingrule: or :dn:matchingrule: */
/* type ends with ':', suppress it */
while (*ptype) {
ptype++;
}
else {
return (-1);
}
/* Search first ':dn' */
/* No dn */
/* if there's a : its separating type and matching rule */
}
} else {
} else {
*dn = '\0';
}
}
rule[0] = '\0';
rule++;
} else {
}
return (-1);
}
return (-1);
}
return (-1);
}
return (-1);
}
/* Code value */
return (-1);
}
return (-1);
}
return (-1);
return (0);
}
int
{
int msgid;
== -1)
}
}
int
{
int msgid;
== -1)
}
/* LDAPv3 API EXTENSIONS */
int *msgidp)
{
int rv;
}
#ifdef _REENTRANT
#endif
"ldap_search\n"), 0, 0, 0);
if (rv == LDAP_SUCCESS)
rv = LDAP_OTHER;
#ifdef _REENTRANT
#endif
return (rv);
}
#ifndef NO_CACHE
#ifdef _REENTRANT
#endif
return (LDAP_SUCCESS);
}
}
#endif /* NO_CACHE */
/* send the message */
if (rv == -1) {
if (rv == LDAP_SUCCESS) {
rv = LDAP_OTHER;
}
#ifdef _REENTRANT
#endif
return (rv);
}
#if _REENTRANT
#endif
return (LDAP_SUCCESS);
}
LDAPMessage **res)
{
int msgid;
int retcode = LDAP_SUCCESS;
&msgid)) != LDAP_SUCCESS)
return (retcode);
#if _REENTRANT
#endif
if (retcode == LDAP_SUCCESS)
#if _REENTRANT
#endif
return (retcode);
}
/*
* Search string for ascii '*' (asterisk) character.
* RFC 1960 permits an escaped asterisk to pass through.
* RFC 2254 adds the definition of encoded characters:
*
* Character ASCII value
* ---------------------------
* * 0x2a
* ( 0x28
* ) 0x29
* \ 0x5c
* NUL 0x00
*
* No distinction of escaped characters is made here.
*/
static char *
star_search(char *str)
{
switch (*str) {
case '*':
return (str);
case '\\':
break; /* input string exahausted */
++str; /* Assume RFC 1960 escaped character */
/* Check for RFC 2254 hex encoding */
if (hex_char2int(str[0]) >= 0 &&
str++; /* skip over RFC 2254 hex encoding */
}
default:
break;
}
}
return (NULL);
}
/*
* Return integer value of hexadecimal character or (-1) if character is
* not a hexadecimal digit [0-9A-Fa-f].
*/
static int
hex_char2int(char c)
{
if (c >= '0' && c <= '9') {
return (c-'0');
} else if (c >= 'A' && c <= 'F') {
return (c-'A'+10);
} else if (c >= 'a' && c <= 'f') {
return (c-'a'+10);
}
return (-1);
}
/*
* Modifys passed string converting escaped hexadecimal characters as
* per RFC 2254 and un-escapes escaped characters. Returns length of
* modified string as it may contain null characters as per RFC 2254.
*/
static int
decode_value(char *start)
{
if (*read == '\\') {
if (*++read == '\0')
break; /* input string exahausted */
/*
* Assume *read is simple RFC 1960 escaped character.
* However check for RFC 2254 hex encoding.
*/
read++;
}
}
}
*write = '\0';
}