]> git.sur5r.net Git - openldap/blob - servers/ldapd/search.c
Tweak the symlink creation rules for braindead "ln" commands.
[openldap] / servers / ldapd / search.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright (c) 1990 Regents of the University of Michigan.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms are permitted
7  * provided that this notice is preserved and that due credit is given
8  * to the University of Michigan at Ann Arbor. The name of the University
9  * may not be used to endorse or promote products derived from this
10  * software without specific prior written permission. This software
11  * is provided ``as is'' without express or implied warranty.
12  */
13
14 #include "portable.h"
15
16 #include <stdio.h>
17
18 #include <ac/socket.h>
19 #include <ac/string.h>
20
21 #include <quipu/commonarg.h>
22 #include <quipu/attrvalue.h>
23 #include <quipu/ds_error.h>
24 #include <quipu/ds_search.h>
25 #include <quipu/dap2.h>
26 #include <quipu/dua.h>
27
28 #include "lber.h"
29 #include "../../libraries/liblber/lber-int.h"   /* get struct berelement */
30 #include "ldap.h"
31 #include "common.h"
32
33 static int      get_filter( BerElement *ber, Filter *filt );
34 static int      get_filter_list( BerElement *ber, Filter f );
35 static int      get_substring_filter( BerElement *ber, Filter f );
36
37 #ifdef LDAP_COMPAT
38 #define SEARCHRESTAG    (ldap_compat == 20 ? OLD_LDAP_RES_SEARCH_RESULT : LDAP_RES_SEARCH_RESULT)
39 #else
40 #define SEARCHRESTAG    LDAP_RES_SEARCH_RESULT
41 #endif
42
43 int
44 do_search(
45     Sockbuf     *clientsb,
46     struct msg  *m,
47     BerElement  *ber
48 )
49 {
50         int                     rc, err;
51         int                     deref, attrsonly;
52         int                     sizelimit, timelimit;
53         char                    *base;
54         char                    **attrs;
55         struct ds_search_arg    sa;
56         static CommonArgs       common = default_common_args;
57
58         Debug( LDAP_DEBUG_TRACE, "do_search\n", 0, 0, 0 );
59
60         /*
61          * Parse the search request.  It looks like this:
62          *      SearchRequest := [APPLICATION 3] SEQUENCE {
63          *              baseObject      DistinguishedName,
64          *              scope           ENUMERATED {
65          *                      baseObject      (0),
66          *                      singleLevel     (1),
67          *                      wholeSubtree    (2)
68          *              },
69          *              derefAliases    ENUMERATED {
70          *                      neverDerefaliases       (0),
71          *                      derefInSearching        (1),
72          *                      derefFindingBaseObj     (2),
73          *                      alwaysDerefAliases      (3)
74          *              },
75          *              sizelimit       INTEGER (0 .. 65535),
76          *              timelimit       INTEGER (0 .. 65535),
77          *              attrsOnly       BOOLEAN,
78          *              filter          Filter,
79          *              attributes      SEQUENCE OF AttributeType
80          *      }
81          */
82
83 #if ISODEPACKAGE == IC
84 #if ICRELEASE > 2
85         DAS_SearchArgument_INIT( &sa );
86 #endif
87 #endif
88
89         if ( ber_scanf( ber, "{aiiiib", &base, &sa.sra_subset, &deref,
90             &sizelimit, &timelimit, &attrsonly ) == LBER_ERROR ) {
91                 send_ldap_msgresult( clientsb, SEARCHRESTAG, m,
92                     LDAP_PROTOCOL_ERROR, NULL, "" );
93                 return( 0 );
94         }
95
96         sa.sra_baseobject = ldap_str2dn( base );
97         if ( sa.sra_baseobject == NULLDN && *base != '\0' ) {
98                 free( base );
99                 send_ldap_msgresult( clientsb, SEARCHRESTAG, m,
100                     LDAP_INVALID_DN_SYNTAX, NULL, "" );
101                 return( 0 );
102         }
103         free( base );
104
105         sa.sra_common = common; /* struct copy */
106         sa.sra_searchaliases = (deref == LDAP_DEREF_SEARCHING ||
107             deref == LDAP_DEREF_ALWAYS);
108         if ( deref == LDAP_DEREF_NEVER || deref == LDAP_DEREF_SEARCHING )
109                 sa.sra_common.ca_servicecontrol.svc_options |=
110                     SVC_OPT_DONTDEREFERENCEALIAS;
111
112         sa.sra_common.ca_servicecontrol.svc_sizelimit = (sizelimit == 0 ?
113             SVC_NOSIZELIMIT : sizelimit);
114
115         sa.sra_common.ca_servicecontrol.svc_timelimit = (timelimit == 0 ?
116             SVC_NOTIMELIMIT : timelimit);
117
118         sa.sra_eis.eis_infotypes = (attrsonly ? EIS_ATTRIBUTETYPESONLY :
119             EIS_ATTRIBUTESANDVALUES);
120
121         /* search filter */
122         if ( (err = get_filter( ber, &sa.sra_filter )) != 0 ) {
123                 send_ldap_msgresult( clientsb, SEARCHRESTAG, m,
124                     err, NULL, "Bad search filter" );
125                 return( 0 );
126         }
127
128 #ifdef LDAP_DEBUG
129         if ( ldap_debug & LDAP_DEBUG_ARGS ) {
130                 PS      ps;
131
132                 ps = ps_alloc( std_open );
133                 std_setup( ps, stderr );
134                 ps_print( ps, "Filter: " );
135                 fi_print( ps, sa.sra_filter, EDBOUT );
136                 ps_print( ps, "\n" );
137                 ps_free( ps );
138         }
139 #endif
140
141         /* attrs to return */
142         attrs = NULL;
143         if ( ber_scanf( ber, "{v}}", &attrs ) == LBER_ERROR ) {
144                 send_ldap_msgresult( clientsb, SEARCHRESTAG, m,
145                     LDAP_PROTOCOL_ERROR, NULL, "" );
146                 return( 0 );
147         }
148         sa.sra_eis.eis_select = NULLATTR;
149         if ( attrs == NULL ) {
150                 sa.sra_eis.eis_allattributes = 1;
151         } else {
152                 Attr_Sequence   as;
153                 int             i;
154
155                 sa.sra_eis.eis_allattributes = 0;
156                 for ( i = 0; attrs[i] != NULL; i++ ) {
157                         AttributeType   type;
158
159                         if ( (type = AttrT_new( attrs[i] )) == NULLAttrT ) {
160                                 Debug( LDAP_DEBUG_TRACE, "unknown attr (%s)\n",
161                                     attrs[i], 0, 0 );
162                                 continue;
163                         }
164
165                         as = as_comp_alloc();
166                         as->attr_type = type;
167                         as->attr_acl = NULLACL_INFO;
168                         as->attr_link = NULLATTR;
169                         as->attr_value = NULLAV;
170
171                         sa.sra_eis.eis_select = as_merge( as,
172                             sa.sra_eis.eis_select );
173                 }
174
175                 /* complain only if we know about none of the attrs */
176                 if ( sa.sra_eis.eis_select == NULLATTR ) {
177                         send_ldap_msgresult( clientsb, SEARCHRESTAG,
178                             m, LDAP_UNDEFINED_TYPE, NULL, attrs[0] );
179                         charlist_free( attrs );
180                         return( 0 );
181                 }
182
183                 charlist_free( attrs );
184         }
185
186         rc = initiate_dap_operation( OP_SEARCH, m, &sa );
187
188 #ifdef LDAP_CONNECTIONLESS
189         if (  m->m_cldap )
190                 m->m_searchbase = sa.sra_baseobject;
191         else
192 #endif /* LDAP_CONNECTIONLESS */
193                 dn_free( sa.sra_baseobject );
194
195         filter_free( sa.sra_filter );
196         as_free( sa.sra_eis.eis_select );
197
198         if ( rc != 0 ) {
199                 send_ldap_msgresult( clientsb, SEARCHRESTAG, m,
200                     rc, NULL, "" );
201                 return( 0 );
202         }
203
204         return( 1 );
205 }
206
207 static int
208 get_filter( BerElement *ber, Filter *filt )
209 {
210         unsigned long   tag, len;
211         int             err;
212         char            typestr[64];
213         Filter          f;
214
215         Debug( LDAP_DEBUG_TRACE, "get_filter\n", 0, 0, 0 );
216
217         /*
218          * A filter looks like this coming in:
219          *      Filter ::= CHOICE {
220          *              and             [0]     SET OF Filter,
221          *              or              [1]     SET OF Filter,
222          *              not             [2]     Filter,
223          *              equalityMatch   [3]     AttributeValueAssertion,
224          *              substrings      [4]     SubstringFilter,
225          *              greaterOrEqual  [5]     AttributeValueAssertion,
226          *              lessOrEqual     [6]     AttributeValueAssertion,
227          *              present         [7]     AttributeType,,
228          *              approxMatch     [8]     AttributeValueAssertion
229          *      }
230          *
231          *      SubstringFilter ::= SEQUENCE {
232          *              type               AttributeType,
233          *              SEQUENCE OF CHOICE {
234          *                      initial          [0] IA5String,
235          *                      any              [1] IA5String,
236          *                      final            [2] IA5String
237          *              }
238          *      }
239          */
240
241         f = filter_alloc();
242         *filt = f;
243         f->flt_next = NULLFILTER;
244
245         err = 0;
246         switch (tag = ber_peek_tag( ber, &len )) {
247 #ifdef LDAP_COMPAT20
248         case OLD_LDAP_FILTER_EQUALITY:
249 #endif
250         case LDAP_FILTER_EQUALITY:
251                 Debug( LDAP_DEBUG_ARGS, "EQUALITY\n", 0, 0, 0 );
252                 f->flt_type = FILTER_ITEM;
253                 f->FUITEM.fi_type = FILTERITEM_EQUALITY;
254 #ifdef LDAP_COMPAT30
255                 if ( ldap_compat == 30 )
256                         (void) ber_skip_tag( ber, &len );
257 #endif
258
259                 if ( (err = get_ava( ber, &f->FUITEM.UNAVA )) != 0 ) {
260                         free( f );
261                         return( err );
262                 }
263                 break;
264
265 #ifdef LDAP_COMPAT20
266         case OLD_LDAP_FILTER_SUBSTRINGS:
267 #endif
268         case LDAP_FILTER_SUBSTRINGS:
269                 Debug( LDAP_DEBUG_ARGS, "SUBSTRINGS\n", 0, 0, 0 );
270                 err = get_substring_filter( ber, f );
271                 break;
272
273 #ifdef LDAP_COMPAT20
274         case OLD_LDAP_FILTER_GE:
275 #endif
276         case LDAP_FILTER_GE:
277                 Debug( LDAP_DEBUG_ARGS, "GE\n", 0, 0, 0 );
278                 f->flt_type = FILTER_ITEM;
279                 f->FUITEM.fi_type = FILTERITEM_GREATEROREQUAL;
280 #ifdef LDAP_COMPAT30
281                 if ( ldap_compat == 30 )
282                         (void) ber_skip_tag( ber, &len );
283 #endif
284                 if ( (err = get_ava( ber, &f->FUITEM.UNAVA )) != 0 ) {
285                         free( f );
286                         return( err );
287                 }
288                 break;
289
290 #ifdef LDAP_COMPAT20
291         case OLD_LDAP_FILTER_LE:
292 #endif
293         case LDAP_FILTER_LE:
294                 Debug( LDAP_DEBUG_ARGS, "LE\n", 0, 0, 0 );
295                 f->flt_type = FILTER_ITEM;
296                 f->FUITEM.fi_type = FILTERITEM_LESSOREQUAL;
297 #ifdef LDAP_COMPAT30
298                 if ( ldap_compat == 30 )
299                         (void) ber_skip_tag( ber, &len );
300 #endif
301
302                 if ( (err = get_ava( ber, &f->FUITEM.UNAVA )) != 0 ) {
303                         free( f );
304                         return( err );
305                 }
306                 break;
307
308 #ifdef LDAP_COMPAT20
309         case OLD_LDAP_FILTER_PRESENT:
310 #endif
311 #ifdef LDAP_COMPAT30
312         case LDAP_FILTER_PRESENT_30:
313 #endif
314         case LDAP_FILTER_PRESENT:
315                 Debug( LDAP_DEBUG_ARGS, "PRESENT\n", 0, 0, 0 );
316                 f->flt_type = FILTER_ITEM;
317                 f->FUITEM.fi_type = FILTERITEM_PRESENT;
318                 len = sizeof(typestr);
319 #ifdef LDAP_COMPAT30
320                 if ( ldap_compat == 30 )
321                         (void) ber_skip_tag( ber, &len );
322 #endif
323
324                 if ( ber_scanf( ber, "s", typestr, &len ) == LBER_ERROR )
325                         return( LDAP_PROTOCOL_ERROR );
326                 if ( (f->FUITEM.UNTYPE = str2AttrT( typestr )) == NULLAttrT )
327                         return( LDAP_UNDEFINED_TYPE );
328                 break;
329
330 #ifdef LDAP_COMPAT20
331         case OLD_LDAP_FILTER_APPROX:
332 #endif
333         case LDAP_FILTER_APPROX:
334                 Debug( LDAP_DEBUG_ARGS, "APPROX\n", 0, 0, 0 );
335                 f->flt_type = FILTER_ITEM;
336                 f->FUITEM.fi_type = FILTERITEM_APPROX;
337 #ifdef LDAP_COMPAT30
338                 if ( ldap_compat == 30 )
339                         (void) ber_skip_tag( ber, &len );
340 #endif
341
342                 if ( (err = get_ava( ber, &f->FUITEM.UNAVA )) != 0 ) {
343                         free( f );
344                         return( err );
345                 }
346                 break;
347
348 #ifdef LDAP_COMPAT20
349         case OLD_LDAP_FILTER_AND:
350 #endif
351         case LDAP_FILTER_AND:
352                 Debug( LDAP_DEBUG_ARGS, "AND\n", 0, 0, 0 );
353                 f->flt_type = FILTER_AND;
354                 err = get_filter_list( ber, f );
355                 break;
356
357 #ifdef LDAP_COMPAT20
358         case OLD_LDAP_FILTER_OR:
359 #endif
360         case LDAP_FILTER_OR:
361                 Debug( LDAP_DEBUG_ARGS, "OR\n", 0, 0, 0 );
362                 f->flt_type = FILTER_OR;
363                 err = get_filter_list( ber, f );
364                 break;
365
366 #ifdef LDAP_COMPAT20
367         case OLD_LDAP_FILTER_NOT:
368 #endif
369         case LDAP_FILTER_NOT:
370                 Debug( LDAP_DEBUG_ARGS, "NOT\n", 0, 0, 0 );
371                 f->flt_type = FILTER_NOT;
372                 (void) ber_skip_tag( ber, &len );
373                 err = get_filter( ber, &f->FUFILT );
374                 break;
375
376         default:
377                 Debug( LDAP_DEBUG_ANY, "unknown filter type %lu\n", tag, 0, 0 );
378                 free( f );
379                 return( LDAP_PROTOCOL_ERROR );
380                 break;
381         }
382
383         Debug( LDAP_DEBUG_TRACE, "end get_filter\n", 0, 0, 0 );
384         return( err );
385 }
386
387 static int
388 get_filter_list( BerElement *ber, Filter f )
389 {
390         Filter          new, tail;
391         int             err;
392         unsigned long   tag, len;
393         char            *last;
394
395         Debug( LDAP_DEBUG_TRACE, "get_filter_list\n", 0, 0, 0 );
396
397 #ifdef LDAP_COMPAT30
398         if ( ldap_compat == 30 )
399                 (void) ber_skip_tag( ber, &len );
400 #endif
401         f->FUFILT = tail = NULLFILTER;
402         for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
403             tag = ber_next_element( ber, &len, last ) ) {
404                 if ( (err = get_filter( ber, &new )) != 0 )
405                         return( err );
406
407                 if ( f->FUFILT == NULLFILTER ) {
408                         f->FUFILT = new;
409                 } else {
410                         tail->flt_next = new;
411                 }
412                 tail = new;
413         }
414
415         Debug( LDAP_DEBUG_TRACE, "end get_filter_list\n", 0, 0, 0 );
416         return( 0 );
417 }
418
419 static int
420 get_substring_filter( BerElement *ber, Filter f )
421 {
422         unsigned long   tag, len;
423         char            typestr[64];
424         AttributeType   type;
425         char            *valstr, *last;
426         AttributeValue  value;
427
428         Debug( LDAP_DEBUG_TRACE, "get_substring_filter\n", 0, 0, 0 );
429
430 #ifdef LDAP_COMPAT30
431         if ( ldap_compat == 30 )
432                 (void) ber_skip_tag( ber, &len );
433 #endif
434
435         f->flt_type = FILTER_ITEM;
436         f->FUITEM.fi_type = FILTERITEM_SUBSTRINGS;
437         len = sizeof(typestr);
438         if ( ber_scanf( ber, "{s", typestr, &len ) == LBER_ERROR ) {
439                 return( LDAP_PROTOCOL_ERROR );
440         }
441         if ( (type = str2AttrT( typestr )) == NULLAttrT ) {
442                 return( LDAP_UNDEFINED_TYPE );
443         }
444         f->FUITEM.UNSUB.fi_sub_type = type;
445         f->FUITEM.UNSUB.fi_sub_initial = NULLAV;
446         f->FUITEM.UNSUB.fi_sub_any = NULLAV;
447         f->FUITEM.UNSUB.fi_sub_final = NULLAV;
448         for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
449             tag = ber_next_element( ber, &len, last ) ) {
450                 AV_Sequence     avs, any_end;
451
452 #ifdef LDAP_COMPAT30
453                 if ( ldap_compat == 30 ) {
454                         if ( ber_scanf( ber, "{a}", &valstr ) == LBER_ERROR ) {
455                                 return( LDAP_PROTOCOL_ERROR );
456                         }
457                 } else
458 #endif
459                         if ( ber_scanf( ber, "a", &valstr ) == LBER_ERROR ) {
460                                 return( LDAP_PROTOCOL_ERROR );
461                         }
462
463                 value = ldap_str2AttrV( valstr, type->oa_syntax );
464                 free( valstr );
465
466                 if ( value == NULLAttrV ) {
467                         return( LDAP_INVALID_SYNTAX );
468                 }
469
470                 if ( (avs = avs_comp_new( value )) == NULLAV )
471                         return( LDAP_OPERATIONS_ERROR );
472
473                 switch ( tag ) {
474 #ifdef LDAP_COMPAT20
475                 case OLD_LDAP_SUBSTRING_INITIAL:
476 #endif
477 #ifdef LDAP_COMPAT30
478                 case LDAP_SUBSTRING_INITIAL_30:
479 #endif
480                 case LDAP_SUBSTRING_INITIAL:
481                         Debug( LDAP_DEBUG_ARGS, "  INITIAL\n", 0, 0, 0 );
482                         if ( f->FUITEM.UNSUB.fi_sub_initial != NULLAV
483                             && f->FUITEM.UNSUB.fi_sub_initial->avseq_next
484                             != NULLAV ) {
485                                 return( LDAP_PROTOCOL_ERROR );
486                         }
487                         f->FUITEM.UNSUB.fi_sub_initial = avs;
488                         break;
489
490 #ifdef LDAP_COMPAT20
491                 case OLD_LDAP_SUBSTRING_ANY:
492 #endif
493 #ifdef LDAP_COMPAT30
494                 case LDAP_SUBSTRING_ANY_30:
495 #endif
496                 case LDAP_SUBSTRING_ANY:
497                         Debug( LDAP_DEBUG_ARGS, "  ANY\n", 0, 0, 0 );
498         
499                         if (f->FUITEM.UNSUB.fi_sub_any != NULLAV) {
500                                 any_end->avseq_next = avs;
501                         } else {
502                                 f->FUITEM.UNSUB.fi_sub_any = avs;
503                         }
504
505                         any_end = avs;
506                         break;
507
508 #ifdef LDAP_COMPAT20
509                 case OLD_LDAP_SUBSTRING_FINAL:
510 #endif
511 #ifdef LDAP_COMPAT30
512                 case LDAP_SUBSTRING_FINAL_30:
513 #endif
514                 case LDAP_SUBSTRING_FINAL:
515                         Debug( LDAP_DEBUG_ARGS, "  FINAL\n", 0, 0, 0 );
516                         if ( f->FUITEM.UNSUB.fi_sub_final != NULLAV
517                             && f->FUITEM.UNSUB.fi_sub_final->avseq_next
518                             != NULLAV ) {
519                                 return( LDAP_PROTOCOL_ERROR );
520                         }
521                         f->FUITEM.UNSUB.fi_sub_final = avs;
522                         break;
523
524                 default:
525                         Debug( LDAP_DEBUG_ARGS, "  unknown type\n", tag, 0, 0 );
526                         return( LDAP_PROTOCOL_ERROR );
527                 }
528         }
529
530         Debug( LDAP_DEBUG_TRACE, "end get_substring_filter\n", 0, 0, 0 );
531         return( 0 );
532 }
533
534 void
535 search_result(
536     Sockbuf                     *sb,
537     struct msg                  *m,
538     struct ds_search_result     *sr
539 )
540 {
541         EntryInfo       *e;
542         BerElement      *ber;
543         int             rc;
544
545         Debug( LDAP_DEBUG_TRACE, "search_result\n", 0, 0, 0 );
546
547         ber = NULL;
548
549         if ( ! sr->srr_correlated ) {
550                 Debug( LDAP_DEBUG_ARGS, "correlating results\n", 0, 0, 0 );
551                 correlate_search_results( sr );
552         }
553
554 #ifdef LDAP_CONNECTIONLESS
555         if ( m->m_cldap ) {
556                 if ((ber = der_alloc()) == NULL ) {
557                         send_ldap_msgresult( sb, SEARCHRESTAG, m,
558                             LDAP_OPERATIONS_ERROR, NULL, "der_alloc" );
559                         return;
560                 }
561                 if ( ber_printf( ber, "t{is{", LBER_SEQUENCE, m->m_msgid,
562                     "" ) == -1 ) {
563                         send_ldap_msgresult( sb, SEARCHRESTAG, m,
564                             LDAP_OPERATIONS_ERROR, NULL, "ber_printf" );
565                         return;
566                 }
567         }
568 #endif
569
570         for ( e = sr->CSR_entries; e != NULLENTRYINFO; e = e->ent_next ) {
571                 Debug( LDAP_DEBUG_ARGS, "\tentry:\n", 0, 0, 0 );
572
573 #ifdef LDAP_CONNECTIONLESS
574                 if ( !m->m_cldap )
575 #endif /* LDAP_CONNECTIONLESS */
576
577                         if ( (ber = der_alloc()) == NULL ) {
578                                 send_ldap_msgresult( sb, SEARCHRESTAG, m,
579                                     LDAP_OPERATIONS_ERROR, NULL, "der_alloc" );
580                                 return;
581                         }
582
583 #ifdef LDAP_COMPAT20
584                 if ( version == 1 ) {
585                         if ( ber_printf( ber, "t{it{", OLD_LBER_SEQUENCE,
586                             m->m_msgid, OLD_LDAP_RES_SEARCH_ENTRY ) == -1 ) {
587                                 send_ldap_msgresult( sb, SEARCHRESTAG, m,
588                                     LDAP_OPERATIONS_ERROR, NULL, "ber_printf" );
589                                 return;
590                         }
591                 } else
592 #endif
593 #ifdef LDAP_COMPAT30
594                 if ( ldap_compat == 30 ) {
595                         if ( ber_printf( ber, "{it{{", m->m_msgid,
596                             LDAP_RES_SEARCH_ENTRY ) == -1 ) {
597                                 send_ldap_msgresult( sb, SEARCHRESTAG, m,
598                                     LDAP_OPERATIONS_ERROR, NULL, "ber_printf" );
599                                 return;
600                         }
601                 } else
602 #endif
603 #ifdef LDAP_CONNECTIONLESS
604                 if ( m->m_cldap )
605                         rc = ber_printf( ber, "t{", LDAP_RES_SEARCH_ENTRY );
606                 else
607 #endif /* LDAP_CONNECTIONLESS */
608                         rc = ber_printf( ber, "{it{", m->m_msgid,
609                             LDAP_RES_SEARCH_ENTRY );
610
611                 if ( rc == -1 ) {
612                         send_ldap_msgresult( sb, SEARCHRESTAG, m,
613                             LDAP_OPERATIONS_ERROR, NULL, "ber_printf" );
614                         return;
615                 }
616
617 #ifdef LDAP_CONNECTIONLESS
618                 if (  m->m_cldap )
619                         rc = encode_dn( ber, e->ent_dn, m->m_searchbase );
620 #endif /* LDAP_CONNECTIONLESS */
621                 else
622                         rc = encode_dn( ber, e->ent_dn, NULLDN );
623
624                 if ( rc == -1 ) {
625                         send_ldap_msgresult( sb, SEARCHRESTAG, m,
626                             LDAP_OPERATIONS_ERROR, NULL, "encode_dn" );
627                         return;
628                 }
629
630                 if ( encode_attrs( ber, e->ent_attr ) == -1 ) {
631                         send_ldap_msgresult( sb, SEARCHRESTAG, m,
632                             LDAP_OPERATIONS_ERROR, NULL, "encode_attrs" );
633                         return;
634                 }
635
636 #ifdef LDAP_COMPAT20
637                 if ( version == 1 ) {
638                         if ( ber_printf( ber, "}}" ) == -1 ) {
639                                 send_ldap_msgresult( sb, SEARCHRESTAG, m,
640                                     LDAP_OPERATIONS_ERROR, NULL,
641                                     "ber_printf 2" );
642                                 return;
643                         }
644                 } else
645 #endif
646 #ifdef LDAP_COMPAT30
647                 if ( ldap_compat == 30 ) {
648                         if ( ber_printf( ber, "}}}" ) == -1 ) {
649                                 send_ldap_msgresult( sb, SEARCHRESTAG, m,
650                                     LDAP_OPERATIONS_ERROR, NULL,
651                                     "ber_printf 2" );
652                                 return;
653                         }
654                 } else
655 #endif
656 #ifdef LDAP_CONNECTIONLESS
657                 if ( m->m_cldap )
658                         rc = ber_printf( ber, "}" );
659                 else
660 #endif /* LDAP_CONNECTIONLESS */
661                         rc = ber_printf( ber, "}}" );
662
663                 if ( rc == -1 ) {
664                         send_ldap_msgresult( sb, SEARCHRESTAG, m,
665                             LDAP_OPERATIONS_ERROR, NULL, "ber_printf 2" );
666                         return;
667                 }
668
669 #ifdef LDAP_DEBUG
670                 if ( ldap_debug & LDAP_DEBUG_BER )
671                         trace_ber( 0, ber->ber_ptr - ber->ber_buf,
672                             ber->ber_buf, stderr, 0, 0 );
673 #endif
674
675 #ifdef LDAP_CONNECTIONLESS
676                 if ( !m->m_cldap )
677 #endif
678                         (void) ber_flush( sb, ber, 1 );
679         }
680
681         switch ( sr->CSR_limitproblem ) {
682         case LSR_NOLIMITPROBLEM:
683                 rc = LDAP_SUCCESS;
684                 break;
685         case LSR_TIMELIMITEXCEEDED:
686                 rc = LDAP_TIMELIMIT_EXCEEDED;
687                 break;
688         case LSR_SIZELIMITEXCEEDED:
689         case LSR_ADMINSIZEEXCEEDED:
690                 rc = LDAP_SIZELIMIT_EXCEEDED;
691                 break;
692         }
693
694         Debug( LDAP_DEBUG_ARGS, "\tresult:\n", 0, 0, 0 );
695
696 #ifdef LDAP_CONNECTIONLESS
697         if ( m->m_cldap ) {
698                 if ( ber_printf( ber, "t{ess}}}", SEARCHRESTAG, rc, "", "" )
699                     == -1 ) {
700                         send_ldap_msgresult( sb, SEARCHRESTAG, m,
701                             LDAP_OPERATIONS_ERROR, NULL, "ber_printf" );
702                         return;
703                 }
704                 ber_pvt_sb_udp_set_dst( sb, &m->m_clientaddr );
705
706                 if ( ber_flush( sb, ber, 1 ) != 0 ) {
707                     send_ldap_msgresult( sb, SEARCHRESTAG, m, 
708                         LDAP_RESULTS_TOO_LARGE, NULL, "ber_flush" );
709                 }
710         } else
711 #endif
712         send_ldap_msgresult( sb, SEARCHRESTAG, m, rc, NULL, "" );
713
714         return;
715 }