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