2 * Copyright (c) 1990 Regents of the University of Michigan.
5 * Redistribution and use in source and binary forms are permitted
6 * provided that this notice is preserved and that due credit is given
7 * to the University of Michigan at Ann Arbor. The name of the University
8 * may not be used to endorse or promote products derived from this
9 * software without specific prior written permission. This software
10 * is provided ``as is'' without express or implied warranty.
15 #include <quipu/commonarg.h>
16 #include <quipu/attrvalue.h>
17 #include <quipu/ds_error.h>
18 #include <quipu/ds_search.h>
19 #include <quipu/dap2.h>
20 #include <quipu/dua.h>
21 #include <sys/types.h>
22 #include <sys/socket.h>
28 static get_filter_list();
29 static get_substring_filter();
33 extern int ldap_compat;
34 #define SEARCHRESTAG (ldap_compat == 20 ? OLD_LDAP_RES_SEARCH_RESULT : LDAP_RES_SEARCH_RESULT)
36 #define SEARCHRESTAG LDAP_RES_SEARCH_RESULT
48 int sizelimit, timelimit;
51 struct ds_search_arg sa;
52 static CommonArgs common = default_common_args;
53 extern DN ldap_str2dn();
55 Debug( LDAP_DEBUG_TRACE, "do_search\n", 0, 0, 0 );
58 * Parse the search request. It looks like this:
59 * SearchRequest := [APPLICATION 3] SEQUENCE {
60 * baseObject DistinguishedName,
66 * derefAliases ENUMERATED {
67 * neverDerefaliases (0),
68 * derefInSearching (1),
69 * derefFindingBaseObj (2),
70 * alwaysDerefAliases (3)
72 * sizelimit INTEGER (0 .. 65535),
73 * timelimit INTEGER (0 .. 65535),
76 * attributes SEQUENCE OF AttributeType
80 #if ISODEPACKAGE == IC
82 DAS_SearchArgument_INIT( &sa );
86 if ( ber_scanf( ber, "{aiiiib", &base, &sa.sra_subset, &deref,
87 &sizelimit, &timelimit, &attrsonly ) == LBER_ERROR ) {
88 send_ldap_msgresult( clientsb, SEARCHRESTAG, m,
89 LDAP_PROTOCOL_ERROR, NULL, "" );
93 sa.sra_baseobject = ldap_str2dn( base );
94 if ( sa.sra_baseobject == NULLDN && *base != '\0' ) {
96 send_ldap_msgresult( clientsb, SEARCHRESTAG, m,
97 LDAP_INVALID_DN_SYNTAX, NULL, "" );
102 sa.sra_common = common; /* struct copy */
103 sa.sra_searchaliases = (deref == LDAP_DEREF_SEARCHING ||
104 deref == LDAP_DEREF_ALWAYS);
105 if ( deref == LDAP_DEREF_NEVER || deref == LDAP_DEREF_SEARCHING )
106 sa.sra_common.ca_servicecontrol.svc_options |=
107 SVC_OPT_DONTDEREFERENCEALIAS;
109 sa.sra_common.ca_servicecontrol.svc_sizelimit = (sizelimit == 0 ?
110 SVC_NOSIZELIMIT : sizelimit);
112 sa.sra_common.ca_servicecontrol.svc_timelimit = (timelimit == 0 ?
113 SVC_NOTIMELIMIT : timelimit);
115 sa.sra_eis.eis_infotypes = (attrsonly ? EIS_ATTRIBUTETYPESONLY :
116 EIS_ATTRIBUTESANDVALUES);
119 if ( (err = get_filter( ber, &sa.sra_filter )) != 0 ) {
120 send_ldap_msgresult( clientsb, SEARCHRESTAG, m,
121 err, NULL, "Bad search filter" );
126 if ( ldap_debug & LDAP_DEBUG_ARGS ) {
129 ps = ps_alloc( std_open );
130 std_setup( ps, stderr );
131 ps_print( ps, "Filter: " );
132 fi_print( ps, sa.sra_filter, EDBOUT );
133 ps_print( ps, "\n" );
138 /* attrs to return */
140 if ( ber_scanf( ber, "{v}}", &attrs ) == LBER_ERROR ) {
141 send_ldap_msgresult( clientsb, SEARCHRESTAG, m,
142 LDAP_PROTOCOL_ERROR, NULL, "" );
145 sa.sra_eis.eis_select = NULLATTR;
146 if ( attrs == NULL ) {
147 sa.sra_eis.eis_allattributes = 1;
152 sa.sra_eis.eis_allattributes = 0;
153 for ( i = 0; attrs[i] != NULL; i++ ) {
156 if ( (type = AttrT_new( attrs[i] )) == NULLAttrT ) {
157 Debug( LDAP_DEBUG_TRACE, "unknown attr (%s)\n",
162 as = as_comp_alloc();
163 as->attr_type = type;
164 as->attr_acl = NULLACL_INFO;
165 as->attr_link = NULLATTR;
166 as->attr_value = NULLAV;
168 sa.sra_eis.eis_select = as_merge( as,
169 sa.sra_eis.eis_select );
172 /* complain only if we know about none of the attrs */
173 if ( sa.sra_eis.eis_select == NULLATTR ) {
174 send_ldap_msgresult( clientsb, SEARCHRESTAG,
175 m, LDAP_UNDEFINED_TYPE, NULL, attrs[0] );
176 charlist_free( attrs );
180 charlist_free( attrs );
183 rc = initiate_dap_operation( OP_SEARCH, m, &sa );
187 m->m_searchbase = sa.sra_baseobject;
190 dn_free( sa.sra_baseobject );
192 filter_free( sa.sra_filter );
193 as_free( sa.sra_eis.eis_select );
196 send_ldap_msgresult( clientsb, SEARCHRESTAG, m,
204 static get_filter( BerElement *ber, Filter *filt )
206 unsigned long tag, len;
211 Debug( LDAP_DEBUG_TRACE, "get_filter\n", 0, 0, 0 );
214 * A filter looks like this coming in:
215 * Filter ::= CHOICE {
216 * and [0] SET OF Filter,
217 * or [1] SET OF Filter,
219 * equalityMatch [3] AttributeValueAssertion,
220 * substrings [4] SubstringFilter,
221 * greaterOrEqual [5] AttributeValueAssertion,
222 * lessOrEqual [6] AttributeValueAssertion,
223 * present [7] AttributeType,,
224 * approxMatch [8] AttributeValueAssertion
227 * SubstringFilter ::= SEQUENCE {
228 * type AttributeType,
229 * SEQUENCE OF CHOICE {
230 * initial [0] IA5String,
232 * final [2] IA5String
239 f->flt_next = NULLFILTER;
242 switch (tag = ber_peek_tag( ber, &len )) {
244 case OLD_LDAP_FILTER_EQUALITY:
246 case LDAP_FILTER_EQUALITY:
247 Debug( LDAP_DEBUG_ARGS, "EQUALITY\n", 0, 0, 0 );
248 f->flt_type = FILTER_ITEM;
249 f->FUITEM.fi_type = FILTERITEM_EQUALITY;
251 if ( ldap_compat == 30 )
252 (void) ber_skip_tag( ber, &len );
255 if ( (err = get_ava( ber, &f->FUITEM.UNAVA )) != 0 ) {
262 case OLD_LDAP_FILTER_SUBSTRINGS:
264 case LDAP_FILTER_SUBSTRINGS:
265 Debug( LDAP_DEBUG_ARGS, "SUBSTRINGS\n", 0, 0, 0 );
266 err = get_substring_filter( ber, f );
270 case OLD_LDAP_FILTER_GE:
273 Debug( LDAP_DEBUG_ARGS, "GE\n", 0, 0, 0 );
274 f->flt_type = FILTER_ITEM;
275 f->FUITEM.fi_type = FILTERITEM_GREATEROREQUAL;
277 if ( ldap_compat == 30 )
278 (void) ber_skip_tag( ber, &len );
280 if ( (err = get_ava( ber, &f->FUITEM.UNAVA )) != 0 ) {
287 case OLD_LDAP_FILTER_LE:
290 Debug( LDAP_DEBUG_ARGS, "LE\n", 0, 0, 0 );
291 f->flt_type = FILTER_ITEM;
292 f->FUITEM.fi_type = FILTERITEM_LESSOREQUAL;
294 if ( ldap_compat == 30 )
295 (void) ber_skip_tag( ber, &len );
298 if ( (err = get_ava( ber, &f->FUITEM.UNAVA )) != 0 ) {
305 case OLD_LDAP_FILTER_PRESENT:
308 case LDAP_FILTER_PRESENT_30:
310 case LDAP_FILTER_PRESENT:
311 Debug( LDAP_DEBUG_ARGS, "PRESENT\n", 0, 0, 0 );
312 f->flt_type = FILTER_ITEM;
313 f->FUITEM.fi_type = FILTERITEM_PRESENT;
314 len = sizeof(typestr);
316 if ( ldap_compat == 30 )
317 (void) ber_skip_tag( ber, &len );
320 if ( ber_scanf( ber, "s", typestr, &len ) == LBER_ERROR )
321 return( LDAP_PROTOCOL_ERROR );
322 if ( (f->FUITEM.UNTYPE = str2AttrT( typestr )) == NULLAttrT )
323 return( LDAP_UNDEFINED_TYPE );
327 case OLD_LDAP_FILTER_APPROX:
329 case LDAP_FILTER_APPROX:
330 Debug( LDAP_DEBUG_ARGS, "APPROX\n", 0, 0, 0 );
331 f->flt_type = FILTER_ITEM;
332 f->FUITEM.fi_type = FILTERITEM_APPROX;
334 if ( ldap_compat == 30 )
335 (void) ber_skip_tag( ber, &len );
338 if ( (err = get_ava( ber, &f->FUITEM.UNAVA )) != 0 ) {
345 case OLD_LDAP_FILTER_AND:
347 case LDAP_FILTER_AND:
348 Debug( LDAP_DEBUG_ARGS, "AND\n", 0, 0, 0 );
349 f->flt_type = FILTER_AND;
350 err = get_filter_list( ber, f );
354 case OLD_LDAP_FILTER_OR:
357 Debug( LDAP_DEBUG_ARGS, "OR\n", 0, 0, 0 );
358 f->flt_type = FILTER_OR;
359 err = get_filter_list( ber, f );
363 case OLD_LDAP_FILTER_NOT:
365 case LDAP_FILTER_NOT:
366 Debug( LDAP_DEBUG_ARGS, "NOT\n", 0, 0, 0 );
367 f->flt_type = FILTER_NOT;
368 (void) ber_skip_tag( ber, &len );
369 err = get_filter( ber, &f->FUFILT );
373 Debug( LDAP_DEBUG_ANY, "unknown filter type %d\n", tag, 0, 0 );
375 return( LDAP_PROTOCOL_ERROR );
379 Debug( LDAP_DEBUG_TRACE, "end get_filter\n", 0, 0, 0 );
383 static get_filter_list( BerElement *ber, Filter f )
387 unsigned long tag, len;
390 Debug( LDAP_DEBUG_TRACE, "get_filter_list\n", 0, 0, 0 );
393 if ( ldap_compat == 30 )
394 (void) ber_skip_tag( ber, &len );
396 f->FUFILT = tail = NULLFILTER;
397 for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
398 tag = ber_next_element( ber, &len, last ) ) {
399 if ( (err = get_filter( ber, &new )) != 0 )
402 if ( f->FUFILT == NULLFILTER ) {
405 tail->flt_next = new;
410 Debug( LDAP_DEBUG_TRACE, "end get_filter_list\n", 0, 0, 0 );
414 static get_substring_filter( BerElement *ber, Filter f )
416 unsigned long tag, len;
420 AttributeValue value;
421 extern short ldap_dn_syntax;
423 Debug( LDAP_DEBUG_TRACE, "get_substring_filter\n", 0, 0, 0 );
426 if ( ldap_compat == 30 )
427 (void) ber_skip_tag( ber, &len );
430 f->flt_type = FILTER_ITEM;
431 f->FUITEM.fi_type = FILTERITEM_SUBSTRINGS;
432 len = sizeof(typestr);
433 if ( ber_scanf( ber, "{s", typestr, &len ) == LBER_ERROR ) {
434 return( LDAP_PROTOCOL_ERROR );
436 if ( (type = str2AttrT( typestr )) == NULLAttrT ) {
437 return( LDAP_UNDEFINED_TYPE );
439 f->FUITEM.UNSUB.fi_sub_type = type;
440 f->FUITEM.UNSUB.fi_sub_initial = NULLAV;
441 f->FUITEM.UNSUB.fi_sub_any = NULLAV;
442 f->FUITEM.UNSUB.fi_sub_final = NULLAV;
443 for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
444 tag = ber_next_element( ber, &len, last ) ) {
445 AV_Sequence avs, any_end;
448 if ( ldap_compat == 30 ) {
449 if ( ber_scanf( ber, "{a}", &valstr ) == LBER_ERROR ) {
450 return( LDAP_PROTOCOL_ERROR );
454 if ( ber_scanf( ber, "a", &valstr ) == LBER_ERROR ) {
455 return( LDAP_PROTOCOL_ERROR );
458 value = ldap_str2AttrV( valstr, type->oa_syntax );
461 if ( value == NULLAttrV ) {
462 return( LDAP_INVALID_SYNTAX );
465 if ( (avs = avs_comp_new( value )) == NULLAV )
466 return( LDAP_OPERATIONS_ERROR );
470 case OLD_LDAP_SUBSTRING_INITIAL:
473 case LDAP_SUBSTRING_INITIAL_30:
475 case LDAP_SUBSTRING_INITIAL:
476 Debug( LDAP_DEBUG_ARGS, " INITIAL\n", 0, 0, 0 );
477 if ( f->FUITEM.UNSUB.fi_sub_initial != NULLAV
478 && f->FUITEM.UNSUB.fi_sub_initial->avseq_next
480 return( LDAP_PROTOCOL_ERROR );
482 f->FUITEM.UNSUB.fi_sub_initial = avs;
486 case OLD_LDAP_SUBSTRING_ANY:
489 case LDAP_SUBSTRING_ANY_30:
491 case LDAP_SUBSTRING_ANY:
492 Debug( LDAP_DEBUG_ARGS, " ANY\n", 0, 0, 0 );
494 if (f->FUITEM.UNSUB.fi_sub_any != NULLAV) {
495 any_end->avseq_next = avs;
497 f->FUITEM.UNSUB.fi_sub_any = avs;
504 case OLD_LDAP_SUBSTRING_FINAL:
507 case LDAP_SUBSTRING_FINAL_30:
509 case LDAP_SUBSTRING_FINAL:
510 Debug( LDAP_DEBUG_ARGS, " FINAL\n", 0, 0, 0 );
511 if ( f->FUITEM.UNSUB.fi_sub_final != NULLAV
512 && f->FUITEM.UNSUB.fi_sub_final->avseq_next
514 return( LDAP_PROTOCOL_ERROR );
516 f->FUITEM.UNSUB.fi_sub_final = avs;
520 Debug( LDAP_DEBUG_ARGS, " unknown type\n", tag, 0, 0 );
521 return( LDAP_PROTOCOL_ERROR );
525 Debug( LDAP_DEBUG_TRACE, "end get_substring_filter\n", 0, 0, 0 );
533 struct ds_search_result *sr
540 Debug( LDAP_DEBUG_TRACE, "search_result\n", 0, 0, 0 );
544 if ( ! sr->srr_correlated ) {
545 Debug( LDAP_DEBUG_ARGS, "correlating results\n", 0, 0, 0 );
546 correlate_search_results( sr );
551 if ((ber = der_alloc()) == NULLBER ) {
552 send_ldap_msgresult( sb, SEARCHRESTAG, m,
553 LDAP_OPERATIONS_ERROR, NULL, "der_alloc" );
556 if ( ber_printf( ber, "t{is{", LBER_SEQUENCE, m->m_msgid,
558 send_ldap_msgresult( sb, SEARCHRESTAG, m,
559 LDAP_OPERATIONS_ERROR, NULL, "ber_printf" );
565 for ( e = sr->CSR_entries; e != NULLENTRYINFO; e = e->ent_next ) {
566 Debug( LDAP_DEBUG_ARGS, "\tentry:\n", 0, 0, 0 );
572 if ( (ber = der_alloc()) == NULLBER ) {
573 send_ldap_msgresult( sb, SEARCHRESTAG, m,
574 LDAP_OPERATIONS_ERROR, NULL, "der_alloc" );
579 if ( version == 1 ) {
580 if ( ber_printf( ber, "t{it{", OLD_LBER_SEQUENCE,
581 m->m_msgid, OLD_LDAP_RES_SEARCH_ENTRY ) == -1 ) {
582 send_ldap_msgresult( sb, SEARCHRESTAG, m,
583 LDAP_OPERATIONS_ERROR, NULL, "ber_printf" );
589 if ( ldap_compat == 30 ) {
590 if ( ber_printf( ber, "{it{{", m->m_msgid,
591 LDAP_RES_SEARCH_ENTRY ) == -1 ) {
592 send_ldap_msgresult( sb, SEARCHRESTAG, m,
593 LDAP_OPERATIONS_ERROR, NULL, "ber_printf" );
600 rc = ber_printf( ber, "t{", LDAP_RES_SEARCH_ENTRY );
603 rc = ber_printf( ber, "{it{", m->m_msgid,
604 LDAP_RES_SEARCH_ENTRY );
607 send_ldap_msgresult( sb, SEARCHRESTAG, m,
608 LDAP_OPERATIONS_ERROR, NULL, "ber_printf" );
614 rc = encode_dn( ber, e->ent_dn, m->m_searchbase );
617 rc = encode_dn( ber, e->ent_dn, NULLDN );
620 send_ldap_msgresult( sb, SEARCHRESTAG, m,
621 LDAP_OPERATIONS_ERROR, NULL, "encode_dn" );
625 if ( encode_attrs( ber, e->ent_attr ) == -1 ) {
626 send_ldap_msgresult( sb, SEARCHRESTAG, m,
627 LDAP_OPERATIONS_ERROR, NULL, "encode_attrs" );
632 if ( version == 1 ) {
633 if ( ber_printf( ber, "}}" ) == -1 ) {
634 send_ldap_msgresult( sb, SEARCHRESTAG, m,
635 LDAP_OPERATIONS_ERROR, NULL,
642 if ( ldap_compat == 30 ) {
643 if ( ber_printf( ber, "}}}" ) == -1 ) {
644 send_ldap_msgresult( sb, SEARCHRESTAG, m,
645 LDAP_OPERATIONS_ERROR, NULL,
653 rc = ber_printf( ber, "}" );
656 rc = ber_printf( ber, "}}" );
659 send_ldap_msgresult( sb, SEARCHRESTAG, m,
660 LDAP_OPERATIONS_ERROR, NULL, "ber_printf 2" );
665 if ( ldap_debug & LDAP_DEBUG_BER )
666 trace_ber( 0, ber->ber_ptr - ber->ber_buf,
667 ber->ber_buf, stderr, 0, 0 );
673 (void) ber_flush( sb, ber, 1 );
676 switch ( sr->CSR_limitproblem ) {
677 case LSR_NOLIMITPROBLEM:
680 case LSR_TIMELIMITEXCEEDED:
681 rc = LDAP_TIMELIMIT_EXCEEDED;
683 case LSR_SIZELIMITEXCEEDED:
684 case LSR_ADMINSIZEEXCEEDED:
685 rc = LDAP_SIZELIMIT_EXCEEDED;
689 Debug( LDAP_DEBUG_ARGS, "\tresult:\n", 0, 0, 0 );
693 if ( ber_printf( ber, "t{ess}}}", SEARCHRESTAG, rc, "", "" )
695 send_ldap_msgresult( sb, SEARCHRESTAG, m,
696 LDAP_OPERATIONS_ERROR, NULL, "ber_printf" );
699 SAFEMEMCPY( (char *)sb->sb_useaddr, &m->m_clientaddr,
700 sizeof( struct sockaddr ));
701 if ( ber_flush( sb, ber, 1 ) != 0 ) {
702 send_ldap_msgresult( sb, SEARCHRESTAG, m,
703 LDAP_RESULTS_TOO_LARGE, NULL, "ber_flush" );
707 send_ldap_msgresult( sb, SEARCHRESTAG, m, rc, NULL, "" );