Newer
Older
/* backend.c - routines for dealing with back-end databases */
#include <ac/string.h>
#include <ac/socket.h>
#ifdef SLAPD_LDAP
#include "back-ldap/external.h"
#endif
#ifdef SLAPD_LDBM
#include "back-ldbm/external.h"
#endif
#ifdef SLAPD_BDB2
#include "back-bdb2/external.h"
#endif
#ifdef SLAPD_PASSWD
#include "back-passwd/external.h"
#endif
#ifdef SLAPD_PERL
#include "back-perl/external.h"
#endif
#ifdef SLAPD_SHELL
#include "back-shell/external.h"
#endif
#ifdef SLAPD_TCL
#include "back-tcl/external.h"
#endif
Bastiaan Bakker
committed
#if defined(SLAPD_LDAP) && !defined(SLAPD_LDAP_DYNAMIC)
{"ldap", ldap_back_initialize},
#endif
Bastiaan Bakker
committed
#if defined(SLAPD_LDBM) && !defined(SLAPD_LDBM_DYNAMIC)
{"ldbm", ldbm_back_initialize},
#endif
Bastiaan Bakker
committed
#if defined(SLAPD_BDB2) && !defined(SLAPD_BDB2_DYNAMIC)
{"bdb2", bdb2_back_initialize},
#endif
Bastiaan Bakker
committed
#if defined(SLAPD_PASSWD) && !defined(SLAPD_PASSWD_DYNAMIC)
{"passwd", passwd_back_initialize},
#endif
Bastiaan Bakker
committed
#if defined(SLAPD_PERL) && !defined(SLAPD_PERL_DYNAMIC)
{"perl", perl_back_initialize},
#endif
Bastiaan Bakker
committed
#if defined(SLAPD_SHELL) && !defined(SLAPD_SHELL_DYNAMIC)
Bastiaan Bakker
committed
#if defined(SLAPD_TCL) && !defined(SLAPD_LDAP_TCL)
{"tcl", tcl_back_initialize},
int nBackendInfo = 0;
BackendInfo *backendInfo = NULL;
int nBackendDB = 0;
BackendDB *backendDB = NULL;
int backend_init(void)
int rc = -1;
if((nBackendInfo != 0) || (backendInfo != NULL)) {
/* already initialized */
Debug( LDAP_DEBUG_ANY,
"backend_init: already initialized.\n", 0, 0, 0 );
return -1;
for( ;
binfo[nBackendInfo].bi_type != NULL;
nBackendInfo++ )
{
rc = binfo[nBackendInfo].bi_init(
&binfo[nBackendInfo] );
if(rc != 0) {
Debug( LDAP_DEBUG_ANY,
"backend_init: initialized for type \"%s\"\n",
binfo[nBackendInfo].bi_type, 0, 0 );
/* destroy those we've already inited */
for( nBackendInfo--;
nBackendInfo >= 0 ;
nBackendInfo-- )
{
if ( binfo[nBackendInfo].bi_destroy ) {
binfo[nBackendInfo].bi_destroy(
&binfo[nBackendInfo] );
}
}
return rc;
}
}
if ( nBackendInfo > 0) {
backendInfo = binfo;
return 0;
Bastiaan Bakker
committed
#ifdef SLAPD_MODULES
return 0;
#else
Debug( LDAP_DEBUG_ANY,
"backend_init: failed\n",
0, 0, 0 );
return rc;
Bastiaan Bakker
committed
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#endif /* SLAPD_MODULES */
}
int backend_add(BackendInfo *aBackendInfo)
{
int rc = 0;
if ((rc = aBackendInfo->bi_init(aBackendInfo)) != 0) {
Debug( LDAP_DEBUG_ANY,
"backend_add: initialization for type \"%s\" failed\n",
aBackendInfo->bi_type, 0, 0 );
return rc;
}
/* now add the backend type to the Backend Info List */
{
BackendInfo *newBackendInfo = 0;
/* if backendInfo == binfo no deallocation of old backendInfo */
if (backendInfo == binfo) {
newBackendInfo = ch_calloc(nBackendInfo + 1, sizeof(BackendInfo));
memcpy(newBackendInfo, backendInfo, sizeof(BackendInfo) *
nBackendInfo);
} else {
newBackendInfo = ch_realloc(backendInfo, sizeof(BackendInfo) *
(nBackendInfo + 1));
}
memcpy(&newBackendInfo[nBackendInfo], aBackendInfo,
sizeof(BackendInfo));
backendInfo = newBackendInfo;
nBackendInfo++;
return 0;
}
}
int backend_startup(int n)
{
int i;
int rc = 0;
if( ! ( nBackendDB > 0 ) ) {
/* no databases */
Debug( LDAP_DEBUG_ANY,
"backend_startup: %d databases to startup.\n",
nBackendDB, 0, 0 );
return 1;
if(n >= 0) {
/* startup a specific backend database */
Debug( LDAP_DEBUG_TRACE,
"backend_startup: starting database %d\n",
n, 0, 0 );
/* make sure, n does not exceed the number of backend databases */
if ( n >= nbackends ) {
Debug( LDAP_DEBUG_ANY,
"backend_startup: database number %d exceeding maximum (%d)\n",
n, nbackends, 0 );
return 1;
}
if ( backendDB[n].bd_info->bi_open ) {
rc = backendDB[n].bd_info->bi_open(
backendDB[n].bd_info );
}
if(rc != 0) {
Debug( LDAP_DEBUG_ANY,
"backend_startup: bi_open failed!\n",
0, 0, 0 );
return rc;
}
if ( backendDB[n].bd_info->bi_db_open ) {
rc = backendDB[n].bd_info->bi_db_open(
&backendDB[n] );
}
if(rc != 0) {
Debug( LDAP_DEBUG_ANY,
"backend_startup: bi_db_open failed!\n",
0, 0, 0 );
return rc;
}
return rc;
/* open each backend type */
for( i = 0; i < nBackendInfo; i++ ) {
if( backendInfo[i].bi_nDB == 0) {
/* no database of this type, don't open */
continue;
}
if( backendInfo[i].bi_open ) {
rc = backendInfo[i].bi_open(
&backendInfo[i] );
}
Debug( LDAP_DEBUG_ANY,
"backend_startup: bi_open %d failed!\n",
i, 0, 0 );
return rc;
}
/* open each backend database */
for( i = 0; i < nBackendDB; i++ ) {
if ( backendDB[i].bd_info->bi_db_open ) {
rc = backendDB[i].bd_info->bi_db_open(
&backendDB[i] );
}
if(rc != 0) {
Debug( LDAP_DEBUG_ANY,
"backend_startup: bi_db_open %d failed!\n",
i, 0, 0 );
return rc;
}
}
return rc;
}
int backend_shutdown(int n)
{
int i;
int rc = 0;
if(n >= 0) {
/* shutdown a specific backend database */
/* make sure, n does not exceed the number of backend databases */
if ( n >= nbackends ) {
Debug( LDAP_DEBUG_ANY,
"backend_startup: database number %d exceeding maximum (%d)\n",
n, nbackends, 0 );
return 1;
}
if ( backendDB[n].bd_info->bi_nDB == 0 ) {
/* no database of this type, we never opened it */
return 0;
}
if ( backendDB[n].bd_info->bi_db_close ) {
backendDB[n].bd_info->bi_db_close(
&backendDB[n] );
}
if( backendDB[n].bd_info->bi_close ) {
backendDB[n].bd_info->bi_close(
backendDB[n].bd_info );
}
return 0;
}
/* close each backend database */
for( i = 0; i < nBackendDB; i++ ) {
BackendInfo *bi;
if ( backendDB[i].bd_info->bi_db_close ) {
backendDB[i].bd_info->bi_db_close(
&backendDB[i] );
}
if(rc != 0) {
Debug( LDAP_DEBUG_ANY,
"backend_close: bi_close %s failed!\n",
bi->bi_type, 0, 0 );
}
}
/* close each backend type */
for( i = 0; i < nBackendInfo; i++ ) {
if( backendInfo[i].bi_nDB == 0 ) {
/* no database of this type */
continue;
}
if( backendInfo[i].bi_close ) {
backendInfo[i].bi_close(
&backendInfo[i] );
}
}
return 0;
}
int backend_destroy(void)
{
int i;
/* destroy each backend database */
for( i = 0; i < nBackendDB; i++ ) {
if ( backendDB[i].bd_info->bi_db_destroy ) {
backendDB[i].bd_info->bi_db_destroy(
&backendDB[i] );
}
}
/* destroy each backend type */
for( i = 0; i < nBackendInfo; i++ ) {
if( backendInfo[i].bi_destroy ) {
backendInfo[i].bi_destroy(
Bastiaan Bakker
committed
#ifdef SLAPD_MODULES
if (backendInfo != binfo) {
free(backendInfo);
}
#endif /* SLAPD_MODULES */
nBackendInfo = 0;
backendInfo = NULL;
return 0;
}
BackendInfo* backend_info(char *type)
{
int i;
/* search for the backend type */
for( i = 0; i < nBackendInfo; i++ ) {
if( strcasecmp(backendInfo[i].bi_type, type) == 0 ) {
return &backendInfo[i];
}
return NULL;
}
BackendDB *
backend_db_init(
char *type
)
{
Backend *be;
BackendInfo *bi = backend_info(type);
int rc = 0;
if( bi == NULL ) {
fprintf( stderr, "Unrecognized database type (%s)\n", type );
return NULL;
}
backendDB = (BackendDB *) ch_realloc(
(char *) backendDB,
(nBackendDB + 1) * sizeof(Backend) );
memset( &backendDB[nbackends], '\0', sizeof(Backend) );
be = &backends[nbackends++];
be->bd_info = bi;
be->be_sizelimit = defsize;
be->be_timelimit = deftime;
if(bi->bi_db_init) {
rc = bi->bi_db_init( be );
}
if(rc != 0) {
fprintf( stderr, "database init failed (%s)\n", type );
nbackends--;
return NULL;
bi->bi_nDB++;
void
be_db_close( void )
{
int i;
for ( i = 0; i < nbackends; i++ ) {
Hallvard Furuseth
committed
if ( backends[i].bd_info->bi_db_close ) {
(*backends[i].bd_info->bi_db_close)( &backends[i] );
}
}
}
Backend *
select_backend( char * dn )
{
int i, j, len, dnlen;
dnlen = strlen( dn );
for ( i = 0; i < nbackends; i++ ) {
for ( j = 0; backends[i].be_nsuffix != NULL &&
backends[i].be_nsuffix[j] != NULL; j++ )
Kurt Zeilenga
committed
{
len = strlen( backends[i].be_nsuffix[j] );
if ( strcmp( backends[i].be_nsuffix[j],
dn + (dnlen - len) ) == 0 ) {
return( &backends[i] );
}
}
}
/* if no proper suffix could be found then check for aliases */
for ( i = 0; i < nbackends; i++ ) {
for ( j = 0;
backends[i].be_suffixAlias != NULL &&
backends[i].be_suffixAlias[j] != NULL;
j += 2 )
{
len = strlen( backends[i].be_suffixAlias[j] );
if ( len > dnlen ) {
continue;
}
dn + (dnlen - len) ) == 0 ) {
return( &backends[i] );
}
}
}
#ifdef LDAP_ALLOW_NULL_SEARCH_BASE
/* Add greg@greg.rim.or.jp
* It's quick hack for cheap client
* Some browser offer a NULL base at ldap_search
*
* Should only be used as a last resort. -Kdz
*/
if(dnlen == 0) {
Debug( LDAP_DEBUG_TRACE,
"select_backend: use default backend\n", 0, 0, 0 );
return( &backends[0] );
}
#endif /* LDAP_ALLOW_NULL_SEARCH_BASE */
return( NULL );
}
int
be_issuffix(
Backend *be,
char *suffix
)
{
int i;
for ( i = 0; be->be_nsuffix != NULL && be->be_nsuffix[i] != NULL; i++ ) {
if ( strcmp( be->be_nsuffix[i], suffix ) == 0 ) {
return( 1 );
}
}
return( 0 );
}
int
be_isroot( Backend *be, char *ndn )
if ( ndn == NULL || be->be_root_ndn == NULL ) {
rc = strcmp( be->be_root_ndn, ndn ) ? 0 : 1;
char *
be_root_dn( Backend *be )
{
if ( be->be_root_dn == NULL ) {
return( "" );
}
return be->be_root_dn;
}
be_isroot_pw( Backend *be, char *ndn, struct berval *cred )
if ( ! be_isroot( be, ndn ) ) {
ldap_pvt_thread_mutex_lock( &crypt_mutex );
result = lutil_passwd( cred->bv_val, be->be_root_pw, NULL );
ldap_pvt_thread_mutex_unlock( &crypt_mutex );
#endif
return result == 0;
int
be_entry_release_rw( Backend *be, Entry *e, int rw )
{
if ( be->be_release ) {
/* free and release entry from backend */
return be->be_release( be, e, rw );
} else {
/* free entry */
entry_free( e );
return 0;
}
}
Connection *conn,
Operation *op
)
{
int i;
for ( i = 0; i < nbackends; i++ ) {
Hallvard Furuseth
committed
if ( backends[i].be_unbind ) {
(*backends[i].be_unbind)( &backends[i], conn, op );
}
}
Bastiaan Bakker
committed
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
int
backend_connection_init(
Connection *conn
)
{
int i;
for ( i = 0; i < nbackends; i++ ) {
if ( backends[i].be_connection_init ) {
(*backends[i].be_connection_init)( &backends[i], conn);
}
}
return 0;
}
int
backend_connection_destroy(
Connection *conn
)
{
int i;
for ( i = 0; i < nbackends; i++ ) {
if ( backends[i].be_connection_destroy ) {
(*backends[i].be_connection_destroy)( &backends[i], conn);
}
}
return 0;
}
Backend *be,
Entry *target,
char *gr_ndn,
char *op_ndn,
char *objectclassValue,
char *groupattrName
)
if (be->be_group)
return( be->be_group(be, target, gr_ndn, op_ndn,
objectclassValue, groupattrName) );
else
return(1);
}
#endif