]> git.sur5r.net Git - openldap/blob - servers/slapd/backend.c
a7a6b2c9f4e890e5c0f48998a723cc918e67aedf
[openldap] / servers / slapd / backend.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6 /* backend.c - routines for dealing with back-end databases */
7
8
9 #include "portable.h"
10
11 #include <stdio.h>
12
13 #include <ac/string.h>
14 #include <ac/socket.h>
15
16 #include <sys/stat.h>
17
18 #include "slap.h"
19 #include "lutil.h"
20
21 #ifdef SLAPD_LDAP
22 #include "back-ldap/external.h"
23 #endif
24 #ifdef SLAPD_LDBM
25 #include "back-ldbm/external.h"
26 #endif
27 #ifdef SLAPD_BDB2
28 #include "back-bdb2/external.h"
29 #endif
30 #ifdef SLAPD_PASSWD
31 #include "back-passwd/external.h"
32 #endif
33 #ifdef SLAPD_PERL
34 #include "back-perl/external.h"
35 #endif
36 #ifdef SLAPD_SHELL
37 #include "back-shell/external.h"
38 #endif
39 #ifdef SLAPD_TCL
40 #include "back-tcl/external.h"
41 #endif
42 #ifdef SLAPD_NTDOMAIN
43 #include "back-domain/external.h"
44 #endif
45
46 static BackendInfo binfo[] = {
47 #if defined(SLAPD_LDAP) && !defined(SLAPD_LDAP_DYNAMIC)
48         {"ldap",        ldap_back_initialize},
49 #endif
50 #if defined(SLAPD_LDBM) && !defined(SLAPD_LDBM_DYNAMIC)
51         {"ldbm",        ldbm_back_initialize},
52 #endif
53 #if defined(SLAPD_BDB2) && !defined(SLAPD_BDB2_DYNAMIC)
54         {"bdb2",        bdb2_back_initialize},
55 #endif
56 #if defined(SLAPD_PASSWD) && !defined(SLAPD_PASSWD_DYNAMIC)
57         {"passwd",      passwd_back_initialize},
58 #endif
59 #if defined(SLAPD_PERL) && !defined(SLAPD_PERL_DYNAMIC)
60         {"perl",        perl_back_initialize},
61 #endif
62 #if defined(SLAPD_SHELL) && !defined(SLAPD_SHELL_DYNAMIC)
63         {"shell",       shell_back_initialize},
64 #endif
65 #if defined(SLAPD_TCL) && !defined(SLAPD_TCL_DYNAMIC)
66         {"tcl",         tcl_back_initialize},
67 #endif
68 #if defined(SLAPD_NTDOMAIN) && !defined(SLAPD_NTDOMAIN_DYNAMIC)
69         {"ntdom",       domain_back_initialize},
70 #endif
71         {NULL}
72 };
73
74 int                     nBackendInfo = 0;
75 BackendInfo     *backendInfo = NULL;
76
77 int                     nBackendDB = 0; 
78 BackendDB       *backendDB = NULL;
79
80 int backend_init(void)
81 {
82         int rc = -1;
83
84         if((nBackendInfo != 0) || (backendInfo != NULL)) {
85                 /* already initialized */
86                 Debug( LDAP_DEBUG_ANY,
87                         "backend_init: already initialized.\n", 0, 0, 0 );
88                 return -1;
89         }
90
91         for( ;
92                 binfo[nBackendInfo].bi_type != NULL;
93                 nBackendInfo++ )
94         {
95                 rc = binfo[nBackendInfo].bi_init( &binfo[nBackendInfo] );
96
97                 if(rc != 0) {
98                         Debug( LDAP_DEBUG_ANY,
99                                 "backend_init: initialized for type \"%s\"\n",
100                                         binfo[nBackendInfo].bi_type, 0, 0 );
101
102                         /* destroy those we've already inited */
103                         for( nBackendInfo--;
104                                 nBackendInfo >= 0 ;
105                                 nBackendInfo-- )
106                         { 
107                                 if ( binfo[nBackendInfo].bi_destroy ) {
108                                         binfo[nBackendInfo].bi_destroy(
109                                                 &binfo[nBackendInfo] );
110                                 }
111                         }
112                         return rc;
113                 }
114         }
115
116         if ( nBackendInfo > 0) {
117                 backendInfo = binfo;
118                 return 0;
119         }
120
121 #ifdef SLAPD_MODULES    
122         return 0;
123 #else
124         Debug( LDAP_DEBUG_ANY,
125                 "backend_init: failed\n",
126                 0, 0, 0 );
127
128         return rc;
129 #endif /* SLAPD_MODULES */
130 }
131
132 int backend_add(BackendInfo *aBackendInfo)
133 {
134    int rc = 0;
135
136    if ((rc = aBackendInfo->bi_init(aBackendInfo)) != 0) {
137       Debug( LDAP_DEBUG_ANY,
138              "backend_add: initialization for type \"%s\" failed\n",
139              aBackendInfo->bi_type, 0, 0 );
140       return rc;
141    }
142
143    /* now add the backend type to the Backend Info List */
144    {
145       BackendInfo *newBackendInfo = 0;
146
147       /* if backendInfo == binfo no deallocation of old backendInfo */
148       if (backendInfo == binfo) {
149          newBackendInfo = ch_calloc(nBackendInfo + 1, sizeof(BackendInfo));
150          memcpy(newBackendInfo, backendInfo, sizeof(BackendInfo) * 
151                 nBackendInfo);
152       } else {
153          newBackendInfo = ch_realloc(backendInfo, sizeof(BackendInfo) * 
154                                      (nBackendInfo + 1));
155       }
156       memcpy(&newBackendInfo[nBackendInfo], aBackendInfo, 
157              sizeof(BackendInfo));
158       backendInfo = newBackendInfo;
159       nBackendInfo++;
160
161       return 0;
162    }        
163 }
164
165 int backend_startup(Backend *be)
166 {
167         int i;
168         int rc = 0;
169
170         if( ! ( nBackendDB > 0 ) ) {
171                 /* no databases */
172                 Debug( LDAP_DEBUG_ANY,
173                         "backend_startup: %d databases to startup.\n",
174                         nBackendDB, 0, 0 );
175                 return 1;
176         }
177
178         if(be != NULL) {
179                 /* startup a specific backend database */
180                 Debug( LDAP_DEBUG_TRACE,
181                         "backend_startup: starting database\n",
182                         0, 0, 0 );
183
184                 if ( be->bd_info->bi_open ) {
185                         rc = be->bd_info->bi_open( be->bd_info );
186                 }
187
188                 if(rc != 0) {
189                         Debug( LDAP_DEBUG_ANY,
190                                 "backend_startup: bi_open failed!\n",
191                                 0, 0, 0 );
192                         return rc;
193                 }
194
195                 if ( be->bd_info->bi_db_open ) {
196                         rc = be->bd_info->bi_db_open( be );
197                 }
198
199                 if(rc != 0) {
200                         Debug( LDAP_DEBUG_ANY,
201                                 "backend_startup: bi_db_open failed!\n",
202                                 0, 0, 0 );
203                         return rc;
204                 }
205
206                 return rc;
207         }
208
209         /* open each backend type */
210         for( i = 0; i < nBackendInfo; i++ ) {
211                 if( backendInfo[i].bi_nDB == 0) {
212                         /* no database of this type, don't open */
213                         continue;
214                 }
215
216                 if( backendInfo[i].bi_open ) {
217                         rc = backendInfo[i].bi_open(
218                                 &backendInfo[i] );
219                 }
220
221                 if(rc != 0) {
222                         Debug( LDAP_DEBUG_ANY,
223                                 "backend_startup: bi_open %d failed!\n",
224                                 i, 0, 0 );
225                         return rc;
226                 }
227         }
228
229         /* open each backend database */
230         for( i = 0; i < nBackendDB; i++ ) {
231                 /* append global access controls */
232                 acl_append( &backendDB[i].be_acl, global_acl );
233
234                 if ( backendDB[i].bd_info->bi_db_open ) {
235                         rc = backendDB[i].bd_info->bi_db_open(
236                                 &backendDB[i] );
237                 }
238
239                 if(rc != 0) {
240                         Debug( LDAP_DEBUG_ANY,
241                                 "backend_startup: bi_db_open %d failed!\n",
242                                 i, 0, 0 );
243                         return rc;
244                 }
245         }
246
247         return rc;
248 }
249
250 int backend_num( Backend *be )
251 {
252         int i;
253
254         if( be == NULL ) return -1;
255
256         for( i = 0; i < nBackendDB; i++ ) {
257                 if( be == &backendDB[i] ) return i;
258         }
259         return -1;
260 }
261
262 int backend_shutdown( Backend *be )
263 {
264         int i;
265         int rc = 0;
266
267         if( be != NULL ) {
268                 /* shutdown a specific backend database */
269
270                 if ( be->bd_info->bi_nDB == 0 ) {
271                         /* no database of this type, we never opened it */
272                         return 0;
273                 }
274
275                 if ( be->bd_info->bi_db_close ) {
276                         be->bd_info->bi_db_close( be );
277                 }
278
279                 if( be->bd_info->bi_close ) {
280                         be->bd_info->bi_close( be->bd_info );
281                 }
282
283                 return 0;
284         }
285
286         /* close each backend database */
287         for( i = 0; i < nBackendDB; i++ ) {
288                 if ( backendDB[i].bd_info->bi_db_close ) {
289                         backendDB[i].bd_info->bi_db_close(
290                                 &backendDB[i] );
291                 }
292
293                 if(rc != 0) {
294                         Debug( LDAP_DEBUG_ANY,
295                                 "backend_close: bi_close %s failed!\n",
296                                 backendDB[i].be_type, 0, 0 );
297                 }
298         }
299
300         /* close each backend type */
301         for( i = 0; i < nBackendInfo; i++ ) {
302                 if( backendInfo[i].bi_nDB == 0 ) {
303                         /* no database of this type */
304                         continue;
305                 }
306
307                 if( backendInfo[i].bi_close ) {
308                         backendInfo[i].bi_close(
309                                 &backendInfo[i] );
310                 }
311         }
312
313         return 0;
314 }
315
316 int backend_destroy(void)
317 {
318         int i;
319
320         /* destroy each backend database */
321         for( i = 0; i < nBackendDB; i++ ) {
322                 if ( backendDB[i].bd_info->bi_db_destroy ) {
323                         backendDB[i].bd_info->bi_db_destroy(
324                                 &backendDB[i] );
325                 }
326         }
327
328         /* destroy each backend type */
329         for( i = 0; i < nBackendInfo; i++ ) {
330                 if( backendInfo[i].bi_destroy ) {
331                         backendInfo[i].bi_destroy(
332                                 &backendInfo[i] );
333                 }
334         }
335
336 #ifdef SLAPD_MODULES
337         if (backendInfo != binfo) {
338            free(backendInfo);
339         }
340 #endif /* SLAPD_MODULES */
341
342         nBackendInfo = 0;
343         backendInfo = NULL;
344
345         return 0;
346 }
347
348 BackendInfo* backend_info(const char *type)
349 {
350         int i;
351
352         /* search for the backend type */
353         for( i = 0; i < nBackendInfo; i++ ) {
354                 if( strcasecmp(backendInfo[i].bi_type, type) == 0 ) {
355                         return &backendInfo[i];
356                 }
357         }
358
359         return NULL;
360 }
361
362
363 BackendDB *
364 backend_db_init(
365     const char  *type
366 )
367 {
368         Backend *be;
369         BackendInfo *bi = backend_info(type);
370         int     rc = 0;
371
372         if( bi == NULL ) {
373                 fprintf( stderr, "Unrecognized database type (%s)\n", type );
374                 return NULL;
375         }
376
377         backendDB = (BackendDB *) ch_realloc(
378                         (char *) backendDB,
379                     (nBackendDB + 1) * sizeof(Backend) );
380
381         memset( &backendDB[nbackends], '\0', sizeof(Backend) );
382
383         be = &backends[nbackends++];
384
385         be->bd_info = bi;
386         be->be_sizelimit = defsize;
387         be->be_timelimit = deftime;
388         be->be_dfltaccess = global_default_access;
389
390         /* assign a default depth limit for alias deref */
391         be->be_max_deref_depth = SLAPD_DEFAULT_MAXDEREFDEPTH; 
392
393         be->be_realm = global_realm != NULL
394                 ? ch_strdup( global_realm ) : NULL;
395
396         if(bi->bi_db_init) {
397                 rc = bi->bi_db_init( be );
398         }
399
400         if(rc != 0) {
401                 fprintf( stderr, "database init failed (%s)\n", type );
402                 nbackends--;
403                 return NULL;
404         }
405
406         bi->bi_nDB++;
407         return( be );
408 }
409
410 void
411 be_db_close( void )
412 {
413         int     i;
414
415         for ( i = 0; i < nbackends; i++ ) {
416                 if ( backends[i].bd_info->bi_db_close ) {
417                         (*backends[i].bd_info->bi_db_close)( &backends[i] );
418                 }
419         }
420 }
421
422 Backend *
423 select_backend( const char * dn )
424 {
425         int     i, j, len, dnlen;
426
427         dnlen = strlen( dn );
428         for ( i = 0; i < nbackends; i++ ) {
429                 for ( j = 0; backends[i].be_nsuffix != NULL &&
430                     backends[i].be_nsuffix[j] != NULL; j++ )
431                 {
432                         len = strlen( backends[i].be_nsuffix[j] );
433
434                         if ( len > dnlen ) {
435                                 continue;
436                         }
437
438                         if ( strcmp( backends[i].be_nsuffix[j],
439                             dn + (dnlen - len) ) == 0 ) {
440                                 return( &backends[i] );
441                         }
442                 }
443         }
444
445 #ifdef LDAP_ALLOW_NULL_SEARCH_BASE
446         /* Add greg@greg.rim.or.jp
447          * It's quick hack for cheap client
448          * Some browser offer a NULL base at ldap_search
449          *
450          * Should only be used as a last resort. -Kdz
451          */
452         if(dnlen == 0) {
453                 Debug( LDAP_DEBUG_TRACE,
454                         "select_backend: use default backend\n", 0, 0, 0 );
455                 return( &backends[0] );
456         }
457 #endif /* LDAP_ALLOW_NULL_SEARCH_BASE */
458
459         return( NULL );
460 }
461
462 int
463 be_issuffix(
464     Backend     *be,
465     const char  *suffix
466 )
467 {
468         int     i;
469
470         for ( i = 0; be->be_nsuffix != NULL && be->be_nsuffix[i] != NULL; i++ ) {
471                 if ( strcmp( be->be_nsuffix[i], suffix ) == 0 ) {
472                         return( 1 );
473                 }
474         }
475
476         return( 0 );
477 }
478
479 int
480 be_isroot( Backend *be, const char *ndn )
481 {
482         int rc;
483
484         if ( ndn == NULL || be->be_root_ndn == NULL ) {
485                 return( 0 );
486         }
487
488         rc = strcmp( be->be_root_ndn, ndn ) ? 0 : 1;
489
490         return(rc);
491 }
492
493 char *
494 be_root_dn( Backend *be )
495 {
496         if ( be->be_root_dn == NULL ) {
497                 return( "" );
498         }
499
500         return be->be_root_dn;
501 }
502
503 int
504 be_isroot_pw( Backend *be, const char *ndn, struct berval *cred )
505 {
506         int result;
507
508         if ( ! be_isroot( be, ndn ) ) {
509                 return( 0 );
510         }
511
512 #ifdef SLAPD_CRYPT
513         ldap_pvt_thread_mutex_lock( &crypt_mutex );
514 #endif
515
516         result = lutil_passwd( cred->bv_val, be->be_root_pw, NULL );
517
518 #ifdef SLAPD_CRYPT
519         ldap_pvt_thread_mutex_unlock( &crypt_mutex );
520 #endif
521
522         return result == 0;
523 }
524
525 int
526 be_entry_release_rw( Backend *be, Entry *e, int rw )
527 {
528         if ( be->be_release ) {
529                 /* free and release entry from backend */
530                 return be->be_release( be, e, rw );
531         } else {
532                 /* free entry */
533                 entry_free( e );
534                 return 0;
535         }
536 }
537
538 int
539 backend_unbind(
540         Connection   *conn,
541         Operation    *op
542 )
543 {
544         int     i;
545
546         for ( i = 0; i < nbackends; i++ ) {
547                 if ( backends[i].be_unbind ) {
548                         (*backends[i].be_unbind)( &backends[i], conn, op );
549                 }
550         }
551
552         return 0;
553 }
554
555 int
556 backend_connection_init(
557         Connection   *conn
558 )
559 {
560         int     i;
561
562         for ( i = 0; i < nbackends; i++ ) {
563                 if ( backends[i].be_connection_init ) {
564                         (*backends[i].be_connection_init)( &backends[i], conn);
565                 }
566         }
567
568         return 0;
569 }
570
571 int
572 backend_connection_destroy(
573         Connection   *conn
574 )
575 {
576         int     i;
577
578         for ( i = 0; i < nbackends; i++ ) {
579                 if ( backends[i].be_connection_destroy ) {
580                         (*backends[i].be_connection_destroy)( &backends[i], conn);
581                 }
582         }
583
584         return 0;
585 }
586
587 int 
588 backend_group(
589         Backend *be,
590         Entry   *target,
591         const char      *gr_ndn,
592         const char      *op_ndn,
593         const char      *objectclassValue,
594         const char      *groupattrName
595 )
596 {
597         if (be->be_group)
598                 return( be->be_group(be, target, gr_ndn, op_ndn,
599                         objectclassValue, groupattrName) );
600         else
601                 return(1);
602 }
603
604 #ifdef SLAPD_SCHEMA_DN
605 Attribute *backend_subschemasubentry( Backend *be )
606 {
607         /* should be backend specific */
608         static struct berval ss_val = {
609                 sizeof(SLAPD_SCHEMA_DN)-1,
610                 SLAPD_SCHEMA_DN };
611         static struct berval *ss_vals[2] = { &ss_val, NULL };
612         static Attribute ss_attr = {
613                 "subschemasubentry",
614                 ss_vals,
615                 SYNTAX_DN | SYNTAX_CIS,
616                 NULL
617         };
618
619         return &ss_attr;
620 }
621 #endif