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.
17 #include <ac/socket.h>
18 #include <ac/string.h>
20 #include <quipu/commonarg.h>
21 #include <quipu/attrvalue.h>
22 #include <quipu/ds_error.h>
23 #include <quipu/ds_search.h>
24 #include <quipu/dap2.h>
25 #include <quipu/dua.h>
28 #include "../../libraries/liblber/lber-int.h" /* get struct berelement */
32 static int get_filter( BerElement *ber, Filter *filt );
33 static int get_filter_list( BerElement *ber, Filter f );
34 static int get_substring_filter( BerElement *ber, Filter f );
37 #define SEARCHRESTAG (ldap_compat == 20 ? OLD_LDAP_RES_SEARCH_RESULT : LDAP_RES_SEARCH_RESULT)
39 #define SEARCHRESTAG LDAP_RES_SEARCH_RESULT
51 int sizelimit, timelimit;
54 struct ds_search_arg sa;
55 static CommonArgs common = default_common_args;
57 Debug( LDAP_DEBUG_TRACE, "do_search\n", 0, 0, 0 );
60 * Parse the search request. It looks like this:
61 * SearchRequest := [APPLICATION 3] SEQUENCE {
62 * baseObject DistinguishedName,
68 * derefAliases ENUMERATED {
69 * neverDerefaliases (0),
70 * derefInSearching (1),
71 * derefFindingBaseObj (2),
72 * alwaysDerefAliases (3)
74 * sizelimit INTEGER (0 .. 65535),
75 * timelimit INTEGER (0 .. 65535),
78 * attributes SEQUENCE OF AttributeType
82 #if ISODEPACKAGE == IC
84 DAS_SearchArgument_INIT( &sa );
88 if ( ber_scanf( ber, "{aiiiib", &base, &sa.sra_subset, &deref,
89 &sizelimit, &timelimit, &attrsonly ) == LBER_ERROR ) {
90 send_ldap_msgresult( clientsb, SEARCHRESTAG, m,
91 LDAP_PROTOCOL_ERROR, NULL, "" );
95 sa.sra_baseobject = ldap_str2dn( base );
96 if ( sa.sra_baseobject == NULLDN && *base != '\0' ) {
98 send_ldap_msgresult( clientsb, SEARCHRESTAG, m,
99 LDAP_INVALID_DN_SYNTAX, NULL, "" );
104 sa.sra_common = common; /* struct copy */
105 sa.sra_searchaliases = (deref == LDAP_DEREF_SEARCHING ||
106 deref == LDAP_DEREF_ALWAYS);
107 if ( deref == LDAP_DEREF_NEVER || deref == LDAP_DEREF_SEARCHING )
108 sa.sra_common.ca_servicecontrol.svc_options |=
109 SVC_OPT_DONTDEREFERENCEALIAS;
111 sa.sra_common.ca_servicecontrol.svc_sizelimit = (sizelimit == 0 ?
112 SVC_NOSIZELIMIT : sizelimit);
114 sa.sra_common.ca_servicecontrol.svc_timelimit = (timelimit == 0 ?
115 SVC_NOTIMELIMIT : timelimit);
117 sa.sra_eis.eis_infotypes = (attrsonly ? EIS_ATTRIBUTETYPESONLY :
118 EIS_ATTRIBUTESANDVALUES);
121 if ( (err = get_filter( ber, &sa.sra_filter )) != 0 ) {
122 send_ldap_msgresult( clientsb, SEARCHRESTAG, m,
123 err, NULL, "Bad search filter" );
128 if ( ldap_debug & LDAP_DEBUG_ARGS ) {
131 ps = ps_alloc( std_open );
132 std_setup( ps, stderr );
133 ps_print( ps, "Filter: " );
134 fi_print( ps, sa.sra_filter, EDBOUT );
135 ps_print( ps, "\n" );
140 /* attrs to return */
142 if ( ber_scanf( ber, "{v}}", &attrs ) == LBER_ERROR ) {
143 send_ldap_msgresult( clientsb, SEARCHRESTAG, m,
144 LDAP_PROTOCOL_ERROR, NULL, "" );
147 sa.sra_eis.eis_select = NULLATTR;
148 if ( attrs == NULL ) {
149 sa.sra_eis.eis_allattributes = 1;
154 sa.sra_eis.eis_allattributes = 0;
155 for ( i = 0; attrs[i] != NULL; i++ ) {
158 if ( (type = AttrT_new( attrs[i] )) == NULLAttrT ) {
159 Debug( LDAP_DEBUG_TRACE, "unknown attr (%s)\n",
164 as = as_comp_alloc();
165 as->attr_type = type;
166 as->attr_acl = NULLACL_INFO;
167 as->attr_link = NULLATTR;
168 as->attr_value = NULLAV;
170 sa.sra_eis.eis_select = as_merge( as,
171 sa.sra_eis.eis_select );
174 /* complain only if we know about none of the attrs */
175 if ( sa.sra_eis.eis_select == NULLATTR ) {
176 send_ldap_msgresult( clientsb, SEARCHRESTAG,
177 m, LDAP_UNDEFINED_TYPE, NULL, attrs[0] );
178 charlist_free( attrs );
182 charlist_free( attrs );
185 rc = initiate_dap_operation( OP_SEARCH, m, &sa );
187 #ifdef LDAP_CONNECTIONLESS
189 m->m_searchbase = sa.sra_baseobject;
191 #endif /* LDAP_CONNECTIONLESS */
192 dn_free( sa.sra_baseobject );
194 filter_free( sa.sra_filter );
195 as_free( sa.sra_eis.eis_select );
198 send_ldap_msgresult( clientsb, SEARCHRESTAG, m,
207 get_filter( BerElement *ber, Filter *filt )
209 unsigned long tag, len;
214 Debug( LDAP_DEBUG_TRACE, "get_filter\n", 0, 0, 0 );
217 * A filter looks like this coming in:
218 * Filter ::= CHOICE {
219 * and [0] SET OF Filter,
220 * or [1] SET OF Filter,
222 * equalityMatch [3] AttributeValueAssertion,
223 * substrings [4] SubstringFilter,
224 * greaterOrEqual [5] AttributeValueAssertion,
225 * lessOrEqual [6] AttributeValueAssertion,
226 * present [7] AttributeType,,
227 * approxMatch [8] AttributeValueAssertion
230 * SubstringFilter ::= SEQUENCE {
231 * type AttributeType,
232 * SEQUENCE OF CHOICE {
233 * initial [0] IA5String,
235 * final [2] IA5String
242 f->flt_next = NULLFILTER;
245 switch (tag = ber_peek_tag( ber, &len )) {
247 case OLD_LDAP_FILTER_EQUALITY:
249 case LDAP_FILTER_EQUALITY:
250 Debug( LDAP_DEBUG_ARGS, "EQUALITY\n", 0, 0, 0 );
251 f->flt_type = FILTER_ITEM;
252 f->FUITEM.fi_type = FILTERITEM_EQUALITY;
254 if ( ldap_compat == 30 )
255 (void) ber_skip_tag( ber, &len );
258 if ( (err = get_ava( ber, &f->FUITEM.UNAVA )) != 0 ) {
265 case OLD_LDAP_FILTER_SUBSTRINGS:
267 case LDAP_FILTER_SUBSTRINGS:
268 Debug( LDAP_DEBUG_ARGS, "SUBSTRINGS\n", 0, 0, 0 );
269 err = get_substring_filter( ber, f );
273 case OLD_LDAP_FILTER_GE:
276 Debug( LDAP_DEBUG_ARGS, "GE\n", 0, 0, 0 );
277 f->flt_type = FILTER_ITEM;
278 f->FUITEM.fi_type = FILTERITEM_GREATEROREQUAL;
280 if ( ldap_compat == 30 )
281 (void) ber_skip_tag( ber, &len );
283 if ( (err = get_ava( ber, &f->FUITEM.UNAVA )) != 0 ) {
290 case OLD_LDAP_FILTER_LE:
293 Debug( LDAP_DEBUG_ARGS, "LE\n", 0, 0, 0 );
294 f->flt_type = FILTER_ITEM;
295 f->FUITEM.fi_type = FILTERITEM_LESSOREQUAL;
297 if ( ldap_compat == 30 )
298 (void) ber_skip_tag( ber, &len );
301 if ( (err = get_ava( ber, &f->FUITEM.UNAVA )) != 0 ) {
308 case OLD_LDAP_FILTER_PRESENT:
311 case LDAP_FILTER_PRESENT_30:
313 case LDAP_FILTER_PRESENT:
314 Debug( LDAP_DEBUG_ARGS, "PRESENT\n", 0, 0, 0 );
315 f->flt_type = FILTER_ITEM;
316 f->FUITEM.fi_type = FILTERITEM_PRESENT;
317 len = sizeof(typestr);
319 if ( ldap_compat == 30 )
320 (void) ber_skip_tag( ber, &len );
323 if ( ber_scanf( ber, "s", typestr, &len ) == LBER_ERROR )
324 return( LDAP_PROTOCOL_ERROR );
325 if ( (f->FUITEM.UNTYPE = str2AttrT( typestr )) == NULLAttrT )
326 return( LDAP_UNDEFINED_TYPE );
330 case OLD_LDAP_FILTER_APPROX:
332 case LDAP_FILTER_APPROX:
333 Debug( LDAP_DEBUG_ARGS, "APPROX\n", 0, 0, 0 );
334 f->flt_type = FILTER_ITEM;
335 f->FUITEM.fi_type = FILTERITEM_APPROX;
337 if ( ldap_compat == 30 )
338 (void) ber_skip_tag( ber, &len );
341 if ( (err = get_ava( ber, &f->FUITEM.UNAVA )) != 0 ) {
348 case OLD_LDAP_FILTER_AND:
350 case LDAP_FILTER_AND:
351 Debug( LDAP_DEBUG_ARGS, "AND\n", 0, 0, 0 );
352 f->flt_type = FILTER_AND;
353 err = get_filter_list( ber, f );
357 case OLD_LDAP_FILTER_OR:
360 Debug( LDAP_DEBUG_ARGS, "OR\n", 0, 0, 0 );
361 f->flt_type = FILTER_OR;
362 err = get_filter_list( ber, f );
366 case OLD_LDAP_FILTER_NOT:
368 case LDAP_FILTER_NOT:
369 Debug( LDAP_DEBUG_ARGS, "NOT\n", 0, 0, 0 );
370 f->flt_type = FILTER_NOT;
371 (void) ber_skip_tag( ber, &len );
372 err = get_filter( ber, &f->FUFILT );
376 Debug( LDAP_DEBUG_ANY, "unknown filter type %lu\n", tag, 0, 0 );
378 return( LDAP_PROTOCOL_ERROR );
382 Debug( LDAP_DEBUG_TRACE, "end get_filter\n", 0, 0, 0 );
387 get_filter_list( BerElement *ber, Filter f )
391 unsigned long tag, len;
394 Debug( LDAP_DEBUG_TRACE, "get_filter_list\n", 0, 0, 0 );
397 if ( ldap_compat == 30 )
398 (void) ber_skip_tag( ber, &len );
400 f->FUFILT = tail = NULLFILTER;
401 for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
402 tag = ber_next_element( ber, &len, last ) ) {
403 if ( (err = get_filter( ber, &new )) != 0 )
406 if ( f->FUFILT == NULLFILTER ) {
409 tail->flt_next = new;
414 Debug( LDAP_DEBUG_TRACE, "end get_filter_list\n", 0, 0, 0 );
419 get_substring_filter( BerElement *ber, Filter f )
421 unsigned long tag, len;
425 AttributeValue value;
427 Debug( LDAP_DEBUG_TRACE, "get_substring_filter\n", 0, 0, 0 );
430 if ( ldap_compat == 30 )
431 (void) ber_skip_tag( ber, &len );
434 f->flt_type = FILTER_ITEM;
435 f->FUITEM.fi_type = FILTERITEM_SUBSTRINGS;
436 len = sizeof(typestr);
437 if ( ber_scanf( ber, "{s", typestr, &len ) == LBER_ERROR ) {
438 return( LDAP_PROTOCOL_ERROR );
440 if ( (type = str2AttrT( typestr )) == NULLAttrT ) {
441 return( LDAP_UNDEFINED_TYPE );
443 f->FUITEM.UNSUB.fi_sub_type = type;
444 f->FUITEM.UNSUB.fi_sub_initial = NULLAV;
445 f->FUITEM.UNSUB.fi_sub_any = NULLAV;
446 f->FUITEM.UNSUB.fi_sub_final = NULLAV;
447 for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
448 tag = ber_next_element( ber, &len, last ) ) {
449 AV_Sequence avs, any_end;
452 if ( ldap_compat == 30 ) {
453 if ( ber_scanf( ber, "{a}", &valstr ) == LBER_ERROR ) {
454 return( LDAP_PROTOCOL_ERROR );
458 if ( ber_scanf( ber, "a", &valstr ) == LBER_ERROR ) {
459 return( LDAP_PROTOCOL_ERROR );
462 value = ldap_str2AttrV( valstr, type->oa_syntax );
465 if ( value == NULLAttrV ) {
466 return( LDAP_INVALID_SYNTAX );
469 if ( (avs = avs_comp_new( value )) == NULLAV )
470 return( LDAP_OPERATIONS_ERROR );
474 case OLD_LDAP_SUBSTRING_INITIAL:
477 case LDAP_SUBSTRING_INITIAL_30:
479 case LDAP_SUBSTRING_INITIAL:
480 Debug( LDAP_DEBUG_ARGS, " INITIAL\n", 0, 0, 0 );
481 if ( f->FUITEM.UNSUB.fi_sub_initial != NULLAV
482 && f->FUITEM.UNSUB.fi_sub_initial->avseq_next
484 return( LDAP_PROTOCOL_ERROR );
486 f->FUITEM.UNSUB.fi_sub_initial = avs;
490 case OLD_LDAP_SUBSTRING_ANY:
493 case LDAP_SUBSTRING_ANY_30:
495 case LDAP_SUBSTRING_ANY:
496 Debug( LDAP_DEBUG_ARGS, " ANY\n", 0, 0, 0 );
498 if (f->FUITEM.UNSUB.fi_sub_any != NULLAV) {
499 any_end->avseq_next = avs;
501 f->FUITEM.UNSUB.fi_sub_any = avs;
508 case OLD_LDAP_SUBSTRING_FINAL:
511 case LDAP_SUBSTRING_FINAL_30:
513 case LDAP_SUBSTRING_FINAL:
514 Debug( LDAP_DEBUG_ARGS, " FINAL\n", 0, 0, 0 );
515 if ( f->FUITEM.UNSUB.fi_sub_final != NULLAV
516 && f->FUITEM.UNSUB.fi_sub_final->avseq_next
518 return( LDAP_PROTOCOL_ERROR );
520 f->FUITEM.UNSUB.fi_sub_final = avs;
524 Debug( LDAP_DEBUG_ARGS, " unknown type\n", tag, 0, 0 );
525 return( LDAP_PROTOCOL_ERROR );
529 Debug( LDAP_DEBUG_TRACE, "end get_substring_filter\n", 0, 0, 0 );
537 struct ds_search_result *sr
544 Debug( LDAP_DEBUG_TRACE, "search_result\n", 0, 0, 0 );
548 if ( ! sr->srr_correlated ) {
549 Debug( LDAP_DEBUG_ARGS, "correlating results\n", 0, 0, 0 );
550 correlate_search_results( sr );
553 #ifdef LDAP_CONNECTIONLESS
555 if ((ber = der_alloc()) == NULL ) {
556 send_ldap_msgresult( sb, SEARCHRESTAG, m,
557 LDAP_OPERATIONS_ERROR, NULL, "der_alloc" );
560 if ( ber_printf( ber, "t{is{", LBER_SEQUENCE, m->m_msgid,
562 send_ldap_msgresult( sb, SEARCHRESTAG, m,
563 LDAP_OPERATIONS_ERROR, NULL, "ber_printf" );
569 for ( e = sr->CSR_entries; e != NULLENTRYINFO; e = e->ent_next ) {
570 Debug( LDAP_DEBUG_ARGS, "\tentry:\n", 0, 0, 0 );
572 #ifdef LDAP_CONNECTIONLESS
574 #endif /* LDAP_CONNECTIONLESS */
576 if ( (ber = der_alloc()) == NULL ) {
577 send_ldap_msgresult( sb, SEARCHRESTAG, m,
578 LDAP_OPERATIONS_ERROR, NULL, "der_alloc" );
583 if ( version == 1 ) {
584 if ( ber_printf( ber, "t{it{", OLD_LBER_SEQUENCE,
585 m->m_msgid, OLD_LDAP_RES_SEARCH_ENTRY ) == -1 ) {
586 send_ldap_msgresult( sb, SEARCHRESTAG, m,
587 LDAP_OPERATIONS_ERROR, NULL, "ber_printf" );
593 if ( ldap_compat == 30 ) {
594 if ( ber_printf( ber, "{it{{", m->m_msgid,
595 LDAP_RES_SEARCH_ENTRY ) == -1 ) {
596 send_ldap_msgresult( sb, SEARCHRESTAG, m,
597 LDAP_OPERATIONS_ERROR, NULL, "ber_printf" );
602 #ifdef LDAP_CONNECTIONLESS
604 rc = ber_printf( ber, "t{", LDAP_RES_SEARCH_ENTRY );
606 #endif /* LDAP_CONNECTIONLESS */
607 rc = ber_printf( ber, "{it{", m->m_msgid,
608 LDAP_RES_SEARCH_ENTRY );
611 send_ldap_msgresult( sb, SEARCHRESTAG, m,
612 LDAP_OPERATIONS_ERROR, NULL, "ber_printf" );
616 #ifdef LDAP_CONNECTIONLESS
618 rc = encode_dn( ber, e->ent_dn, m->m_searchbase );
619 #endif /* LDAP_CONNECTIONLESS */
621 rc = encode_dn( ber, e->ent_dn, NULLDN );
624 send_ldap_msgresult( sb, SEARCHRESTAG, m,
625 LDAP_OPERATIONS_ERROR, NULL, "encode_dn" );
629 if ( encode_attrs( ber, e->ent_attr ) == -1 ) {
630 send_ldap_msgresult( sb, SEARCHRESTAG, m,
631 LDAP_OPERATIONS_ERROR, NULL, "encode_attrs" );
636 if ( version == 1 ) {
637 if ( ber_printf( ber, "}}" ) == -1 ) {
638 send_ldap_msgresult( sb, SEARCHRESTAG, m,
639 LDAP_OPERATIONS_ERROR, NULL,
646 if ( ldap_compat == 30 ) {
647 if ( ber_printf( ber, "}}}" ) == -1 ) {
648 send_ldap_msgresult( sb, SEARCHRESTAG, m,
649 LDAP_OPERATIONS_ERROR, NULL,
655 #ifdef LDAP_CONNECTIONLESS
657 rc = ber_printf( ber, "}" );
659 #endif /* LDAP_CONNECTIONLESS */
660 rc = ber_printf( ber, "}}" );
663 send_ldap_msgresult( sb, SEARCHRESTAG, m,
664 LDAP_OPERATIONS_ERROR, NULL, "ber_printf 2" );
669 if ( ldap_debug & LDAP_DEBUG_BER )
670 trace_ber( 0, ber->ber_ptr - ber->ber_buf,
671 ber->ber_buf, stderr, 0, 0 );
674 #ifdef LDAP_CONNECTIONLESS
677 (void) ber_flush( sb, ber, 1 );
680 switch ( sr->CSR_limitproblem ) {
681 case LSR_NOLIMITPROBLEM:
684 case LSR_TIMELIMITEXCEEDED:
685 rc = LDAP_TIMELIMIT_EXCEEDED;
687 case LSR_SIZELIMITEXCEEDED:
688 case LSR_ADMINSIZEEXCEEDED:
689 rc = LDAP_SIZELIMIT_EXCEEDED;
693 Debug( LDAP_DEBUG_ARGS, "\tresult:\n", 0, 0, 0 );
695 #ifdef LDAP_CONNECTIONLESS
697 if ( ber_printf( ber, "t{ess}}}", SEARCHRESTAG, rc, "", "" )
699 send_ldap_msgresult( sb, SEARCHRESTAG, m,
700 LDAP_OPERATIONS_ERROR, NULL, "ber_printf" );
703 ber_pvt_sb_udp_set_dst( sb, &m->m_clientaddr );
705 if ( ber_flush( sb, ber, 1 ) != 0 ) {
706 send_ldap_msgresult( sb, SEARCHRESTAG, m,
707 LDAP_RESULTS_TOO_LARGE, NULL, "ber_flush" );
711 send_ldap_msgresult( sb, SEARCHRESTAG, m, rc, NULL, "" );