1 /*        $NetBSD: backend.c,v 1.3 2021/08/14 16:14:58 christos Exp $ */
2 
3 /* backend.c - routines for dealing with back-end databases */
4 /* $OpenLDAP$ */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6  *
7  * Copyright 1998-2021 The OpenLDAP Foundation.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted only as authorized by the OpenLDAP
12  * Public License.
13  *
14  * A copy of this license is available in the file LICENSE in the
15  * top-level directory of the distribution or, alternatively, at
16  * <http://www.OpenLDAP.org/license.html>.
17  */
18 /* Portions Copyright (c) 1995 Regents of the University of Michigan.
19  * All rights reserved.
20  *
21  * Redistribution and use in source and binary forms are permitted
22  * provided that this notice is preserved and that due credit is given
23  * to the University of Michigan at Ann Arbor. The name of the University
24  * may not be used to endorse or promote products derived from this
25  * software without specific prior written permission. This software
26  * is provided ``as is'' without express or implied warranty.
27  */
28 
29 
30 #include <sys/cdefs.h>
31 __RCSID("$NetBSD: backend.c,v 1.3 2021/08/14 16:14:58 christos Exp $");
32 
33 #include "portable.h"
34 
35 #include <stdio.h>
36 
37 #include <ac/string.h>
38 #include <ac/socket.h>
39 #include <sys/stat.h>
40 
41 #include "slap.h"
42 #include "slap-config.h"
43 #include "lutil.h"
44 #include "lber_pvt.h"
45 
46 /*
47  * If a module is configured as dynamic, its header should not
48  * get included into slapd. While this is a general rule and does
49  * not have much of an effect in UNIX, this rule should be adhered
50  * to for Windows, where dynamic object code should not be implicitly
51  * imported into slapd without appropriate __declspec(dllimport) directives.
52  */
53 
54 int                           nBackendInfo = 0;
55 slap_bi_head backendInfo = LDAP_STAILQ_HEAD_INITIALIZER(backendInfo);
56 
57 int                           nBackendDB = 0;
58 slap_be_head backendDB = LDAP_STAILQ_HEAD_INITIALIZER(backendDB);
59 
60 static int
backend_init_controls(BackendInfo * bi)61 backend_init_controls( BackendInfo *bi )
62 {
63           if ( bi->bi_controls ) {
64                     int       i;
65 
66                     for ( i = 0; bi->bi_controls[ i ]; i++ ) {
67                               int       cid;
68 
69                               if ( slap_find_control_id( bi->bi_controls[ i ], &cid )
70                                                   == LDAP_CONTROL_NOT_FOUND )
71                               {
72                                         if ( !( slapMode & SLAP_TOOL_MODE ) ) {
73                                                   assert( 0 );
74                                         }
75 
76                                         return -1;
77                               }
78 
79                               bi->bi_ctrls[ cid ] = 1;
80                     }
81           }
82 
83           return 0;
84 }
85 
86 extern int syncrepl_monitor_init(void);
87 
backend_init(void)88 int backend_init(void)
89 {
90           int rc = -1;
91           BackendInfo *bi;
92 
93           if((nBackendInfo != 0) || !LDAP_STAILQ_EMPTY(&backendInfo)) {
94                     /* already initialized */
95                     Debug( LDAP_DEBUG_ANY,
96                               "backend_init: already initialized\n" );
97                     return -1;
98           }
99 
100           for( bi=slap_binfo; bi->bi_type != NULL; bi++,nBackendInfo++ ) {
101                     assert( bi->bi_init != 0 );
102 
103                     rc = bi->bi_init( bi );
104 
105                     if(rc != 0) {
106                               Debug( LDAP_DEBUG_ANY,
107                                         "backend_init: initialized for type \"%s\"\n",
108                                         bi->bi_type );
109                               /* destroy those we've already inited */
110                               for( nBackendInfo--;
111                                         nBackendInfo >= 0 ;
112                                         nBackendInfo-- )
113                               {
114                                         if ( slap_binfo[nBackendInfo].bi_destroy ) {
115                                                   slap_binfo[nBackendInfo].bi_destroy(
116                                                             &slap_binfo[nBackendInfo] );
117                                         }
118                               }
119                               return rc;
120                     }
121 
122                     LDAP_STAILQ_INSERT_TAIL(&backendInfo, bi, bi_next);
123           }
124           /* HACK: need schema defined in deterministic order */
125           syncrepl_monitor_init();
126 
127           if ( nBackendInfo > 0) {
128                     return 0;
129           }
130 
131 #ifdef SLAPD_MODULES
132           return 0;
133 #else
134 
135           Debug( LDAP_DEBUG_ANY,
136                     "backend_init: failed\n" );
137 
138           return rc;
139 #endif /* SLAPD_MODULES */
140 }
141 
backend_add(BackendInfo * aBackendInfo)142 int backend_add(BackendInfo *aBackendInfo)
143 {
144           int rc = 0;
145 
146           if ( aBackendInfo->bi_init == NULL ) {
147                     Debug( LDAP_DEBUG_ANY, "backend_add: "
148                               "backend type \"%s\" does not have the (mandatory)init function\n",
149                               aBackendInfo->bi_type );
150                     return -1;
151           }
152 
153           rc = aBackendInfo->bi_init(aBackendInfo);
154           if ( rc != 0) {
155                     Debug( LDAP_DEBUG_ANY,
156                               "backend_add:  initialization for type \"%s\" failed\n",
157                               aBackendInfo->bi_type );
158                     return rc;
159           }
160 
161           (void)backend_init_controls( aBackendInfo );
162 
163           /* now add the backend type to the Backend Info List */
164           LDAP_STAILQ_INSERT_TAIL( &backendInfo, aBackendInfo, bi_next );
165           nBackendInfo++;
166           return 0;
167 }
168 
169 static int
backend_set_controls(BackendDB * be)170 backend_set_controls( BackendDB *be )
171 {
172           BackendInfo         *bi = be->bd_info;
173 
174           /* back-relay takes care of itself; so may do other */
175           if ( overlay_is_over( be ) ) {
176                     bi = ((slap_overinfo *)be->bd_info->bi_private)->oi_orig;
177           }
178 
179           if ( bi->bi_controls ) {
180                     if ( be->be_ctrls[ SLAP_MAX_CIDS ] == 0 ) {
181                               AC_MEMCPY( be->be_ctrls, bi->bi_ctrls,
182                                                   sizeof( be->be_ctrls ) );
183                               be->be_ctrls[ SLAP_MAX_CIDS ] = 1;
184 
185                     } else {
186                               int       i;
187 
188                               for ( i = 0; i < SLAP_MAX_CIDS; i++ ) {
189                                         if ( bi->bi_ctrls[ i ] ) {
190                                                   be->be_ctrls[ i ] = bi->bi_ctrls[ i ];
191                                         }
192                               }
193                     }
194 
195           }
196 
197           return 0;
198 }
199 
200 /* startup a specific backend database */
backend_startup_one(Backend * be,ConfigReply * cr)201 int backend_startup_one(Backend *be, ConfigReply *cr)
202 {
203           int                 rc = 0;
204 
205           assert( be != NULL );
206 
207           be->be_pending_csn_list = (struct be_pcl *)
208                     ch_calloc( 1, sizeof( struct be_pcl ) );
209 
210           LDAP_TAILQ_INIT( be->be_pending_csn_list );
211 
212           Debug( LDAP_DEBUG_TRACE,
213                     "backend_startup_one: starting \"%s\"\n",
214                     be->be_suffix ? be->be_suffix[0].bv_val : "(unknown)" );
215 
216           /* set database controls */
217           (void)backend_set_controls( be );
218 
219 #if 0
220           if ( !BER_BVISEMPTY( &be->be_rootndn )
221                     && select_backend( &be->be_rootndn, 0 ) == be
222                     && BER_BVISNULL( &be->be_rootpw ) )
223           {
224                     /* warning: if rootdn entry is created,
225                      * it can take rootdn privileges;
226                      * set empty rootpw to prevent */
227           }
228 #endif
229 
230           if ( be->bd_info->bi_db_open ) {
231                     rc = be->bd_info->bi_db_open( be, cr );
232                     if ( rc == 0 ) {
233                               (void)backend_set_controls( be );
234                               be->be_flags |= SLAP_DBFLAG_OPEN;
235 
236                     } else {
237                               char *type = be->bd_info->bi_type;
238                               char *suffix = "(null)";
239 
240                               if ( overlay_is_over( be ) ) {
241                                         slap_overinfo       *oi = (slap_overinfo *)be->bd_info->bi_private;
242                                         type = oi->oi_orig->bi_type;
243                               }
244 
245                               if ( be->be_suffix != NULL && !BER_BVISNULL( &be->be_suffix[0] ) ) {
246                                         suffix = be->be_suffix[0].bv_val;
247                               }
248 
249                               Debug( LDAP_DEBUG_ANY,
250                                         "backend_startup_one (type=%s, suffix=\"%s\"): "
251                                         "bi_db_open failed! (%d)\n",
252                                         type, suffix, rc );
253                     }
254           }
255 
256           return rc;
257 }
258 
backend_startup(Backend * be)259 int backend_startup(Backend *be)
260 {
261           int i;
262           int rc = 0;
263           BackendInfo *bi;
264           ConfigReply cr={0, ""};
265 
266           if( ! ( nBackendDB > 0 ) ) {
267                     /* no databases */
268                     Debug( LDAP_DEBUG_ANY,
269                               "backend_startup: %d databases to startup.\n",
270                               nBackendDB );
271                     return 1;
272           }
273 
274           if(be != NULL) {
275                     /* silent noop if disabled */
276                     if ( SLAP_DBDISABLED( be ))
277                               return 0;
278                     if ( be->bd_info->bi_open ) {
279                               rc = be->bd_info->bi_open( be->bd_info );
280                               if ( rc != 0 ) {
281                                         Debug( LDAP_DEBUG_ANY,
282                                                   "backend_startup: bi_open failed!\n" );
283 
284                                         return rc;
285                               }
286                     }
287 
288                     return backend_startup_one( be, &cr );
289           }
290 
291           /* open frontend, if required */
292           if ( frontendDB->bd_info->bi_db_open ) {
293                     rc = frontendDB->bd_info->bi_db_open( frontendDB, &cr );
294                     if ( rc != 0 ) {
295                               Debug( LDAP_DEBUG_ANY,
296                                         "backend_startup: bi_db_open(frontend) failed! (%d)\n",
297                                         rc );
298                               return rc;
299                     }
300                     frontendDB->be_flags |= SLAP_DBFLAG_OPEN;
301           }
302 
303           /* open each backend type */
304           i = -1;
305           LDAP_STAILQ_FOREACH(bi, &backendInfo, bi_next) {
306                     i++;
307                     if( bi->bi_nDB == 0) {
308                               /* no database of this type, don't open */
309                               continue;
310                     }
311 
312                     if( bi->bi_open ) {
313                               rc = bi->bi_open( bi );
314                               if ( rc != 0 ) {
315                                         Debug( LDAP_DEBUG_ANY,
316                                                   "backend_startup: bi_open %d (%s) failed!\n",
317                                                   i, bi->bi_type );
318                                         return rc;
319                               }
320                     }
321 
322                     (void)backend_init_controls( bi );
323           }
324 
325           /* open each backend database */
326           i = -1;
327           LDAP_STAILQ_FOREACH(be, &backendDB, be_next) {
328                     i++;
329                     if ( SLAP_DBDISABLED( be ))
330                               continue;
331                     if ( be->be_suffix == NULL ) {
332                               Debug( LDAP_DEBUG_ANY,
333                                         "backend_startup: warning, database %d (%s) "
334                                         "has no suffix\n",
335                                         i, be->bd_info->bi_type );
336                     }
337 
338                     rc = backend_startup_one( be, &cr );
339 
340                     if ( rc ) return rc;
341           }
342 
343           return rc;
344 }
345 
backend_num(Backend * be)346 int backend_num( Backend *be )
347 {
348           int i = 0;
349           BackendDB *b2;
350 
351           if( be == NULL ) return -1;
352 
353           LDAP_STAILQ_FOREACH( b2, &backendDB, be_next ) {
354                     if( be == b2 ) return i;
355                     i++;
356           }
357           return -1;
358 }
359 
backend_shutdown(Backend * be)360 int backend_shutdown( Backend *be )
361 {
362           int rc = 0;
363           BackendInfo *bi;
364 
365           if( be != NULL ) {
366                     /* shutdown a specific backend database */
367 
368                     if ( be->bd_info->bi_nDB == 0 ) {
369                               /* no database of this type, we never opened it */
370                               return 0;
371                     }
372 
373                     if ( be->bd_info->bi_db_close ) {
374                               rc = be->bd_info->bi_db_close( be, NULL );
375                               be->be_flags &= ~SLAP_DBFLAG_OPEN;
376                               if ( rc ) return rc;
377                     }
378 
379                     if( be->bd_info->bi_close ) {
380                               rc = be->bd_info->bi_close( be->bd_info );
381                               if ( rc ) return rc;
382                     }
383 
384                     return 0;
385           }
386 
387           /* close each backend database */
388           LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) {
389                     if ( SLAP_DBDISABLED( be ))
390                               continue;
391                     if ( be->bd_info->bi_db_close ) {
392                               be->bd_info->bi_db_close( be, NULL );
393                               be->be_flags &= ~SLAP_DBFLAG_OPEN;
394                     }
395 
396                     if(rc != 0) {
397                               Debug( LDAP_DEBUG_ANY,
398                                         "backend_close: bi_db_close %s failed!\n",
399                                         be->be_type );
400                     }
401           }
402 
403           /* close each backend type */
404           LDAP_STAILQ_FOREACH( bi, &backendInfo, bi_next ) {
405                     if( bi->bi_nDB == 0 ) {
406                               /* no database of this type */
407                               continue;
408                     }
409 
410                     if( bi->bi_close ) {
411                               bi->bi_close( bi );
412                     }
413           }
414 
415           /* close frontend, if required */
416           if ( frontendDB->bd_info->bi_db_close ) {
417                     rc = frontendDB->bd_info->bi_db_close ( frontendDB, NULL );
418                     frontendDB->be_flags &= ~SLAP_DBFLAG_OPEN;
419                     if ( rc != 0 ) {
420                               Debug( LDAP_DEBUG_ANY,
421                                         "backend_startup: bi_db_close(frontend) failed! (%d)\n",
422                                         rc );
423                     }
424           }
425 
426           return 0;
427 }
428 
429 /*
430  * This function is supposed to be the exact counterpart
431  * of backend_startup_one(), although this one calls bi_db_destroy()
432  * while backend_startup_one() calls bi_db_open().
433  *
434  * Make sure backend_stopdown_one() destroys resources allocated
435  * by backend_startup_one(); only call backend_destroy_one() when
436  * all stuff in a BackendDB needs to be destroyed
437  */
438 void
backend_stopdown_one(BackendDB * bd)439 backend_stopdown_one( BackendDB *bd )
440 {
441           if ( bd->be_pending_csn_list ) {
442                     struct slap_csn_entry *csne;
443                     csne = LDAP_TAILQ_FIRST( bd->be_pending_csn_list );
444                     while ( csne ) {
445                               struct slap_csn_entry *tmp_csne = csne;
446 
447                               LDAP_TAILQ_REMOVE( bd->be_pending_csn_list, csne, ce_csn_link );
448                               ch_free( csne->ce_csn.bv_val );
449                               csne = LDAP_TAILQ_NEXT( csne, ce_csn_link );
450                               ch_free( tmp_csne );
451                     }
452                     ch_free( bd->be_pending_csn_list );
453           }
454 
455           if ( bd->bd_info->bi_db_destroy ) {
456                     bd->bd_info->bi_db_destroy( bd, NULL );
457           }
458 }
459 
backend_destroy_one(BackendDB * bd,int dynamic)460 void backend_destroy_one( BackendDB *bd, int dynamic )
461 {
462           if ( dynamic ) {
463                     LDAP_STAILQ_REMOVE(&backendDB, bd, BackendDB, be_next );
464           }
465 
466           if ( bd->be_syncinfo ) {
467                     syncinfo_free( bd->be_syncinfo, 1 );
468           }
469 
470           backend_stopdown_one( bd );
471 
472           ber_bvarray_free( bd->be_suffix );
473           ber_bvarray_free( bd->be_nsuffix );
474           if ( !BER_BVISNULL( &bd->be_rootdn ) ) {
475                     free( bd->be_rootdn.bv_val );
476           }
477           if ( !BER_BVISNULL( &bd->be_rootndn ) ) {
478                     free( bd->be_rootndn.bv_val );
479           }
480           if ( !BER_BVISNULL( &bd->be_rootpw ) ) {
481                     free( bd->be_rootpw.bv_val );
482           }
483           acl_destroy( bd->be_acl );
484           limits_destroy( bd->be_limits );
485           if ( bd->be_extra_anlist ) {
486                     anlist_free( bd->be_extra_anlist, 1, NULL );
487           }
488           if ( !BER_BVISNULL( &bd->be_update_ndn ) ) {
489                     ch_free( bd->be_update_ndn.bv_val );
490           }
491           if ( bd->be_update_refs ) {
492                     ber_bvarray_free( bd->be_update_refs );
493           }
494 
495           ldap_pvt_thread_mutex_destroy( &bd->be_pcl_mutex );
496 
497           if ( dynamic ) {
498                     free( bd );
499           }
500 }
501 
backend_destroy(void)502 int backend_destroy(void)
503 {
504           BackendDB *bd;
505           BackendInfo *bi;
506 
507           /* destroy each backend database */
508           while (( bd = LDAP_STAILQ_FIRST(&backendDB))) {
509                     backend_destroy_one( bd, 1 );
510           }
511 
512           /* destroy each backend type */
513           LDAP_STAILQ_FOREACH( bi, &backendInfo, bi_next ) {
514                     if( bi->bi_destroy ) {
515                               bi->bi_destroy( bi );
516                     }
517           }
518 
519           nBackendInfo = 0;
520           LDAP_STAILQ_INIT(&backendInfo);
521 
522           /* destroy frontend database */
523           bd = frontendDB;
524           if ( bd ) {
525                     if ( bd->bd_info->bi_db_destroy ) {
526                               bd->bd_info->bi_db_destroy( bd, NULL );
527                     }
528                     ber_bvarray_free( bd->be_suffix );
529                     ber_bvarray_free( bd->be_nsuffix );
530                     if ( !BER_BVISNULL( &bd->be_rootdn ) ) {
531                               free( bd->be_rootdn.bv_val );
532                     }
533                     if ( !BER_BVISNULL( &bd->be_rootndn ) ) {
534                               free( bd->be_rootndn.bv_val );
535                     }
536                     if ( !BER_BVISNULL( &bd->be_rootpw ) ) {
537                               free( bd->be_rootpw.bv_val );
538                     }
539                     acl_destroy( bd->be_acl );
540                     frontendDB = NULL;
541           }
542 
543           return 0;
544 }
545 
backend_info(const char * type)546 BackendInfo* backend_info(const char *type)
547 {
548           BackendInfo *bi;
549 
550           /* search for the backend type */
551           LDAP_STAILQ_FOREACH(bi,&backendInfo,bi_next) {
552                     if( strcasecmp(bi->bi_type, type) == 0 ) {
553                               return bi;
554                     }
555           }
556 
557           return NULL;
558 }
559 
560 void
backend_db_insert(BackendDB * be,int idx)561 backend_db_insert(
562           BackendDB *be,
563           int idx
564 )
565 {
566           /* If idx < 0, just add to end of list */
567           if ( idx < 0 ) {
568                     LDAP_STAILQ_INSERT_TAIL(&backendDB, be, be_next);
569           } else if ( idx == 0 ) {
570                     LDAP_STAILQ_INSERT_HEAD(&backendDB, be, be_next);
571           } else {
572                     int i;
573                     BackendDB *b2;
574 
575                     b2 = LDAP_STAILQ_FIRST(&backendDB);
576                     idx--;
577                     for (i=0; i<idx; i++) {
578                               b2 = LDAP_STAILQ_NEXT(b2, be_next);
579                     }
580                     LDAP_STAILQ_INSERT_AFTER(&backendDB, b2, be, be_next);
581           }
582 }
583 
584 void
backend_db_move(BackendDB * be,int idx)585 backend_db_move(
586           BackendDB *be,
587           int idx
588 )
589 {
590           LDAP_STAILQ_REMOVE(&backendDB, be, BackendDB, be_next);
591           backend_db_insert(be, idx);
592 }
593 
594 BackendDB *
backend_db_init(const char * type,BackendDB * b0,int idx,ConfigReply * cr)595 backend_db_init(
596     const char      *type,
597           BackendDB *b0,
598           int idx,
599           ConfigReply *cr)
600 {
601           BackendInfo *bi = backend_info(type);
602           BackendDB *be = b0;
603           int       rc = 0;
604 
605           if( bi == NULL ) {
606                     fprintf( stderr, "Unrecognized database type (%s)\n", type );
607                     return NULL;
608           }
609 
610           /* If be is provided, treat it as private. Otherwise allocate
611            * one and add it to the global list.
612            */
613           if ( !be ) {
614                     be = ch_calloc( 1, sizeof(Backend) );
615                     /* Just append */
616                     if ( idx >= nbackends )
617                               idx = -1;
618                     nbackends++;
619                     backend_db_insert( be, idx );
620           }
621 
622           be->bd_info = bi;
623           be->bd_self = be;
624 
625           be->be_def_limit = frontendDB->be_def_limit;
626           be->be_dfltaccess = frontendDB->be_dfltaccess;
627 
628           be->be_restrictops = frontendDB->be_restrictops;
629           be->be_requires = frontendDB->be_requires;
630           be->be_ssf_set = frontendDB->be_ssf_set;
631 
632           ldap_pvt_thread_mutex_init( &be->be_pcl_mutex );
633 
634           /* assign a default depth limit for alias deref */
635           be->be_max_deref_depth = SLAPD_DEFAULT_MAXDEREFDEPTH;
636 
637           if ( bi->bi_db_init ) {
638                     rc = bi->bi_db_init( be, cr );
639           }
640 
641           if ( rc != 0 ) {
642                     fprintf( stderr, "database init failed (%s)\n", type );
643                     /* If we created and linked this be, remove it and free it */
644                     if ( !b0 ) {
645                               LDAP_STAILQ_REMOVE(&backendDB, be, BackendDB, be_next);
646                               ldap_pvt_thread_mutex_destroy( &be->be_pcl_mutex );
647                               ch_free( be );
648                               be = NULL;
649                               nbackends--;
650                     }
651           } else {
652                     if ( !bi->bi_nDB ) {
653                               backend_init_controls( bi );
654                     }
655                     bi->bi_nDB++;
656           }
657           return( be );
658 }
659 
660 void
be_db_close(void)661 be_db_close( void )
662 {
663           BackendDB *be;
664 
665           LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) {
666                     if ( be->bd_info->bi_db_close ) {
667                               be->bd_info->bi_db_close( be, NULL );
668                               be->be_flags &= ~SLAP_DBFLAG_OPEN;
669                     }
670           }
671 
672           if ( frontendDB->bd_info->bi_db_close ) {
673                     frontendDB->bd_info->bi_db_close( frontendDB, NULL );
674           }
675 
676 }
677 
678 Backend *
select_backend(struct berval * dn,int noSubs)679 select_backend(
680           struct berval * dn,
681           int noSubs )
682 {
683           int                 j;
684           ber_len_t len, dnlen = dn->bv_len;
685           Backend             *be;
686 
687           LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) {
688                     if ( be->be_nsuffix == NULL || SLAP_DBHIDDEN( be ) || SLAP_DBDISABLED( be )) {
689                               continue;
690                     }
691 
692                     for ( j = 0; !BER_BVISNULL( &be->be_nsuffix[j] ); j++ )
693                     {
694                               if ( ( SLAP_GLUE_SUBORDINATE( be ) ) && noSubs )
695                               {
696                                         continue;
697                               }
698 
699                               len = be->be_nsuffix[j].bv_len;
700 
701                               if ( len > dnlen ) {
702                                         /* suffix is longer than DN */
703                                         continue;
704                               }
705 
706                               /*
707                                * input DN is normalized, so the separator check
708                                * need not look at escaping
709                                */
710                               if ( len && len < dnlen &&
711                                         !DN_SEPARATOR( dn->bv_val[(dnlen-len)-1] ))
712                               {
713                                         continue;
714                               }
715 
716                               if ( strcmp( be->be_nsuffix[j].bv_val,
717                                         &dn->bv_val[dnlen-len] ) == 0 )
718                               {
719                                         return be;
720                               }
721                     }
722           }
723 
724           return be;
725 }
726 
727 int
be_issuffix(Backend * be,struct berval * bvsuffix)728 be_issuffix(
729     Backend *be,
730     struct berval *bvsuffix )
731 {
732           int       i;
733 
734           if ( be->be_nsuffix == NULL ) {
735                     return 0;
736           }
737 
738           for ( i = 0; !BER_BVISNULL( &be->be_nsuffix[i] ); i++ ) {
739                     if ( bvmatch( &be->be_nsuffix[i], bvsuffix ) ) {
740                               return 1;
741                     }
742           }
743 
744           return 0;
745 }
746 
747 int
be_issubordinate(Backend * be,struct berval * bvsubordinate)748 be_issubordinate(
749     Backend *be,
750     struct berval *bvsubordinate )
751 {
752           int       i;
753 
754           if ( be->be_nsuffix == NULL ) {
755                     return 0;
756           }
757 
758           for ( i = 0; !BER_BVISNULL( &be->be_nsuffix[i] ); i++ ) {
759                     if ( dnIsSuffix( bvsubordinate, &be->be_nsuffix[i] ) ) {
760                               return 1;
761                     }
762           }
763 
764           return 0;
765 }
766 
767 int
be_isroot_dn(Backend * be,struct berval * ndn)768 be_isroot_dn( Backend *be, struct berval *ndn )
769 {
770           if ( BER_BVISEMPTY( ndn ) || BER_BVISEMPTY( &be->be_rootndn ) ) {
771                     return 0;
772           }
773 
774           return dn_match( &be->be_rootndn, ndn );
775 }
776 
777 int
be_slurp_update(Operation * op)778 be_slurp_update( Operation *op )
779 {
780           return ( SLAP_SLURP_SHADOW( op->o_bd ) &&
781                     be_isupdate_dn( op->o_bd, &op->o_ndn ) );
782 }
783 
784 int
be_shadow_update(Operation * op)785 be_shadow_update( Operation *op )
786 {
787           /* This assumes that all internal ops (connid <= -1000) on a syncrepl
788            * database are syncrepl operations.
789            */
790           return ( ( SLAP_SYNC_SHADOW( op->o_bd ) && SLAPD_SYNC_IS_SYNCCONN( op->o_connid ) ) ||
791                     ( SLAP_SHADOW( op->o_bd ) && be_isupdate_dn( op->o_bd, &op->o_ndn ) ) );
792 }
793 
794 int
be_isupdate_dn(Backend * be,struct berval * ndn)795 be_isupdate_dn( Backend *be, struct berval *ndn )
796 {
797           if ( BER_BVISEMPTY( ndn ) || BER_BVISEMPTY( &be->be_update_ndn ) ) {
798                     return 0;
799           }
800 
801           return dn_match( &be->be_update_ndn, ndn );
802 }
803 
804 struct berval *
be_root_dn(Backend * be)805 be_root_dn( Backend *be )
806 {
807           return &be->be_rootdn;
808 }
809 
810 int
be_isroot(Operation * op)811 be_isroot( Operation *op )
812 {
813           return be_isroot_dn( op->o_bd, &op->o_ndn );
814 }
815 
816 int
be_isroot_pw(Operation * op)817 be_isroot_pw( Operation *op )
818 {
819           return be_rootdn_bind( op, NULL ) == LDAP_SUCCESS;
820 }
821 
822 /*
823  * checks if binding as rootdn
824  *
825  * return value:
826  *        SLAP_CB_CONTINUE              if not the rootdn, or if rootpw is null
827  *        LDAP_SUCCESS                            if rootdn & rootpw
828  *        LDAP_INVALID_CREDENTIALS      if rootdn & !rootpw
829  *
830  * if rs != NULL
831  *        if LDAP_SUCCESS, op->orb_edn is set
832  *        if LDAP_INVALID_CREDENTIALS, response is sent to client
833  */
834 int
be_rootdn_bind(Operation * op,SlapReply * rs)835 be_rootdn_bind( Operation *op, SlapReply *rs )
836 {
837           int                 rc;
838 #ifdef SLAPD_SPASSWD
839           void      *old_authctx = NULL;
840 #endif
841 
842           assert( op->o_tag == LDAP_REQ_BIND );
843           assert( op->orb_method == LDAP_AUTH_SIMPLE );
844 
845           if ( !be_isroot_dn( op->o_bd, &op->o_req_ndn ) ) {
846                     return SLAP_CB_CONTINUE;
847           }
848 
849           if ( BER_BVISNULL( &op->o_bd->be_rootpw ) ) {
850                     /* give the database a chance */
851                     return SLAP_CB_CONTINUE;
852           }
853 
854           if ( BER_BVISEMPTY( &op->o_bd->be_rootpw ) ) {
855                     /* rootdn bind explicitly disallowed */
856                     rc = LDAP_INVALID_CREDENTIALS;
857                     if ( rs ) {
858                               goto send_result;
859                     }
860 
861                     return rc;
862           }
863 
864 #ifdef SLAPD_SPASSWD
865           ldap_pvt_thread_pool_setkey( op->o_threadctx, (void *)slap_sasl_bind,
866                     op->o_conn->c_sasl_authctx, 0, &old_authctx, NULL );
867 #endif
868 
869           rc = lutil_passwd( &op->o_bd->be_rootpw, &op->orb_cred, NULL, NULL );
870 
871 #ifdef SLAPD_SPASSWD
872           ldap_pvt_thread_pool_setkey( op->o_threadctx, (void *)slap_sasl_bind,
873                     old_authctx, 0, NULL, NULL );
874 #endif
875 
876           rc = ( rc == 0 ? LDAP_SUCCESS : LDAP_INVALID_CREDENTIALS );
877           if ( rs ) {
878 send_result:;
879                     rs->sr_err = rc;
880 
881                     Debug( LDAP_DEBUG_TRACE, "%s: rootdn=\"%s\" bind%s\n",
882                               op->o_log_prefix, op->o_bd->be_rootdn.bv_val,
883                               rc == LDAP_SUCCESS ? " succeeded" : " failed" );
884 
885                     if ( rc == LDAP_SUCCESS ) {
886                               /* Set to the pretty rootdn */
887                               ber_dupbv( &op->orb_edn, &op->o_bd->be_rootdn );
888 
889                     } else {
890                               send_ldap_result( op, rs );
891                     }
892           }
893 
894           return rc;
895 }
896 
897 /* Inlined in proto-slap.h, sans assertions, when !(USE_RS_ASSERT) */
898 int
899 (slap_bi_op)(
900           BackendInfo *bi,
901           slap_operation_t which,
902           Operation *op,
903           SlapReply *rs )
904 {
905           int rc;
906 #ifndef slap_bi_op
907           void (*rsCheck)( const SlapReply *rs ) =
908                     which < op_aux_operational ? rs_assert_ready : rs_assert_ok;
909 #else
910 #         define rsCheck(rs) ((void) 0)
911 #endif
912           BI_op_func *fn;
913 
914           assert( bi != NULL );
915           assert( (unsigned) which < (unsigned) op_last );
916 
917           fn = (&bi->bi_op_bind)[ which ];
918 
919           assert( op != NULL );
920           assert( rs != NULL );
921           assert( fn != 0 );
922           rsCheck( rs );
923 
924           rc = fn( op, rs );
925 
926 #ifndef slap_bi_op
927           if ( rc != SLAP_CB_CONTINUE && rc != SLAP_CB_BYPASS ) {
928                     int err = rs->sr_err;
929 
930                     if ( 0 )  /* TODO */
931                     if ( err == LDAP_COMPARE_TRUE || err == LDAP_COMPARE_FALSE ) {
932                               assert( which == op_compare );
933                               assert( rc == LDAP_SUCCESS );
934                     }
935 
936                     rsCheck = which < op_extended ? rs_assert_done : rs_assert_ok;
937                     if ( which == op_aux_chk_referrals ) {
938                               if      ( rc == LDAP_SUCCESS  ) rsCheck = rs_assert_ready;
939                               else if ( rc == LDAP_REFERRAL ) rsCheck = rs_assert_done;
940                     } else if ( which == op_bind ) {
941                               if      ( rc == LDAP_SUCCESS  ) rsCheck = rs_assert_ok;
942                     }
943 
944                     /* TODO: Just what is the relation between rc and rs->sr_err? */
945                     if ( rc != err &&
946                               (rc != LDAP_SUCCESS ||
947                                (err != LDAP_COMPARE_TRUE && err != LDAP_COMPARE_FALSE)) )
948                     {
949                               rs->sr_err = rc;
950                               rsCheck( rs );
951                               rs->sr_err = err;
952                     }
953           }
954           rsCheck( rs );
955 #endif
956 
957           return rc;
958 }
959 
960 int
be_entry_release_rw(Operation * op,Entry * e,int rw)961 be_entry_release_rw(
962           Operation *op,
963           Entry *e,
964           int rw )
965 {
966           if ( op->o_bd->be_release ) {
967                     /* free and release entry from backend */
968                     return op->o_bd->be_release( op, e, rw );
969           } else {
970                     /* free entry */
971                     entry_free( e );
972                     return 0;
973           }
974 }
975 
976 int
backend_unbind(Operation * op,SlapReply * rs)977 backend_unbind( Operation *op, SlapReply *rs )
978 {
979           BackendDB *be;
980 
981           LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) {
982                     if ( be->be_unbind ) {
983                               op->o_bd = be;
984                               be->be_unbind( op, rs );
985                     }
986           }
987 
988           return 0;
989 }
990 
991 int
backend_connection_init(Connection * conn)992 backend_connection_init(
993           Connection   *conn )
994 {
995           BackendDB *be;
996 
997           LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) {
998                     if ( be->be_connection_init ) {
999                               be->be_connection_init( be, conn );
1000                     }
1001           }
1002 
1003           return 0;
1004 }
1005 
1006 int
backend_connection_destroy(Connection * conn)1007 backend_connection_destroy(
1008           Connection   *conn )
1009 {
1010           BackendDB *be;
1011 
1012           LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) {
1013                     if ( be->be_connection_destroy ) {
1014                               be->be_connection_destroy( be, conn);
1015                     }
1016           }
1017 
1018           return 0;
1019 }
1020 
1021 int
backend_check_controls(Operation * op,SlapReply * rs)1022 backend_check_controls(
1023           Operation *op,
1024           SlapReply *rs )
1025 {
1026           LDAPControl **ctrls = op->o_ctrls;
1027           rs->sr_err = LDAP_SUCCESS;
1028 
1029           if( ctrls ) {
1030                     for( ; *ctrls != NULL ; ctrls++ ) {
1031                               int cid;
1032 
1033                               switch ( slap_global_control( op, (*ctrls)->ldctl_oid, &cid ) ) {
1034                               case LDAP_CONTROL_NOT_FOUND:
1035                                         /* unrecognized control */
1036                                         if ( (*ctrls)->ldctl_iscritical ) {
1037                                                   /* should not be reachable */
1038                                                   Debug( LDAP_DEBUG_ANY, "backend_check_controls: "
1039                                                             "unrecognized critical control: %s\n",
1040                                                             (*ctrls)->ldctl_oid );
1041                                                   assert( 0 );
1042                                         } else {
1043                                                   Debug( LDAP_DEBUG_TRACE, "backend_check_controls: "
1044                                                             "unrecognized non-critical control: %s\n",
1045                                                             (*ctrls)->ldctl_oid );
1046                                         }
1047                                         break;
1048 
1049                               case LDAP_COMPARE_FALSE:
1050                                         if ( !op->o_bd->be_ctrls[cid] && (*ctrls)->ldctl_iscritical ) {
1051 #ifdef SLAP_CONTROL_X_WHATFAILED
1052                                                   if ( get_whatFailed( op ) ) {
1053                                                             char *oids[ 2 ];
1054                                                             oids[ 0 ] = (*ctrls)->ldctl_oid;
1055                                                             oids[ 1 ] = NULL;
1056                                                             slap_ctrl_whatFailed_add( op, rs, oids );
1057                                                   }
1058 #endif
1059                                                   /* RFC 4511 allows unavailableCriticalExtension to be
1060                                                    * returned when the server is unwilling to perform
1061                                                    * an operation extended by a recognized critical
1062                                                    * control.
1063                                                    */
1064                                                   rs->sr_text = "critical control unavailable in context";
1065                                                   rs->sr_err = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
1066                                                   goto done;
1067                                         }
1068                                         break;
1069 
1070                               case LDAP_COMPARE_TRUE:
1071                                         break;
1072 
1073                               default:
1074                                         /* unreachable */
1075                                         Debug( LDAP_DEBUG_ANY,
1076                                                   "backend_check_controls: unable to check control: %s\n",
1077                                                   (*ctrls)->ldctl_oid );
1078                                         assert( 0 );
1079 
1080                                         rs->sr_text = "unable to check control";
1081                                         rs->sr_err = LDAP_OTHER;
1082                                         goto done;
1083                               }
1084                     }
1085           }
1086 
1087 #if 0 /* temporarily removed */
1088           /* check should be generalized */
1089           if( get_relax(op) && !be_isroot(op)) {
1090                     rs->sr_text = "requires manager authorization";
1091                     rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1092           }
1093 #endif
1094 
1095 done:;
1096           return rs->sr_err;
1097 }
1098 
1099 int
backend_check_restrictions(Operation * op,SlapReply * rs,struct berval * opdata)1100 backend_check_restrictions(
1101           Operation *op,
1102           SlapReply *rs,
1103           struct berval *opdata )
1104 {
1105           slap_mask_t restrictops;
1106           slap_mask_t requires;
1107           slap_mask_t opflag;
1108           slap_mask_t exopflag = 0;
1109           slap_ssf_set_t ssfs, *ssf;
1110           int updateop = 0;
1111           int starttls = 0;
1112           int session = 0;
1113 
1114           restrictops = frontendDB->be_restrictops;
1115           requires = frontendDB->be_requires;
1116           ssfs = frontendDB->be_ssf_set;
1117           ssf = &ssfs;
1118 
1119           if ( op->o_bd ) {
1120                     slap_ssf_t *fssf, *bssf;
1121                     int       rc = SLAP_CB_CONTINUE, i;
1122 
1123                     if ( op->o_bd->be_chk_controls ) {
1124                               rc = ( *op->o_bd->be_chk_controls )( op, rs );
1125                     }
1126 
1127                     if ( rc == SLAP_CB_CONTINUE ) {
1128                               rc = backend_check_controls( op, rs );
1129                     }
1130 
1131                     if ( rc != LDAP_SUCCESS ) {
1132                               return rs->sr_err;
1133                     }
1134 
1135                     restrictops |= op->o_bd->be_restrictops;
1136                     requires |= op->o_bd->be_requires;
1137                     bssf = &op->o_bd->be_ssf_set.sss_ssf;
1138                     fssf = &ssfs.sss_ssf;
1139                     for ( i=0; i < (int)(sizeof(ssfs)/sizeof(slap_ssf_t)); i++ ) {
1140                               if ( bssf[i] ) fssf[i] = bssf[i];
1141                     }
1142           }
1143 
1144           switch( op->o_tag ) {
1145           case LDAP_REQ_ADD:
1146                     opflag = SLAP_RESTRICT_OP_ADD;
1147                     updateop++;
1148                     break;
1149           case LDAP_REQ_BIND:
1150                     opflag = SLAP_RESTRICT_OP_BIND;
1151                     session++;
1152                     break;
1153           case LDAP_REQ_COMPARE:
1154                     opflag = SLAP_RESTRICT_OP_COMPARE;
1155                     break;
1156           case LDAP_REQ_DELETE:
1157                     updateop++;
1158                     opflag = SLAP_RESTRICT_OP_DELETE;
1159                     break;
1160           case LDAP_REQ_EXTENDED:
1161                     opflag = SLAP_RESTRICT_OP_EXTENDED;
1162 
1163                     if( !opdata ) {
1164                               /* treat unspecified as a modify */
1165                               opflag = SLAP_RESTRICT_OP_MODIFY;
1166                               updateop++;
1167                               break;
1168                     }
1169 
1170                     if( bvmatch( opdata, &slap_EXOP_START_TLS ) ) {
1171                               session++;
1172                               starttls++;
1173                               exopflag = SLAP_RESTRICT_EXOP_START_TLS;
1174                               break;
1175                     }
1176 
1177                     if( bvmatch( opdata, &slap_EXOP_WHOAMI ) ) {
1178                               exopflag = SLAP_RESTRICT_EXOP_WHOAMI;
1179                               break;
1180                     }
1181 
1182                     if ( bvmatch( opdata, &slap_EXOP_CANCEL ) ) {
1183                               exopflag = SLAP_RESTRICT_EXOP_CANCEL;
1184                               break;
1185                     }
1186 
1187                     if ( bvmatch( opdata, &slap_EXOP_MODIFY_PASSWD ) ) {
1188                               exopflag = SLAP_RESTRICT_EXOP_MODIFY_PASSWD;
1189                               updateop++;
1190                               break;
1191                     }
1192 
1193                     /* treat everything else as a modify */
1194                     opflag = SLAP_RESTRICT_OP_MODIFY;
1195                     updateop++;
1196                     break;
1197 
1198           case LDAP_REQ_MODIFY:
1199                     updateop++;
1200                     opflag = SLAP_RESTRICT_OP_MODIFY;
1201                     break;
1202           case LDAP_REQ_RENAME:
1203                     updateop++;
1204                     opflag = SLAP_RESTRICT_OP_RENAME;
1205                     break;
1206           case LDAP_REQ_SEARCH:
1207                     opflag = SLAP_RESTRICT_OP_SEARCH;
1208                     break;
1209           case LDAP_REQ_UNBIND:
1210                     session++;
1211                     opflag = 0;
1212                     break;
1213           default:
1214                     rs->sr_text = "restrict operations internal error";
1215                     rs->sr_err = LDAP_OTHER;
1216                     return rs->sr_err;
1217           }
1218 
1219           if ( !starttls ) {
1220                     /* these checks don't apply to StartTLS */
1221 
1222                     rs->sr_err = LDAP_CONFIDENTIALITY_REQUIRED;
1223                     if( op->o_transport_ssf < ssf->sss_transport ) {
1224                               rs->sr_text = op->o_transport_ssf
1225                                         ? "stronger transport confidentiality required"
1226                                         : "transport confidentiality required";
1227                               return rs->sr_err;
1228                     }
1229 
1230                     if( op->o_tls_ssf < ssf->sss_tls ) {
1231                               rs->sr_text = op->o_tls_ssf
1232                                         ? "stronger TLS confidentiality required"
1233                                         : "TLS confidentiality required";
1234                               return rs->sr_err;
1235                     }
1236 
1237 
1238                     if( op->o_tag == LDAP_REQ_BIND && opdata == NULL ) {
1239                               /* simple bind specific check */
1240                               if( op->o_ssf < ssf->sss_simple_bind ) {
1241                                         rs->sr_text = op->o_ssf
1242                                                   ? "stronger confidentiality required"
1243                                                   : "confidentiality required";
1244                                         return rs->sr_err;
1245                               }
1246                     }
1247 
1248                     if( op->o_tag != LDAP_REQ_BIND || opdata == NULL ) {
1249                               /* these checks don't apply to SASL bind */
1250 
1251                               if( op->o_sasl_ssf < ssf->sss_sasl ) {
1252                                         rs->sr_text = op->o_sasl_ssf
1253                                                   ? "stronger SASL confidentiality required"
1254                                                   : "SASL confidentiality required";
1255                                         return rs->sr_err;
1256                               }
1257 
1258                               if( op->o_ssf < ssf->sss_ssf ) {
1259                                         rs->sr_text = op->o_ssf
1260                                                   ? "stronger confidentiality required"
1261                                                   : "confidentiality required";
1262                                         return rs->sr_err;
1263                               }
1264                     }
1265 
1266                     if( updateop ) {
1267                               if( op->o_transport_ssf < ssf->sss_update_transport ) {
1268                                         rs->sr_text = op->o_transport_ssf
1269                                                   ? "stronger transport confidentiality required for update"
1270                                                   : "transport confidentiality required for update";
1271                                         return rs->sr_err;
1272                               }
1273 
1274                               if( op->o_tls_ssf < ssf->sss_update_tls ) {
1275                                         rs->sr_text = op->o_tls_ssf
1276                                                   ? "stronger TLS confidentiality required for update"
1277                                                   : "TLS confidentiality required for update";
1278                                         return rs->sr_err;
1279                               }
1280 
1281                               if( op->o_sasl_ssf < ssf->sss_update_sasl ) {
1282                                         rs->sr_text = op->o_sasl_ssf
1283                                                   ? "stronger SASL confidentiality required for update"
1284                                                   : "SASL confidentiality required for update";
1285                                         return rs->sr_err;
1286                               }
1287 
1288                               if( op->o_ssf < ssf->sss_update_ssf ) {
1289                                         rs->sr_text = op->o_ssf
1290                                                   ? "stronger confidentiality required for update"
1291                                                   : "confidentiality required for update";
1292                                         return rs->sr_err;
1293                               }
1294 
1295                               if( !( global_allows & SLAP_ALLOW_UPDATE_ANON ) &&
1296                                         BER_BVISEMPTY( &op->o_ndn ) )
1297                               {
1298                                         rs->sr_text = "modifications require authentication";
1299                                         rs->sr_err = LDAP_STRONG_AUTH_REQUIRED;
1300                                         return rs->sr_err;
1301                               }
1302 
1303 #ifdef SLAP_X_LISTENER_MOD
1304                               if ( op->o_conn->c_listener &&
1305                                         ! ( op->o_conn->c_listener->sl_perms & ( !BER_BVISEMPTY( &op->o_ndn )
1306                                                   ? (S_IWUSR|S_IWOTH) : S_IWOTH ) ) )
1307                               {
1308                                         /* no "w" mode means readonly */
1309                                         rs->sr_text = "modifications not allowed on this listener";
1310                                         rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1311                                         return rs->sr_err;
1312                               }
1313 #endif /* SLAP_X_LISTENER_MOD */
1314                     }
1315           }
1316 
1317           if ( !session ) {
1318                     /* these checks don't apply to Bind, StartTLS, or Unbind */
1319 
1320                     if( requires & SLAP_REQUIRE_STRONG ) {
1321                               /* should check mechanism */
1322                               if( ( op->o_transport_ssf < ssf->sss_transport
1323                                         && op->o_authtype == LDAP_AUTH_SIMPLE )
1324                                         || BER_BVISEMPTY( &op->o_dn ) )
1325                               {
1326                                         rs->sr_text = "strong(er) authentication required";
1327                                         rs->sr_err = LDAP_STRONG_AUTH_REQUIRED;
1328                                         return rs->sr_err;
1329                               }
1330                     }
1331 
1332                     if( requires & SLAP_REQUIRE_SASL ) {
1333                               if( op->o_authtype != LDAP_AUTH_SASL || BER_BVISEMPTY( &op->o_dn ) ) {
1334                                         rs->sr_text = "SASL authentication required";
1335                                         rs->sr_err = LDAP_STRONG_AUTH_REQUIRED;
1336                                         return rs->sr_err;
1337                               }
1338                     }
1339 
1340                     if( requires & SLAP_REQUIRE_AUTHC ) {
1341                               if( BER_BVISEMPTY( &op->o_dn ) ) {
1342                                         rs->sr_text = "authentication required";
1343                                         rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1344                                         return rs->sr_err;
1345                               }
1346                     }
1347 
1348                     if( requires & SLAP_REQUIRE_BIND ) {
1349                               int version;
1350                               ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
1351                               version = op->o_conn->c_protocol;
1352                               ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
1353 
1354                               if( !version ) {
1355                                         /* no bind has occurred */
1356                                         rs->sr_text = "BIND required";
1357                                         rs->sr_err = LDAP_OPERATIONS_ERROR;
1358                                         return rs->sr_err;
1359                               }
1360                     }
1361 
1362                     if( requires & SLAP_REQUIRE_LDAP_V3 ) {
1363                               if( op->o_protocol < LDAP_VERSION3 ) {
1364                                         /* no bind has occurred */
1365                                         rs->sr_text = "operation restricted to LDAPv3 clients";
1366                                         rs->sr_err = LDAP_OPERATIONS_ERROR;
1367                                         return rs->sr_err;
1368                               }
1369                     }
1370 
1371 #ifdef SLAP_X_LISTENER_MOD
1372                     if ( !starttls && BER_BVISEMPTY( &op->o_dn ) ) {
1373                               if ( op->o_conn->c_listener &&
1374                                         !( op->o_conn->c_listener->sl_perms & S_IXOTH ))
1375                     {
1376                                         /* no "x" mode means bind required */
1377                                         rs->sr_text = "bind required on this listener";
1378                                         rs->sr_err = LDAP_STRONG_AUTH_REQUIRED;
1379                                         return rs->sr_err;
1380                               }
1381                     }
1382 
1383                     if ( !starttls && !updateop ) {
1384                               if ( op->o_conn->c_listener &&
1385                                         !( op->o_conn->c_listener->sl_perms &
1386                                                   ( !BER_BVISEMPTY( &op->o_dn )
1387                                                             ? (S_IRUSR|S_IROTH) : S_IROTH )))
1388                               {
1389                                         /* no "r" mode means no read */
1390                                         rs->sr_text = "read not allowed on this listener";
1391                                         rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1392                                         return rs->sr_err;
1393                               }
1394                     }
1395 #endif /* SLAP_X_LISTENER_MOD */
1396 
1397           }
1398 
1399           if( ( restrictops & opflag )
1400                               || ( exopflag && ( restrictops & exopflag ) )
1401                               || (( restrictops & SLAP_RESTRICT_READONLY ) && updateop )) {
1402                     if( ( restrictops & SLAP_RESTRICT_OP_MASK) == SLAP_RESTRICT_OP_READS ) {
1403                               rs->sr_text = "read operations restricted";
1404                     } else if ( restrictops & exopflag ) {
1405                               rs->sr_text = "extended operation restricted";
1406                     } else {
1407                               rs->sr_text = "operation restricted";
1408                     }
1409                     rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1410                     return rs->sr_err;
1411           }
1412 
1413           rs->sr_err = LDAP_SUCCESS;
1414           return rs->sr_err;
1415 }
1416 
backend_check_referrals(Operation * op,SlapReply * rs)1417 int backend_check_referrals( Operation *op, SlapReply *rs )
1418 {
1419           rs->sr_err = LDAP_SUCCESS;
1420 
1421           if( op->o_bd->be_chk_referrals ) {
1422                     rs->sr_err = op->o_bd->be_chk_referrals( op, rs );
1423 
1424                     if( rs->sr_err != LDAP_SUCCESS && rs->sr_err != LDAP_REFERRAL ) {
1425                               send_ldap_result( op, rs );
1426                     }
1427           }
1428 
1429           return rs->sr_err;
1430 }
1431 
1432 int
be_entry_get_rw(Operation * op,struct berval * ndn,ObjectClass * oc,AttributeDescription * at,int rw,Entry ** e)1433 be_entry_get_rw(
1434           Operation *op,
1435           struct berval *ndn,
1436           ObjectClass *oc,
1437           AttributeDescription *at,
1438           int rw,
1439           Entry **e )
1440 {
1441           *e = NULL;
1442 
1443           if ( op->o_bd == NULL ) {
1444                     return LDAP_NO_SUCH_OBJECT;
1445           }
1446 
1447           if ( op->o_bd->be_fetch ) {
1448                     return op->o_bd->be_fetch( op, ndn, oc, at, rw, e );
1449           }
1450 
1451           return LDAP_UNWILLING_TO_PERFORM;
1452 }
1453 
1454 int
fe_acl_group(Operation * op,Entry * target,struct berval * gr_ndn,struct berval * op_ndn,ObjectClass * group_oc,AttributeDescription * group_at)1455 fe_acl_group(
1456           Operation *op,
1457           Entry     *target,
1458           struct berval *gr_ndn,
1459           struct berval *op_ndn,
1460           ObjectClass *group_oc,
1461           AttributeDescription *group_at )
1462 {
1463           Entry *e;
1464           void *o_priv = op->o_private, *e_priv = NULL;
1465           Attribute *a;
1466           int rc;
1467           GroupAssertion *g;
1468           Backend *be = op->o_bd;
1469           OpExtra             *oex;
1470 
1471           LDAP_SLIST_FOREACH(oex, &op->o_extra, oe_next) {
1472                     if ( oex->oe_key == (void *)backend_group )
1473                               break;
1474           }
1475 
1476           if ( oex && ((OpExtraDB *)oex)->oe_db )
1477                     op->o_bd = ((OpExtraDB *)oex)->oe_db;
1478 
1479           if ( !op->o_bd || !SLAP_DBHIDDEN( op->o_bd ))
1480                     op->o_bd = select_backend( gr_ndn, 0 );
1481 
1482           for ( g = op->o_groups; g; g = g->ga_next ) {
1483                     if ( g->ga_be != op->o_bd || g->ga_oc != group_oc ||
1484                               g->ga_at != group_at || g->ga_len != gr_ndn->bv_len )
1485                     {
1486                               continue;
1487                     }
1488                     if ( strcmp( g->ga_ndn, gr_ndn->bv_val ) == 0 ) {
1489                               break;
1490                     }
1491           }
1492 
1493           if ( g ) {
1494                     rc = g->ga_res;
1495                     goto done;
1496           }
1497 
1498           if ( target && dn_match( &target->e_nname, gr_ndn ) ) {
1499                     e = target;
1500                     rc = 0;
1501 
1502           } else {
1503                     op->o_private = NULL;
1504                     rc = be_entry_get_rw( op, gr_ndn, group_oc, group_at, 0, &e );
1505                     e_priv = op->o_private;
1506                     op->o_private = o_priv;
1507           }
1508 
1509           if ( e ) {
1510                     a = attr_find( e->e_attrs, group_at );
1511                     if ( a ) {
1512                               /* If the attribute is a subtype of labeledURI,
1513                                * treat this as a dynamic group ala groupOfURLs
1514                                */
1515                               if ( is_at_subtype( group_at->ad_type,
1516                                         slap_schema.si_ad_labeledURI->ad_type ) )
1517                               {
1518                                         int i;
1519                                         LDAPURLDesc *ludp;
1520                                         struct berval bv, nbase;
1521                                         Filter *filter;
1522                                         Entry *user = NULL;
1523                                         void *user_priv = NULL;
1524                                         Backend *b2 = op->o_bd;
1525 
1526                                         if ( target && dn_match( &target->e_nname, op_ndn ) ) {
1527                                                   user = target;
1528                                         }
1529 
1530                                         rc = LDAP_COMPARE_FALSE;
1531                                         for ( i = 0; !BER_BVISNULL( &a->a_vals[i] ); i++ ) {
1532                                                   if ( ldap_url_parse( a->a_vals[i].bv_val, &ludp ) !=
1533                                                             LDAP_URL_SUCCESS )
1534                                                   {
1535                                                             continue;
1536                                                   }
1537 
1538                                                   BER_BVZERO( &nbase );
1539 
1540                                                   /* host, attrs and extensions parts must be empty */
1541                                                   if ( ( ludp->lud_host && *ludp->lud_host )
1542                                                             || ludp->lud_attrs
1543                                                             || ludp->lud_exts )
1544                                                   {
1545                                                             goto loopit;
1546                                                   }
1547 
1548                                                   ber_str2bv( ludp->lud_dn, 0, 0, &bv );
1549                                                   if ( dnNormalize( 0, NULL, NULL, &bv, &nbase,
1550                                                             op->o_tmpmemctx ) != LDAP_SUCCESS )
1551                                                   {
1552                                                             goto loopit;
1553                                                   }
1554 
1555                                                   switch ( ludp->lud_scope ) {
1556                                                   case LDAP_SCOPE_BASE:
1557                                                             if ( !dn_match( &nbase, op_ndn ) ) {
1558                                                                       goto loopit;
1559                                                             }
1560                                                             break;
1561                                                   case LDAP_SCOPE_ONELEVEL:
1562                                                             dnParent( op_ndn, &bv );
1563                                                             if ( !dn_match( &nbase, &bv ) ) {
1564                                                                       goto loopit;
1565                                                             }
1566                                                             break;
1567                                                   case LDAP_SCOPE_SUBTREE:
1568                                                             if ( !dnIsSuffix( op_ndn, &nbase ) ) {
1569                                                                       goto loopit;
1570                                                             }
1571                                                             break;
1572                                                   case LDAP_SCOPE_SUBORDINATE:
1573                                                             if ( dn_match( &nbase, op_ndn ) ||
1574                                                                       !dnIsSuffix( op_ndn, &nbase ) )
1575                                                             {
1576                                                                       goto loopit;
1577                                                             }
1578                                                   }
1579 
1580                                                   /* NOTE: this could be NULL
1581                                                    * if no filter is provided,
1582                                                    * or if filter parsing fails.
1583                                                    * In the latter case,
1584                                                    * we should give up. */
1585                                                   if ( ludp->lud_filter != NULL && *ludp->lud_filter != '\0') {
1586                                                             filter = str2filter_x( op, ludp->lud_filter );
1587                                                             if ( filter == NULL ) {
1588                                                                       /* give up... */
1589                                                                       rc = LDAP_OTHER;
1590                                                                       goto loopit;
1591                                                             }
1592 
1593                                                             /* only get user if required
1594                                                              * and not available yet */
1595                                                             if ( user == NULL ) {
1596                                                                       int rc2;
1597 
1598                                                                       op->o_bd = select_backend( op_ndn, 0 );
1599                                                                       op->o_private = NULL;
1600                                                                       rc2 = be_entry_get_rw( op, op_ndn, NULL, NULL, 0, &user );
1601                                                                       user_priv = op->o_private;
1602                                                                       op->o_private = o_priv;
1603                                                                       if ( rc2 != 0 ) {
1604                                                                                 /* give up... */
1605                                                                                 rc = (rc2 == LDAP_NO_SUCH_OBJECT) ? rc2 : LDAP_OTHER;
1606                                                                                 goto loopit;
1607                                                                       }
1608                                                             }
1609 
1610                                                             if ( test_filter( NULL, user, filter ) ==
1611                                                                       LDAP_COMPARE_TRUE )
1612                                                             {
1613                                                                       rc = 0;
1614                                                             }
1615                                                             filter_free_x( op, filter, 1 );
1616                                                   }
1617 loopit:
1618                                                   ldap_free_urldesc( ludp );
1619                                                   if ( !BER_BVISNULL( &nbase ) ) {
1620                                                             op->o_tmpfree( nbase.bv_val, op->o_tmpmemctx );
1621                                                   }
1622                                                   if ( rc != LDAP_COMPARE_FALSE ) {
1623                                                             break;
1624                                                   }
1625                                         }
1626 
1627                                         if ( user != NULL && user != target ) {
1628                                                   op->o_private = user_priv;
1629                                                   be_entry_release_r( op, user );
1630                                                   op->o_private = o_priv;
1631                                         }
1632                                         op->o_bd = b2;
1633 
1634                               } else {
1635                                         rc = attr_valfind( a,
1636                                                   SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
1637                                                   SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
1638                                                   op_ndn, NULL, op->o_tmpmemctx );
1639                                         if ( rc == LDAP_NO_SUCH_ATTRIBUTE ) {
1640                                                   rc = LDAP_COMPARE_FALSE;
1641                                         }
1642                               }
1643 
1644                     } else {
1645                               rc = LDAP_NO_SUCH_ATTRIBUTE;
1646                     }
1647 
1648                     if ( e != target ) {
1649                               op->o_private = e_priv;
1650                               be_entry_release_r( op, e );
1651                               op->o_private = o_priv;
1652                     }
1653 
1654           } else {
1655                     rc = LDAP_NO_SUCH_OBJECT;
1656           }
1657 
1658           if ( op->o_tag != LDAP_REQ_BIND && !op->o_do_not_cache ) {
1659                     g = op->o_tmpalloc( sizeof( GroupAssertion ) + gr_ndn->bv_len,
1660                               op->o_tmpmemctx );
1661                     g->ga_be = op->o_bd;
1662                     g->ga_oc = group_oc;
1663                     g->ga_at = group_at;
1664                     g->ga_res = rc;
1665                     g->ga_len = gr_ndn->bv_len;
1666                     strcpy( g->ga_ndn, gr_ndn->bv_val );
1667                     g->ga_next = op->o_groups;
1668                     op->o_groups = g;
1669           }
1670 
1671 done:
1672           op->o_bd = be;
1673           return rc;
1674 }
1675 
1676 int
backend_group(Operation * op,Entry * target,struct berval * gr_ndn,struct berval * op_ndn,ObjectClass * group_oc,AttributeDescription * group_at)1677 backend_group(
1678           Operation *op,
1679           Entry     *target,
1680           struct berval *gr_ndn,
1681           struct berval *op_ndn,
1682           ObjectClass *group_oc,
1683           AttributeDescription *group_at )
1684 {
1685           int                           rc;
1686           BackendDB *be_orig;
1687           OpExtraDB oex;
1688 
1689           if ( op->o_abandon ) {
1690                     return SLAPD_ABANDON;
1691           }
1692 
1693           oex.oe_db = op->o_bd;
1694           oex.oe.oe_key = (void *)backend_group;
1695           LDAP_SLIST_INSERT_HEAD(&op->o_extra, &oex.oe, oe_next);
1696 
1697           be_orig = op->o_bd;
1698           op->o_bd = frontendDB;
1699           rc = frontendDB->be_group( op, target, gr_ndn,
1700                     op_ndn, group_oc, group_at );
1701           op->o_bd = be_orig;
1702           LDAP_SLIST_REMOVE(&op->o_extra, &oex.oe, OpExtra, oe_next);
1703 
1704           return rc;
1705 }
1706 
1707 int
fe_acl_attribute(Operation * op,Entry * target,struct berval * edn,AttributeDescription * entry_at,BerVarray * vals,slap_access_t access)1708 fe_acl_attribute(
1709           Operation *op,
1710           Entry     *target,
1711           struct berval       *edn,
1712           AttributeDescription *entry_at,
1713           BerVarray *vals,
1714           slap_access_t access )
1715 {
1716           Entry                         *e = NULL;
1717           void                          *o_priv = op->o_private, *e_priv = NULL;
1718           Attribute           *a = NULL;
1719           int                           freeattr = 0, i, j, rc = LDAP_SUCCESS;
1720           AccessControlState  acl_state = ACL_STATE_INIT;
1721           Backend                       *be = op->o_bd;
1722           OpExtra             *oex;
1723 
1724           LDAP_SLIST_FOREACH(oex, &op->o_extra, oe_next) {
1725                     if ( oex->oe_key == (void *)backend_attribute )
1726                               break;
1727           }
1728 
1729           if ( oex && ((OpExtraDB *)oex)->oe_db )
1730                     op->o_bd = ((OpExtraDB *)oex)->oe_db;
1731 
1732           if ( !op->o_bd || !SLAP_DBHIDDEN( op->o_bd ))
1733                     op->o_bd = select_backend( edn, 0 );
1734 
1735           if ( target && dn_match( &target->e_nname, edn ) ) {
1736                     e = target;
1737 
1738           } else {
1739                     op->o_private = NULL;
1740                     rc = be_entry_get_rw( op, edn, NULL, entry_at, 0, &e );
1741                     e_priv = op->o_private;
1742                     op->o_private = o_priv;
1743           }
1744 
1745           if ( e ) {
1746                     if ( entry_at == slap_schema.si_ad_entry || entry_at == slap_schema.si_ad_children ) {
1747                               assert( vals == NULL );
1748 
1749                               rc = LDAP_SUCCESS;
1750                               if ( op->o_conn && access > ACL_NONE &&
1751                                         access_allowed( op, e, entry_at, NULL,
1752                                                             access, &acl_state ) == 0 )
1753                               {
1754                                         rc = LDAP_INSUFFICIENT_ACCESS;
1755                               }
1756                               goto freeit;
1757                     }
1758 
1759                     a = attr_find( e->e_attrs, entry_at );
1760                     if ( a == NULL ) {
1761                               SlapReply rs = { REP_SEARCH };
1762                               AttributeName       anlist[ 2 ];
1763 
1764                               anlist[ 0 ].an_name = entry_at->ad_cname;
1765                               anlist[ 0 ].an_desc = entry_at;
1766                               BER_BVZERO( &anlist[ 1 ].an_name );
1767                               rs.sr_attrs = anlist;
1768 
1769                               /* NOTE: backend_operational() is also called
1770                                * when returning results, so it's supposed
1771                                * to do no harm to entries */
1772                               rs.sr_entry = e;
1773                               rc = backend_operational( op, &rs );
1774 
1775                               if ( rc == LDAP_SUCCESS ) {
1776                                         if ( rs.sr_operational_attrs ) {
1777                                                   freeattr = 1;
1778                                                   a = rs.sr_operational_attrs;
1779 
1780                                         } else {
1781                                                   rc = LDAP_NO_SUCH_ATTRIBUTE;
1782                                         }
1783                               }
1784                     }
1785 
1786                     if ( a ) {
1787                               BerVarray v;
1788 
1789                               if ( op->o_conn && access > ACL_NONE &&
1790                                         access_allowed( op, e, entry_at, NULL,
1791                                                             access, &acl_state ) == 0 )
1792                               {
1793                                         rc = LDAP_INSUFFICIENT_ACCESS;
1794                                         goto freeit;
1795                               }
1796 
1797                               i = a->a_numvals;
1798                               v = op->o_tmpalloc( sizeof(struct berval) * ( i + 1 ),
1799                                         op->o_tmpmemctx );
1800                               for ( i = 0, j = 0; !BER_BVISNULL( &a->a_vals[i] ); i++ )
1801                               {
1802                                         if ( op->o_conn && access > ACL_NONE &&
1803                                                   access_allowed( op, e, entry_at,
1804                                                                       &a->a_nvals[i],
1805                                                                       access,
1806                                                                       &acl_state ) == 0 )
1807                                         {
1808                                                   continue;
1809                                         }
1810                                         ber_dupbv_x( &v[j], &a->a_nvals[i],
1811                                                             op->o_tmpmemctx );
1812                                         if ( !BER_BVISNULL( &v[j] ) ) {
1813                                                   j++;
1814                                         }
1815                               }
1816                               if ( j == 0 ) {
1817                                         op->o_tmpfree( v, op->o_tmpmemctx );
1818                                         *vals = NULL;
1819                                         rc = LDAP_INSUFFICIENT_ACCESS;
1820 
1821                               } else {
1822                                         BER_BVZERO( &v[j] );
1823                                         *vals = v;
1824                                         rc = LDAP_SUCCESS;
1825                               }
1826                     }
1827 freeit:             if ( e != target ) {
1828                               op->o_private = e_priv;
1829                               be_entry_release_r( op, e );
1830                               op->o_private = o_priv;
1831                     }
1832                     if ( freeattr ) {
1833                               attr_free( a );
1834                     }
1835           }
1836 
1837           op->o_bd = be;
1838           return rc;
1839 }
1840 
1841 int
backend_attribute(Operation * op,Entry * target,struct berval * edn,AttributeDescription * entry_at,BerVarray * vals,slap_access_t access)1842 backend_attribute(
1843           Operation *op,
1844           Entry     *target,
1845           struct berval       *edn,
1846           AttributeDescription *entry_at,
1847           BerVarray *vals,
1848           slap_access_t access )
1849 {
1850           int                           rc;
1851           BackendDB *be_orig;
1852           OpExtraDB oex;
1853 
1854           oex.oe_db = op->o_bd;
1855           oex.oe.oe_key = (void *)backend_attribute;
1856           LDAP_SLIST_INSERT_HEAD(&op->o_extra, &oex.oe, oe_next);
1857 
1858           be_orig = op->o_bd;
1859           op->o_bd = frontendDB;
1860           rc = frontendDB->be_attribute( op, target, edn,
1861                     entry_at, vals, access );
1862           op->o_bd = be_orig;
1863           LDAP_SLIST_REMOVE(&op->o_extra, &oex.oe, OpExtra, oe_next);
1864 
1865           return rc;
1866 }
1867 
1868 int
backend_access(Operation * op,Entry * target,struct berval * edn,AttributeDescription * entry_at,struct berval * nval,slap_access_t access,slap_mask_t * mask)1869 backend_access(
1870           Operation           *op,
1871           Entry                         *target,
1872           struct berval                 *edn,
1873           AttributeDescription          *entry_at,
1874           struct berval                 *nval,
1875           slap_access_t                 access,
1876           slap_mask_t                   *mask )
1877 {
1878           Entry               *e = NULL;
1879           void                *o_priv, *e_priv = NULL;
1880           int                 rc = LDAP_INSUFFICIENT_ACCESS;
1881           Backend             *be;
1882 
1883           /* pedantic */
1884           assert( op != NULL );
1885           assert( op->o_conn != NULL );
1886           assert( edn != NULL );
1887           assert( access > ACL_NONE );
1888 
1889           be = op->o_bd;
1890           o_priv = op->o_private;
1891 
1892           if ( !op->o_bd ) {
1893                     op->o_bd = select_backend( edn, 0 );
1894           }
1895 
1896           if ( target && dn_match( &target->e_nname, edn ) ) {
1897                     e = target;
1898 
1899           } else {
1900                     op->o_private = NULL;
1901                     rc = be_entry_get_rw( op, edn, NULL, entry_at, 0, &e );
1902                     e_priv = op->o_private;
1903                     op->o_private = o_priv;
1904           }
1905 
1906           if ( e ) {
1907                     Attribute *a = NULL;
1908                     int                 freeattr = 0;
1909 
1910                     if ( entry_at == NULL ) {
1911                               entry_at = slap_schema.si_ad_entry;
1912                     }
1913 
1914                     if ( entry_at == slap_schema.si_ad_entry || entry_at == slap_schema.si_ad_children )
1915                     {
1916                               if ( access_allowed_mask( op, e, entry_at,
1917                                                   NULL, access, NULL, mask ) == 0 )
1918                               {
1919                                         rc = LDAP_INSUFFICIENT_ACCESS;
1920 
1921                               } else {
1922                                         rc = LDAP_SUCCESS;
1923                               }
1924 
1925                     } else {
1926                               a = attr_find( e->e_attrs, entry_at );
1927                               if ( a == NULL ) {
1928                                         SlapReply rs = { REP_SEARCH };
1929                                         AttributeName       anlist[ 2 ];
1930 
1931                                         anlist[ 0 ].an_name = entry_at->ad_cname;
1932                                         anlist[ 0 ].an_desc = entry_at;
1933                                         BER_BVZERO( &anlist[ 1 ].an_name );
1934                                         rs.sr_attrs = anlist;
1935 
1936                                         rs.sr_attr_flags = slap_attr_flags( rs.sr_attrs );
1937 
1938                                         /* NOTE: backend_operational() is also called
1939                                          * when returning results, so it's supposed
1940                                          * to do no harm to entries */
1941                                         rs.sr_entry = e;
1942                                         rc = backend_operational( op, &rs );
1943 
1944                                         if ( rc == LDAP_SUCCESS ) {
1945                                                   if ( rs.sr_operational_attrs ) {
1946                                                             freeattr = 1;
1947                                                             a = rs.sr_operational_attrs;
1948 
1949                                                   } else {
1950                                                             rc = LDAP_NO_SUCH_OBJECT;
1951                                                   }
1952                                         }
1953                               }
1954 
1955                               if ( a ) {
1956                                         if ( access_allowed_mask( op, e, entry_at,
1957                                                             nval, access, NULL, mask ) == 0 )
1958                                         {
1959                                                   rc = LDAP_INSUFFICIENT_ACCESS;
1960                                                   goto freeit;
1961                                         }
1962                                         rc = LDAP_SUCCESS;
1963                               }
1964                     }
1965 freeit:             if ( e != target ) {
1966                               op->o_private = e_priv;
1967                               be_entry_release_r( op, e );
1968                               op->o_private = o_priv;
1969                     }
1970                     if ( freeattr ) {
1971                               attr_free( a );
1972                     }
1973           }
1974 
1975           op->o_bd = be;
1976           return rc;
1977 }
1978 
1979 int
fe_aux_operational(Operation * op,SlapReply * rs)1980 fe_aux_operational(
1981           Operation *op,
1982           SlapReply *rs )
1983 {
1984           Attribute           **ap;
1985           int                           rc = LDAP_SUCCESS;
1986           BackendDB           *be_orig = op->o_bd;
1987           OpExtra             *oex;
1988 
1989           LDAP_SLIST_FOREACH(oex, &op->o_extra, oe_next) {
1990                     if ( oex->oe_key == (void *)backend_operational )
1991                               break;
1992           }
1993 
1994           for ( ap = &rs->sr_operational_attrs; *ap; ap = &(*ap)->a_next )
1995                     /* just count them */ ;
1996 
1997           /*
1998            * If operational attributes (allegedly) are required,
1999            * and the backend supports specific operational attributes,
2000            * add them to the attribute list
2001            */
2002           if ( !( rs->sr_flags & REP_NO_ENTRYDN )
2003                     && ( SLAP_OPATTRS( rs->sr_attr_flags ) || ( rs->sr_attrs &&
2004                     ad_inlist( slap_schema.si_ad_entryDN, rs->sr_attrs ) ) ) )
2005           {
2006                     *ap = slap_operational_entryDN( rs->sr_entry );
2007                     ap = &(*ap)->a_next;
2008           }
2009 
2010           if ( !( rs->sr_flags & REP_NO_SUBSCHEMA)
2011                     && ( SLAP_OPATTRS( rs->sr_attr_flags ) || ( rs->sr_attrs &&
2012                     ad_inlist( slap_schema.si_ad_subschemaSubentry, rs->sr_attrs ) ) ) )
2013           {
2014                     *ap = slap_operational_subschemaSubentry( op->o_bd );
2015                     ap = &(*ap)->a_next;
2016           }
2017 
2018           /* Let the overlays have a chance at this */
2019           if ( oex && ((OpExtraDB *)oex)->oe_db )
2020                     op->o_bd = ((OpExtraDB *)oex)->oe_db;
2021 
2022           if ( !op->o_bd || !SLAP_DBHIDDEN( op->o_bd ))
2023                     op->o_bd = select_backend( &op->o_req_ndn, 0 );
2024 
2025           if ( op->o_bd != NULL && !be_match( op->o_bd, frontendDB ) &&
2026                     ( SLAP_OPATTRS( rs->sr_attr_flags ) || rs->sr_attrs ) &&
2027                     op->o_bd->be_operational != NULL )
2028           {
2029                     rc = op->o_bd->be_operational( op, rs );
2030           }
2031           op->o_bd = be_orig;
2032 
2033           return rc;
2034 }
2035 
backend_operational(Operation * op,SlapReply * rs)2036 int backend_operational( Operation *op, SlapReply *rs )
2037 {
2038           int rc;
2039           BackendDB *be_orig;
2040           OpExtraDB oex;
2041 
2042           oex.oe_db = op->o_bd;
2043           oex.oe.oe_key = (void *)backend_operational;
2044           LDAP_SLIST_INSERT_HEAD(&op->o_extra, &oex.oe, oe_next);
2045 
2046           /* Moved this into the frontend so global overlays are called */
2047 
2048           be_orig = op->o_bd;
2049           op->o_bd = frontendDB;
2050           rc = frontendDB->be_operational( op, rs );
2051           op->o_bd = be_orig;
2052           LDAP_SLIST_REMOVE(&op->o_extra, &oex.oe, OpExtra, oe_next);
2053 
2054           return rc;
2055 }
2056 
2057 /* helper that calls the bi_tool_entry_first_x() variant with default args;
2058  * use to initialize a backend's bi_tool_entry_first() when appropriate
2059  */
2060 ID
backend_tool_entry_first(BackendDB * be)2061 backend_tool_entry_first( BackendDB *be )
2062 {
2063           return be->bd_info->bi_tool_entry_first_x( be,
2064                     NULL, LDAP_SCOPE_DEFAULT, NULL );
2065 }
2066