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