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