Newer
Older
/*
* Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
*/
/* 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
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
153
154
155
156
157
158
#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;
be->be_realm = global_realm != NULL
? ch_strdup( global_realm ) : NULL;
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] );
}
}
}
#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
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
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);
#ifdef SLAPD_SCHEMA_DN
Attribute *backend_subschemasubentry( Backend *be )
{
/* should be backend specific */
static struct berval ss_val = {
sizeof(SLAPD_SCHEMA_DN)-1,
SLAPD_SCHEMA_DN };
static struct berval *ss_vals[2] = { &ss_val, NULL };
static Attribute ss_attr = {
"subschemasubentry",
ss_vals,
SYNTAX_DN | SYNTAX_CIS,
NULL
};
return &ss_attr;
}
#endif