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