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();
33 static int get_filter_list();
34 static int get_substring_filter();
38 extern int ldap_compat;
39 #define SEARCHRESTAG (ldap_compat == 20 ? OLD_LDAP_RES_SEARCH_RESULT : LDAP_RES_SEARCH_RESULT)
41 #define SEARCHRESTAG LDAP_RES_SEARCH_RESULT
53 int sizelimit, timelimit;
56 struct ds_search_arg sa;
57 static CommonArgs common = default_common_args;
58 extern DN ldap_str2dn();
60 Debug( LDAP_DEBUG_TRACE, "do_search\n", 0, 0, 0 );
63 * Parse the search request. It looks like this:
64 * SearchRequest := [APPLICATION 3] SEQUENCE {
65 * baseObject DistinguishedName,
71 * derefAliases ENUMERATED {
72 * neverDerefaliases (0),
73 * derefInSearching (1),
74 * derefFindingBaseObj (2),
75 * alwaysDerefAliases (3)
77 * sizelimit INTEGER (0 .. 65535),
78 * timelimit INTEGER (0 .. 65535),
81 * attributes SEQUENCE OF AttributeType
85 #if ISODEPACKAGE == IC
87 DAS_SearchArgument_INIT( &sa );
91 if ( ber_scanf( ber, "{aiiiib", &base, &sa.sra_subset, &deref,
92 &sizelimit, &timelimit, &attrsonly ) == LBER_ERROR ) {
93 send_ldap_msgresult( clientsb, SEARCHRESTAG, m,
94 LDAP_PROTOCOL_ERROR, NULL, "" );
98 sa.sra_baseobject = ldap_str2dn( base );
99 if ( sa.sra_baseobject == NULLDN && *base != '\0' ) {
101 send_ldap_msgresult( clientsb, SEARCHRESTAG, m,
102 LDAP_INVALID_DN_SYNTAX, NULL, "" );
107 sa.sra_common = common; /* struct copy */
108 sa.sra_searchaliases = (deref == LDAP_DEREF_SEARCHING ||
109 deref == LDAP_DEREF_ALWAYS);
110 if ( deref == LDAP_DEREF_NEVER || deref == LDAP_DEREF_SEARCHING )
111 sa.sra_common.ca_servicecontrol.svc_options |=
112 SVC_OPT_DONTDEREFERENCEALIAS;
114 sa.sra_common.ca_servicecontrol.svc_sizelimit = (sizelimit == 0 ?
115 SVC_NOSIZELIMIT : sizelimit);
117 sa.sra_common.ca_servicecontrol.svc_timelimit = (timelimit == 0 ?
118 SVC_NOTIMELIMIT : timelimit);
120 sa.sra_eis.eis_infotypes = (attrsonly ? EIS_ATTRIBUTETYPESONLY :
121 EIS_ATTRIBUTESANDVALUES);
124 if ( (err = get_filter( ber, &sa.sra_filter )) != 0 ) {
125 send_ldap_msgresult( clientsb, SEARCHRESTAG, m,
126 err, NULL, "Bad search filter" );
131 if ( ldap_debug & LDAP_DEBUG_ARGS ) {
134 ps = ps_alloc( std_open );
135 std_setup( ps, stderr );
136 ps_print( ps, "Filter: " );
137 fi_print( ps, sa.sra_filter, EDBOUT );
138 ps_print( ps, "\n" );
143 /* attrs to return */
145 if ( ber_scanf( ber, "{v}}", &attrs ) == LBER_ERROR ) {
146 send_ldap_msgresult( clientsb, SEARCHRESTAG, m,
147 LDAP_PROTOCOL_ERROR, NULL, "" );
150 sa.sra_eis.eis_select = NULLATTR;
151 if ( attrs == NULL ) {
152 sa.sra_eis.eis_allattributes = 1;
157 sa.sra_eis.eis_allattributes = 0;
158 for ( i = 0; attrs[i] != NULL; i++ ) {
161 if ( (type = AttrT_new( attrs[i] )) == NULLAttrT ) {
162 Debug( LDAP_DEBUG_TRACE, "unknown attr (%s)\n",
167 as = as_comp_alloc();
168 as->attr_type = type;
169 as->attr_acl = NULLACL_INFO;
170 as->attr_link = NULLATTR;
171 as->attr_value = NULLAV;
173 sa.sra_eis.eis_select = as_merge( as,
174 sa.sra_eis.eis_select );
177 /* complain only if we know about none of the attrs */
178 if ( sa.sra_eis.eis_select == NULLATTR ) {
179 send_ldap_msgresult( clientsb, SEARCHRESTAG,
180 m, LDAP_UNDEFINED_TYPE, NULL, attrs[0] );
181 charlist_free( attrs );
185 charlist_free( attrs );
188 rc = initiate_dap_operation( OP_SEARCH, m, &sa );
190 #ifdef LDAP_CONNECTIONLESS
192 m->m_searchbase = sa.sra_baseobject;
194 #endif /* LDAP_CONNECTIONLESS */
195 dn_free( sa.sra_baseobject );
197 filter_free( sa.sra_filter );
198 as_free( sa.sra_eis.eis_select );
201 send_ldap_msgresult( clientsb, SEARCHRESTAG, m,
210 get_filter( BerElement *ber, Filter *filt )
212 unsigned long tag, len;
217 Debug( LDAP_DEBUG_TRACE, "get_filter\n", 0, 0, 0 );
220 * A filter looks like this coming in:
221 * Filter ::= CHOICE {
222 * and [0] SET OF Filter,
223 * or [1] SET OF Filter,
225 * equalityMatch [3] AttributeValueAssertion,
226 * substrings [4] SubstringFilter,
227 * greaterOrEqual [5] AttributeValueAssertion,
228 * lessOrEqual [6] AttributeValueAssertion,
229 * present [7] AttributeType,,
230 * approxMatch [8] AttributeValueAssertion
233 * SubstringFilter ::= SEQUENCE {
234 * type AttributeType,
235 * SEQUENCE OF CHOICE {
236 * initial [0] IA5String,
238 * final [2] IA5String
245 f->flt_next = NULLFILTER;
248 switch (tag = ber_peek_tag( ber, &len )) {
250 case OLD_LDAP_FILTER_EQUALITY:
252 case LDAP_FILTER_EQUALITY:
253 Debug( LDAP_DEBUG_ARGS, "EQUALITY\n", 0, 0, 0 );
254 f->flt_type = FILTER_ITEM;
255 f->FUITEM.fi_type = FILTERITEM_EQUALITY;
257 if ( ldap_compat == 30 )
258 (void) ber_skip_tag( ber, &len );
261 if ( (err = get_ava( ber, &f->FUITEM.UNAVA )) != 0 ) {
268 case OLD_LDAP_FILTER_SUBSTRINGS:
270 case LDAP_FILTER_SUBSTRINGS:
271 Debug( LDAP_DEBUG_ARGS, "SUBSTRINGS\n", 0, 0, 0 );
272 err = get_substring_filter( ber, f );
276 case OLD_LDAP_FILTER_GE:
279 Debug( LDAP_DEBUG_ARGS, "GE\n", 0, 0, 0 );
280 f->flt_type = FILTER_ITEM;
281 f->FUITEM.fi_type = FILTERITEM_GREATEROREQUAL;
283 if ( ldap_compat == 30 )
284 (void) ber_skip_tag( ber, &len );
286 if ( (err = get_ava( ber, &f->FUITEM.UNAVA )) != 0 ) {
293 case OLD_LDAP_FILTER_LE:
296 Debug( LDAP_DEBUG_ARGS, "LE\n", 0, 0, 0 );
297 f->flt_type = FILTER_ITEM;
298 f->FUITEM.fi_type = FILTERITEM_LESSOREQUAL;
300 if ( ldap_compat == 30 )
301 (void) ber_skip_tag( ber, &len );
304 if ( (err = get_ava( ber, &f->FUITEM.UNAVA )) != 0 ) {
311 case OLD_LDAP_FILTER_PRESENT:
314 case LDAP_FILTER_PRESENT_30:
316 case LDAP_FILTER_PRESENT:
317 Debug( LDAP_DEBUG_ARGS, "PRESENT\n", 0, 0, 0 );
318 f->flt_type = FILTER_ITEM;
319 f->FUITEM.fi_type = FILTERITEM_PRESENT;
320 len = sizeof(typestr);
322 if ( ldap_compat == 30 )
323 (void) ber_skip_tag( ber, &len );
326 if ( ber_scanf( ber, "s", typestr, &len ) == LBER_ERROR )
327 return( LDAP_PROTOCOL_ERROR );
328 if ( (f->FUITEM.UNTYPE = str2AttrT( typestr )) == NULLAttrT )
329 return( LDAP_UNDEFINED_TYPE );
333 case OLD_LDAP_FILTER_APPROX:
335 case LDAP_FILTER_APPROX:
336 Debug( LDAP_DEBUG_ARGS, "APPROX\n", 0, 0, 0 );
337 f->flt_type = FILTER_ITEM;
338 f->FUITEM.fi_type = FILTERITEM_APPROX;
340 if ( ldap_compat == 30 )
341 (void) ber_skip_tag( ber, &len );
344 if ( (err = get_ava( ber, &f->FUITEM.UNAVA )) != 0 ) {
351 case OLD_LDAP_FILTER_AND:
353 case LDAP_FILTER_AND:
354 Debug( LDAP_DEBUG_ARGS, "AND\n", 0, 0, 0 );
355 f->flt_type = FILTER_AND;
356 err = get_filter_list( ber, f );
360 case OLD_LDAP_FILTER_OR:
363 Debug( LDAP_DEBUG_ARGS, "OR\n", 0, 0, 0 );
364 f->flt_type = FILTER_OR;
365 err = get_filter_list( ber, f );
369 case OLD_LDAP_FILTER_NOT:
371 case LDAP_FILTER_NOT:
372 Debug( LDAP_DEBUG_ARGS, "NOT\n", 0, 0, 0 );
373 f->flt_type = FILTER_NOT;
374 (void) ber_skip_tag( ber, &len );
375 err = get_filter( ber, &f->FUFILT );
379 Debug( LDAP_DEBUG_ANY, "unknown filter type %lu\n", tag, 0, 0 );
381 return( LDAP_PROTOCOL_ERROR );
385 Debug( LDAP_DEBUG_TRACE, "end get_filter\n", 0, 0, 0 );
390 get_filter_list( BerElement *ber, Filter f )
394 unsigned long tag, len;
397 Debug( LDAP_DEBUG_TRACE, "get_filter_list\n", 0, 0, 0 );
400 if ( ldap_compat == 30 )
401 (void) ber_skip_tag( ber, &len );
403 f->FUFILT = tail = NULLFILTER;
404 for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
405 tag = ber_next_element( ber, &len, last ) ) {
406 if ( (err = get_filter( ber, &new )) != 0 )
409 if ( f->FUFILT == NULLFILTER ) {
412 tail->flt_next = new;
417 Debug( LDAP_DEBUG_TRACE, "end get_filter_list\n", 0, 0, 0 );
422 get_substring_filter( BerElement *ber, Filter f )
424 unsigned long tag, len;
428 AttributeValue value;
429 extern short ldap_dn_syntax;
431 Debug( LDAP_DEBUG_TRACE, "get_substring_filter\n", 0, 0, 0 );
434 if ( ldap_compat == 30 )
435 (void) ber_skip_tag( ber, &len );
438 f->flt_type = FILTER_ITEM;
439 f->FUITEM.fi_type = FILTERITEM_SUBSTRINGS;
440 len = sizeof(typestr);
441 if ( ber_scanf( ber, "{s", typestr, &len ) == LBER_ERROR ) {
442 return( LDAP_PROTOCOL_ERROR );
444 if ( (type = str2AttrT( typestr )) == NULLAttrT ) {
445 return( LDAP_UNDEFINED_TYPE );
447 f->FUITEM.UNSUB.fi_sub_type = type;
448 f->FUITEM.UNSUB.fi_sub_initial = NULLAV;
449 f->FUITEM.UNSUB.fi_sub_any = NULLAV;
450 f->FUITEM.UNSUB.fi_sub_final = NULLAV;
451 for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
452 tag = ber_next_element( ber, &len, last ) ) {
453 AV_Sequence avs, any_end;
456 if ( ldap_compat == 30 ) {
457 if ( ber_scanf( ber, "{a}", &valstr ) == LBER_ERROR ) {
458 return( LDAP_PROTOCOL_ERROR );
462 if ( ber_scanf( ber, "a", &valstr ) == LBER_ERROR ) {
463 return( LDAP_PROTOCOL_ERROR );
466 value = ldap_str2AttrV( valstr, type->oa_syntax );
469 if ( value == NULLAttrV ) {
470 return( LDAP_INVALID_SYNTAX );
473 if ( (avs = avs_comp_new( value )) == NULLAV )
474 return( LDAP_OPERATIONS_ERROR );
478 case OLD_LDAP_SUBSTRING_INITIAL:
481 case LDAP_SUBSTRING_INITIAL_30:
483 case LDAP_SUBSTRING_INITIAL:
484 Debug( LDAP_DEBUG_ARGS, " INITIAL\n", 0, 0, 0 );
485 if ( f->FUITEM.UNSUB.fi_sub_initial != NULLAV
486 && f->FUITEM.UNSUB.fi_sub_initial->avseq_next
488 return( LDAP_PROTOCOL_ERROR );
490 f->FUITEM.UNSUB.fi_sub_initial = avs;
494 case OLD_LDAP_SUBSTRING_ANY:
497 case LDAP_SUBSTRING_ANY_30:
499 case LDAP_SUBSTRING_ANY:
500 Debug( LDAP_DEBUG_ARGS, " ANY\n", 0, 0, 0 );
502 if (f->FUITEM.UNSUB.fi_sub_any != NULLAV) {
503 any_end->avseq_next = avs;
505 f->FUITEM.UNSUB.fi_sub_any = avs;
512 case OLD_LDAP_SUBSTRING_FINAL:
515 case LDAP_SUBSTRING_FINAL_30:
517 case LDAP_SUBSTRING_FINAL:
518 Debug( LDAP_DEBUG_ARGS, " FINAL\n", 0, 0, 0 );
519 if ( f->FUITEM.UNSUB.fi_sub_final != NULLAV
520 && f->FUITEM.UNSUB.fi_sub_final->avseq_next
522 return( LDAP_PROTOCOL_ERROR );
524 f->FUITEM.UNSUB.fi_sub_final = avs;
528 Debug( LDAP_DEBUG_ARGS, " unknown type\n", tag, 0, 0 );
529 return( LDAP_PROTOCOL_ERROR );
533 Debug( LDAP_DEBUG_TRACE, "end get_substring_filter\n", 0, 0, 0 );
541 struct ds_search_result *sr
548 Debug( LDAP_DEBUG_TRACE, "search_result\n", 0, 0, 0 );
552 if ( ! sr->srr_correlated ) {
553 Debug( LDAP_DEBUG_ARGS, "correlating results\n", 0, 0, 0 );
554 correlate_search_results( sr );
557 #ifdef LDAP_CONNECTIONLESS
559 if ((ber = der_alloc()) == NULLBER ) {
560 send_ldap_msgresult( sb, SEARCHRESTAG, m,
561 LDAP_OPERATIONS_ERROR, NULL, "der_alloc" );
564 if ( ber_printf( ber, "t{is{", LBER_SEQUENCE, m->m_msgid,
566 send_ldap_msgresult( sb, SEARCHRESTAG, m,
567 LDAP_OPERATIONS_ERROR, NULL, "ber_printf" );
573 for ( e = sr->CSR_entries; e != NULLENTRYINFO; e = e->ent_next ) {
574 Debug( LDAP_DEBUG_ARGS, "\tentry:\n", 0, 0, 0 );
576 #ifdef LDAP_CONNECTIONLESS
578 #endif /* LDAP_CONNECTIONLESS */
580 if ( (ber = der_alloc()) == NULLBER ) {
581 send_ldap_msgresult( sb, SEARCHRESTAG, m,
582 LDAP_OPERATIONS_ERROR, NULL, "der_alloc" );
587 if ( version == 1 ) {
588 if ( ber_printf( ber, "t{it{", OLD_LBER_SEQUENCE,
589 m->m_msgid, OLD_LDAP_RES_SEARCH_ENTRY ) == -1 ) {
590 send_ldap_msgresult( sb, SEARCHRESTAG, m,
591 LDAP_OPERATIONS_ERROR, NULL, "ber_printf" );
597 if ( ldap_compat == 30 ) {
598 if ( ber_printf( ber, "{it{{", m->m_msgid,
599 LDAP_RES_SEARCH_ENTRY ) == -1 ) {
600 send_ldap_msgresult( sb, SEARCHRESTAG, m,
601 LDAP_OPERATIONS_ERROR, NULL, "ber_printf" );
606 #ifdef LDAP_CONNECTIONLESS
608 rc = ber_printf( ber, "t{", LDAP_RES_SEARCH_ENTRY );
610 #endif /* LDAP_CONNECTIONLESS */
611 rc = ber_printf( ber, "{it{", m->m_msgid,
612 LDAP_RES_SEARCH_ENTRY );
615 send_ldap_msgresult( sb, SEARCHRESTAG, m,
616 LDAP_OPERATIONS_ERROR, NULL, "ber_printf" );
620 #ifdef LDAP_CONNECTIONLESS
622 rc = encode_dn( ber, e->ent_dn, m->m_searchbase );
623 #endif /* LDAP_CONNECTIONLESS */
625 rc = encode_dn( ber, e->ent_dn, NULLDN );
628 send_ldap_msgresult( sb, SEARCHRESTAG, m,
629 LDAP_OPERATIONS_ERROR, NULL, "encode_dn" );
633 if ( encode_attrs( ber, e->ent_attr ) == -1 ) {
634 send_ldap_msgresult( sb, SEARCHRESTAG, m,
635 LDAP_OPERATIONS_ERROR, NULL, "encode_attrs" );
640 if ( version == 1 ) {
641 if ( ber_printf( ber, "}}" ) == -1 ) {
642 send_ldap_msgresult( sb, SEARCHRESTAG, m,
643 LDAP_OPERATIONS_ERROR, NULL,
650 if ( ldap_compat == 30 ) {
651 if ( ber_printf( ber, "}}}" ) == -1 ) {
652 send_ldap_msgresult( sb, SEARCHRESTAG, m,
653 LDAP_OPERATIONS_ERROR, NULL,
659 #ifdef LDAP_CONNECTIONLESS
661 rc = ber_printf( ber, "}" );
663 #endif /* LDAP_CONNECTIONLESS */
664 rc = ber_printf( ber, "}}" );
667 send_ldap_msgresult( sb, SEARCHRESTAG, m,
668 LDAP_OPERATIONS_ERROR, NULL, "ber_printf 2" );
673 if ( ldap_debug & LDAP_DEBUG_BER )
674 trace_ber( 0, ber->ber_ptr - ber->ber_buf,
675 ber->ber_buf, stderr, 0, 0 );
678 #ifdef LDAP_CONNECTIONLESS
681 (void) ber_flush( sb, ber, 1 );
684 switch ( sr->CSR_limitproblem ) {
685 case LSR_NOLIMITPROBLEM:
688 case LSR_TIMELIMITEXCEEDED:
689 rc = LDAP_TIMELIMIT_EXCEEDED;
691 case LSR_SIZELIMITEXCEEDED:
692 case LSR_ADMINSIZEEXCEEDED:
693 rc = LDAP_SIZELIMIT_EXCEEDED;
697 Debug( LDAP_DEBUG_ARGS, "\tresult:\n", 0, 0, 0 );
699 #ifdef LDAP_CONNECTIONLESS
701 if ( ber_printf( ber, "t{ess}}}", SEARCHRESTAG, rc, "", "" )
703 send_ldap_msgresult( sb, SEARCHRESTAG, m,
704 LDAP_OPERATIONS_ERROR, NULL, "ber_printf" );
707 SAFEMEMCPY( (char *)sb->sb_useaddr, &m->m_clientaddr,
708 sizeof( struct sockaddr ));
709 if ( ber_flush( sb, ber, 1 ) != 0 ) {
710 send_ldap_msgresult( sb, SEARCHRESTAG, m,
711 LDAP_RESULTS_TOO_LARGE, NULL, "ber_flush" );
715 send_ldap_msgresult( sb, SEARCHRESTAG, m, rc, NULL, "" );