]> git.sur5r.net Git - openldap/blob - servers/ldapd/search.c
30d9141e28eb0e65a499bb87e362c2cb7da6ea9d
[openldap] / servers / ldapd / search.c
1 /*
2  * Copyright (c) 1990 Regents of the University of Michigan.
3  * All rights reserved.
4  *
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.
11  */
12
13 #include "portable.h"
14
15 #include <stdio.h>
16
17 #include <ac/socket.h>
18 #include <ac/string.h>
19
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>
26
27 #include "lber.h"
28 #include "../../libraries/liblber/lber-int.h"   /* get struct berelement */
29 #include "ldap.h"
30 #include "common.h"
31
32 static int      get_filter();
33 static int      get_filter_list();
34 static int      get_substring_filter();
35
36 #ifdef LDAP_COMPAT
37 extern int      version;
38 extern int      ldap_compat;
39 #define SEARCHRESTAG    (ldap_compat == 20 ? OLD_LDAP_RES_SEARCH_RESULT : LDAP_RES_SEARCH_RESULT)
40 #else
41 #define SEARCHRESTAG    LDAP_RES_SEARCH_RESULT
42 #endif
43
44 int
45 do_search(
46     Sockbuf     *clientsb,
47     struct msg  *m,
48     BerElement  *ber
49 )
50 {
51         int                     rc, err;
52         int                     deref, attrsonly;
53         int                     sizelimit, timelimit;
54         char                    *base;
55         char                    **attrs;
56         struct ds_search_arg    sa;
57         static CommonArgs       common = default_common_args;
58         extern DN               ldap_str2dn();
59
60         Debug( LDAP_DEBUG_TRACE, "do_search\n", 0, 0, 0 );
61
62         /*
63          * Parse the search request.  It looks like this:
64          *      SearchRequest := [APPLICATION 3] SEQUENCE {
65          *              baseObject      DistinguishedName,
66          *              scope           ENUMERATED {
67          *                      baseObject      (0),
68          *                      singleLevel     (1),
69          *                      wholeSubtree    (2)
70          *              },
71          *              derefAliases    ENUMERATED {
72          *                      neverDerefaliases       (0),
73          *                      derefInSearching        (1),
74          *                      derefFindingBaseObj     (2),
75          *                      alwaysDerefAliases      (3)
76          *              },
77          *              sizelimit       INTEGER (0 .. 65535),
78          *              timelimit       INTEGER (0 .. 65535),
79          *              attrsOnly       BOOLEAN,
80          *              filter          Filter,
81          *              attributes      SEQUENCE OF AttributeType
82          *      }
83          */
84
85 #if ISODEPACKAGE == IC
86 #if ICRELEASE > 2
87         DAS_SearchArgument_INIT( &sa );
88 #endif
89 #endif
90
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, "" );
95                 return( 0 );
96         }
97
98         sa.sra_baseobject = ldap_str2dn( base );
99         if ( sa.sra_baseobject == NULLDN && *base != '\0' ) {
100                 free( base );
101                 send_ldap_msgresult( clientsb, SEARCHRESTAG, m,
102                     LDAP_INVALID_DN_SYNTAX, NULL, "" );
103                 return( 0 );
104         }
105         free( base );
106
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;
113
114         sa.sra_common.ca_servicecontrol.svc_sizelimit = (sizelimit == 0 ?
115             SVC_NOSIZELIMIT : sizelimit);
116
117         sa.sra_common.ca_servicecontrol.svc_timelimit = (timelimit == 0 ?
118             SVC_NOTIMELIMIT : timelimit);
119
120         sa.sra_eis.eis_infotypes = (attrsonly ? EIS_ATTRIBUTETYPESONLY :
121             EIS_ATTRIBUTESANDVALUES);
122
123         /* search filter */
124         if ( (err = get_filter( ber, &sa.sra_filter )) != 0 ) {
125                 send_ldap_msgresult( clientsb, SEARCHRESTAG, m,
126                     err, NULL, "Bad search filter" );
127                 return( 0 );
128         }
129
130 #ifdef LDAP_DEBUG
131         if ( ldap_debug & LDAP_DEBUG_ARGS ) {
132                 PS      ps;
133
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" );
139                 ps_free( ps );
140         }
141 #endif
142
143         /* attrs to return */
144         attrs = NULL;
145         if ( ber_scanf( ber, "{v}}", &attrs ) == LBER_ERROR ) {
146                 send_ldap_msgresult( clientsb, SEARCHRESTAG, m,
147                     LDAP_PROTOCOL_ERROR, NULL, "" );
148                 return( 0 );
149         }
150         sa.sra_eis.eis_select = NULLATTR;
151         if ( attrs == NULL ) {
152                 sa.sra_eis.eis_allattributes = 1;
153         } else {
154                 Attr_Sequence   as;
155                 int             i;
156
157                 sa.sra_eis.eis_allattributes = 0;
158                 for ( i = 0; attrs[i] != NULL; i++ ) {
159                         AttributeType   type;
160
161                         if ( (type = AttrT_new( attrs[i] )) == NULLAttrT ) {
162                                 Debug( LDAP_DEBUG_TRACE, "unknown attr (%s)\n",
163                                     attrs[i], 0, 0 );
164                                 continue;
165                         }
166
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;
172
173                         sa.sra_eis.eis_select = as_merge( as,
174                             sa.sra_eis.eis_select );
175                 }
176
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 );
182                         return( 0 );
183                 }
184
185                 charlist_free( attrs );
186         }
187
188         rc = initiate_dap_operation( OP_SEARCH, m, &sa );
189
190 #ifdef LDAP_CONNECTIONLESS
191         if (  m->m_cldap )
192                 m->m_searchbase = sa.sra_baseobject;
193         else
194 #endif /* LDAP_CONNECTIONLESS */
195                 dn_free( sa.sra_baseobject );
196
197         filter_free( sa.sra_filter );
198         as_free( sa.sra_eis.eis_select );
199
200         if ( rc != 0 ) {
201                 send_ldap_msgresult( clientsb, SEARCHRESTAG, m,
202                     rc, NULL, "" );
203                 return( 0 );
204         }
205
206         return( 1 );
207 }
208
209 static int
210 get_filter( BerElement *ber, Filter *filt )
211 {
212         unsigned long   tag, len;
213         int             err;
214         char            typestr[64];
215         Filter          f;
216
217         Debug( LDAP_DEBUG_TRACE, "get_filter\n", 0, 0, 0 );
218
219         /*
220          * A filter looks like this coming in:
221          *      Filter ::= CHOICE {
222          *              and             [0]     SET OF Filter,
223          *              or              [1]     SET OF Filter,
224          *              not             [2]     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
231          *      }
232          *
233          *      SubstringFilter ::= SEQUENCE {
234          *              type               AttributeType,
235          *              SEQUENCE OF CHOICE {
236          *                      initial          [0] IA5String,
237          *                      any              [1] IA5String,
238          *                      final            [2] IA5String
239          *              }
240          *      }
241          */
242
243         f = filter_alloc();
244         *filt = f;
245         f->flt_next = NULLFILTER;
246
247         err = 0;
248         switch (tag = ber_peek_tag( ber, &len )) {
249 #ifdef LDAP_COMPAT20
250         case OLD_LDAP_FILTER_EQUALITY:
251 #endif
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;
256 #ifdef LDAP_COMPAT30
257                 if ( ldap_compat == 30 )
258                         (void) ber_skip_tag( ber, &len );
259 #endif
260
261                 if ( (err = get_ava( ber, &f->FUITEM.UNAVA )) != 0 ) {
262                         free( f );
263                         return( err );
264                 }
265                 break;
266
267 #ifdef LDAP_COMPAT20
268         case OLD_LDAP_FILTER_SUBSTRINGS:
269 #endif
270         case LDAP_FILTER_SUBSTRINGS:
271                 Debug( LDAP_DEBUG_ARGS, "SUBSTRINGS\n", 0, 0, 0 );
272                 err = get_substring_filter( ber, f );
273                 break;
274
275 #ifdef LDAP_COMPAT20
276         case OLD_LDAP_FILTER_GE:
277 #endif
278         case 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;
282 #ifdef LDAP_COMPAT30
283                 if ( ldap_compat == 30 )
284                         (void) ber_skip_tag( ber, &len );
285 #endif
286                 if ( (err = get_ava( ber, &f->FUITEM.UNAVA )) != 0 ) {
287                         free( f );
288                         return( err );
289                 }
290                 break;
291
292 #ifdef LDAP_COMPAT20
293         case OLD_LDAP_FILTER_LE:
294 #endif
295         case 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;
299 #ifdef LDAP_COMPAT30
300                 if ( ldap_compat == 30 )
301                         (void) ber_skip_tag( ber, &len );
302 #endif
303
304                 if ( (err = get_ava( ber, &f->FUITEM.UNAVA )) != 0 ) {
305                         free( f );
306                         return( err );
307                 }
308                 break;
309
310 #ifdef LDAP_COMPAT20
311         case OLD_LDAP_FILTER_PRESENT:
312 #endif
313 #ifdef LDAP_COMPAT30
314         case LDAP_FILTER_PRESENT_30:
315 #endif
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);
321 #ifdef LDAP_COMPAT30
322                 if ( ldap_compat == 30 )
323                         (void) ber_skip_tag( ber, &len );
324 #endif
325
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 );
330                 break;
331
332 #ifdef LDAP_COMPAT20
333         case OLD_LDAP_FILTER_APPROX:
334 #endif
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;
339 #ifdef LDAP_COMPAT30
340                 if ( ldap_compat == 30 )
341                         (void) ber_skip_tag( ber, &len );
342 #endif
343
344                 if ( (err = get_ava( ber, &f->FUITEM.UNAVA )) != 0 ) {
345                         free( f );
346                         return( err );
347                 }
348                 break;
349
350 #ifdef LDAP_COMPAT20
351         case OLD_LDAP_FILTER_AND:
352 #endif
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 );
357                 break;
358
359 #ifdef LDAP_COMPAT20
360         case OLD_LDAP_FILTER_OR:
361 #endif
362         case 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 );
366                 break;
367
368 #ifdef LDAP_COMPAT20
369         case OLD_LDAP_FILTER_NOT:
370 #endif
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 );
376                 break;
377
378         default:
379                 Debug( LDAP_DEBUG_ANY, "unknown filter type %lu\n", tag, 0, 0 );
380                 free( f );
381                 return( LDAP_PROTOCOL_ERROR );
382                 break;
383         }
384
385         Debug( LDAP_DEBUG_TRACE, "end get_filter\n", 0, 0, 0 );
386         return( err );
387 }
388
389 static int
390 get_filter_list( BerElement *ber, Filter f )
391 {
392         Filter          new, tail;
393         int             err;
394         unsigned long   tag, len;
395         char            *last;
396
397         Debug( LDAP_DEBUG_TRACE, "get_filter_list\n", 0, 0, 0 );
398
399 #ifdef LDAP_COMPAT30
400         if ( ldap_compat == 30 )
401                 (void) ber_skip_tag( ber, &len );
402 #endif
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 )
407                         return( err );
408
409                 if ( f->FUFILT == NULLFILTER ) {
410                         f->FUFILT = new;
411                 } else {
412                         tail->flt_next = new;
413                 }
414                 tail = new;
415         }
416
417         Debug( LDAP_DEBUG_TRACE, "end get_filter_list\n", 0, 0, 0 );
418         return( 0 );
419 }
420
421 static int
422 get_substring_filter( BerElement *ber, Filter f )
423 {
424         unsigned long   tag, len;
425         char            typestr[64];
426         AttributeType   type;
427         char            *valstr, *last;
428         AttributeValue  value;
429         extern short    ldap_dn_syntax;
430
431         Debug( LDAP_DEBUG_TRACE, "get_substring_filter\n", 0, 0, 0 );
432
433 #ifdef LDAP_COMPAT30
434         if ( ldap_compat == 30 )
435                 (void) ber_skip_tag( ber, &len );
436 #endif
437
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 );
443         }
444         if ( (type = str2AttrT( typestr )) == NULLAttrT ) {
445                 return( LDAP_UNDEFINED_TYPE );
446         }
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;
454
455 #ifdef LDAP_COMPAT30
456                 if ( ldap_compat == 30 ) {
457                         if ( ber_scanf( ber, "{a}", &valstr ) == LBER_ERROR ) {
458                                 return( LDAP_PROTOCOL_ERROR );
459                         }
460                 } else
461 #endif
462                         if ( ber_scanf( ber, "a", &valstr ) == LBER_ERROR ) {
463                                 return( LDAP_PROTOCOL_ERROR );
464                         }
465
466                 value = ldap_str2AttrV( valstr, type->oa_syntax );
467                 free( valstr );
468
469                 if ( value == NULLAttrV ) {
470                         return( LDAP_INVALID_SYNTAX );
471                 }
472
473                 if ( (avs = avs_comp_new( value )) == NULLAV )
474                         return( LDAP_OPERATIONS_ERROR );
475
476                 switch ( tag ) {
477 #ifdef LDAP_COMPAT20
478                 case OLD_LDAP_SUBSTRING_INITIAL:
479 #endif
480 #ifdef LDAP_COMPAT30
481                 case LDAP_SUBSTRING_INITIAL_30:
482 #endif
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
487                             != NULLAV ) {
488                                 return( LDAP_PROTOCOL_ERROR );
489                         }
490                         f->FUITEM.UNSUB.fi_sub_initial = avs;
491                         break;
492
493 #ifdef LDAP_COMPAT20
494                 case OLD_LDAP_SUBSTRING_ANY:
495 #endif
496 #ifdef LDAP_COMPAT30
497                 case LDAP_SUBSTRING_ANY_30:
498 #endif
499                 case LDAP_SUBSTRING_ANY:
500                         Debug( LDAP_DEBUG_ARGS, "  ANY\n", 0, 0, 0 );
501         
502                         if (f->FUITEM.UNSUB.fi_sub_any != NULLAV) {
503                                 any_end->avseq_next = avs;
504                         } else {
505                                 f->FUITEM.UNSUB.fi_sub_any = avs;
506                         }
507
508                         any_end = avs;
509                         break;
510
511 #ifdef LDAP_COMPAT20
512                 case OLD_LDAP_SUBSTRING_FINAL:
513 #endif
514 #ifdef LDAP_COMPAT30
515                 case LDAP_SUBSTRING_FINAL_30:
516 #endif
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
521                             != NULLAV ) {
522                                 return( LDAP_PROTOCOL_ERROR );
523                         }
524                         f->FUITEM.UNSUB.fi_sub_final = avs;
525                         break;
526
527                 default:
528                         Debug( LDAP_DEBUG_ARGS, "  unknown type\n", tag, 0, 0 );
529                         return( LDAP_PROTOCOL_ERROR );
530                 }
531         }
532
533         Debug( LDAP_DEBUG_TRACE, "end get_substring_filter\n", 0, 0, 0 );
534         return( 0 );
535 }
536
537 void
538 search_result(
539     Sockbuf                     *sb,
540     struct msg                  *m,
541     struct ds_search_result     *sr
542 )
543 {
544         EntryInfo       *e;
545         BerElement      *ber;
546         int             rc;
547
548         Debug( LDAP_DEBUG_TRACE, "search_result\n", 0, 0, 0 );
549
550         ber = NULL;
551
552         if ( ! sr->srr_correlated ) {
553                 Debug( LDAP_DEBUG_ARGS, "correlating results\n", 0, 0, 0 );
554                 correlate_search_results( sr );
555         }
556
557 #ifdef LDAP_CONNECTIONLESS
558         if ( m->m_cldap ) {
559                 if ((ber = der_alloc()) == NULLBER ) {
560                         send_ldap_msgresult( sb, SEARCHRESTAG, m,
561                             LDAP_OPERATIONS_ERROR, NULL, "der_alloc" );
562                         return;
563                 }
564                 if ( ber_printf( ber, "t{is{", LBER_SEQUENCE, m->m_msgid,
565                     "" ) == -1 ) {
566                         send_ldap_msgresult( sb, SEARCHRESTAG, m,
567                             LDAP_OPERATIONS_ERROR, NULL, "ber_printf" );
568                         return;
569                 }
570         }
571 #endif
572
573         for ( e = sr->CSR_entries; e != NULLENTRYINFO; e = e->ent_next ) {
574                 Debug( LDAP_DEBUG_ARGS, "\tentry:\n", 0, 0, 0 );
575
576 #ifdef LDAP_CONNECTIONLESS
577                 if ( !m->m_cldap )
578 #endif /* LDAP_CONNECTIONLESS */
579
580                         if ( (ber = der_alloc()) == NULLBER ) {
581                                 send_ldap_msgresult( sb, SEARCHRESTAG, m,
582                                     LDAP_OPERATIONS_ERROR, NULL, "der_alloc" );
583                                 return;
584                         }
585
586 #ifdef LDAP_COMPAT20
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" );
592                                 return;
593                         }
594                 } else
595 #endif
596 #ifdef LDAP_COMPAT30
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" );
602                                 return;
603                         }
604                 } else
605 #endif
606 #ifdef LDAP_CONNECTIONLESS
607                 if ( m->m_cldap )
608                         rc = ber_printf( ber, "t{", LDAP_RES_SEARCH_ENTRY );
609                 else
610 #endif /* LDAP_CONNECTIONLESS */
611                         rc = ber_printf( ber, "{it{", m->m_msgid,
612                             LDAP_RES_SEARCH_ENTRY );
613
614                 if ( rc == -1 ) {
615                         send_ldap_msgresult( sb, SEARCHRESTAG, m,
616                             LDAP_OPERATIONS_ERROR, NULL, "ber_printf" );
617                         return;
618                 }
619
620 #ifdef LDAP_CONNECTIONLESS
621                 if (  m->m_cldap )
622                         rc = encode_dn( ber, e->ent_dn, m->m_searchbase );
623 #endif /* LDAP_CONNECTIONLESS */
624                 else
625                         rc = encode_dn( ber, e->ent_dn, NULLDN );
626
627                 if ( rc == -1 ) {
628                         send_ldap_msgresult( sb, SEARCHRESTAG, m,
629                             LDAP_OPERATIONS_ERROR, NULL, "encode_dn" );
630                         return;
631                 }
632
633                 if ( encode_attrs( ber, e->ent_attr ) == -1 ) {
634                         send_ldap_msgresult( sb, SEARCHRESTAG, m,
635                             LDAP_OPERATIONS_ERROR, NULL, "encode_attrs" );
636                         return;
637                 }
638
639 #ifdef LDAP_COMPAT20
640                 if ( version == 1 ) {
641                         if ( ber_printf( ber, "}}" ) == -1 ) {
642                                 send_ldap_msgresult( sb, SEARCHRESTAG, m,
643                                     LDAP_OPERATIONS_ERROR, NULL,
644                                     "ber_printf 2" );
645                                 return;
646                         }
647                 } else
648 #endif
649 #ifdef LDAP_COMPAT30
650                 if ( ldap_compat == 30 ) {
651                         if ( ber_printf( ber, "}}}" ) == -1 ) {
652                                 send_ldap_msgresult( sb, SEARCHRESTAG, m,
653                                     LDAP_OPERATIONS_ERROR, NULL,
654                                     "ber_printf 2" );
655                                 return;
656                         }
657                 } else
658 #endif
659 #ifdef LDAP_CONNECTIONLESS
660                 if ( m->m_cldap )
661                         rc = ber_printf( ber, "}" );
662                 else
663 #endif /* LDAP_CONNECTIONLESS */
664                         rc = ber_printf( ber, "}}" );
665
666                 if ( rc == -1 ) {
667                         send_ldap_msgresult( sb, SEARCHRESTAG, m,
668                             LDAP_OPERATIONS_ERROR, NULL, "ber_printf 2" );
669                         return;
670                 }
671
672 #ifdef LDAP_DEBUG
673                 if ( ldap_debug & LDAP_DEBUG_BER )
674                         trace_ber( 0, ber->ber_ptr - ber->ber_buf,
675                             ber->ber_buf, stderr, 0, 0 );
676 #endif
677
678 #ifdef LDAP_CONNECTIONLESS
679                 if ( !m->m_cldap )
680 #endif
681                         (void) ber_flush( sb, ber, 1 );
682         }
683
684         switch ( sr->CSR_limitproblem ) {
685         case LSR_NOLIMITPROBLEM:
686                 rc = LDAP_SUCCESS;
687                 break;
688         case LSR_TIMELIMITEXCEEDED:
689                 rc = LDAP_TIMELIMIT_EXCEEDED;
690                 break;
691         case LSR_SIZELIMITEXCEEDED:
692         case LSR_ADMINSIZEEXCEEDED:
693                 rc = LDAP_SIZELIMIT_EXCEEDED;
694                 break;
695         }
696
697         Debug( LDAP_DEBUG_ARGS, "\tresult:\n", 0, 0, 0 );
698
699 #ifdef LDAP_CONNECTIONLESS
700         if ( m->m_cldap ) {
701                 if ( ber_printf( ber, "t{ess}}}", SEARCHRESTAG, rc, "", "" )
702                     == -1 ) {
703                         send_ldap_msgresult( sb, SEARCHRESTAG, m,
704                             LDAP_OPERATIONS_ERROR, NULL, "ber_printf" );
705                         return;
706                 }
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" );
712                 }
713         } else
714 #endif
715         send_ldap_msgresult( sb, SEARCHRESTAG, m, rc, NULL, "" );
716
717         return;
718 }