]> git.sur5r.net Git - openldap/blob - servers/ldapd/search.c
Import some lint removal
[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 <stdio.h>
14 #include <string.h>
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>
23 #include "lber.h"
24 #include "ldap.h"
25 #include "common.h"
26
27 static get_filter();
28 static get_filter_list();
29 static get_substring_filter();
30
31 #ifdef COMPAT
32 extern int      version;
33 extern int      ldap_compat;
34 #define SEARCHRESTAG    (ldap_compat == 20 ? OLD_LDAP_RES_SEARCH_RESULT : LDAP_RES_SEARCH_RESULT)
35 #else
36 #define SEARCHRESTAG    LDAP_RES_SEARCH_RESULT
37 #endif
38
39 int
40 do_search(
41     Sockbuf     *clientsb,
42     struct msg  *m,
43     BerElement  *ber
44 )
45 {
46         int                     rc, err;
47         int                     deref, attrsonly;
48         int                     sizelimit, timelimit;
49         char                    *base;
50         char                    **attrs;
51         struct ds_search_arg    sa;
52         static CommonArgs       common = default_common_args;
53         extern DN               ldap_str2dn();
54
55         Debug( LDAP_DEBUG_TRACE, "do_search\n", 0, 0, 0 );
56
57         /*
58          * Parse the search request.  It looks like this:
59          *      SearchRequest := [APPLICATION 3] SEQUENCE {
60          *              baseObject      DistinguishedName,
61          *              scope           ENUMERATED {
62          *                      baseObject      (0),
63          *                      singleLevel     (1),
64          *                      wholeSubtree    (2)
65          *              },
66          *              derefAliases    ENUMERATED {
67          *                      neverDerefaliases       (0),
68          *                      derefInSearching        (1),
69          *                      derefFindingBaseObj     (2),
70          *                      alwaysDerefAliases      (3)
71          *              },
72          *              sizelimit       INTEGER (0 .. 65535),
73          *              timelimit       INTEGER (0 .. 65535),
74          *              attrsOnly       BOOLEAN,
75          *              filter          Filter,
76          *              attributes      SEQUENCE OF AttributeType
77          *      }
78          */
79
80 #if ISODEPACKAGE == IC
81 #if ICRELEASE > 2
82         DAS_SearchArgument_INIT( &sa );
83 #endif
84 #endif
85
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, "" );
90                 return( 0 );
91         }
92
93         sa.sra_baseobject = ldap_str2dn( base );
94         if ( sa.sra_baseobject == NULLDN && *base != '\0' ) {
95                 free( base );
96                 send_ldap_msgresult( clientsb, SEARCHRESTAG, m,
97                     LDAP_INVALID_DN_SYNTAX, NULL, "" );
98                 return( 0 );
99         }
100         free( base );
101
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;
108
109         sa.sra_common.ca_servicecontrol.svc_sizelimit = (sizelimit == 0 ?
110             SVC_NOSIZELIMIT : sizelimit);
111
112         sa.sra_common.ca_servicecontrol.svc_timelimit = (timelimit == 0 ?
113             SVC_NOTIMELIMIT : timelimit);
114
115         sa.sra_eis.eis_infotypes = (attrsonly ? EIS_ATTRIBUTETYPESONLY :
116             EIS_ATTRIBUTESANDVALUES);
117
118         /* search filter */
119         if ( (err = get_filter( ber, &sa.sra_filter )) != 0 ) {
120                 send_ldap_msgresult( clientsb, SEARCHRESTAG, m,
121                     err, NULL, "Bad search filter" );
122                 return( 0 );
123         }
124
125 #ifdef LDAP_DEBUG
126         if ( ldap_debug & LDAP_DEBUG_ARGS ) {
127                 PS      ps;
128
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" );
134                 ps_free( ps );
135         }
136 #endif
137
138         /* attrs to return */
139         attrs = NULL;
140         if ( ber_scanf( ber, "{v}}", &attrs ) == LBER_ERROR ) {
141                 send_ldap_msgresult( clientsb, SEARCHRESTAG, m,
142                     LDAP_PROTOCOL_ERROR, NULL, "" );
143                 return( 0 );
144         }
145         sa.sra_eis.eis_select = NULLATTR;
146         if ( attrs == NULL ) {
147                 sa.sra_eis.eis_allattributes = 1;
148         } else {
149                 Attr_Sequence   as;
150                 int             i;
151
152                 sa.sra_eis.eis_allattributes = 0;
153                 for ( i = 0; attrs[i] != NULL; i++ ) {
154                         AttributeType   type;
155
156                         if ( (type = AttrT_new( attrs[i] )) == NULLAttrT ) {
157                                 Debug( LDAP_DEBUG_TRACE, "unknown attr (%s)\n",
158                                     attrs[i], 0, 0 );
159                                 continue;
160                         }
161
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;
167
168                         sa.sra_eis.eis_select = as_merge( as,
169                             sa.sra_eis.eis_select );
170                 }
171
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 );
177                         return( 0 );
178                 }
179
180                 charlist_free( attrs );
181         }
182
183         rc = initiate_dap_operation( OP_SEARCH, m, &sa );
184
185 #ifdef CLDAP
186         if (  m->m_cldap )
187                 m->m_searchbase = sa.sra_baseobject;
188         else
189 #endif /* CLDAP */
190                 dn_free( sa.sra_baseobject );
191
192         filter_free( sa.sra_filter );
193         as_free( sa.sra_eis.eis_select );
194
195         if ( rc != 0 ) {
196                 send_ldap_msgresult( clientsb, SEARCHRESTAG, m,
197                     rc, NULL, "" );
198                 return( 0 );
199         }
200
201         return( 1 );
202 }
203
204 static get_filter( BerElement *ber, Filter *filt )
205 {
206         unsigned long   tag, len;
207         int             err;
208         char            typestr[64];
209         Filter          f;
210
211         Debug( LDAP_DEBUG_TRACE, "get_filter\n", 0, 0, 0 );
212
213         /*
214          * A filter looks like this coming in:
215          *      Filter ::= CHOICE {
216          *              and             [0]     SET OF Filter,
217          *              or              [1]     SET OF Filter,
218          *              not             [2]     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
225          *      }
226          *
227          *      SubstringFilter ::= SEQUENCE {
228          *              type               AttributeType,
229          *              SEQUENCE OF CHOICE {
230          *                      initial          [0] IA5String,
231          *                      any              [1] IA5String,
232          *                      final            [2] IA5String
233          *              }
234          *      }
235          */
236
237         f = filter_alloc();
238         *filt = f;
239         f->flt_next = NULLFILTER;
240
241         err = 0;
242         switch (tag = ber_peek_tag( ber, &len )) {
243 #ifdef COMPAT20
244         case OLD_LDAP_FILTER_EQUALITY:
245 #endif
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;
250 #ifdef COMPAT30
251                 if ( ldap_compat == 30 )
252                         (void) ber_skip_tag( ber, &len );
253 #endif
254
255                 if ( (err = get_ava( ber, &f->FUITEM.UNAVA )) != 0 ) {
256                         free( f );
257                         return( err );
258                 }
259                 break;
260
261 #ifdef COMPAT20
262         case OLD_LDAP_FILTER_SUBSTRINGS:
263 #endif
264         case LDAP_FILTER_SUBSTRINGS:
265                 Debug( LDAP_DEBUG_ARGS, "SUBSTRINGS\n", 0, 0, 0 );
266                 err = get_substring_filter( ber, f );
267                 break;
268
269 #ifdef COMPAT20
270         case OLD_LDAP_FILTER_GE:
271 #endif
272         case 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;
276 #ifdef COMPAT30
277                 if ( ldap_compat == 30 )
278                         (void) ber_skip_tag( ber, &len );
279 #endif
280                 if ( (err = get_ava( ber, &f->FUITEM.UNAVA )) != 0 ) {
281                         free( f );
282                         return( err );
283                 }
284                 break;
285
286 #ifdef COMPAT20
287         case OLD_LDAP_FILTER_LE:
288 #endif
289         case 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;
293 #ifdef COMPAT30
294                 if ( ldap_compat == 30 )
295                         (void) ber_skip_tag( ber, &len );
296 #endif
297
298                 if ( (err = get_ava( ber, &f->FUITEM.UNAVA )) != 0 ) {
299                         free( f );
300                         return( err );
301                 }
302                 break;
303
304 #ifdef COMPAT20
305         case OLD_LDAP_FILTER_PRESENT:
306 #endif
307 #ifdef COMPAT30
308         case LDAP_FILTER_PRESENT_30:
309 #endif
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);
315 #ifdef COMPAT30
316                 if ( ldap_compat == 30 )
317                         (void) ber_skip_tag( ber, &len );
318 #endif
319
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 );
324                 break;
325
326 #ifdef COMPAT20
327         case OLD_LDAP_FILTER_APPROX:
328 #endif
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;
333 #ifdef COMPAT30
334                 if ( ldap_compat == 30 )
335                         (void) ber_skip_tag( ber, &len );
336 #endif
337
338                 if ( (err = get_ava( ber, &f->FUITEM.UNAVA )) != 0 ) {
339                         free( f );
340                         return( err );
341                 }
342                 break;
343
344 #ifdef COMPAT20
345         case OLD_LDAP_FILTER_AND:
346 #endif
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 );
351                 break;
352
353 #ifdef COMPAT20
354         case OLD_LDAP_FILTER_OR:
355 #endif
356         case 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 );
360                 break;
361
362 #ifdef COMPAT20
363         case OLD_LDAP_FILTER_NOT:
364 #endif
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 );
370                 break;
371
372         default:
373                 Debug( LDAP_DEBUG_ANY, "unknown filter type %d\n", tag, 0, 0 );
374                 free( f );
375                 return( LDAP_PROTOCOL_ERROR );
376                 break;
377         }
378
379         Debug( LDAP_DEBUG_TRACE, "end get_filter\n", 0, 0, 0 );
380         return( err );
381 }
382
383 static get_filter_list( BerElement *ber, Filter f )
384 {
385         Filter          new, tail;
386         int             err;
387         unsigned long   tag, len;
388         char            *last;
389
390         Debug( LDAP_DEBUG_TRACE, "get_filter_list\n", 0, 0, 0 );
391
392 #ifdef COMPAT30
393         if ( ldap_compat == 30 )
394                 (void) ber_skip_tag( ber, &len );
395 #endif
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 )
400                         return( err );
401
402                 if ( f->FUFILT == NULLFILTER ) {
403                         f->FUFILT = new;
404                 } else {
405                         tail->flt_next = new;
406                 }
407                 tail = new;
408         }
409
410         Debug( LDAP_DEBUG_TRACE, "end get_filter_list\n", 0, 0, 0 );
411         return( 0 );
412 }
413
414 static get_substring_filter( BerElement *ber, Filter f )
415 {
416         unsigned long   tag, len;
417         char            typestr[64];
418         AttributeType   type;
419         char            *valstr, *last;
420         AttributeValue  value;
421         extern short    ldap_dn_syntax;
422
423         Debug( LDAP_DEBUG_TRACE, "get_substring_filter\n", 0, 0, 0 );
424
425 #ifdef COMPAT30
426         if ( ldap_compat == 30 )
427                 (void) ber_skip_tag( ber, &len );
428 #endif
429
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 );
435         }
436         if ( (type = str2AttrT( typestr )) == NULLAttrT ) {
437                 return( LDAP_UNDEFINED_TYPE );
438         }
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;
446
447 #ifdef COMPAT30
448                 if ( ldap_compat == 30 ) {
449                         if ( ber_scanf( ber, "{a}", &valstr ) == LBER_ERROR ) {
450                                 return( LDAP_PROTOCOL_ERROR );
451                         }
452                 } else
453 #endif
454                         if ( ber_scanf( ber, "a", &valstr ) == LBER_ERROR ) {
455                                 return( LDAP_PROTOCOL_ERROR );
456                         }
457
458                 value = ldap_str2AttrV( valstr, type->oa_syntax );
459                 free( valstr );
460
461                 if ( value == NULLAttrV ) {
462                         return( LDAP_INVALID_SYNTAX );
463                 }
464
465                 if ( (avs = avs_comp_new( value )) == NULLAV )
466                         return( LDAP_OPERATIONS_ERROR );
467
468                 switch ( tag ) {
469 #ifdef COMPAT20
470                 case OLD_LDAP_SUBSTRING_INITIAL:
471 #endif
472 #ifdef COMPAT30
473                 case LDAP_SUBSTRING_INITIAL_30:
474 #endif
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
479                             != NULLAV ) {
480                                 return( LDAP_PROTOCOL_ERROR );
481                         }
482                         f->FUITEM.UNSUB.fi_sub_initial = avs;
483                         break;
484
485 #ifdef COMPAT20
486                 case OLD_LDAP_SUBSTRING_ANY:
487 #endif
488 #ifdef COMPAT30
489                 case LDAP_SUBSTRING_ANY_30:
490 #endif
491                 case LDAP_SUBSTRING_ANY:
492                         Debug( LDAP_DEBUG_ARGS, "  ANY\n", 0, 0, 0 );
493         
494                         if (f->FUITEM.UNSUB.fi_sub_any != NULLAV) {
495                                 any_end->avseq_next = avs;
496                         } else {
497                                 f->FUITEM.UNSUB.fi_sub_any = avs;
498                         }
499
500                         any_end = avs;
501                         break;
502
503 #ifdef COMPAT20
504                 case OLD_LDAP_SUBSTRING_FINAL:
505 #endif
506 #ifdef COMPAT30
507                 case LDAP_SUBSTRING_FINAL_30:
508 #endif
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
513                             != NULLAV ) {
514                                 return( LDAP_PROTOCOL_ERROR );
515                         }
516                         f->FUITEM.UNSUB.fi_sub_final = avs;
517                         break;
518
519                 default:
520                         Debug( LDAP_DEBUG_ARGS, "  unknown type\n", tag, 0, 0 );
521                         return( LDAP_PROTOCOL_ERROR );
522                 }
523         }
524
525         Debug( LDAP_DEBUG_TRACE, "end get_substring_filter\n", 0, 0, 0 );
526         return( 0 );
527 }
528
529 void
530 search_result(
531     Sockbuf                     *sb,
532     struct msg                  *m,
533     struct ds_search_result     *sr
534 )
535 {
536         EntryInfo       *e;
537         BerElement      *ber;
538         int             rc;
539
540         Debug( LDAP_DEBUG_TRACE, "search_result\n", 0, 0, 0 );
541
542         ber = NULL;
543
544         if ( ! sr->srr_correlated ) {
545                 Debug( LDAP_DEBUG_ARGS, "correlating results\n", 0, 0, 0 );
546                 correlate_search_results( sr );
547         }
548
549 #ifdef CLDAP
550         if ( m->m_cldap ) {
551                 if ((ber = der_alloc()) == NULLBER ) {
552                         send_ldap_msgresult( sb, SEARCHRESTAG, m,
553                             LDAP_OPERATIONS_ERROR, NULL, "der_alloc" );
554                         return;
555                 }
556                 if ( ber_printf( ber, "t{is{", LBER_SEQUENCE, m->m_msgid,
557                     "" ) == -1 ) {
558                         send_ldap_msgresult( sb, SEARCHRESTAG, m,
559                             LDAP_OPERATIONS_ERROR, NULL, "ber_printf" );
560                         return;
561                 }
562         }
563 #endif
564
565         for ( e = sr->CSR_entries; e != NULLENTRYINFO; e = e->ent_next ) {
566                 Debug( LDAP_DEBUG_ARGS, "\tentry:\n", 0, 0, 0 );
567
568 #ifdef CLDAP
569                 if ( !m->m_cldap )
570 #endif /* CLDAP */
571
572                         if ( (ber = der_alloc()) == NULLBER ) {
573                                 send_ldap_msgresult( sb, SEARCHRESTAG, m,
574                                     LDAP_OPERATIONS_ERROR, NULL, "der_alloc" );
575                                 return;
576                         }
577
578 #ifdef COMPAT20
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" );
584                                 return;
585                         }
586                 } else
587 #endif
588 #ifdef COMPAT30
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" );
594                                 return;
595                         }
596                 } else
597 #endif
598 #ifdef CLDAP
599                 if ( m->m_cldap )
600                         rc = ber_printf( ber, "t{", LDAP_RES_SEARCH_ENTRY );
601                 else
602 #endif /* CLDAP */
603                         rc = ber_printf( ber, "{it{", m->m_msgid,
604                             LDAP_RES_SEARCH_ENTRY );
605
606                 if ( rc == -1 ) {
607                         send_ldap_msgresult( sb, SEARCHRESTAG, m,
608                             LDAP_OPERATIONS_ERROR, NULL, "ber_printf" );
609                         return;
610                 }
611
612 #ifdef CLDAP
613                 if (  m->m_cldap )
614                         rc = encode_dn( ber, e->ent_dn, m->m_searchbase );
615 #endif /* CLDAP */
616                 else
617                         rc = encode_dn( ber, e->ent_dn, NULLDN );
618
619                 if ( rc == -1 ) {
620                         send_ldap_msgresult( sb, SEARCHRESTAG, m,
621                             LDAP_OPERATIONS_ERROR, NULL, "encode_dn" );
622                         return;
623                 }
624
625                 if ( encode_attrs( ber, e->ent_attr ) == -1 ) {
626                         send_ldap_msgresult( sb, SEARCHRESTAG, m,
627                             LDAP_OPERATIONS_ERROR, NULL, "encode_attrs" );
628                         return;
629                 }
630
631 #ifdef COMPAT20
632                 if ( version == 1 ) {
633                         if ( ber_printf( ber, "}}" ) == -1 ) {
634                                 send_ldap_msgresult( sb, SEARCHRESTAG, m,
635                                     LDAP_OPERATIONS_ERROR, NULL,
636                                     "ber_printf 2" );
637                                 return;
638                         }
639                 } else
640 #endif
641 #ifdef COMPAT30
642                 if ( ldap_compat == 30 ) {
643                         if ( ber_printf( ber, "}}}" ) == -1 ) {
644                                 send_ldap_msgresult( sb, SEARCHRESTAG, m,
645                                     LDAP_OPERATIONS_ERROR, NULL,
646                                     "ber_printf 2" );
647                                 return;
648                         }
649                 } else
650 #endif
651 #ifdef CLDAP
652                 if ( m->m_cldap )
653                         rc = ber_printf( ber, "}" );
654                 else
655 #endif /* CLDAP */
656                         rc = ber_printf( ber, "}}" );
657
658                 if ( rc == -1 ) {
659                         send_ldap_msgresult( sb, SEARCHRESTAG, m,
660                             LDAP_OPERATIONS_ERROR, NULL, "ber_printf 2" );
661                         return;
662                 }
663
664 #ifdef LDAP_DEBUG
665                 if ( ldap_debug & LDAP_DEBUG_BER )
666                         trace_ber( 0, ber->ber_ptr - ber->ber_buf,
667                             ber->ber_buf, stderr, 0, 0 );
668 #endif
669
670 #ifdef CLDAP
671                 if ( !m->m_cldap )
672 #endif
673                         (void) ber_flush( sb, ber, 1 );
674         }
675
676         switch ( sr->CSR_limitproblem ) {
677         case LSR_NOLIMITPROBLEM:
678                 rc = LDAP_SUCCESS;
679                 break;
680         case LSR_TIMELIMITEXCEEDED:
681                 rc = LDAP_TIMELIMIT_EXCEEDED;
682                 break;
683         case LSR_SIZELIMITEXCEEDED:
684         case LSR_ADMINSIZEEXCEEDED:
685                 rc = LDAP_SIZELIMIT_EXCEEDED;
686                 break;
687         }
688
689         Debug( LDAP_DEBUG_ARGS, "\tresult:\n", 0, 0, 0 );
690
691 #ifdef CLDAP
692         if ( m->m_cldap ) {
693                 if ( ber_printf( ber, "t{ess}}}", SEARCHRESTAG, rc, "", "" )
694                     == -1 ) {
695                         send_ldap_msgresult( sb, SEARCHRESTAG, m,
696                             LDAP_OPERATIONS_ERROR, NULL, "ber_printf" );
697                         return;
698                 }
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" );
704                 }
705         } else
706 #endif
707         send_ldap_msgresult( sb, SEARCHRESTAG, m, rc, NULL, "" );
708
709         return;
710 }