]> git.sur5r.net Git - openldap/blob - servers/slapd/backend.c
Add a field to count the number of databases per type (bi_nDB) to
[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                 BackendInfo  *bi;
183
184                 /* open the backend type, if not done already */
185                 bi =  backendDB[i].bd_info;
186
187                 if( bi->bi_nDB == 0) {
188                         /* no database of this type, don't open */
189                         Debug(LDAP_DEBUG_ANY, 
190                                 "backend_startup: there should be no database (%d) of %s type.!\n",
191                                 i, bi->bi_type, 0 );
192
193                         return -1;
194                 }
195
196                 if ( backendDB[i].bd_info->bi_db_open ) {
197                         rc = backendDB[i].bd_info->bi_db_open(
198                                 &backendDB[i] );
199                 }
200
201                 if(rc != 0) {
202                         Debug( LDAP_DEBUG_ANY,
203                                 "backend_startup: bi_db_open %d failed!\n",
204                                 i, 0, 0 );
205                         return rc;
206                 }
207         }
208
209         return rc;
210 }
211
212 int backend_shutdown(int n)
213 {
214         int i;
215         int rc = 0;
216
217         if(n >= 0) {
218                 /* shutdown a specific backend database */
219
220                 /* make sure, n does not exceed the number of backend databases */
221                 if ( n >= nbackends ) {
222
223                         Debug( LDAP_DEBUG_ANY,
224                                 "backend_startup: database number %d exceeding maximum (%d)\n",
225                                 n, nbackends, 0 );
226                         return 1;
227                 }
228
229                 if ( backendDB[n].bd_info->bi_nDB == 0 ) {
230                         /* no database of this type, we never opened it */
231                         return 0;
232                 }
233
234                 if ( backendDB[n].bd_info->bi_db_close ) {
235                         backendDB[n].bd_info->bi_db_close(
236                                 &backendDB[n] );
237                 }
238
239                 if( backendDB[n].bd_info->bi_close ) {
240                         backendDB[n].bd_info->bi_close(
241                                 backendDB[n].bd_info );
242                 }
243
244                 return 0;
245         }
246
247         /* close each backend database */
248         for( i = 0; i < nBackendDB; i++ ) {
249                 BackendInfo  *bi;
250
251                 if ( backendDB[i].bd_info->bi_db_close ) {
252                         backendDB[i].bd_info->bi_db_close(
253                                 &backendDB[i] );
254                 }
255
256                 if(rc != 0) {
257                         Debug( LDAP_DEBUG_ANY,
258                                 "backend_close: bi_close %s failed!\n",
259                                 bi->bi_type, 0, 0 );
260                 }
261         }
262
263         /* close each backend type */
264         for( i = 0; i < nBackendInfo; i++ ) {
265                 if( backendInfo[i].bi_nDB == 0 ) {
266                         /* no database of this type */
267                         continue;
268                 }
269
270                 if( backendInfo[i].bi_close ) {
271                         backendInfo[i].bi_close(
272                                 &backendInfo[i] );
273                 }
274         }
275
276         return 0;
277 }
278
279 int backend_destroy(void)
280 {
281         int i;
282
283         /* destroy each backend database */
284         for( i = 0; i < nBackendDB; i++ ) {
285                 if ( backendDB[i].bd_info->bi_db_destroy ) {
286                         backendDB[i].bd_info->bi_db_destroy(
287                                 &backendDB[i] );
288                 }
289         }
290
291         /* destroy each backend type */
292         for( i = 0; i < nBackendInfo; i++ ) {
293                 if( backendInfo[i].bi_destroy ) {
294                         backendInfo[i].bi_destroy(
295                                 &backendInfo[i] );
296                 }
297         }
298
299         return 0;
300 }
301
302 BackendInfo* backend_info(char *type)
303 {
304         int i;
305
306         /* search for the backend type */
307         for( i = 0; i < nBackendInfo; i++ ) {
308                 if( strcasecmp(backendInfo[i].bi_type, type) == 0 ) {
309                         return &backendInfo[i];
310                 }
311         }
312
313         return NULL;
314 }
315
316
317 BackendDB *
318 backend_db_init(
319     char        *type
320 )
321 {
322         Backend *be;
323         BackendInfo *bi = backend_info(type);
324         int     rc = 0;
325
326         if( bi == NULL ) {
327                 fprintf( stderr, "Unrecognized database type (%s)\n", type );
328                 return NULL;
329         }
330
331         backendDB = (BackendDB *) ch_realloc(
332                         (char *) backendDB,
333                     (nBackendDB + 1) * sizeof(Backend) );
334
335         memset( &backendDB[nbackends], '\0', sizeof(Backend) );
336
337         be = &backends[nbackends++];
338
339         be->bd_info = bi;
340         be->be_sizelimit = defsize;
341         be->be_timelimit = deftime;
342
343         if(bi->bi_db_init) {
344                 rc = bi->bi_db_init( be );
345         }
346
347         if(rc != 0) {
348                 fprintf( stderr, "database init failed (%s)\n", type );
349                 nbackends--;
350                 return NULL;
351         }
352
353         bi->bi_nDB++;
354         return( be );
355 }
356
357 void
358 be_db_close( void )
359 {
360         int     i;
361
362         for ( i = 0; i < nbackends; i++ ) {
363                 if ( backends[i].bd_info->bi_db_close != NULL ) {
364                         (*backends[i].bd_info->bi_db_close)( &backends[i] );
365                 }
366         }
367 }
368
369 Backend *
370 select_backend( char * dn )
371 {
372         int     i, j, len, dnlen;
373
374         dnlen = strlen( dn );
375         for ( i = 0; i < nbackends; i++ ) {
376                 for ( j = 0; backends[i].be_suffix != NULL &&
377                     backends[i].be_suffix[j] != NULL; j++ )
378                 {
379                         len = strlen( backends[i].be_suffix[j] );
380
381                         if ( len > dnlen ) {
382                                 continue;
383                         }
384
385                         if ( strcmp( backends[i].be_suffix[j],
386                             dn + (dnlen - len) ) == 0 ) {
387                                 return( &backends[i] );
388                         }
389                 }
390         }
391
392         /* if no proper suffix could be found then check for aliases */
393         for ( i = 0; i < nbackends; i++ ) {
394                 for ( j = 0; 
395                       backends[i].be_suffixAlias != NULL && 
396                       backends[i].be_suffixAlias[j] != NULL; 
397                       j += 2 )
398                 {
399                         len = strlen( backends[i].be_suffixAlias[j] );
400
401                         if ( len > dnlen ) {
402                                 continue;
403                         }
404
405                         if ( strcmp( backends[i].be_suffixAlias[j],
406                             dn + (dnlen - len) ) == 0 ) {
407                                 return( &backends[i] );
408                         }
409                 }
410         }
411
412 #ifdef LDAP_ALLOW_NULL_SEARCH_BASE
413         /* Add greg@greg.rim.or.jp
414          * It's quick hack for cheap client
415          * Some browser offer a NULL base at ldap_search
416          *
417          * Should only be used as a last resort. -Kdz
418          */
419         if(dnlen == 0) {
420                 Debug( LDAP_DEBUG_TRACE,
421                         "select_backend: use default backend\n", 0, 0, 0 );
422                 return( &backends[0] );
423         }
424 #endif /* LDAP_ALLOW_NULL_SEARCH_BASE */
425
426         return( NULL );
427 }
428
429 int
430 be_issuffix(
431     Backend     *be,
432     char        *suffix
433 )
434 {
435         int     i;
436
437         for ( i = 0; be->be_suffix != NULL && be->be_suffix[i] != NULL; i++ ) {
438                 if ( strcmp( be->be_suffix[i], suffix ) == 0 ) {
439                         return( 1 );
440                 }
441         }
442
443         return( 0 );
444 }
445
446 int
447 be_isroot( Backend *be, char *ndn )
448 {
449         int rc;
450
451         if ( ndn == NULL || be->be_root_ndn == NULL ) {
452                 return( 0 );
453         }
454
455         rc = strcmp( be->be_root_ndn, ndn ) ? 0 : 1;
456
457         return(rc);
458 }
459
460 char *
461 be_root_dn( Backend *be )
462 {
463         int rc;
464
465         if ( be->be_root_dn == NULL ) {
466                 return( "" );
467         }
468
469         return be->be_root_dn;
470 }
471
472 int
473 be_isroot_pw( Backend *be, char *ndn, struct berval *cred )
474 {
475         int result;
476
477         if ( ! be_isroot( be, ndn ) ) {
478                 return( 0 );
479         }
480
481 #ifdef SLAPD_CRYPT
482         ldap_pvt_thread_mutex_lock( &crypt_mutex );
483 #endif
484
485         result = lutil_passwd( cred->bv_val, be->be_root_pw );
486
487 #ifdef SLAPD_CRYPT
488         ldap_pvt_thread_mutex_unlock( &crypt_mutex );
489 #endif
490
491         return result == 0;
492 }
493
494 int
495 backend_unbind(
496         Connection   *conn,
497         Operation    *op
498 )
499 {
500         int     i;
501
502         for ( i = 0; i < nbackends; i++ ) {
503                 if ( backends[i].be_unbind != NULL ) {
504                         (*backends[i].be_unbind)( &backends[i], conn, op );
505                 }
506         }
507
508         return 0;
509 }
510
511 #ifdef SLAPD_ACLGROUPS
512 int 
513 backend_group(
514         Backend *be,
515         Entry   *target,
516         char    *gr_ndn,
517         char    *op_ndn,
518         char    *objectclassValue,
519         char    *groupattrName
520 )
521 {
522         if (be->be_group)
523                 return( be->be_group(be, target, gr_ndn, op_ndn,
524                         objectclassValue, groupattrName) );
525         else
526                 return(1);
527 }
528 #endif