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