]> git.sur5r.net Git - openldap/blob - servers/slapd/backend.c
Update of back-bdb2 to KDZ's new entry lock schema.
[openldap] / servers / slapd / backend.c
1 /* backend.c - routines for dealing with back-end databases */
2
3
4 #include "portable.h"
5
6 #include <stdio.h>
7
8 #include <ac/string.h>
9 #include <ac/socket.h>
10
11 #include <sys/stat.h>
12
13 #include "slap.h"
14
15 #ifdef SLAPD_LDBM
16 #include "back-ldbm/external.h"
17 #endif
18 #ifdef SLAPD_BDB2
19 #include "back-bdb2/external.h"
20 #endif
21 #ifdef SLAPD_PASSWD
22 #include "back-passwd/external.h"
23 #endif
24 #ifdef SLAPD_PERL
25 #include "back-perl/external.h"
26 #endif
27 #ifdef SLAPD_SHELL
28 #include "back-shell/external.h"
29 #endif
30
31 static BackendInfo binfo[] = {
32 #ifdef SLAPD_LDBM
33         {"ldbm",        ldbm_back_initialize},
34 #endif
35 #ifdef SLAPD_BDB2
36         {"bdb2",        bdb2_back_initialize},
37 #endif
38 #ifdef SLAPD_PASSWD
39         {"passwd",      passwd_back_initialize},
40 #endif
41 #ifdef SLAPD_PERL
42         {"perl",        perl_back_initialize},
43 #endif
44 #ifdef SLAPD_SHELL
45         {"shell",       shell_back_initialize},
46 #endif
47         {NULL}
48 };
49
50 int                     nBackendInfo = 0;
51 BackendInfo     *backendInfo = NULL;
52
53 int                     nBackendDB = 0; 
54 BackendDB       *backendDB = NULL;
55
56 int backend_init(void)
57 {
58         int rc = -1;
59
60         if((nBackendInfo != 0) || (backendInfo != NULL)) {
61                 /* already initialized */
62                 Debug( LDAP_DEBUG_ANY,
63                         "backend_init: already initialized.\n", 0, 0, 0 );
64                 return -1;
65         }
66
67         for( ;
68                 binfo[nBackendInfo].bi_type !=  NULL;
69                 nBackendInfo++ )
70         {
71                 rc = binfo[nBackendInfo].bi_init(
72                         &binfo[nBackendInfo] );
73
74                 if(rc != 0) {
75                         Debug( LDAP_DEBUG_ANY,
76                                 "backend_init: initialized for type \"%s\"\n",
77                                         binfo[nBackendInfo].bi_type, 0, 0 );
78
79                         /* destroy those we've already inited */
80                         for( nBackendInfo--;
81                                 nBackendInfo >= 0 ;
82                                 nBackendInfo-- )
83                         { 
84                                 if ( binfo[nBackendInfo].bi_destroy ) {
85                                         binfo[nBackendInfo].bi_destroy(
86                                                 &binfo[nBackendInfo] );
87                                 }
88                         }
89                         return rc;
90                 }
91         }
92
93         if ( nBackendInfo > 0) {
94                 backendInfo = binfo;
95                 return 0;
96         }
97
98         Debug( LDAP_DEBUG_ANY,
99                 "backend_init: failed\n",
100                 0, 0, 0 );
101
102         return rc;
103 }
104
105 int backend_startup(int n)
106 {
107         int i;
108         int rc = 0;
109
110         if( ! ( nBackendDB > 0 ) ) {
111                 /* no databases */
112                 Debug( LDAP_DEBUG_ANY,
113                         "backend_startup: %d databases to startup.\n",
114                         nBackendDB, 0, 0 );
115                 return 1;
116         }
117
118         if(n >= 0) {
119                 /* startup a specific backend database */
120                 Debug( LDAP_DEBUG_TRACE,
121                         "backend_startup: starting database %d\n",
122                         n, 0, 0 );
123
124                 /* make sure, n does not exceed the number of backend databases */
125                 if ( n >= nbackends ) {
126
127                         Debug( LDAP_DEBUG_ANY,
128                                 "backend_startup: database number %d exceeding maximum (%d)\n",
129                                 n, nbackends, 0 );
130                         return 1;
131                 }
132
133                 if ( backendDB[n].bd_info->bi_open ) {
134                         rc = backendDB[n].bd_info->bi_open(
135                                 backendDB[n].bd_info );
136                 }
137
138                 if(rc != 0) {
139                         Debug( LDAP_DEBUG_ANY,
140                                 "backend_startup: bi_open failed!\n",
141                                 0, 0, 0 );
142                         return rc;
143                 }
144
145                 if ( backendDB[n].bd_info->bi_db_open ) {
146                         rc = backendDB[n].bd_info->bi_db_open(
147                                 &backendDB[n] );
148                 }
149
150                 if(rc != 0) {
151                         Debug( LDAP_DEBUG_ANY,
152                                 "backend_startup: bi_db_open failed!\n",
153                                 0, 0, 0 );
154                         return rc;
155                 }
156
157                 return rc;
158         }
159
160         /* open each backend type */
161         for( i = 0; i < nBackendInfo; i++ ) {
162                 if( backendInfo[i].bi_nDB == 0) {
163                         /* no database of this type, don't open */
164                         continue;
165                 }
166
167                 if( backendInfo[i].bi_open ) {
168                         rc = backendInfo[i].bi_open(
169                                 &backendInfo[i] );
170                 }
171
172                 if(rc != 0) {
173                         Debug( LDAP_DEBUG_ANY,
174                                 "backend_startup: bi_open %d failed!\n",
175                                 i, 0, 0 );
176                         return rc;
177                 }
178         }
179
180         /* open each backend database */
181         for( i = 0; i < nBackendDB; i++ ) {
182                 if ( backendDB[i].bd_info->bi_db_open ) {
183                         rc = backendDB[i].bd_info->bi_db_open(
184                                 &backendDB[i] );
185                 }
186
187                 if(rc != 0) {
188                         Debug( LDAP_DEBUG_ANY,
189                                 "backend_startup: bi_db_open %d failed!\n",
190                                 i, 0, 0 );
191                         return rc;
192                 }
193         }
194
195         return rc;
196 }
197
198 int backend_shutdown(int n)
199 {
200         int i;
201         int rc = 0;
202
203         if(n >= 0) {
204                 /* shutdown a specific backend database */
205
206                 /* make sure, n does not exceed the number of backend databases */
207                 if ( n >= nbackends ) {
208
209                         Debug( LDAP_DEBUG_ANY,
210                                 "backend_startup: database number %d exceeding maximum (%d)\n",
211                                 n, nbackends, 0 );
212                         return 1;
213                 }
214
215                 if ( backendDB[n].bd_info->bi_nDB == 0 ) {
216                         /* no database of this type, we never opened it */
217                         return 0;
218                 }
219
220                 if ( backendDB[n].bd_info->bi_db_close ) {
221                         backendDB[n].bd_info->bi_db_close(
222                                 &backendDB[n] );
223                 }
224
225                 if( backendDB[n].bd_info->bi_close ) {
226                         backendDB[n].bd_info->bi_close(
227                                 backendDB[n].bd_info );
228                 }
229
230                 return 0;
231         }
232
233         /* close each backend database */
234         for( i = 0; i < nBackendDB; i++ ) {
235                 BackendInfo  *bi;
236
237                 if ( backendDB[i].bd_info->bi_db_close ) {
238                         backendDB[i].bd_info->bi_db_close(
239                                 &backendDB[i] );
240                 }
241
242                 if(rc != 0) {
243                         Debug( LDAP_DEBUG_ANY,
244                                 "backend_close: bi_close %s failed!\n",
245                                 bi->bi_type, 0, 0 );
246                 }
247         }
248
249         /* close each backend type */
250         for( i = 0; i < nBackendInfo; i++ ) {
251                 if( backendInfo[i].bi_nDB == 0 ) {
252                         /* no database of this type */
253                         continue;
254                 }
255
256                 if( backendInfo[i].bi_close ) {
257                         backendInfo[i].bi_close(
258                                 &backendInfo[i] );
259                 }
260         }
261
262         return 0;
263 }
264
265 int backend_destroy(void)
266 {
267         int i;
268
269         /* destroy each backend database */
270         for( i = 0; i < nBackendDB; i++ ) {
271                 if ( backendDB[i].bd_info->bi_db_destroy ) {
272                         backendDB[i].bd_info->bi_db_destroy(
273                                 &backendDB[i] );
274                 }
275         }
276
277         /* destroy each backend type */
278         for( i = 0; i < nBackendInfo; i++ ) {
279                 if( backendInfo[i].bi_destroy ) {
280                         backendInfo[i].bi_destroy(
281                                 &backendInfo[i] );
282                 }
283         }
284
285         return 0;
286 }
287
288 BackendInfo* backend_info(char *type)
289 {
290         int i;
291
292         /* search for the backend type */
293         for( i = 0; i < nBackendInfo; i++ ) {
294                 if( strcasecmp(backendInfo[i].bi_type, type) == 0 ) {
295                         return &backendInfo[i];
296                 }
297         }
298
299         return NULL;
300 }
301
302
303 BackendDB *
304 backend_db_init(
305     char        *type
306 )
307 {
308         Backend *be;
309         BackendInfo *bi = backend_info(type);
310         int     rc = 0;
311
312         if( bi == NULL ) {
313                 fprintf( stderr, "Unrecognized database type (%s)\n", type );
314                 return NULL;
315         }
316
317         backendDB = (BackendDB *) ch_realloc(
318                         (char *) backendDB,
319                     (nBackendDB + 1) * sizeof(Backend) );
320
321         memset( &backendDB[nbackends], '\0', sizeof(Backend) );
322
323         be = &backends[nbackends++];
324
325         be->bd_info = bi;
326         be->be_sizelimit = defsize;
327         be->be_timelimit = deftime;
328
329         if(bi->bi_db_init) {
330                 rc = bi->bi_db_init( be );
331         }
332
333         if(rc != 0) {
334                 fprintf( stderr, "database init failed (%s)\n", type );
335                 nbackends--;
336                 return NULL;
337         }
338
339         bi->bi_nDB++;
340         return( be );
341 }
342
343 void
344 be_db_close( void )
345 {
346         int     i;
347
348         for ( i = 0; i < nbackends; i++ ) {
349                 if ( backends[i].bd_info->bi_db_close != NULL ) {
350                         (*backends[i].bd_info->bi_db_close)( &backends[i] );
351                 }
352         }
353 }
354
355 Backend *
356 select_backend( char * dn )
357 {
358         int     i, j, len, dnlen;
359
360         dnlen = strlen( dn );
361         for ( i = 0; i < nbackends; i++ ) {
362                 for ( j = 0; backends[i].be_suffix != NULL &&
363                     backends[i].be_suffix[j] != NULL; j++ )
364                 {
365                         len = strlen( backends[i].be_suffix[j] );
366
367                         if ( len > dnlen ) {
368                                 continue;
369                         }
370
371                         if ( strcmp( backends[i].be_suffix[j],
372                             dn + (dnlen - len) ) == 0 ) {
373                                 return( &backends[i] );
374                         }
375                 }
376         }
377
378         /* if no proper suffix could be found then check for aliases */
379         for ( i = 0; i < nbackends; i++ ) {
380                 for ( j = 0; 
381                       backends[i].be_suffixAlias != NULL && 
382                       backends[i].be_suffixAlias[j] != NULL; 
383                       j += 2 )
384                 {
385                         len = strlen( backends[i].be_suffixAlias[j] );
386
387                         if ( len > dnlen ) {
388                                 continue;
389                         }
390
391                         if ( strcmp( backends[i].be_suffixAlias[j],
392                             dn + (dnlen - len) ) == 0 ) {
393                                 return( &backends[i] );
394                         }
395                 }
396         }
397
398 #ifdef LDAP_ALLOW_NULL_SEARCH_BASE
399         /* Add greg@greg.rim.or.jp
400          * It's quick hack for cheap client
401          * Some browser offer a NULL base at ldap_search
402          *
403          * Should only be used as a last resort. -Kdz
404          */
405         if(dnlen == 0) {
406                 Debug( LDAP_DEBUG_TRACE,
407                         "select_backend: use default backend\n", 0, 0, 0 );
408                 return( &backends[0] );
409         }
410 #endif /* LDAP_ALLOW_NULL_SEARCH_BASE */
411
412         return( NULL );
413 }
414
415 int
416 be_issuffix(
417     Backend     *be,
418     char        *suffix
419 )
420 {
421         int     i;
422
423         for ( i = 0; be->be_suffix != NULL && be->be_suffix[i] != NULL; i++ ) {
424                 if ( strcmp( be->be_suffix[i], suffix ) == 0 ) {
425                         return( 1 );
426                 }
427         }
428
429         return( 0 );
430 }
431
432 int
433 be_isroot( Backend *be, char *ndn )
434 {
435         int rc;
436
437         if ( ndn == NULL || be->be_root_ndn == NULL ) {
438                 return( 0 );
439         }
440
441         rc = strcmp( be->be_root_ndn, ndn ) ? 0 : 1;
442
443         return(rc);
444 }
445
446 char *
447 be_root_dn( Backend *be )
448 {
449         int rc;
450
451         if ( be->be_root_dn == NULL ) {
452                 return( "" );
453         }
454
455         return be->be_root_dn;
456 }
457
458 int
459 be_isroot_pw( Backend *be, char *ndn, struct berval *cred )
460 {
461         int result;
462
463         if ( ! be_isroot( be, ndn ) ) {
464                 return( 0 );
465         }
466
467 #ifdef SLAPD_CRYPT
468         ldap_pvt_thread_mutex_lock( &crypt_mutex );
469 #endif
470
471         result = lutil_passwd( cred->bv_val, be->be_root_pw );
472
473 #ifdef SLAPD_CRYPT
474         ldap_pvt_thread_mutex_unlock( &crypt_mutex );
475 #endif
476
477         return result == 0;
478 }
479
480 int
481 backend_unbind(
482         Connection   *conn,
483         Operation    *op
484 )
485 {
486         int     i;
487
488         for ( i = 0; i < nbackends; i++ ) {
489                 if ( backends[i].be_unbind != NULL ) {
490                         (*backends[i].be_unbind)( &backends[i], conn, op );
491                 }
492         }
493
494         return 0;
495 }
496
497 #ifdef SLAPD_ACLGROUPS
498 int 
499 backend_group(
500         Backend *be,
501         Entry   *target,
502         char    *gr_ndn,
503         char    *op_ndn,
504         char    *objectclassValue,
505         char    *groupattrName
506 )
507 {
508         if (be->be_group)
509                 return( be->be_group(be, target, gr_ndn, op_ndn,
510                         objectclassValue, groupattrName) );
511         else
512                 return(1);
513 }
514 #endif