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