From: Kurt Zeilenga Date: Mon, 12 Jul 1999 19:02:42 +0000 (+0000) Subject: Round two of referrals/aliases: WORK IN PROGRESS, may not compile! X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=1a7ea74d55afa9981aecff92378dea7bb23b8637;p=openldap Round two of referrals/aliases: WORK IN PROGRESS, may not compile! Basic support for "named referrals", manageDSAit control. Disabled alias support for now. Will implemented "named aliases" to replace current alias/suffix-alias support. --- diff --git a/build/main.dsw b/build/main.dsw new file mode 100644 index 0000000000..e728552c96 --- /dev/null +++ b/build/main.dsw @@ -0,0 +1,725 @@ +Microsoft Developer Studio Workspace File, Format Version 5.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "apitest"=..\libraries\libldap\apitest.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name libldap + End Project Dependency + Begin Project Dependency + Project_Dep_Name liblber + End Project Dependency +}}} + +############################################################################### + +Project: "apitest_r"=..\libraries\libldap_r\apitest_r.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name libldap_r + End Project Dependency + Begin Project Dependency + Project_Dep_Name liblber + End Project Dependency +}}} + +############################################################################### + +Project: "backldbm"="..\servers\slapd\back-ldbm\backldbm.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "build"=.\build.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name apitest + End Project Dependency + Begin Project Dependency + Project_Dep_Name apitest_r + End Project Dependency + Begin Project Dependency + Project_Dep_Name dtest + End Project Dependency + Begin Project Dependency + Project_Dep_Name etest + End Project Dependency + Begin Project Dependency + Project_Dep_Name ldapdelete + End Project Dependency + Begin Project Dependency + Project_Dep_Name ldapmodify + End Project Dependency + Begin Project Dependency + Project_Dep_Name ldapmodrdn + End Project Dependency + Begin Project Dependency + Project_Dep_Name ldappasswd + End Project Dependency + Begin Project Dependency + Project_Dep_Name ldapsearch + End Project Dependency + Begin Project Dependency + Project_Dep_Name ldbmcat + End Project Dependency + Begin Project Dependency + Project_Dep_Name ldbmtest + End Project Dependency + Begin Project Dependency + Project_Dep_Name ldif + End Project Dependency + Begin Project Dependency + Project_Dep_Name ldif2id2children + End Project Dependency + Begin Project Dependency + Project_Dep_Name ldif2id2entry + End Project Dependency + Begin Project Dependency + Project_Dep_Name ldif2index + End Project Dependency + Begin Project Dependency + Project_Dep_Name ldif2ldbm + End Project Dependency + Begin Project Dependency + Project_Dep_Name slapd + End Project Dependency + Begin Project Dependency + Project_Dep_Name testavl + End Project Dependency + Begin Project Dependency + Project_Dep_Name ud + End Project Dependency +}}} + +############################################################################### + +Project: "dtest"=..\libraries\liblber\dtest.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name liblber + End Project Dependency +}}} + +############################################################################### + +Project: "etest"=..\libraries\liblber\etest.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name liblber + End Project Dependency +}}} + +############################################################################### + +Project: "ldapdelete"=..\clients\tools\ldapdelete.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name libldap + End Project Dependency + Begin Project Dependency + Project_Dep_Name liblutil + End Project Dependency + Begin Project Dependency + Project_Dep_Name liblber + End Project Dependency +}}} + +############################################################################### + +Project: "ldapmodify"=..\clients\tools\ldapmodify.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name libldap + End Project Dependency + Begin Project Dependency + Project_Dep_Name liblutil + End Project Dependency + Begin Project Dependency + Project_Dep_Name libldif + End Project Dependency + Begin Project Dependency + Project_Dep_Name liblber + End Project Dependency +}}} + +############################################################################### + +Project: "ldapmodrdn"=..\clients\tools\ldapmodrdn.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name libldap + End Project Dependency + Begin Project Dependency + Project_Dep_Name liblutil + End Project Dependency + Begin Project Dependency + Project_Dep_Name liblber + End Project Dependency +}}} + +############################################################################### + +Project: "ldappasswd"=..\clients\tools\ldappasswd.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name libldap + End Project Dependency + Begin Project Dependency + Project_Dep_Name liblutil + End Project Dependency + Begin Project Dependency + Project_Dep_Name liblber + End Project Dependency +}}} + +############################################################################### + +Project: "ldapsearch"=..\clients\tools\ldapsearch.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name libldap + End Project Dependency + Begin Project Dependency + Project_Dep_Name liblutil + End Project Dependency + Begin Project Dependency + Project_Dep_Name libldif + End Project Dependency + Begin Project Dependency + Project_Dep_Name liblber + End Project Dependency +}}} + +############################################################################### + +Project: "ldbmcat"=..\servers\slapd\tools\ldbmcat.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name libldbm + End Project Dependency + Begin Project Dependency + Project_Dep_Name backldbm + End Project Dependency + Begin Project Dependency + Project_Dep_Name libslapd + End Project Dependency + Begin Project Dependency + Project_Dep_Name liblber + End Project Dependency + Begin Project Dependency + Project_Dep_Name libldap_r + End Project Dependency + Begin Project Dependency + Project_Dep_Name liblutil + End Project Dependency +}}} + +############################################################################### + +Project: "ldbmtest"=..\servers\slapd\tools\ldbmtest.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name backldbm + End Project Dependency + Begin Project Dependency + Project_Dep_Name liblber + End Project Dependency + Begin Project Dependency + Project_Dep_Name libldap_r + End Project Dependency + Begin Project Dependency + Project_Dep_Name libldbm + End Project Dependency + Begin Project Dependency + Project_Dep_Name liblutil + End Project Dependency + Begin Project Dependency + Project_Dep_Name libslapd + End Project Dependency + Begin Project Dependency + Project_Dep_Name libavl + End Project Dependency + Begin Project Dependency + Project_Dep_Name libldif + End Project Dependency +}}} + +############################################################################### + +Project: "ldif"=..\servers\slapd\tools\ldif.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name liblber + End Project Dependency +}}} + +############################################################################### + +Project: "ldif2id2children"=..\servers\slapd\tools\ldif2id2children.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name backldbm + End Project Dependency + Begin Project Dependency + Project_Dep_Name libldap_r + End Project Dependency + Begin Project Dependency + Project_Dep_Name libldif + End Project Dependency + Begin Project Dependency + Project_Dep_Name libavl + End Project Dependency + Begin Project Dependency + Project_Dep_Name liblutil + End Project Dependency + Begin Project Dependency + Project_Dep_Name liblber + End Project Dependency + Begin Project Dependency + Project_Dep_Name libldbm + End Project Dependency + Begin Project Dependency + Project_Dep_Name libslapd + End Project Dependency +}}} + +############################################################################### + +Project: "ldif2id2entry"=..\servers\slapd\tools\ldif2id2entry.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name backldbm + End Project Dependency + Begin Project Dependency + Project_Dep_Name libavl + End Project Dependency + Begin Project Dependency + Project_Dep_Name libldap_r + End Project Dependency + Begin Project Dependency + Project_Dep_Name libldif + End Project Dependency + Begin Project Dependency + Project_Dep_Name liblutil + End Project Dependency + Begin Project Dependency + Project_Dep_Name liblber + End Project Dependency + Begin Project Dependency + Project_Dep_Name libldbm + End Project Dependency + Begin Project Dependency + Project_Dep_Name libslapd + End Project Dependency +}}} + +############################################################################### + +Project: "ldif2index"=..\servers\slapd\tools\ldif2index.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name backldbm + End Project Dependency + Begin Project Dependency + Project_Dep_Name libldap_r + End Project Dependency + Begin Project Dependency + Project_Dep_Name libavl + End Project Dependency + Begin Project Dependency + Project_Dep_Name liblutil + End Project Dependency + Begin Project Dependency + Project_Dep_Name libldif + End Project Dependency + Begin Project Dependency + Project_Dep_Name liblber + End Project Dependency + Begin Project Dependency + Project_Dep_Name libldbm + End Project Dependency + Begin Project Dependency + Project_Dep_Name libslapd + End Project Dependency +}}} + +############################################################################### + +Project: "ldif2ldbm"=..\servers\slapd\tools\ldif2ldbm.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name backldbm + End Project Dependency + Begin Project Dependency + Project_Dep_Name libavl + End Project Dependency + Begin Project Dependency + Project_Dep_Name libldap_r + End Project Dependency + Begin Project Dependency + Project_Dep_Name libldif + End Project Dependency + Begin Project Dependency + Project_Dep_Name liblutil + End Project Dependency + Begin Project Dependency + Project_Dep_Name liblber + End Project Dependency + Begin Project Dependency + Project_Dep_Name libslapd + End Project Dependency + Begin Project Dependency + Project_Dep_Name libldbm + End Project Dependency +}}} + +############################################################################### + +Project: "libavl"=..\libraries\libavl\libavl.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "liblber"=..\libraries\liblber\liblber.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libldap"=..\libraries\libldap\libldap.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libldap_r"=..\libraries\libldap_r\libldap_r.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libldbm"=..\libraries\libldbm\libldbm.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libldif"=..\libraries\libldif\libldif.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "liblutil"=..\libraries\liblutil\liblutil.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libslapd"=..\servers\slapd\libslapd.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "ltest"=..\libraries\libldap\ltest.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name libldap + End Project Dependency + Begin Project Dependency + Project_Dep_Name liblutil + End Project Dependency + Begin Project Dependency + Project_Dep_Name liblber + End Project Dependency +}}} + +############################################################################### + +Project: "ltest_r"=..\libraries\libldap_r\ltest_r.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name libldap_r + End Project Dependency + Begin Project Dependency + Project_Dep_Name liblutil + End Project Dependency + Begin Project Dependency + Project_Dep_Name liblber + End Project Dependency +}}} + +############################################################################### + +Project: "setup"=..\include\setup.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "slapd"=..\servers\slapd\slapd.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name backldbm + End Project Dependency + Begin Project Dependency + Project_Dep_Name libldap_r + End Project Dependency + Begin Project Dependency + Project_Dep_Name libavl + End Project Dependency + Begin Project Dependency + Project_Dep_Name libldif + End Project Dependency + Begin Project Dependency + Project_Dep_Name liblutil + End Project Dependency + Begin Project Dependency + Project_Dep_Name setup + End Project Dependency + Begin Project Dependency + Project_Dep_Name liblber + End Project Dependency + Begin Project Dependency + Project_Dep_Name libldbm + End Project Dependency + Begin Project Dependency + Project_Dep_Name libslapd + End Project Dependency +}}} + +############################################################################### + +Project: "testavl"=..\libraries\libavl\testavl.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name libavl + End Project Dependency +}}} + +############################################################################### + +Project: "ud"=..\clients\ud\ud.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name libldap + End Project Dependency + Begin Project Dependency + Project_Dep_Name liblber + End Project Dependency + Begin Project Dependency + Project_Dep_Name liblutil + End Project Dependency +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/libraries/libldbm/libldbm.dsp b/libraries/libldbm/libldbm.dsp new file mode 100644 index 0000000000..60e8320349 --- /dev/null +++ b/libraries/libldbm/libldbm.dsp @@ -0,0 +1,133 @@ +# Microsoft Developer Studio Project File - Name="libldbm" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=libldbm - Win32 Single Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libldbm.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libldbm.mak" CFG="libldbm - Win32 Single Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libldbm - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "libldbm - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE "libldbm - Win32 Single Debug" (based on "Win32 (x86) Static Library") +!MESSAGE "libldbm - Win32 Single Release" (based on\ + "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe + +!IF "$(CFG)" == "libldbm - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\Release" +# PROP Intermediate_Dir "Release\libldbm" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"..\Release\oldbm32.lib" + +!ELSEIF "$(CFG)" == "libldbm - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\Debug" +# PROP Intermediate_Dir "Debug\libldbm" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"..\Debug\oldbm32.lib" + +!ELSEIF "$(CFG)" == "libldbm - Win32 Single Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "libldbm_" +# PROP BASE Intermediate_Dir "libldbm_" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\SDebug" +# PROP Intermediate_Dir "SDebug\libldbm" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo /out:"..\Debug\oldbm32.lib" +# ADD LIB32 /nologo /out:"..\SDebug\oldbm32.lib" + +!ELSEIF "$(CFG)" == "libldbm - Win32 Single Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "libldbm0" +# PROP BASE Intermediate_Dir "libldbm0" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\SRelease" +# PROP Intermediate_Dir "SRelease\libldbm" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo /out:"..\Release\oldbm32.lib" +# ADD LIB32 /nologo /out:"..\SRelease\oldbm32.lib" + +!ENDIF + +# Begin Target + +# Name "libldbm - Win32 Release" +# Name "libldbm - Win32 Debug" +# Name "libldbm - Win32 Single Debug" +# Name "libldbm - Win32 Single Release" +# Begin Source File + +SOURCE=.\ldbm.c +# End Source File +# Begin Source File + +SOURCE=..\..\include\ldbm.h +# End Source File +# End Target +# End Project diff --git a/servers/slapd/acl.c b/servers/slapd/acl.c index 6c3b22ee85..1520bca475 100644 --- a/servers/slapd/acl.c +++ b/servers/slapd/acl.c @@ -1,35 +1,22 @@ /* acl.c - routines to parse and check acl's */ +#include "portable.h" + #include -#include -#include -#include -#include -#include -#ifdef sunos5 -#include "regexpr.h" -#else -#include "regex.h" -#endif -#include "slap.h" -extern Attribute *attr_find(); -extern char *re_comp(); -extern struct acl *global_acl; -extern int global_default_access; -extern char *access2str(); -extern char *dn_normalize_case(); +#include +#include +#include -int acl_access_allowed(); -int access_allowed(); -struct acl *acl_get_applicable(); +#include "slap.h" -static int regex_matches(); +static int regex_matches(char *pat, char *str, char *buf, regmatch_t *matches); +static void string_expand(char *newbuf, int bufsiz, char *pattern, + char *match, regmatch_t *matches); -extern pthread_mutex_t regex_mutex; /* - * access_allowed - check whether dn is allowed the requested access + * access_allowed - check whether op->o_ndn is allowed the requested access * to entry e, attribute attr, value val. if val is null, access to * the whole attribute is assumed (all values). this routine finds * the applicable acl and calls acl_access_allowed() to make the @@ -47,19 +34,55 @@ access_allowed( Entry *e, char *attr, struct berval *val, - char *dn, int access ) { - int rc; - struct acl *a; + int rc; + struct acl *a; + char *edn; + + regmatch_t matches[MAXREMATCHES]; + int i; + int n; if ( be == NULL ) { return( 0 ); } - a = acl_get_applicable( be, op, e, attr ); - rc = acl_access_allowed( a, be, conn, e, val, op, access ); + edn = e->e_ndn; + + Debug( LDAP_DEBUG_ACL, "\n=> access_allowed: entry (%s) attr (%s)\n", + e->e_dn, attr, 0 ); + + /* the lastmod attributes are ignored by ACL checking */ + if ( oc_check_no_usermod_attr( attr ) ) { + Debug( LDAP_DEBUG_ACL, "Operational attribute: %s access allowed\n", + attr, 0, 0 ); + return(1); + } + + memset(matches, 0, sizeof(matches)); + + a = acl_get_applicable( be, op, e, attr, MAXREMATCHES, matches ); + + if (a) { + for (i = 0; i < MAXREMATCHES && matches[i].rm_so > 0; i++) { + Debug( LDAP_DEBUG_ARGS, "=> match[%d]: %d %d ", i, + (int)matches[i].rm_so, (int)matches[i].rm_eo ); + + if( matches[i].rm_so <= matches[0].rm_eo ) { + for ( n = matches[i].rm_so; n < matches[i].rm_eo; n++) { + Debug( LDAP_DEBUG_ARGS, "%c", edn[n], 0, 0 ); + } + } + Debug( LDAP_DEBUG_ARGS, "\n", 0, 0, 0 ); + } + } + + rc = acl_access_allowed( a, be, conn, e, val, op, access, edn, matches ); + + Debug( LDAP_DEBUG_ACL, "\n=> access_allowed: exit (%s) attr (%s)\n", + e->e_dn, attr, 0); return( rc ); } @@ -75,72 +98,94 @@ acl_get_applicable( Backend *be, Operation *op, Entry *e, - char *attr + char *attr, + int nmatch, + regmatch_t *matches ) { int i; struct acl *a; - char *edn; + char *edn; - Debug( LDAP_DEBUG_ACL, "=> acl_get: entry (%s) attr (%s)\n", e->e_dn, - attr, 0 ); + Debug( LDAP_DEBUG_ACL, "\n=> acl_get: entry (%s) attr (%s)\n", + e->e_dn, attr, 0 ); - if ( be_isroot( be, op->o_dn ) ) { + if ( be_isroot( be, op->o_ndn ) ) { Debug( LDAP_DEBUG_ACL, "<= acl_get: no acl applicable to database root\n", 0, 0, 0 ); return( NULL ); } + edn = e->e_ndn; + + Debug( LDAP_DEBUG_ARGS, "=> acl_get: edn %s\n", edn, 0, 0 ); + /* check for a backend-specific acl that matches the entry */ for ( i = 1, a = be->be_acl; a != NULL; a = a->acl_next, i++ ) { - if ( a->acl_dnpat != NULL ) { - edn = dn_normalize_case( strdup( e->e_dn ) ); - if ( ! regex_matches( a->acl_dnpat, edn ) ) { - free( edn ); + if (a->acl_dnpat != NULL) { + Debug( LDAP_DEBUG_TRACE, "=> dnpat: [%d] %s nsub: %d\n", + i, a->acl_dnpat, (int) a->acl_dnre.re_nsub); + + if (regexec(&a->acl_dnre, edn, nmatch, matches, 0)) continue; - } - free( edn ); + else + Debug( LDAP_DEBUG_TRACE, "=> acl_get:[%d] backend ACL match\n", + i, 0, 0); } + if ( a->acl_filter != NULL ) { - if ( test_filter( NULL, NULL, NULL, e, a->acl_filter ) - != 0 ) { + if ( test_filter( NULL, NULL, NULL, e, a->acl_filter ) != 0 ) { continue; } } + + Debug( LDAP_DEBUG_ARGS, "=> acl_get: [%d] check attr %s\n", i, attr, 0); + if ( attr == NULL || a->acl_attrs == NULL || - charray_inlist( a->acl_attrs, attr ) ) { - Debug( LDAP_DEBUG_ACL, "<= acl_get: backend acl #%d\n", - i, e->e_dn, attr ); + charray_inlist( a->acl_attrs, attr ) ) + { + Debug( LDAP_DEBUG_ACL, "<= acl_get: [%d] backend acl %s attr: %s\n", + i, e->e_dn, attr ); return( a ); } + matches[0].rm_so = matches[0].rm_eo = -1; } /* check for a global acl that matches the entry */ for ( i = 1, a = global_acl; a != NULL; a = a->acl_next, i++ ) { - if ( a->acl_dnpat != NULL ) { - edn = dn_normalize_case( strdup( e->e_dn ) ); - if ( ! regex_matches( a->acl_dnpat, edn ) ) { - free( edn ); + if (a->acl_dnpat != NULL) { + Debug( LDAP_DEBUG_TRACE, "=> dnpat: [%d] %s nsub: %d\n", + i, a->acl_dnpat, (int) a->acl_dnre.re_nsub); + + if (regexec(&a->acl_dnre, edn, nmatch, matches, 0)) { continue; + } else { + Debug( LDAP_DEBUG_TRACE, "=> acl_get: [%d] global ACL match\n", + i, 0, 0); } - free( edn ); } + if ( a->acl_filter != NULL ) { - if ( test_filter( NULL, NULL, NULL, e, a->acl_filter ) - != 0 ) { + if ( test_filter( NULL, NULL, NULL, e, a->acl_filter ) != 0 ) { continue; } } - if ( attr == NULL || a->acl_attrs == NULL || charray_inlist( - a->acl_attrs, attr ) ) { - Debug( LDAP_DEBUG_ACL, "<= acl_get: global acl #%d\n", - i, e->e_dn, attr ); + + Debug( LDAP_DEBUG_ARGS, "=> acl_get: [%d] check attr\n", i, 0, 0); + + if ( attr == NULL || a->acl_attrs == NULL || + charray_inlist( a->acl_attrs, attr ) ) + { + Debug( LDAP_DEBUG_ACL, "<= acl_get: [%d] global acl %s attr: %s\n", + i, e->e_dn, attr ); return( a ); } + + matches[0].rm_so = matches[0].rm_eo = -1; } - Debug( LDAP_DEBUG_ACL, "<= acl_get: no match\n", 0, 0, 0 ); + Debug( LDAP_DEBUG_ACL, "<= acl_get: no match\n", 0, 0, 0 ); return( NULL ); } @@ -161,144 +206,182 @@ acl_access_allowed( Entry *e, struct berval *val, Operation *op, - int access + int access, + char *edn, + regmatch_t *matches ) { int i; - char *edn, *odn; struct access *b; Attribute *at; struct berval bv; int default_access; - Debug( LDAP_DEBUG_ACL, "=> acl: %s access to value \"%s\" by \"%s\"\n", - access2str( access ), val ? val->bv_val : "any", op->o_dn ? - op->o_dn : "" ); + Debug( LDAP_DEBUG_ACL, + "\n=> acl_access_allowed: %s access to entry \"%s\"\n", + access2str( access ), e->e_dn, 0 ); - if ( be_isroot( be, op->o_dn ) ) { - Debug( LDAP_DEBUG_ACL, "<= acl: granted to database root\n", + Debug( LDAP_DEBUG_ACL, + "\n=> acl_access_allowed: %s access to value \"%s\" by \"%s\"\n", + access2str( access ), + val ? val->bv_val : "any", + op->o_ndn ? op->o_ndn : "" ); + + if ( be_isroot( be, op->o_ndn ) ) { + Debug( LDAP_DEBUG_ACL, + "<= acl_access_allowed: granted to database root\n", 0, 0, 0 ); return( 1 ); } - default_access = be->be_dfltaccess ? be->be_dfltaccess : - global_default_access; + default_access = be->be_dfltaccess ? be->be_dfltaccess : global_default_access; + if ( a == NULL ) { Debug( LDAP_DEBUG_ACL, - "<= acl: %s by default (no matching to)\n", + "<= acl_access_allowed: %s by default (no matching to)\n", default_access >= access ? "granted" : "denied", 0, 0 ); return( default_access >= access ); } - odn = NULL; - if ( op->o_dn != NULL ) { - odn = dn_normalize_case( strdup( op->o_dn ) ); - bv.bv_val = odn; - bv.bv_len = strlen( odn ); + if ( op->o_ndn != NULL ) { + bv.bv_val = op->o_ndn; + bv.bv_len = strlen( bv.bv_val ); } + for ( i = 1, b = a->acl_access; b != NULL; b = b->a_next, i++ ) { if ( b->a_dnpat != NULL ) { + Debug( LDAP_DEBUG_TRACE, "<= check a_dnpat: %s\n", + b->a_dnpat, 0, 0); /* * if access applies to the entry itself, and the * user is bound as somebody in the same namespace as * the entry, OR the given dn matches the dn pattern */ - if ( strcasecmp( b->a_dnpat, "self" ) == 0 && op->o_dn - != NULL && *(op->o_dn) && e->e_dn != NULL ) { - edn = dn_normalize_case( strdup( e->e_dn ) ); - if ( strcasecmp( edn, op->o_dn ) == 0 ) { - free( edn ); - if ( odn ) free( odn ); + if ( strcasecmp( b->a_dnpat, "anonymous" ) == 0 && + (op->o_ndn == NULL || *(op->o_ndn) == '\0' ) ) + { + Debug( LDAP_DEBUG_ACL, + "<= acl_access_allowed: matched by clause #%d access %s\n", + i, ACL_GRANT(b->a_access, access) + ? "granted" : "denied", 0 ); + + return ACL_GRANT(b->a_access, access ); + + } else if ( strcasecmp( b->a_dnpat, "self" ) == 0 && + op->o_ndn != NULL && *(op->o_ndn) && e->e_dn != NULL ) + { + if ( strcmp( edn, op->o_ndn ) == 0 ) { Debug( LDAP_DEBUG_ACL, - "<= acl: matched by clause #%d access %s\n", - i, (b->a_access & ~ACL_SELF) >= - access ? "granted" : "denied", 0 ); + "<= acl_access_allowed: matched by clause #%d access %s\n", + i, ACL_GRANT(b->a_access, access) + ? "granted" : "denied", 0 ); - return( (b->a_access & ~ACL_SELF) - >= access ); + return ACL_GRANT(b->a_access, access ); } - free( edn ); } else { - if ( regex_matches( b->a_dnpat, odn ) ) { - if ( odn ) free( odn ); + if ( regex_matches( b->a_dnpat, op->o_ndn, edn, matches ) ) { Debug( LDAP_DEBUG_ACL, - "<= acl: matched by clause #%d access %s\n", - i, (b->a_access & ~ACL_SELF) >= access ? - "granted" : "denied", 0 ); + "<= acl_access_allowed: matched by clause #%d access %s\n", + i, ACL_GRANT(b->a_access, access) + ? "granted" : "denied", 0 ); - return( (b->a_access & ~ACL_SELF) - >= access ); + return ACL_GRANT(b->a_access, access ); } } } if ( b->a_addrpat != NULL ) { - if ( regex_matches( b->a_addrpat, conn->c_addr ) ) { - if ( odn ) free( odn ); + if ( regex_matches( b->a_addrpat, conn->c_client_addr, + edn, matches ) ) + { Debug( LDAP_DEBUG_ACL, - "<= acl: matched by clause #%d access %s\n", - i, (b->a_access & ~ACL_SELF) >= access ? - "granted" : "denied", 0 ); + "<= acl_access_allowed: matched by clause #%d access %s\n", + i, ACL_GRANT(b->a_access, access) + ? "granted" : "denied", 0 ); - return( (b->a_access & ~ACL_SELF) >= access ); + return ACL_GRANT(b->a_access, access ); } } if ( b->a_domainpat != NULL ) { - if ( regex_matches( b->a_domainpat, conn->c_domain ) ) { - if ( odn ) free( odn ); + Debug( LDAP_DEBUG_ARGS, "<= check a_domainpath: %s\n", + b->a_domainpat, 0, 0 ); + if ( regex_matches( b->a_domainpat, conn->c_client_name, + edn, matches ) ) + { Debug( LDAP_DEBUG_ACL, - "<= acl: matched by clause #%d access %s\n", - i, (b->a_access & ~ACL_SELF) >= access ? - "granted" : "denied", 0 ); + "<= acl_access_allowed: matched by clause #%d access %s\n", + i, ACL_GRANT(b->a_access, access) + ? "granted" : "denied", 0 ); - return( (b->a_access & ~ACL_SELF) >= access ); + return ACL_GRANT(b->a_access, access ); } } - if ( b->a_dnattr != NULL && op->o_dn != NULL ) { + if ( b->a_dnattr != NULL && op->o_ndn != NULL ) { + Debug( LDAP_DEBUG_ARGS, "<= check a_dnattr: %s\n", + b->a_dnattr, 0, 0); /* see if asker is listed in dnattr */ - if ( (at = attr_find( e->e_attrs, b->a_dnattr )) - != NULL && value_find( at->a_vals, &bv, - at->a_syntax, 3 ) == 0 ) + if ( (at = attr_find( e->e_attrs, b->a_dnattr )) != NULL && + value_find( at->a_vals, &bv, at->a_syntax, 1 ) == 0 ) { - if ( (b->a_access & ACL_SELF) && (val == NULL - || value_cmp( &bv, val, at->a_syntax, - 2 )) ) { + if ( ACL_IS_SELF(b->a_access) && + (val == NULL || value_cmp( &bv, val, at->a_syntax, 2 )) ) + { continue; } - if ( odn ) free( odn ); Debug( LDAP_DEBUG_ACL, - "<= acl: matched by clause #%d access %s\n", - i, (b->a_access & ~ACL_SELF) >= access ? - "granted" : "denied", 0 ); + "<= acl_acces_allowed: matched by clause #%d access %s\n", + i, ACL_GRANT(b->a_access, access) + ? "granted" : "denied", 0 ); - return( (b->a_access & ~ACL_SELF) >= access ); + return ACL_GRANT(b->a_access, access ); } /* asker not listed in dnattr - check for self access */ - if ( ! (b->a_access & ACL_SELF) || val == NULL || - value_cmp( &bv, val, at->a_syntax, 2 ) != 0 ) { + if ( ! ACL_IS_SELF(b->a_access) || val == NULL || + value_cmp( &bv, val, at->a_syntax, 2 ) != 0 ) + { continue; } - if ( odn ) free( odn ); Debug( LDAP_DEBUG_ACL, - "<= acl: matched by clause #%d (self) access %s\n", - i, (b->a_access & ~ACL_SELF) >= access ? "granted" - : "denied", 0 ); + "<= acl_access_allowed: matched by clause #%d (self) access %s\n", + i, ACL_GRANT(b->a_access, access) + ? "granted" : "denied", 0 ); - return( (b->a_access & ~ACL_SELF) >= access ); + return ACL_GRANT(b->a_access, access ); + } + + if ( b->a_group != NULL && op->o_ndn != NULL ) { + char buf[1024]; + + /* b->a_group is an unexpanded entry name, expanded it should be an + * entry with objectclass group* and we test to see if odn is one of + * the values in the attribute group + */ + /* see if asker is listed in dnattr */ + string_expand(buf, sizeof(buf), b->a_group, edn, matches); + (void) dn_normalize_case(buf); + + if (backend_group(be, e, buf, op->o_ndn, + b->a_group_oc, b->a_group_at) == 0) + { + Debug( LDAP_DEBUG_ACL, + "<= acl_access_allowed: matched by clause #%d (group) access granted\n", + i, 0, 0 ); + return ACL_GRANT(b->a_access, access ); + } } } - if ( odn ) free( odn ); - Debug( LDAP_DEBUG_ACL, "<= acl: %s by default (no matching by)\n", + Debug( LDAP_DEBUG_ACL, + "<= acl_access_allowed: %s by default (no matching by)\n", default_access >= access ? "granted" : "denied", 0, 0 ); return( default_access >= access ); } /* - * acl_check_mods - check access control on the given entry to see if + * acl_check_modlist - check access control on the given entry to see if * it allows the given modifications by the user associated with op. * returns LDAP_SUCCESS mods allowed ok * anything else mods not allowed - return is an error @@ -306,50 +389,59 @@ acl_access_allowed( */ int -acl_check_mods( +acl_check_modlist( Backend *be, Connection *conn, Operation *op, Entry *e, - LDAPMod *mods + LDAPModList *mlist ) { int i; struct acl *a; + char *edn = e->e_ndn; - for ( ; mods != NULL; mods = mods->mod_next ) { - if ( strcasecmp( mods->mod_type, "modifiersname" ) == 0 || - strcasecmp( mods->mod_type, "modifytimestamp" ) == 0 ) { + for ( ; mlist != NULL; mlist = mlist->ml_next ) { + regmatch_t matches[MAXREMATCHES]; + + /* the lastmod attributes are ignored by ACL checking */ + if ( oc_check_no_usermod_attr( mlist->ml_type ) ) { + Debug( LDAP_DEBUG_ACL, "Operational attribute: %s access allowed\n", + mlist->ml_type, 0, 0 ); continue; } - a = acl_get_applicable( be, op, e, mods->mod_type ); + a = acl_get_applicable( be, op, e, mlist->ml_type, + MAXREMATCHES, matches ); - switch ( mods->mod_op & ~LDAP_MOD_BVALUES ) { + switch ( mlist->ml_op & ~LDAP_MOD_BVALUES ) { case LDAP_MOD_REPLACE: case LDAP_MOD_ADD: - if ( mods->mod_bvalues == NULL ) { + if ( mlist->ml_bvalues == NULL ) { break; } - for ( i = 0; mods->mod_bvalues[i] != NULL; i++ ) { - if ( ! acl_access_allowed( a, be, conn, e, - mods->mod_bvalues[i], op, ACL_WRITE ) ) { + for ( i = 0; mlist->ml_bvalues[i] != NULL; i++ ) { + if ( ! acl_access_allowed( a, be, conn, e, mlist->ml_bvalues[i], + op, ACL_WRITE, edn, matches) ) + { return( LDAP_INSUFFICIENT_ACCESS ); } } break; case LDAP_MOD_DELETE: - if ( mods->mod_bvalues == NULL ) { + if ( mlist->ml_bvalues == NULL ) { if ( ! acl_access_allowed( a, be, conn, e, - NULL, op, ACL_WRITE ) ) { + NULL, op, ACL_WRITE, edn, matches) ) + { return( LDAP_INSUFFICIENT_ACCESS ); } break; } - for ( i = 0; mods->mod_bvalues[i] != NULL; i++ ) { - if ( ! acl_access_allowed( a, be, conn, e, - mods->mod_bvalues[i], op, ACL_WRITE ) ) { + for ( i = 0; mlist->ml_bvalues[i] != NULL; i++ ) { + if ( ! acl_access_allowed( a, be, conn, e, mlist->ml_bvalues[i], + op, ACL_WRITE, edn, matches) ) + { return( LDAP_INSUFFICIENT_ACCESS ); } } @@ -360,45 +452,93 @@ acl_check_mods( return( LDAP_SUCCESS ); } -#ifdef sunos5 - -static int -regex_matches( char *pat, char *str ) +static void +string_expand( + char *newbuf, + int bufsiz, + char *pat, + char *match, + regmatch_t *matches) { - char *e; - int rc; - - if ( (e = compile( pat, NULL, NULL )) == NULL ) { - Debug( LDAP_DEBUG_ANY, - "compile( \"%s\", \"%s\") failed\n", pat, str, 0 ); - return( 0 ); + int size; + char *sp; + char *dp; + int flag; + + size = 0; + newbuf[0] = '\0'; + + flag = 0; + for ( dp = newbuf, sp = pat; size < bufsiz && *sp ; sp++) { + /* did we previously see a $ */ + if (flag) { + if (*sp == '$') { + *dp++ = '$'; + size++; + } else if (*sp >= '0' && *sp <= '9' ) { + int n; + int i; + int l; + + n = *sp - '0'; + *dp = '\0'; + i = matches[n].rm_so; + l = matches[n].rm_eo; + for ( ; size < 512 && i < l; size++, i++ ) { + *dp++ = match[i]; + size++; + } + *dp = '\0'; + } + flag = 0; + } else { + if (*sp == '$') { + flag = 1; + } else { + *dp++ = *sp; + size++; + } + } } - rc = step( str ? str : "", e ); - free( e ); + *dp = '\0'; - return( rc ); + Debug( LDAP_DEBUG_TRACE, "=> string_expand: pattern: %s\n", pat, 0, 0 ); + Debug( LDAP_DEBUG_TRACE, "=> string_expand: expanded: %s\n", newbuf, 0, 0 ); } -#else /* sunos5 */ - static int -regex_matches( char *pat, char *str ) +regex_matches( + char *pat, /* pattern to expand and match against */ + char *str, /* string to match against pattern */ + char *buf, /* buffer with $N expansion variables */ + regmatch_t *matches /* offsets in buffer for $N expansion variables */ +) { - char *e; + regex_t re; + char newbuf[512]; int rc; - pthread_mutex_lock( ®ex_mutex ); - if ( (e = re_comp( pat )) != NULL ) { - Debug( LDAP_DEBUG_ANY, - "re_comp( \"%s\", \"%s\") failed because (%s)\n", pat, str, - e ); - pthread_mutex_unlock( ®ex_mutex ); + if(str == NULL) str = ""; + + string_expand(newbuf, sizeof(newbuf), pat, buf, matches); + if (( rc = regcomp(&re, newbuf, REG_EXTENDED|REG_ICASE))) { + char error[512]; + regerror(rc, &re, error, sizeof(error)); + + Debug( LDAP_DEBUG_TRACE, + "compile( \"%s\", \"%s\") failed %s\n", + pat, str, error ); return( 0 ); } - rc = re_exec( str ? str : "" ); - pthread_mutex_unlock( ®ex_mutex ); - return( rc == 1 ); + rc = regexec(&re, str, 0, NULL, 0); + regfree( &re ); + + Debug( LDAP_DEBUG_TRACE, + "=> regex_matches: string: %s\n", str, 0, 0 ); + Debug( LDAP_DEBUG_TRACE, + "=> regex_matches: rc: %d %s\n", + rc, !rc ? "matches" : "no matches", 0 ); + return( !rc ); } -#endif /* sunos5 */ diff --git a/servers/slapd/aclparse.c b/servers/slapd/aclparse.c index 10fa6a0721..3c69482fce 100644 --- a/servers/slapd/aclparse.c +++ b/servers/slapd/aclparse.c @@ -1,31 +1,82 @@ /* acl.c - routines to parse and check acl's */ +#include "portable.h" #include -#include -#include -#include -#include -#include -#include "regex.h" -#include "slap.h" -#include "portable.h" -extern Filter *str2filter(); -extern char *re_comp(); -extern struct acl *global_acl; -extern char **str2charray(); -extern char *dn_upcase(); +#include +#include +#include +#include +#include -static void split(); -static void acl_append(); -static void access_append(); -static void acl_usage(); +#include "slap.h" + +static void split(char *line, int splitchar, char **left, char **right); +static void acl_append(struct acl **l, struct acl *a); +static void access_append(struct access **l, struct access *a); +static void acl_usage(void); #ifdef LDAP_DEBUG -static void print_acl(); -static void print_access(); +static void print_acl(struct acl *a); +static void print_access(struct access *b); #endif +static int +regtest(char *fname, int lineno, char *pat) { + int e; + regex_t re; + + char buf[512]; + unsigned size; + + char *sp; + char *dp; + int flag; + + sp = pat; + dp = buf; + size = 0; + buf[0] = '\0'; + + for (size = 0, flag = 0; (size < sizeof(buf)) && *sp; sp++) { + if (flag) { + if (*sp == '$'|| (*sp >= '0' && *sp <= '9')) { + *dp++ = *sp; + size++; + } + flag = 0; + + } else { + if (*sp == '$') { + flag = 1; + } else { + *dp++ = *sp; + size++; + } + } + } + + *dp = '\0'; + if ( size >= (sizeof(buf)-1) ) { + fprintf( stderr, + "%s: line %d: regular expression \"%s\" too large\n", + fname, lineno, pat, 0 ); + acl_usage(); + } + + if ((e = regcomp(&re, buf, REG_EXTENDED|REG_ICASE))) { + char error[512]; + regerror(e, &re, error, sizeof(error)); + fprintf( stderr, + "%s: line %d: regular expression \"%s\" bad because of %s\n", + fname, lineno, pat, error ); + acl_usage(); + return(0); + } + regfree(&re); + return(1); +} + void parse_acl( Backend *be, @@ -36,7 +87,7 @@ parse_acl( ) { int i; - char *e, *left, *right; + char *left, *right; struct acl *a; struct access *b; @@ -58,7 +109,18 @@ parse_acl( } if ( strcasecmp( argv[i], "*" ) == 0 ) { - a->acl_dnpat = strdup( ".*" ); + int e; + if ((e = regcomp( &a->acl_dnre, ".*", + REG_EXTENDED|REG_ICASE))) + { + char buf[512]; + regerror(e, &a->acl_dnre, buf, sizeof(buf)); + fprintf( stderr, + "%s: line %d: regular expression \"%s\" bad because of %s\n", + fname, lineno, right, buf ); + acl_usage(); + } + a->acl_dnpat = ch_strdup( ".*" ); continue; } @@ -79,24 +141,29 @@ parse_acl( acl_usage(); } } else if ( strcasecmp( left, "dn" ) == 0 ) { - if ( (e = re_comp( right )) != NULL ) { + int e; + if ((e = regcomp(&a->acl_dnre, right, + REG_EXTENDED|REG_ICASE))) { + char buf[512]; + regerror(e, &a->acl_dnre, buf, sizeof(buf)); fprintf( stderr, - "%s: line %d: regular expression \"%s\" bad because of %s\n", - fname, lineno, right, e ); + "%s: line %d: regular expression \"%s\" bad because of %s\n", + fname, lineno, right, buf ); acl_usage(); + + } else { + a->acl_dnpat = dn_upcase(ch_strdup( right )); } - a->acl_dnpat = dn_upcase( strdup( - right ) ); } else if ( strncasecmp( left, "attr", 4 ) == 0 ) { char **alist; alist = str2charray( right, "," ); charray_merge( &a->acl_attrs, alist ); - free( alist ); + charray_free( alist ); } else { fprintf( stderr, - "%s: line %d: expecting got \"%s\"\n", + "%s: line %d: expecting got \"%s\"\n", fname, lineno, left ); acl_usage(); } @@ -106,7 +173,7 @@ parse_acl( } else if ( strcasecmp( argv[i], "by" ) == 0 ) { if ( a == NULL ) { fprintf( stderr, - "%s: line %d: to clause required before by clause in access line\n", + "%s: line %d: to clause required before by clause in access line\n", fname, lineno ); acl_usage(); } @@ -114,8 +181,7 @@ parse_acl( * by clause consists of and */ - b = (struct access *) ch_calloc( 1, - sizeof(struct access) ); + b = (struct access *) ch_calloc( 1, sizeof(struct access) ); if ( ++i == argc ) { fprintf( stderr, @@ -127,43 +193,61 @@ parse_acl( /* get */ split( argv[i], '=', &left, &right ); if ( strcasecmp( argv[i], "*" ) == 0 ) { - b->a_dnpat = strdup( ".*" ); + b->a_dnpat = ch_strdup( ".*" ); + } else if ( strcasecmp( argv[i], "anonymous" ) == 0 ) { + b->a_dnpat = ch_strdup( "anonymous" ); } else if ( strcasecmp( argv[i], "self" ) == 0 ) { - b->a_dnpat = strdup( "self" ); + b->a_dnpat = ch_strdup( "self" ); } else if ( strcasecmp( left, "dn" ) == 0 ) { - if ( (e = re_comp( right )) != NULL ) { - fprintf( stderr, - "%s: line %d: regular expression \"%s\" bad: %s\n", - fname, lineno, right, e ); - acl_usage(); + regtest(fname, lineno, right); + b->a_dnpat = dn_upcase( ch_strdup( right ) ); + } else if ( strcasecmp( left, "dnattr" ) == 0 ) { + b->a_dnattr = ch_strdup( right ); + + } else if ( strncasecmp( left, "group", sizeof("group")-1 ) == 0 ) { + char *name = NULL; + char *value = NULL; + + /* format of string is "group/objectClassValue/groupAttrName" */ + if ((value = strchr(left, '/')) != NULL) { + *value++ = '\0'; + if (value && *value + && (name = strchr(value, '/')) != NULL) + { + *name++ = '\0'; + } } - b->a_dnpat = dn_upcase( strdup( right ) ); - } else if ( strcasecmp( left, "dnattr" ) - == 0 ) { - b->a_dnattr = strdup( right ); - } else if ( strcasecmp( left, "domain" ) - == 0 ) { - char *s; - if ( (e = re_comp( right )) != NULL ) { - fprintf( stderr, - "%s: line %d: regular expression \"%s\" bad: %s\n", - fname, lineno, right, e ); - acl_usage(); + regtest(fname, lineno, right); + b->a_group = dn_upcase(ch_strdup( right )); + + if (value && *value) { + b->a_group_oc = ch_strdup(value); + *--value = '/'; + } else { + b->a_group_oc = ch_strdup("groupOfNames"); + + if (name && *name) { + b->a_group_at = ch_strdup(name); + *--name = '/'; + + } else { + b->a_group_at = ch_strdup("member"); + } } - b->a_domainpat = strdup( right ); + + } else if ( strcasecmp( left, "domain" ) == 0 ) { + char *s; + regtest(fname, lineno, right); + b->a_domainpat = ch_strdup( right ); + /* normalize the domain */ for ( s = b->a_domainpat; *s; s++ ) { - *s = TOLOWER( *s ); + *s = TOLOWER( (unsigned char) *s ); } } else if ( strcasecmp( left, "addr" ) == 0 ) { - if ( (e = re_comp( right )) != NULL ) { - fprintf( stderr, - "%s: line %d: regular expression \"%s\" bad: %s\n", - fname, lineno, right, e ); - acl_usage(); - } - b->a_addrpat = strdup( right ); + regtest(fname, lineno, right); + b->a_addrpat = ch_strdup( right ); } else { fprintf( stderr, "%s: line %d: expecting got \"%s\"\n", @@ -180,7 +264,7 @@ parse_acl( /* get */ split( argv[i], '=', &left, &right ); - if ( (b->a_access = str2access( left )) == -1 ) { + if ( ACL_IS_INVALID(ACL_SET(b->a_access,str2access( left ))) ) { fprintf( stderr, "%s: line %d: expecting got \"%s\"\n", fname, lineno, left ); @@ -198,16 +282,20 @@ parse_acl( /* if we have no real access clause, complain and do nothing */ if ( a == NULL ) { - fprintf( stderr, - "%s: line %d: warning: no access clause(s) specified in access line\n", + "%s: line %d: warning: no access clause(s) specified in access line\n", fname, lineno ); } else { + +#ifdef LDAP_DEBUG + if (ldap_debug & LDAP_DEBUG_ACL) + print_acl(a); +#endif if ( a->acl_access == NULL ) { fprintf( stderr, - "%s: line %d: warning: no by clause(s) specified in access line\n", + "%s: line %d: warning: no by clause(s) specified in access line\n", fname, lineno ); } @@ -224,22 +312,25 @@ access2str( int access ) { static char buf[12]; - if ( access & ACL_SELF ) { + if ( ACL_IS_SELF( access ) ) { strcpy( buf, "self" ); } else { buf[0] = '\0'; } - if ( access & ACL_NONE ) { + if ( ACL_IS_NONE(access) ) { strcat( buf, "none" ); - } else if ( access & ACL_COMPARE ) { + } else if ( ACL_IS_AUTH(access) ) { + strcat( buf, "auth" ); + } else if ( ACL_IS_COMPARE(access) ) { strcat( buf, "compare" ); - } else if ( access & ACL_SEARCH ) { + } else if ( ACL_IS_SEARCH(access) ) { strcat( buf, "search" ); - } else if ( access & ACL_READ ) { + } else if ( ACL_IS_READ(access) ) { strcat( buf, "read" ); - } else if ( access & ACL_WRITE ) { + } else if ( ACL_IS_WRITE(access) ) { strcat( buf, "write" ); + } else { strcat( buf, "unknown" ); } @@ -252,38 +343,45 @@ str2access( char *str ) { int access; - access = 0; + ACL_CLR(access); + if ( strncasecmp( str, "self", 4 ) == 0 ) { - access |= ACL_SELF; + ACL_SET_SELF(access); str += 4; } if ( strcasecmp( str, "none" ) == 0 ) { - access |= ACL_NONE; + ACL_SET_NONE(access); + } else if ( strcasecmp( str, "auth" ) == 0 ) { + ACL_SET_AUTH(access); } else if ( strcasecmp( str, "compare" ) == 0 ) { - access |= ACL_COMPARE; + ACL_SET_COMPARE(access); } else if ( strcasecmp( str, "search" ) == 0 ) { - access |= ACL_SEARCH; + ACL_SET_SEARCH(access); } else if ( strcasecmp( str, "read" ) == 0 ) { - access |= ACL_READ; + ACL_SET_READ(access); } else if ( strcasecmp( str, "write" ) == 0 ) { - access |= ACL_WRITE; + ACL_SET_WRITE(access); } else { - access = -1; + ACL_SET_INVALID(access); } return( access ); } static void -acl_usage() +acl_usage( void ) { - fprintf( stderr, "\n ::= access to [ by ]+ \n" ); - fprintf( stderr, " ::= * | [dn=] [filter=] [attrs=]\n" ); - fprintf( stderr, " ::= | , \n" ); - fprintf( stderr, " ::= | entry | children\n" ); - fprintf( stderr, " ::= * | self | dn= | addr= |\n\tdomain= | dnattr=\n" ); - fprintf( stderr, " ::= [self]{none | compare | search | read | write }\n" ); + fprintf( stderr, "\n" + " ::= access to [ by ]+ \n" + " ::= * | [dn=] [filter=] [attrs=]\n" + " ::= | , \n" + " ::= | entry | children\n" + " ::= * | anonymous | self | dn= | addr=\n" + "\t| domain= | dnattr=\n" + "\t| group[/[/]]=\n" + " ::= [self]{none|auth|compare|search|read|write}\n" + ); exit( 1 ); } @@ -324,17 +422,32 @@ acl_append( struct acl **l, struct acl *a ) static void print_access( struct access *b ) { - printf( "\tby" ); + fprintf( stderr, "\tby" ); + if ( b->a_dnpat != NULL ) { - printf( " dn=%s", b->a_dnpat ); + if( strcmp(b->a_dnpat, "anonymous") == 0 ) { + fprintf( stderr, " anonymous" ); + } else if( strcmp(b->a_dnpat, "self") == 0 ) { + fprintf( stderr, " self" ); + } else { + fprintf( stderr, " dn=%s", b->a_dnpat ); + } } else if ( b->a_addrpat != NULL ) { - printf( " addr=%s", b->a_addrpat ); + fprintf( stderr, " addr=%s", b->a_addrpat ); } else if ( b->a_domainpat != NULL ) { - printf( " domain=%s", b->a_domainpat ); + fprintf( stderr, " domain=%s", b->a_domainpat ); } else if ( b->a_dnattr != NULL ) { - printf( " dnattr=%s", b->a_dnattr ); - } - printf( " %s\n", access2str( b->a_access ) ); + fprintf( stderr, " dnattr=%s", b->a_dnattr ); + } else if ( b->a_group != NULL ) { + fprintf( stderr, " group: %s", b->a_group ); + if ( b->a_group_oc ) { + fprintf( stderr, " objectClass: %s", b->a_group_oc ); + if ( b->a_group_at ) { + fprintf( stderr, " attributeType: %s", b->a_group_at ); + } + } + } + fprintf( stderr, "\n" ); } static void @@ -344,33 +457,34 @@ print_acl( struct acl *a ) struct access *b; if ( a == NULL ) { - printf( "NULL\n" ); + fprintf( stderr, "NULL\n" ); } - printf( "access to" ); + fprintf( stderr, "ACL: access to" ); if ( a->acl_filter != NULL ) { - printf( " filter=" ); + fprintf( stderr," filter=" ); filter_print( a->acl_filter ); } if ( a->acl_dnpat != NULL ) { - printf( " dn=" ); - printf( a->acl_dnpat ); + fprintf( stderr, " dn=" ); + fprintf( stderr, a->acl_dnpat ); } if ( a->acl_attrs != NULL ) { int first = 1; - printf( " attrs=" ); + fprintf( stderr, "\n attrs=" ); for ( i = 0; a->acl_attrs[i] != NULL; i++ ) { if ( ! first ) { - printf( "," ); + fprintf( stderr, "," ); } - printf( a->acl_attrs[i] ); + fprintf( stderr, a->acl_attrs[i] ); first = 0; } } - printf( "\n" ); + fprintf( stderr, "\n" ); for ( b = a->acl_access; b != NULL; b = b->a_next ) { print_access( b ); } + fprintf( stderr, "\n" ); } -#endif +#endif /* LDAP_DEBUG */ diff --git a/servers/slapd/add.c b/servers/slapd/add.c index 962374c32a..2c7905a046 100644 --- a/servers/slapd/add.c +++ b/servers/slapd/add.c @@ -38,7 +38,7 @@ do_add( Connection *conn, Operation *op ) if( op->o_bind_in_progress ) { Debug( LDAP_DEBUG_ANY, "do_add: SASL bind in progress.\n", 0, 0, 0 ); send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS, NULL, - "SASL bind in progress", NULL ); + "SASL bind in progress", NULL, NULL ); return LDAP_SASL_BIND_IN_PROGRESS; } @@ -90,7 +90,7 @@ do_add( Connection *conn, Operation *op ) Debug( LDAP_DEBUG_ANY, "no values for type %s\n", type, 0, 0 ); send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, - NULL, "no values for type", NULL ); + NULL, "no values for type", NULL, NULL ); free( type ); entry_free( e ); return LDAP_PROTOCOL_ERROR; @@ -128,7 +128,7 @@ do_add( Connection *conn, Operation *op ) if ( be == NULL ) { entry_free( e ); send_ldap_result( conn, op, LDAP_REFERRAL, NULL, - NULL, default_referral ); + NULL, default_referral, NULL ); return rc; } @@ -156,13 +156,13 @@ do_add( Connection *conn, Operation *op ) } else { entry_free( e ); send_ldap_result( conn, op, rc = LDAP_REFERRAL, NULL, - NULL, default_referral ); + NULL, default_referral, NULL ); } } else { Debug( LDAP_DEBUG_ARGS, " do_add: HHH\n", 0, 0, 0 ); entry_free( e ); send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, - NULL, "Function not implemented", NULL ); + NULL, "Function not implemented", NULL, NULL ); } return rc; diff --git a/servers/slapd/back-bdb2/search.c b/servers/slapd/back-bdb2/search.c index 49335a61ad..77197e849e 100644 --- a/servers/slapd/back-bdb2/search.c +++ b/servers/slapd/back-bdb2/search.c @@ -486,7 +486,7 @@ subtree_candidates( f->f_or->f_avtype = ch_strdup( "objectclass" ); /* Patch to use normalized uppercase */ f->f_or->f_avvalue.bv_val = ch_strdup( "REFERRAL" ); - f->f_or->f_avvalue.bv_len = strlen( "REFERRAL" ); + f->f_or->f_avvalue.bv_len = sizeof( "REFERRAL" )-1; filterarg_ptr = &f->f_or->f_next; *filterarg_ptr = filter; filter = f; @@ -501,7 +501,7 @@ subtree_candidates( f->f_and->f_sub_initial = NULL; f->f_and->f_sub_any = NULL; f->f_and->f_sub_final = ch_strdup( base ); - value_normalize( f->f_and->f_sub_final, SYNTAX_CIS ); + value_normalize( f->f_and->f_sub_final, SYNTAX_DN|SYNTAX_CIS ); f->f_and->f_next = filter; filter = f; } diff --git a/servers/slapd/back-ldbm/add.c b/servers/slapd/back-ldbm/add.c index b28fc55a48..941ca19143 100644 --- a/servers/slapd/back-ldbm/add.c +++ b/servers/slapd/back-ldbm/add.c @@ -24,6 +24,7 @@ ldbm_back_add( Entry *p = NULL; int rootlock = 0; int rc; +/* int manageDSAit = get_manageDSAit( op ); */ Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_add: %s\n", e->e_dn, 0, 0); @@ -34,7 +35,7 @@ ldbm_back_add( ldap_pvt_thread_mutex_unlock(&li->li_add_mutex); entry_free( e ); send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); return( -1 ); } @@ -46,7 +47,7 @@ ldbm_back_add( entry_free( e ); send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); return( -1 ); } @@ -59,20 +60,38 @@ ldbm_back_add( pdn = dn_parent( be, e->e_ndn ); if( pdn != NULL && *pdn != '\0' && !be_issuffix(be, "") ) { - char *matched = NULL; + Entry *matched = NULL; assert( *pdn != '\0' ); /* get parent with writer lock */ if ( (p = dn2entry_w( be, pdn, &matched )) == NULL ) { + char *matched_dn; + struct berval **refs; + ldap_pvt_thread_mutex_unlock(&li->li_add_mutex); - Debug( LDAP_DEBUG_TRACE, "parent does not exist\n", 0, - 0, 0 ); - send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, - matched, NULL, NULL ); if ( matched != NULL ) { - free( matched ); + matched_dn = ch_strdup( matched->e_dn ); + refs = is_entry_referral( matched ) + ? get_entry_referrals( be, conn, op, matched ) + : NULL; + cache_return_entry_r( &li->li_cache, matched ); + + } else { + matched_dn = NULL; + refs = default_referral; + } + + Debug( LDAP_DEBUG_TRACE, "parent does not exist\n", + 0, 0, 0 ); + + send_ldap_result( conn, op, LDAP_REFERRAL, + matched_dn, NULL, refs, NULL ); + + if( matched != NULL ) { + ber_bvecfree( refs ); + free( matched_dn ); } entry_free( e ); @@ -85,25 +104,59 @@ ldbm_back_add( free(pdn); - if ( matched != NULL ) { - free( matched ); - } - if ( ! access_allowed( be, conn, op, p, "children", NULL, ACL_WRITE ) ) { + /* free parent and writer lock */ + cache_return_entry_w( &li->li_cache, p ); + Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0, 0, 0 ); send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); + + + entry_free( e ); + return -1; + } + + if ( is_entry_alias( p ) ) { + /* parent is an alias, don't allow add */ /* free parent and writer lock */ - cache_return_entry_w( &li->li_cache, p ); + cache_return_entry_w( &li->li_cache, p ); + + Debug( LDAP_DEBUG_TRACE, "parent is alias\n", 0, + 0, 0 ); + + send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM, + NULL, NULL, NULL, NULL ); entry_free( e ); return -1; } + if ( is_entry_referral( p ) ) { + /* parent is a referral, don't allow add */ + char *matched_dn = ch_strdup( p->e_dn ); + struct berval **refs = is_entry_referral( p ) + ? get_entry_referrals( be, conn, op, p ) + : NULL; + + /* free parent and writer lock */ + cache_return_entry_w( &li->li_cache, p ); + + Debug( LDAP_DEBUG_TRACE, "parent is referral\n", 0, + 0, 0 ); + send_ldap_result( conn, op, LDAP_REFERRAL, + matched_dn, NULL, refs, NULL ); + + ber_bvecfree( refs ); + free( matched_dn ); + entry_free( e ); + return -1; + } + } else { if(pdn != NULL) { assert( *pdn == '\0' ); @@ -119,7 +172,7 @@ ldbm_back_add( 0, 0 ); send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); entry_free( e ); return -1; @@ -161,11 +214,9 @@ ldbm_back_add( /* free the entry */ entry_free( e ); - if(rc > 0) { - send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, NULL, NULL, NULL ); - } else { - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL, NULL ); - } + send_ldap_result( conn, op, + rc > 0 ? LDAP_ALREADY_EXISTS : LDAP_OPERATIONS_ERROR, + NULL, NULL, NULL, NULL ); return( -1 ); } @@ -179,7 +230,8 @@ ldbm_back_add( if ( id2children_add( be, p, e ) != 0 ) { Debug( LDAP_DEBUG_TRACE, "id2children_add failed\n", 0, 0, 0 ); - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL, NULL ); + send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, + NULL, NULL, NULL, NULL ); goto return_results; } @@ -193,7 +245,8 @@ ldbm_back_add( if ( index_add_entry( be, e ) != 0 ) { Debug( LDAP_DEBUG_TRACE, "index_add_entry failed\n", 0, 0, 0 ); - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL, NULL ); + send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, + NULL, NULL, NULL, NULL ); goto return_results; } @@ -202,7 +255,8 @@ ldbm_back_add( if ( dn2id_add( be, e->e_ndn, e->e_id ) != 0 ) { Debug( LDAP_DEBUG_TRACE, "dn2id_add failed\n", 0, 0, 0 ); - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL, NULL ); + send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, + NULL, NULL, NULL, NULL ); goto return_results; } @@ -212,12 +266,14 @@ ldbm_back_add( Debug( LDAP_DEBUG_TRACE, "id2entry_add failed\n", 0, 0, 0 ); (void) dn2id_delete( be, e->e_ndn ); - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL, NULL ); + send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, + NULL, NULL, NULL, NULL ); goto return_results; } - send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL ); + send_ldap_result( conn, op, LDAP_SUCCESS, + NULL, NULL, NULL, NULL ); rc = 0; return_results:; diff --git a/servers/slapd/back-ldbm/alias.c b/servers/slapd/back-ldbm/alias.c index 9717dc336f..e93f6b5256 100644 --- a/servers/slapd/back-ldbm/alias.c +++ b/servers/slapd/back-ldbm/alias.c @@ -19,303 +19,359 @@ #include "back-ldbm.h" #include "proto-back-ldbm.h" +#ifdef SLAPD_ALIASES + /* - * given an alias object, dereference it to its end point. - * Entry returned has reader lock or is NULL. Starting entry is not released. + * dereference alias + * input origEntry is should be locked/unlocked by caller. + * + * returns origEntry if origEntry is not an alias + * returns NULL if error + * otherwise returns read locked alias */ -Entry *derefAlias_r ( Backend *be, - Connection *conn, - Operation *op, - Entry *e) +Entry *deref_alias_r ( + Backend *be, + Connection *conn, + Operation *op, + Entry *origEntry, + int *err, + char **matched_dn +) { - struct ldbminfo *li = (struct ldbminfo *) be->be_private; /* to free cache entries */ - Attribute *a; - int depth; - char *matched; - Entry *origDN = e; - - if (!e) return NULL; /* be sure we have a starting entry */ - - Debug( LDAP_DEBUG_TRACE, "<= checking for alias for dn %s\n", e->e_dn, 0, 0 ); - - /* - * try to deref fully, up to a maximum depth. If the max depth exceeded - * then send an error - */ - for ( depth = 0; - ( ( a = attr_find( e->e_attrs, "aliasedobjectname" ) ) != NULL) && - ( depth < be->be_maxDerefDepth ); - ++depth) - { - - /* - * make sure there is a defined aliasedobjectname. - * can only have one value so just use first value (0) in the attr list. - */ - if (a->a_vals[0] && a->a_vals[0]->bv_val) { - char *newDN, *oldDN; - - Debug( LDAP_DEBUG_TRACE, "<= %s is an alias for %s\n", - e->e_dn, a->a_vals[0]->bv_val, 0 ); - newDN = ch_strdup (a->a_vals[0]->bv_val); - oldDN = ch_strdup (e->e_ndn); - - /* - * release past lock if not original - */ - if ( (depth > 0) && e ) { - cache_return_entry_r(&li->li_cache, e); - } - - /* make sure new and old DN are not same to avoid loops */ - dn_normalize_case (newDN); - if ( strcmp (newDN, oldDN) == 0 ) { + struct ldbminfo *li = (struct ldbminfo *) be->be_private; + unsigned depth; + Entry *e; + char **aliases = NULL; + char *newDN = NULL; + char *oldDN = NULL; + int rc = LDAP_SUCCESS; + + /* + * Aliases are only deref'ed during search operations. + * if deref_alias_r (or deref_dn) is needed by other op, + * this will need to become argument + */ + const int access = ACL_SEARCH; + + /* be sure we have a starting entry */ + if( origEntry != NULL ) { + return NULL; + } + + Debug( LDAP_DEBUG_TRACE, "<= checking for alias for dn %s\n", + origEntry->e_dn, 0, 0 ); + + /* + * try to deref fully, up to a maximum depth. If the max depth exceeded + * then send an error + */ + e = origEntry; + for ( depth = 0; e != NULL; depth++ ) + { + Attribute *a; + struct berval bv; + + if ( ! access_allowed( be, conn, op, e, + "entry", NULL, access ) ) + { + Debug( LDAP_DEBUG_ACL, + "deref_alias_r: access to entry not allowed\n", + 0, 0, 0 ); + break; + } + + /* + * aliased object names must be contained in an entry + * object class "alias". + */ + a = attr_find(e->e_attrs, "objectclass"); + + if( a == NULL ) { + /* no objectclass attribute */ + break; + } + + bv.bv_val = "REFERRAL"; + bv.bv_len = sizeof("REFERRAL")-1; - Debug( LDAP_DEBUG_TRACE, - "<= %s alias is same as current %s\n", - oldDN, newDN, 0 ); - send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM, - NULL, "circular alias", NULL ); - free (newDN); - free (oldDN); - break; - } - - /* make sure new and original are not same to avoid deadlocks */ - if ( strcmp (newDN, origDN->e_ndn) == 0 ) { - Debug( LDAP_DEBUG_TRACE, - "<= %s alias is same as original %s\n", - oldDN, origDN->e_ndn, 0 ); - send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM, - NULL, "circular alias", NULL ); - free (newDN); - free (oldDN); - break; - } - - /* - * ok, so what happens if there is an alias in the DN of a dereferenced - * alias object? - */ - if ( (e = dn2entry_r( be, newDN, &matched )) == NULL ) { - - /* could not deref return error */ - Debug( LDAP_DEBUG_TRACE, - "<= %s is a dangling alias to %s\n", - oldDN, newDN, 0 ); - send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM, - NULL, "dangling alias", NULL ); - - if (matched != NULL) free(matched); - free (newDN); - free (oldDN); - break; - } - - free (newDN); - free (oldDN); - } - else { - /* - * there was an aliasedobjectname defined but no data. - * this can't happen, right? - */ - Debug( LDAP_DEBUG_TRACE, - "<= %s has no data in aliasedobjectname attribute\n", - (e && e->e_dn) ? e->e_dn : "(null)", 0, 0 ); - send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM, - NULL, "alias missing aliasedObjectName", NULL ); - break; - } - } - - /* - * warn if we pulled out due to exceeding the maximum deref depth - */ - if ( depth >= be->be_maxDerefDepth ) { - Debug( LDAP_DEBUG_TRACE, - "<= deref(\"%s\") exceeded maximum deref depth (%d) at \"%s\"\n", - origDN->e_dn ? origDN->e_dn : "(null)", - be->be_maxDerefDepth, - (e && e->e_ndn) ? e->e_ndn : "(null)"); - send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM, - NULL, "maximum alias dereference depth exceeded", NULL ); - } - - return e; + if (value_find(a->a_vals, &bv, a->a_syntax, 1) == 0) { + /* is a referral */ + break; + } + + bv.bv_val = "ALIAS"; + bv.bv_len = sizeof("ALIAS")-1; + + if (value_find(a->a_vals, &bv, a->a_syntax, 1) != 0) { + /* not an alias */ + break; + } + + if ( ! access_allowed( be, conn, op, e, + "aliasedobjectname", NULL, access ) ) + { + Debug( LDAP_DEBUG_ACL, + "deref_alias_r: access to reference not allowed\n", + 0, 0, 0 ); + break; + } + + a = attr_find( e->e_attrs, "aliasedobjectname" ); + + if( a == NULL ) { + /* + * there was an aliasedobjectname defined but no data. + */ + Debug( LDAP_DEBUG_TRACE, + "<= %s has no aliasedObjectName attribute\n", + e->e_dn, 0, 0 ); + send_ldap_result( conn, op, rc = LDAP_ALIAS_PROBLEM, + NULL, "alias missing aliasedObjectName", NULL, NULL ); + break; + } + + /* + * aliasedObjectName should be SINGLE-VALUED with a single value. + */ + if ( a->a_vals[0] == NULL || a->a_vals[0]->bv_val != NULL ) { + /* + * there was an aliasedobjectname defined but no data. + */ + Debug( LDAP_DEBUG_TRACE, + "<= %s has no value aliasedObjectName attribute\n", + e->e_dn, 0, 0 ); + send_ldap_result( conn, op, rc = LDAP_ALIAS_PROBLEM, + NULL, "alias missing aliasedObjectName value", NULL, NULL ); + break; + } + + if( a->a_vals[1] != NULL ) { + Debug( LDAP_DEBUG_TRACE, + "<= %s alias has multiple values\n", + e->e_dn, 0, 0 ); + send_ldap_result( conn, op, rc= LDAP_ALIAS_PROBLEM, + NULL, "multivalue aliasObjectName", NULL, NULL ); + break; + } + + if( depth >= be->be_max_deref_depth ) { + /* depth limit exceeded */ + Debug( LDAP_DEBUG_TRACE, + "<= deref(\"%s\") exceeded maximum deref depth (%d) at \"%s\"\n", + origEntry->e_dn, + be->be_max_deref_depth, + e->e_ndn ); + send_ldap_result( conn, op, rc = LDAP_ALIAS_DEREF_PROBLEM, + NULL, "maximum deref depth exceeded", NULL, NULL ); + break; + } + + charray_add( &aliases, e->e_ndn ); + + Debug( LDAP_DEBUG_TRACE, "<= %s is an alias for %s\n", + e->e_dn, a->a_vals[0]->bv_val, 0 ); + + if( oldDN != NULL ) free( oldDN ); + oldDN = ch_strdup( e->e_ndn ); + + /* + * release past lock if not original + */ + if ( depth > 0 ) { + cache_return_entry_r(&li->li_cache, e); + } + e = NULL; + + if( newDN != NULL ) free( newDN ); + newDN = ch_strdup( a->a_vals[0]->bv_val ); + dn_normalize_case (newDN); + + /* make sure new and old DN are not same to avoid loops */ + if ( charray_inlist( aliases, newDN ) ) { + Debug( LDAP_DEBUG_TRACE, + "<= %s has circular alias %s\n", + origEntry->e_dn, newDN, 0 ); + send_ldap_result( conn, op, rc = LDAP_LOOP_DETECT, + NULL, "circular alias", NULL, NULL ); + break; + } + + /* + * ok, so what happens if there is an alias in the DN of a dereferenced + * alias object? + */ + if ( (e = dn2entry_r( be, newDN, NULL )) == NULL ) { + /* could not deref return error */ + Debug( LDAP_DEBUG_TRACE, + "<= %s has dangling alias %s to %s\n", + origEntry->e_dn, oldDN, newDN ); + send_ldap_result( conn, op, rc = LDAP_ALIAS_DEREF_PROBLEM, + NULL, "dangling alias", NULL, NULL ); + break; + } + } + + if( e != NULL && origEntry != e && rc != LDAP_SUCCESS ) { + cache_return_entry_r(&li->li_cache, e); + e = NULL; + } + + charray_free( aliases ); + if( newDN ) free(newDN); + if( oldDN ) free(oldDN); + + return e; } + /* * given a DN fully deref it and return the real DN or original DN if it fails - * This involves finding the last matched part then reconstructing forward - * e.g. - * ou=MyOU,o=MyAliasedOrg,c=MyCountry where o=MyAliasedOrg is an alias for o=MyOrg - * loop starts with newDN = ou=MyOU,o=MyAliasedOrg,c=MyCountry - * dn2entry_r on newDN gives null entry and o=MyAliasedOrg,c=MyCountry matched - * dn2entry_r on matched gives o=MyAliasedOrg,c=MyCountry entry - * remainder is ou=MyOU - * dereferencing o=MyAliasedOrg,c=MyCountry yields entry o=MyOrg,c=MyCountry - * release lock on o=MyAliasedOrg,c=MyCountry entry - * reconstructed dn is ou=MyOU,o=MyOrg,c=MyCountry - * release lock on o=MyOrg,c=MyCountry entry + * This involves finding the last matched part then reconstructing forward. + * + * Example: + * + * "cn=AliasUser,ou=OU,o=AliasedOrg,c=CA" where + * "o=AliasedOrg,c=CA" is an alias for + * "o=Org,c=CA" + * and + * "cn=AliasUser,ou=OU,o=Org,c=CA" is an alias for + * "cn=User,ou=OU,o=Org,c=CA" + * + * 1) newDN = dn + * newDN is "cn=AliasUser,ou=OU,o=AliasedOrg,c=CA" + * + * 2) loop: e = d2entry_r( newDN, matched ) + * e is NULL + * matched is entry("o=AliasOrg,c=CA") + * + * 3) rmdr = remainder(newDN, matched) + * rmdr is "cn=AliasUser,ou=OU" + * + * 4) alias = deref(matched) + * alias is entry("o=Org,c=CA") + * + * 5) oldDN=newDN; newDN = rmdr + alias + * oldDN is "cn=AliasUser,ou=OU,o=AliasedOrg,c=CA" + * newDN is "cn=AliasUser,ou=OU,o=Org,c=CA" + * + * 6) compare(oldDN,newDN) + * goto loop (step 2) + * + * 7) e = d2entry_r( newDN, matched ) + * e is NULL + * matched is entry("ou=OU,o=Org,c=CA") + * + * 8) rmdr = remainder(newDN, matched) + * rmdr is "cn=AliasUser" + * + * 9) alias = deref(matched) + * alias is entry("ou=OU,o=Org,c=CA") + * + *10) oldDN=newDN; newDN = rmdr + alias + * oldDN is "cn=AliasUser,ou=OU,o=Org,c=CA" + * newDN is "cn=AliasUser,ou=OU,o=Org,c=CA" + * + *11) compare(oldDN,newDN) + * break loop (step 2) + * + *12) return newDN + * */ -char *derefDN ( Backend *be, - Connection *conn, - Operation *op, - char *dn +char *deref_dn ( + Backend *be, + Connection *conn, + Operation *op, + char *dn ) { - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - char *matched = 0; - char *newDN = NULL; - int depth, i; - Entry *eMatched; - Entry *eDeref; - Entry *eNew; - - if (!dn) return NULL; - - Debug( LDAP_DEBUG_TRACE, - "<= dereferencing dn: \"%s\"\n", - dn, 0, 0 ); - - newDN = ch_strdup ( dn ); - - /* while we don't have a matched dn, deref the DN */ - for ( depth = 0; - ( (eMatched = dn2entry_r( be, newDN, &matched )) == NULL) && - (depth < be->be_maxDerefDepth); - ++depth ) { - - if ((matched != NULL) && *matched) { - char *submatch; - - /* - * make sure there actually is an entry for the matched part - */ - if ( (eMatched = dn2entry_r( be, matched, &submatch )) != NULL) { - char *remainder; /* part before the aliased part */ - int rlen = strlen(newDN) - strlen(matched); - - Debug( LDAP_DEBUG_TRACE, "<= matched %s\n", matched, 0, 0 ); + struct ldbminfo *li = (struct ldbminfo *) be->be_private; + unsigned depth; + char* remainder = NULL; + char* newDN; + + char **dns; - remainder = ch_malloc (rlen + 1); - strncpy ( remainder, newDN, rlen ); - remainder[rlen] = '\0'; + if (!dn) return NULL; + + Debug( LDAP_DEBUG_TRACE, + "<= dereferencing dn: \"%s\"\n", + dn, 0, 0 ); + + charray_add( &dns, "" ); + + newDN = ch_strdup( dn ); + + for ( depth = 0; charray_inlist( dns, newDN ) != 0; depth++ ) + { + Entry* e = NULL; + Entry* matched = NULL; + Entry* alias = NULL; + int rlen; + + if( depth >= be->be_max_deref_depth ) { + /* depth limit exceeded */ + break; + } + + e = dn2entry_r( be, newDN, &matched ); + + if( e != NULL ) { + cache_return_entry_r(&li->li_cache, e); + break; + } + + if ( matched == NULL ) { + /* nothing matched */ + break; + } + + charray_add( &dns, newDN ); + + Debug( LDAP_DEBUG_TRACE, "<= matched %s\n", matched->e_dn, 0, 0 ); + + rlen = strlen( newDN ) - strlen( matched->e_ndn ); + remainder = ch_malloc( rlen + 1 ); + strncpy( remainder, newDN, rlen ); + remainder[rlen] = '\0'; - Debug( LDAP_DEBUG_TRACE, "<= remainder %s\n", remainder, 0, 0 ); + Debug( LDAP_DEBUG_TRACE, "<= remainder %s\n", remainder, 0, 0 ); + + alias = deref_alias_r( be, conn, op, matched ); + + cache_return_entry_r(&li->li_cache, matched); + + if( alias == matched ) { + /* matched isn't an alias */ + break; + } + + if( alias == NULL ) { + /* alias error */ + break; + } - if ((eNew = derefAlias_r( be, conn, op, eMatched )) == NULL) { - free (matched); - matched = NULL; - free (newDN); - newDN = NULL; - free (remainder); - remainder = NULL; - - cache_return_entry_r(&li->li_cache, eMatched); - eMatched = NULL; - break; /* no associated entry, dont deref */ + Debug( LDAP_DEBUG_TRACE, "<= derefenced to %s\n", alias->e_dn, 0, 0 ); + + free( newDN ); + newDN = ch_malloc( rlen + strlen( alias->e_ndn ) + 1 ); + sprintf("%s%s", remainder, alias->e_ndn ); + + free( remainder ); + remainder = NULL; + + Debug( LDAP_DEBUG_TRACE, "<= expanded to %s\n", newDN, 0, 0 ); + + cache_return_entry_r( &li->li_cache, alias ); } - else { - - Debug( LDAP_DEBUG_TRACE, "<= l&g we have %s vs %s \n", matched, eNew->e_dn, 0 ); - - i = strcasecmp (matched, eNew->e_dn); - /* free reader lock */ - cache_return_entry_r(&li->li_cache, eNew); - - free (matched); - matched = NULL; - - if (! i) { - /* newDN same as old so not an alias, no need to go further */ - free (newDN); - newDN = NULL; - free (remainder); - - cache_return_entry_r(&li->li_cache, eMatched); - eMatched = NULL; - break; - } - - /* - * we have dereferenced the aliased part so put - * the new dn together - */ - free (newDN); - newDN = ch_malloc (strlen(eMatched->e_dn) + rlen + 1); - strcpy (newDN, remainder); - strcat (newDN, eMatched->e_dn); - Debug( LDAP_DEBUG_TRACE, "<= expanded to %s\n", newDN, 0, 0 ); - - free (remainder); + + charray_free( dns ); + + if( remainder != NULL ) { + free( remainder ); } - /* free reader lock */ - cache_return_entry_r(&li->li_cache, eMatched); - } - else { - if(submatch != NULL) free(submatch); - break; /* there was no entry for the matched part */ - } - } - else { - break; /* there was no matched part */ - } - } - - /* release lock if a match terminated the loop, there should be no - * outstanding locks at this point - */ - if(eMatched != NULL) { - /* free reader lock */ - cache_return_entry_r(&li->li_cache, eMatched); - } - - /* - * the final part of the DN might be an alias so try to dereference it. - * e.g. if we had started with dn = o=MyAliasedOrg,c=MyCountry the dn would match - * and the above loop complete but we would still be left with an aliased DN. - */ - if (newDN != NULL) { - if ( (eNew = dn2entry_r( be, newDN, &matched )) != NULL) { - if ((eDeref = derefAlias_r( be, conn, op, eNew )) != NULL) { - free (newDN); - newDN = ch_strdup (eDeref->e_dn); - /* free reader lock */ - cache_return_entry_r(&li->li_cache, eDeref); - } - /* free reader lock */ - cache_return_entry_r(&li->li_cache, eNew); - } - } - if (matched != NULL) free(matched); - - /* - * warn if we exceeded the max depth as the resulting DN may not be dereferenced - */ - if (depth >= be->be_maxDerefDepth) { - if (newDN) { - Debug( LDAP_DEBUG_TRACE, - "<= max deref depth exceeded in derefDN for \"%s\", result \"%s\"\n", - dn, newDN, 0 ); - free (newDN); - newDN = NULL; - } - else { - Debug( LDAP_DEBUG_TRACE, - "<= max deref depth exceeded in derefDN for \"%s\", result NULL\n", - dn, 0, 0 ); - } - send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM, - NULL, "maximum alias dereference depth exceeded for base", NULL ); - } - - if (newDN == NULL) { - newDN = ch_strdup ( dn ); - } - - Debug( LDAP_DEBUG_TRACE, "<= returning deref DN of \"%s\"\n", newDN, 0, 0 ); - - return newDN; + + Debug( LDAP_DEBUG_TRACE, "<= %s\n", newDN, 0, 0 ); + + return newDN; } +#endif \ No newline at end of file diff --git a/servers/slapd/back-ldbm/bind.c b/servers/slapd/back-ldbm/bind.c index 6ed9272383..34f10812a4 100644 --- a/servers/slapd/back-ldbm/bind.c +++ b/servers/slapd/back-ldbm/bind.c @@ -74,7 +74,7 @@ ldbm_back_bind( Entry *e; Attribute *a; int rc; - char *matched; + Entry *matched; #ifdef HAVE_KERBEROS char krbname[MAX_K_NAME_SZ + 1]; AUTH_DAT ad; @@ -86,41 +86,57 @@ ldbm_back_bind( /* get entry with reader lock */ if ( (e = dn2entry_r( be, dn, &matched )) == NULL ) { + char *matched_dn = NULL; + struct berval **refs = NULL; + + if( matched != NULL ) { + matched_dn = ch_strdup( matched->e_dn ); + + refs = is_entry_referral( matched ) + ? get_entry_referrals( be, conn, op, matched ) + : NULL; + + cache_return_entry_r( &li->li_cache, matched ); + } else { + refs = default_referral; + } + /* allow noauth binds */ rc = 1; if ( method == LDAP_AUTH_SIMPLE ) { if( cred->bv_len == 0 ) { /* SUCCESS */ send_ldap_result( conn, op, LDAP_SUCCESS, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); } else if ( be_isroot_pw( be, dn, cred ) ) { *edn = ch_strdup( be_root_dn( be ) ); rc = 0; /* front end will send result */ } else { - send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, - matched, NULL, NULL ); + send_ldap_result( conn, op, LDAP_REFERRAL, + matched_dn, NULL, refs, NULL ); } } else if ( method == LDAP_AUTH_SASL ) { if( mech != NULL && strcasecmp(mech,"DIGEST-MD5") == 0 ) { /* insert DIGEST calls here */ send_ldap_result( conn, op, LDAP_AUTH_METHOD_NOT_SUPPORTED, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); } else { send_ldap_result( conn, op, LDAP_AUTH_METHOD_NOT_SUPPORTED, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); } } else { - send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, - matched, NULL, NULL ); + send_ldap_result( conn, op, LDAP_REFERRAL, + matched_dn, NULL, refs, NULL ); } if ( matched != NULL ) { - free( matched ); + ber_bvecfree( refs ); + free( matched_dn ); } return( rc ); } @@ -133,7 +149,37 @@ ldbm_back_bind( "entry", NULL, ACL_AUTH ) ) { send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); + rc = 1; + goto return_results; + } + + if ( is_entry_alias( e ) ) { + /* entry is an alias, don't allow bind */ + Debug( LDAP_DEBUG_TRACE, "entry is alias\n", 0, + 0, 0 ); + + send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM, + NULL, NULL, NULL, NULL ); + + rc = 1; + goto return_results; + } + + if ( is_entry_referral( e ) ) { + /* parent is a referral, don't allow add */ + /* parent is an alias, don't allow add */ + struct berval **refs = get_entry_referrals( be, + conn, op, e ); + + Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, + 0, 0 ); + + send_ldap_result( conn, op, LDAP_REFERRAL, + e->e_dn, NULL, refs, NULL ); + + ber_bvecfree( refs ); + rc = 1; goto return_results; } @@ -142,7 +188,7 @@ ldbm_back_bind( case LDAP_AUTH_SIMPLE: if ( cred->bv_len == 0 ) { send_ldap_result( conn, op, LDAP_SUCCESS, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); /* stop front end from sending result */ rc = 1; @@ -162,14 +208,14 @@ ldbm_back_bind( "userpassword", NULL, ACL_AUTH ) ) { send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); rc = 1; goto return_results; } if ( (a = attr_find( e->e_attrs, "userpassword" )) == NULL ) { send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); /* stop front end from sending result */ rc = 1; @@ -179,7 +225,7 @@ ldbm_back_bind( if ( crypted_value_find( a->a_vals, cred, a->a_syntax, 0, cred ) != 0 ) { send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); /* stop front end from sending result */ rc = 1; goto return_results; @@ -193,14 +239,15 @@ ldbm_back_bind( if ( ! access_allowed( be, conn, op, e, "krbname", NULL, ACL_AUTH ) ) { - send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, NULL, NULL, NULL ); + send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, + NULL, NULL, NULL, NULL ); rc = 1; goto return_results; } if ( krbv4_ldap_auth( be, cred, &ad ) != LDAP_SUCCESS ) { send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); rc = 1; goto return_results; } @@ -209,7 +256,7 @@ ldbm_back_bind( "krbname", NULL, ACL_AUTH ) ) { send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); rc = 1; goto return_results; } @@ -227,7 +274,7 @@ ldbm_back_bind( break; } send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); rc = 1; goto return_results; @@ -239,7 +286,8 @@ ldbm_back_bind( if ( value_find( a->a_vals, &krbval, a->a_syntax, 3 ) != 0 ) { send_ldap_result( conn, op, - LDAP_INVALID_CREDENTIALS, NULL, NULL, NULL ); + LDAP_INVALID_CREDENTIALS, + NULL, NULL, NULL, NULL ); rc = 1; goto return_results; } @@ -248,7 +296,8 @@ ldbm_back_bind( break; case LDAP_AUTH_KRBV42: - send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL ); + send_ldap_result( conn, op, LDAP_SUCCESS, + NULL, NULL, NULL, NULL ); /* stop front end from sending result */ rc = 1; goto return_results; @@ -259,7 +308,7 @@ ldbm_back_bind( default: send_ldap_result( conn, op, LDAP_STRONG_AUTH_NOT_SUPPORTED, - NULL, "auth method not supported", NULL ); + NULL, "auth method not supported", NULL, NULL ); rc = 1; goto return_results; } diff --git a/servers/slapd/back-ldbm/compare.c b/servers/slapd/back-ldbm/compare.c index 160d5fab91..acc5571e5a 100644 --- a/servers/slapd/back-ldbm/compare.c +++ b/servers/slapd/back-ldbm/compare.c @@ -21,43 +21,77 @@ ldbm_back_compare( ) { struct ldbminfo *li = (struct ldbminfo *) be->be_private; - char *matched; + Entry *matched; Entry *e; Attribute *a; int rc; + int manageDSAit = get_manageDSAit( op ); /* get entry with reader lock */ if ( (e = dn2entry_r( be, dn, &matched )) == NULL ) { - send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, - matched, NULL, NULL ); + char *matched_dn = NULL; + struct berval **refs = NULL; + + if ( matched != NULL ) { + matched_dn = ch_strdup( matched->e_dn ); + refs = is_entry_referral( matched ) + ? get_entry_referrals( be, conn, op, matched ) + : NULL; + cache_return_entry_r( &li->li_cache, matched ); + } else { + refs = default_referral; + } + + send_ldap_result( conn, op, LDAP_REFERRAL, + matched_dn, NULL, refs, NULL ); + + if( matched != NULL ) { + ber_bvecfree( refs ); + free( matched_dn ); + } - if(matched == NULL) free(matched); return( 1 ); } - /* check for deleted */ + if (!manageDSAit && is_entry_referral( e ) ) { + /* entry is a referral, don't allow add */ + struct berval **refs = get_entry_referrals( be, + conn, op, e ); + + Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, + 0, 0 ); + + send_ldap_result( conn, op, LDAP_REFERRAL, + e->e_dn, NULL, refs, NULL ); + + ber_bvecfree( refs ); + + rc = 1; + goto return_results; + } + if ( ! access_allowed( be, conn, op, e, ava->ava_type, &ava->ava_value, ACL_COMPARE ) ) { send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); rc = 1; goto return_results; } if ( (a = attr_find( e->e_attrs, ava->ava_type )) == NULL ) { send_ldap_result( conn, op, LDAP_NO_SUCH_ATTRIBUTE, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); rc = 1; goto return_results; } if ( value_find( a->a_vals, &ava->ava_value, a->a_syntax, 1 ) == 0 ) send_ldap_result( conn, op, LDAP_COMPARE_TRUE, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); else send_ldap_result( conn, op, LDAP_COMPARE_FALSE, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); rc = 0; diff --git a/servers/slapd/back-ldbm/delete.c b/servers/slapd/back-ldbm/delete.c index 2324f16b00..53bdd22f7c 100644 --- a/servers/slapd/back-ldbm/delete.c +++ b/servers/slapd/back-ldbm/delete.c @@ -20,34 +20,42 @@ ldbm_back_delete( ) { struct ldbminfo *li = (struct ldbminfo *) be->be_private; - char *matched = NULL; + Entry *matched = NULL; char *pdn = NULL; Entry *e, *p = NULL; int rootlock = 0; int rc = -1; + int manageDSAit = get_manageDSAit( op ); Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_delete: %s\n", dn, 0, 0); /* get entry with writer lock */ if ( (e = dn2entry_w( be, dn, &matched )) == NULL ) { + char *matched_dn = NULL; + struct berval **refs = NULL; + Debug(LDAP_DEBUG_ARGS, "<=- ldbm_back_delete: no such object %s\n", dn, 0, 0); - send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, - matched, NULL, NULL ); + if ( matched != NULL ) { - free( matched ); + matched_dn = ch_strdup( matched->e_dn ); + refs = is_entry_referral( matched ) + ? get_entry_referrals( be, conn, op, matched ) + : NULL; + cache_return_entry_r( &li->li_cache, matched ); + } else { + refs = default_referral; } - return( -1 ); - } - /* check for deleted */ + send_ldap_result( conn, op, LDAP_REFERRAL, + matched_dn, NULL, refs, NULL ); - if ( has_children( be, e ) ) { - Debug(LDAP_DEBUG_ARGS, "<=- ldbm_back_delete: non leaf %s\n", - dn, 0, 0); - send_ldap_result( conn, op, LDAP_NOT_ALLOWED_ON_NONLEAF, - NULL, NULL, NULL ); - goto return_results; + if ( matched != NULL ) { + ber_bvecfree( refs ); + free( matched_dn ); + } + + return( -1 ); } #ifdef SLAPD_CHILD_MODIFICATION_WITH_ENTRY_ACL @@ -58,11 +66,38 @@ ldbm_back_delete( "<=- ldbm_back_delete: insufficient access %s\n", dn, 0, 0); send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); goto return_results; } #endif + if ( !manageDSAit && is_entry_referral( e ) ) { + /* parent is a referral, don't allow add */ + /* parent is an alias, don't allow add */ + struct berval **refs = get_entry_referrals( be, + conn, op, e ); + + Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, + 0, 0 ); + + send_ldap_result( conn, op, LDAP_REFERRAL, + e->e_dn, NULL, refs, NULL ); + + ber_bvecfree( refs ); + + rc = 1; + goto return_results; + } + + + if ( has_children( be, e ) ) { + Debug(LDAP_DEBUG_ARGS, "<=- ldbm_back_delete: non leaf %s\n", + dn, 0, 0); + send_ldap_result( conn, op, LDAP_NOT_ALLOWED_ON_NONLEAF, + NULL, NULL, NULL, NULL ); + goto return_results; + } + /* delete from parent's id2children entry */ if( (pdn = dn_parent( be, e->e_ndn )) != NULL ) { if( (p = dn2entry_w( be, pdn, &matched )) == NULL) { @@ -70,7 +105,7 @@ ldbm_back_delete( "<=- ldbm_back_delete: parent does not exist\n", 0, 0, 0); send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); goto return_results; } @@ -82,7 +117,7 @@ ldbm_back_delete( "<=- ldbm_back_delete: no access to parent\n", 0, 0, 0 ); send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); goto return_results; } @@ -93,7 +128,7 @@ ldbm_back_delete( "<=- ldbm_back_delete: no parent & not root\n", 0, 0, 0); send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); goto return_results; } @@ -106,7 +141,7 @@ ldbm_back_delete( "<=- ldbm_back_delete: operations error %s\n", dn, 0, 0); send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); goto return_results; } @@ -116,7 +151,7 @@ ldbm_back_delete( "<=- ldbm_back_delete: operations error %s\n", dn, 0, 0); send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); goto return_results; } @@ -126,12 +161,12 @@ ldbm_back_delete( "<=- ldbm_back_delete: operations error %s\n", dn, 0, 0); send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); goto return_results; } send_ldap_result( conn, op, LDAP_SUCCESS, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); rc = 0; return_results:; diff --git a/servers/slapd/back-ldbm/dn2id.c b/servers/slapd/back-ldbm/dn2id.c index c4116086b0..71b97641bb 100644 --- a/servers/slapd/back-ldbm/dn2id.c +++ b/servers/slapd/back-ldbm/dn2id.c @@ -1,17 +1,15 @@ /* dn2id.c - routines to deal with the dn2id index */ +#include "portable.h" + #include -#include -#include -#include + +#include +#include + #include "slap.h" #include "back-ldbm.h" - -extern struct dbcache *ldbm_cache_open(); -extern Entry *cache_find_entry_dn(); -extern Entry *id2entry(); -extern char *dn_parent(); -extern Datum ldbm_cache_fetch(); +#include "proto-back-ldbm.h" int dn2id_add( @@ -20,9 +18,13 @@ dn2id_add( ID id ) { - int rc; + int rc, flags; struct dbcache *db; Datum key, data; + struct ldbminfo *li = (struct ldbminfo *) be->be_private; + + ldbm_datum_init( key ); + ldbm_datum_init( data ); Debug( LDAP_DEBUG_TRACE, "=> dn2id_add( \"%s\", %ld )\n", dn, id, 0 ); @@ -33,7 +35,7 @@ dn2id_add( return( -1 ); } - dn = strdup( dn ); + dn = ch_strdup( dn ); dn_normalize_case( dn ); key.dptr = dn; @@ -41,7 +43,10 @@ dn2id_add( data.dptr = (char *) &id; data.dsize = sizeof(ID); - rc = ldbm_cache_store( db, key, data, LDBM_INSERT ); + flags = LDBM_INSERT; + if ( li->li_dbcachewsync ) flags |= LDBM_SYNC; + + rc = ldbm_cache_store( db, key, data, flags ); free( dn ); ldbm_cache_close( be, db ); @@ -58,31 +63,29 @@ dn2id( { struct ldbminfo *li = (struct ldbminfo *) be->be_private; struct dbcache *db; - Entry *e; ID id; Datum key, data; - Debug( LDAP_DEBUG_TRACE, "=> dn2id( \"%s\" )\n", dn, 0, 0 ); + ldbm_datum_init( key ); + ldbm_datum_init( data ); - dn = strdup( dn ); + dn = ch_strdup( dn ); + Debug( LDAP_DEBUG_TRACE, "=> dn2id( \"%s\" )\n", dn, 0, 0 ); dn_normalize_case( dn ); /* first check the cache */ - if ( (e = cache_find_entry_dn( &li->li_cache, dn )) != NULL ) { - id = e->e_id; + if ( (id = cache_find_entry_dn2id( be, &li->li_cache, dn )) != NOID ) { free( dn ); - Debug( LDAP_DEBUG_TRACE, "<= dn2id %d (in cache)\n", e->e_id, - 0, 0 ); - cache_return_entry( &li->li_cache, e ); - + Debug( LDAP_DEBUG_TRACE, "<= dn2id %ld (in cache)\n", id, + 0, 0 ); return( id ); } if ( (db = ldbm_cache_open( be, "dn2id", LDBM_SUFFIX, LDBM_WRCREAT )) - == NULL ) { + == NULL ) { free( dn ); Debug( LDAP_DEBUG_ANY, "<= dn2id could not open dn2id%s\n", - LDBM_SUFFIX, 0, 0 ); + LDBM_SUFFIX, 0, 0 ); return( NOID ); } @@ -103,7 +106,7 @@ dn2id( ldbm_datum_free( db->dbc_db, data ); - Debug( LDAP_DEBUG_TRACE, "<= dn2id %d\n", id, 0, 0 ); + Debug( LDAP_DEBUG_TRACE, "<= dn2id %ld\n", id, 0, 0 ); return( id ); } @@ -113,11 +116,12 @@ dn2id_delete( char *dn ) { - struct ldbminfo *li = (struct ldbminfo *) be->be_private; struct dbcache *db; Datum key; int rc; + ldbm_datum_init( key ); + Debug( LDAP_DEBUG_TRACE, "=> dn2id_delete( \"%s\" )\n", dn, 0, 0 ); if ( (db = ldbm_cache_open( be, "dn2id", LDBM_SUFFIX, LDBM_WRCREAT )) @@ -128,12 +132,15 @@ dn2id_delete( return( -1 ); } + dn = ch_strdup( dn ); dn_normalize_case( dn ); key.dptr = dn; key.dsize = strlen( dn ) + 1; rc = ldbm_cache_delete( db, key ); + free( dn ); + ldbm_cache_close( be, db ); Debug( LDAP_DEBUG_TRACE, "<= dn2id_delete %d\n", rc, 0, 0 ); @@ -146,37 +153,52 @@ dn2id_delete( */ Entry * -dn2entry( +dn2entry_rw( Backend *be, char *dn, - char **matched + Entry **matched, + int rw ) { struct ldbminfo *li = (struct ldbminfo *) be->be_private; ID id; - Entry *e; + Entry *e = NULL; char *pdn; - if ( (id = dn2id( be, dn )) != NOID && (e = id2entry( be, id )) - != NULL ) { + Debug(LDAP_DEBUG_TRACE, "dn2entry_%s: dn: \"%s\"\n", + rw ? "w" : "r", dn, 0); + + if( matched != NULL ) { + /* caller care about match */ + *matched = NULL; + } + + if ( (id = dn2id( be, dn )) != NOID && + (e = id2entry_rw( be, id, rw )) != NULL ) + { return( e ); } - *matched = NULL; - /* stop when we get to the suffix */ - if ( be_issuffix( be, dn ) ) { - return( NULL ); + if ( id != NOID ) { + Debug(LDAP_DEBUG_ANY, + "dn2entry_%s: no entry for valid id (%ld), dn \"%s\"\n", + rw ? "w" : "r", id, dn); + /* must have been deleted from underneath us */ + /* treat as if NOID was found */ } + /* caller doesn't care about match */ + if( matched == NULL ) return NULL; + /* entry does not exist - see how much of the dn does exist */ if ( (pdn = dn_parent( be, dn )) != NULL ) { - if ( (e = dn2entry( be, pdn, matched )) != NULL ) { - *matched = pdn; - cache_return_entry( &li->li_cache, e ); - } else { - free( pdn ); + /* get entry with reader lock */ + if ( (e = dn2entry_r( be, pdn, matched )) != NULL ) { + *matched = e; } + free( pdn ); } - return( NULL ); + return NULL; } + diff --git a/servers/slapd/back-ldbm/group.c b/servers/slapd/back-ldbm/group.c new file mode 100644 index 0000000000..aee659e83f --- /dev/null +++ b/servers/slapd/back-ldbm/group.c @@ -0,0 +1,150 @@ +/* group.c - ldbm backend acl group routine */ + +#include "portable.h" + +#include + +#include +#include + +#include "slap.h" +#include "back-ldbm.h" +#include "proto-back-ldbm.h" + + +/* return 0 IFF op_dn is a value in member attribute + * of entry with gr_dn AND that entry has an objectClass + * value of groupOfNames + */ +int +ldbm_back_group( + Backend *be, + Entry *target, + char *gr_ndn, + char *op_ndn, + char *objectclassValue, + char *groupattrName +) +{ + struct ldbminfo *li = (struct ldbminfo *) be->be_private; + Entry *e; + int rc = 1; + + Attribute *attr; + struct berval bv; + + Debug( LDAP_DEBUG_ARGS, + "=> ldbm_back_group: gr dn: \"%s\"\n", + gr_ndn, 0, 0 ); + Debug( LDAP_DEBUG_ARGS, + "=> ldbm_back_group: op dn: \"%s\"\n", + op_ndn, 0, 0 ); + Debug( LDAP_DEBUG_ARGS, + "=> ldbm_back_group: objectClass: \"%s\" attrName: \"%s\"\n", + objectclassValue, groupattrName, 0 ); + + Debug( LDAP_DEBUG_ARGS, + "=> ldbm_back_group: tr dn: \"%s\"\n", + target->e_ndn, 0, 0 ); + + if (strcmp(target->e_ndn, gr_ndn) == 0) { + /* we already have a LOCKED copy of the entry */ + e = target; + Debug( LDAP_DEBUG_ARGS, + "=> ldbm_back_group: target is group: \"%s\"\n", + gr_ndn, 0, 0 ); + + } else { + /* can we find group entry with reader lock */ + if ((e = dn2entry_r(be, gr_ndn, NULL )) == NULL) { + Debug( LDAP_DEBUG_ACL, + "=> ldbm_back_group: cannot find group: \"%s\"\n", + gr_ndn, 0, 0 ); + return( 1 ); + } + + Debug( LDAP_DEBUG_ACL, + "=> ldbm_back_group: found group: \"%s\"\n", + gr_ndn, 0, 0 ); + } + + /* find it's objectClass and member attribute values + * make sure this is a group entry + * finally test if we can find op_dn in the member attribute value list * + */ + + rc = 1; + + if ((attr = attr_find(e->e_attrs, "objectclass")) == NULL) { + Debug( LDAP_DEBUG_ACL, + "<= ldbm_back_group: failed to find objectClass\n", 0, 0, 0 ); + goto return_results; + } + + bv.bv_val = "ALIAS"; + bv.bv_len = sizeof("ALIAS")-1; + + if ( value_find(attr->a_vals, &bv, attr->a_syntax, 1) == 0) { + Debug( LDAP_DEBUG_ACL, + "<= ldbm_back_group: group is an alias\n", 0, 0, 0 ); + goto return_results; + } + + bv.bv_val = "REFERRAL"; + bv.bv_len = sizeof("REFERRAL")-1; + + if ( value_find(attr->a_vals, &bv, attr->a_syntax, 1) == 0) { + Debug( LDAP_DEBUG_ACL, + "<= ldbm_back_group: group is a referral\n", + 0, 0, 0 ); + goto return_results; + } + + bv.bv_val = objectclassValue; + bv.bv_len = strlen( bv.bv_val ); + + if (value_find(attr->a_vals, &bv, attr->a_syntax, 1) != 0) { + Debug( LDAP_DEBUG_ACL, + "<= ldbm_back_group: failed to find %s in objectClass\n", + objectclassValue, 0, 0 ); + goto return_results; + } + + if ((attr = attr_find(e->e_attrs, groupattrName)) == NULL) { + Debug( LDAP_DEBUG_ACL, + "<= ldbm_back_group: failed to find %s\n", + groupattrName, 0, 0 ); + goto return_results; + } + + Debug( LDAP_DEBUG_ACL, + "<= ldbm_back_group: found objectClass and %s\n", + groupattrName, 0, 0 ); + + bv.bv_val = op_ndn; + bv.bv_len = strlen( op_ndn ); + + if( value_find( attr->a_vals, &bv, attr->a_syntax, 1) != 0 ) + { + Debug( LDAP_DEBUG_ACL, + "<= ldbm_back_group: \"%s\" not in \"%s\": %s\n", + op_ndn, gr_ndn, groupattrName ); + goto return_results; + } + + Debug( LDAP_DEBUG_ACL, + "<= ldbm_back_group: \"%s\" is in \"%s\": %s\n", + op_ndn, gr_ndn, groupattrName ); + + rc = 0; + +return_results: + if( target != e ) { + /* free entry and reader lock */ + cache_return_entry_r( &li->li_cache, e ); + } + + Debug( LDAP_DEBUG_TRACE, "ldbm_back_group: rc=%d\n", rc, 0, 0 ); + return(rc); +} + diff --git a/servers/slapd/back-ldbm/modify.c b/servers/slapd/back-ldbm/modify.c index 941203a100..d9e9b8ed4c 100644 --- a/servers/slapd/back-ldbm/modify.c +++ b/servers/slapd/back-ldbm/modify.c @@ -120,8 +120,10 @@ int ldbm_modify_internal( if ( (err = acl_check_modlist( be, conn, op, e, modlist )) - != LDAP_SUCCESS ) { - send_ldap_result( conn, op, err, NULL, NULL, NULL ); + != LDAP_SUCCESS ) + { + send_ldap_result( conn, op, err, + NULL, NULL, NULL, NULL ); return -1; } @@ -173,7 +175,8 @@ int ldbm_modify_internal( if ( err != LDAP_SUCCESS ) { /* unlock entry, delete from cache */ - send_ldap_result( conn, op, err, NULL, NULL, NULL ); + send_ldap_result( conn, op, err, + NULL, NULL, NULL, NULL ); return -1; } } @@ -182,7 +185,7 @@ int ldbm_modify_internal( if ( global_schemacheck && oc_schema_check( e ) != 0 ) { Debug( LDAP_DEBUG_ANY, "entry failed schema check\n", 0, 0, 0 ); send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); return -1; } @@ -197,7 +200,7 @@ int ldbm_modify_internal( /* modify indexes */ if ( index_add_mods( be, modlist, e->e_id ) != 0 ) { send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); return -1; } @@ -224,21 +227,55 @@ ldbm_back_modify( ) { struct ldbminfo *li = (struct ldbminfo *) be->be_private; - char *matched; + Entry *matched; Entry *e; + int manageDSAit = get_manageDSAit( op ); Debug(LDAP_DEBUG_ARGS, "ldbm_back_modify:\n", 0, 0, 0); /* acquire and lock entry */ if ( (e = dn2entry_w( be, dn, &matched )) == NULL ) { - send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, - matched, NULL, NULL ); + char* matched_dn = NULL; + struct berval **refs = NULL; + + if ( matched != NULL ) { + matched_dn = ch_strdup( matched->e_dn ); + refs = is_entry_referral( matched ) + ? get_entry_referrals( be, conn, op, matched ) + : NULL; + cache_return_entry_r( &li->li_cache, matched ); + } else { + refs = default_referral; + } + + send_ldap_result( conn, op, LDAP_REFERRAL, + matched_dn, NULL, refs, NULL ); + if ( matched != NULL ) { - free( matched ); + ber_bvecfree( refs ); + free( matched_dn ); } + return( -1 ); } + if ( !manageDSAit && is_entry_referral( e ) ) { + /* parent is a referral, don't allow add */ + /* parent is an alias, don't allow add */ + struct berval **refs = get_entry_referrals( be, + conn, op, e ); + + Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, + 0, 0 ); + + send_ldap_result( conn, op, LDAP_REFERRAL, + e->e_dn, NULL, refs, NULL ); + + ber_bvecfree( refs ); + + goto error_return; + } + /* Modify the entry */ if ( ldbm_modify_internal( be, conn, op, dn, modlist, e ) != 0 ) { goto error_return; @@ -247,12 +284,12 @@ ldbm_back_modify( /* change the entry itself */ if ( id2entry_add( be, e ) != 0 ) { send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); goto error_return; } send_ldap_result( conn, op, LDAP_SUCCESS, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); cache_return_entry_w( &li->li_cache, e ); return( 0 ); diff --git a/servers/slapd/back-ldbm/modrdn.c b/servers/slapd/back-ldbm/modrdn.c index e724b9c18b..4f743c473c 100644 --- a/servers/slapd/back-ldbm/modrdn.c +++ b/servers/slapd/back-ldbm/modrdn.c @@ -39,10 +39,10 @@ ldbm_back_modrdn( ) { struct ldbminfo *li = (struct ldbminfo *) be->be_private; - char *matched = NULL; char *p_dn = NULL, *p_ndn = NULL; char *new_dn = NULL, *new_ndn = NULL; Entry *e, *p = NULL; + Entry *matched = NULL; int rootlock = 0; int rc = -1; /* Added to support LDAP v2 correctly (deleteoldrdn thing) */ @@ -62,7 +62,7 @@ ldbm_back_modrdn( struct berval del_bv; /* Stores old rdn att */ struct berval *del_bvals[2]; /* Stores old rdn att */ LDAPModList mod[2]; /* Used to delete old rdn */ - + int manageDSAit = get_manageDSAit( op ); Debug( LDAP_DEBUG_TRACE, "==>ldbm_back_modrdn(newSuperior=%s)\n", (newSuperior ? newSuperior : "NULL"), @@ -70,30 +70,62 @@ ldbm_back_modrdn( /* get entry with writer lock */ if ( (e = dn2entry_w( be, dn, &matched )) == NULL ) { - send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, - matched, NULL, NULL ); + char* matched_dn = NULL; + struct berval** refs = NULL; + + if( matched != NULL ) { + matched_dn = strdup( matched->e_dn ); + refs = is_entry_referral( matched ) + ? get_entry_referrals( be, conn, op, matched ) + : NULL; + cache_return_entry_r( &li->li_cache, matched ); + } else { + refs = default_referral; + } + + send_ldap_result( conn, op, LDAP_REFERRAL, + matched_dn, NULL, refs, NULL ); + if ( matched != NULL ) { - free( matched ); + ber_bvecfree( refs ); + free( matched_dn ); } + return( -1 ); } #ifdef SLAPD_CHILD_MODIFICATION_WITH_ENTRY_ACL - /* check parent for "children" acl */ if ( ! access_allowed( be, conn, op, e, "entry", NULL, ACL_WRITE ) ) { Debug( LDAP_DEBUG_TRACE, "no access to entry\n", 0, 0, 0 ); send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, - "", "" ); + NULL, NULL, NULL, NULL ); goto return_results; } #endif + if (!manageDSAit && is_entry_referral( e ) ) { + /* parent is a referral, don't allow add */ + /* parent is an alias, don't allow add */ + struct berval **refs = get_entry_referrals( be, + conn, op, e ); + + Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, + 0, 0 ); + + send_ldap_result( conn, op, LDAP_REFERRAL, + e->e_dn, NULL, refs, NULL ); + + ber_bvecfree( refs ); + + goto return_results; + } + if ( (p_ndn = dn_parent( be, e->e_ndn )) != NULL ) { - /* Make sure parent entry exist and we can write its + /* Make sure parent entry exist and we can write its * children. */ @@ -101,7 +133,7 @@ ldbm_back_modrdn( Debug( LDAP_DEBUG_TRACE, "parent does not exist\n", 0, 0, 0); send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); goto return_results; } @@ -112,7 +144,7 @@ ldbm_back_modrdn( Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0, 0, 0 ); send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); goto return_results; } @@ -132,7 +164,7 @@ ldbm_back_modrdn( Debug( LDAP_DEBUG_TRACE, "no parent & not root\n", 0, 0, 0); send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); goto return_results; } @@ -163,12 +195,11 @@ ldbm_back_modrdn( /* Get Entry with dn=newSuperior. Does newSuperior exist? */ if( (np = dn2entry_w( be, np_ndn, &matched )) == NULL) { - Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: newSup(ndn=%s) not here!\n", np_ndn, 0, 0); send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); goto return_results; } @@ -184,7 +215,30 @@ ldbm_back_modrdn( "ldbm_back_modrdn: no wr to newSup children\n", 0, 0, 0 ); send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); + goto return_results; + } + + if ( is_entry_alias( np ) ) { + /* entry is an alias, don't allow bind */ + Debug( LDAP_DEBUG_TRACE, "entry is alias\n", 0, + 0, 0 ); + + send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM, + NULL, NULL, NULL, NULL ); + + goto return_results; + } + + if ( is_entry_referral( np ) ) { + /* parent is a referral, don't allow add */ + /* parent is an alias, don't allow add */ + Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, + 0, 0 ); + + send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, + NULL, NULL, NULL, NULL ); + goto return_results; } @@ -192,9 +246,7 @@ ldbm_back_modrdn( "ldbm_back_modrdn: wr to new parent's children OK\n", 0, 0 , 0 ); - new_parent_dn = np_dn; - } /* Build target dn and make sure target entry doesn't exist already. */ @@ -209,7 +261,7 @@ ldbm_back_modrdn( if (dn2id ( be, new_ndn ) != NOID) { send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); goto return_results; } @@ -228,7 +280,7 @@ ldbm_back_modrdn( /* delete old one */ if ( dn2id_delete( be, e->e_ndn ) != 0 ) { send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); goto return_results; } @@ -241,7 +293,7 @@ ldbm_back_modrdn( /* add new one */ if ( dn2id_add( be, e->e_ndn, e->e_id ) != 0 ) { send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); goto return_results; } @@ -256,7 +308,7 @@ ldbm_back_modrdn( "ldbm_back_modrdn: can't figure out type of newrdn\n", 0, 0, 0 ); send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); goto return_results; } @@ -267,7 +319,7 @@ ldbm_back_modrdn( "ldbm_back_modrdn: can't figure out val of newrdn\n", 0, 0, 0 ); send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); goto return_results; } @@ -284,7 +336,7 @@ ldbm_back_modrdn( "ldbm_back_modrdn: can't figure out old_rdn from dn\n", 0, 0, 0 ); send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); goto return_results; } @@ -295,7 +347,7 @@ ldbm_back_modrdn( "ldbm_back_modrdn: can't figure out the old_rdn type\n", 0, 0, 0 ); send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); goto return_results; } @@ -331,7 +383,6 @@ ldbm_back_modrdn( /* Remove old rdn value if required */ if (deleteoldrdn) { - /* Get value of old rdn */ if ((old_rdn_val = rdn_attr_value( old_rdn )) @@ -340,12 +391,9 @@ ldbm_back_modrdn( Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: can't figure out old_rdn_val from old_rdn\n", 0, 0, 0 ); - send_ldap_result( conn, op, - LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL ); + send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, + NULL, NULL, NULL, NULL ); goto return_results; - - } del_bvals[0] = &del_bv; /* Array of bervals */ @@ -383,7 +431,7 @@ ldbm_back_modrdn( 0, 0, 0 ); send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); goto return_results; } @@ -406,11 +454,12 @@ ldbm_back_modrdn( if ( id2entry_add( be, e ) != 0 ) { entry_free( e ); send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); goto return_results_after; } - send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL ); + send_ldap_result( conn, op, LDAP_SUCCESS, + NULL, NULL, NULL, NULL ); rc = 0; goto return_results_after; diff --git a/servers/slapd/back-ldbm/proto-back-ldbm.h b/servers/slapd/back-ldbm/proto-back-ldbm.h index acc69ca33c..19da039055 100644 --- a/servers/slapd/back-ldbm/proto-back-ldbm.h +++ b/servers/slapd/back-ldbm/proto-back-ldbm.h @@ -1,107 +1,191 @@ #ifndef _PROTO_BACK_LDBM #define _PROTO_BACK_LDBM +#include + +#include "external.h" + +LDAP_BEGIN_DECL + +/* + * alias.c + */ +Entry *deref_alias_r LDAP_P(( + Backend *be, + Connection *conn, + Operation *op, + Entry *e )); + +char *deref_dn LDAP_P(( + Backend *be, + Connection *conn, + Operation *op, + char *dn )); + +Entry *alias_dn2entry_r LDAP_P(( + Backend *be, + char *dn, + Entry **matched, + int *err )); + +Entry *alias_id2entry_r LDAP_P(( + Backend *be, + ID id, + Entry **matched, + int *err )); + /* * attr.c */ -void attr_masks( struct ldbminfo *li, char *type, int *indexmask, - int *syntaxmask ); -void attr_index_config( struct ldbminfo *li, char *fname, int lineno, - int argc, char **argv, int init ); +void attr_masks LDAP_P(( struct ldbminfo *li, char *type, int *indexmask, + int *syntaxmask )); +void attr_index_config LDAP_P(( struct ldbminfo *li, char *fname, int lineno, + int argc, char **argv, int init )); +#ifdef SLAP_CLEANUP +void attr_index_destroy LDAP_P(( Avlnode *tree )); +#endif /* * cache.c */ -void cache_set_state( struct cache *cache, Entry *e, int state ); -void cache_return_entry( struct cache *cache, Entry *e ); -int cache_add_entry_lock( struct cache *cache, Entry *e, int state ); -Entry * cache_find_entry_dn( struct cache *cache, char *dn ); -Entry * cache_find_entry_id( struct cache *cache, ID id ); -int cache_delete_entry( struct cache *cache, Entry *e ); +int cache_add_entry_rw LDAP_P(( struct cache *cache, Entry *e, int rw )); +int cache_update_entry LDAP_P(( struct cache *cache, Entry *e )); +void cache_return_entry_rw LDAP_P(( struct cache *cache, Entry *e, int rw )); +#define cache_return_entry_r(c, e) cache_return_entry_rw((c), (e), 0) +#define cache_return_entry_w(c, e) cache_return_entry_rw((c), (e), 1) + +ID cache_find_entry_dn2id LDAP_P(( Backend *be, struct cache *cache, char *dn )); +Entry * cache_find_entry_id LDAP_P(( struct cache *cache, ID id, int rw )); +int cache_delete_entry LDAP_P(( struct cache *cache, Entry *e )); +#ifdef SLAP_CLEANUP +void cache_release_all LDAP_P(( struct cache *cache )); +#endif /* * dbcache.c */ -struct dbcache * ldbm_cache_open( Backend *be, char *name, char *suffix, - int flags ); -void ldbm_cache_close( Backend *be, struct dbcache *db ); -void ldbm_cache_flush_all( Backend *be ); -Datum ldbm_cache_fetch( struct dbcache *db, Datum key ); -int ldbm_cache_store( struct dbcache *db, Datum key, Datum data, int flags ); -int ldbm_cache_delete( struct dbcache *db, Datum key ); +struct dbcache * ldbm_cache_open LDAP_P(( Backend *be, char *name, char *suffix, + int flags )); +void ldbm_cache_close LDAP_P(( Backend *be, struct dbcache *db )); +void ldbm_cache_really_close LDAP_P(( Backend *be, struct dbcache *db )); +void ldbm_cache_flush_all LDAP_P(( Backend *be )); +Datum ldbm_cache_fetch LDAP_P(( struct dbcache *db, Datum key )); +int ldbm_cache_store LDAP_P(( struct dbcache *db, Datum key, Datum data, int flags )); +int ldbm_cache_delete LDAP_P(( struct dbcache *db, Datum key )); /* * dn2id.c */ -int dn2id_add( Backend *be, char *dn, ID id ); -ID dn2id( Backend *be, char *dn ); -int dn2id_delete( Backend *be, char *dn ); -Entry * dn2entry( Backend *be, char *dn, char **matched ); +int dn2id_add LDAP_P(( Backend *be, char *dn, ID id )); +ID dn2id LDAP_P(( Backend *be, char *dn )); +int dn2id_delete LDAP_P(( Backend *be, char *dn )); + +Entry * dn2entry_rw LDAP_P(( Backend *be, char *dn, Entry **matched, int rw )); +#define dn2entry_r(be, dn, m) dn2entry_rw((be), (dn), (m), 0) +#define dn2entry_w(be, dn, m) dn2entry_rw((be), (dn), (m), 1) + +/* + * entry.c + */ +int ldbm_back_entry_release_rw LDAP_P(( Backend *be, Entry *e, int rw )); /* * filterindex.c */ -IDList * filter_candidates( Backend *be, Filter *f ); +ID_BLOCK * filter_candidates LDAP_P(( Backend *be, Filter *f )); /* * id2children.c */ -int id2children_add( Backend *be, Entry *p, Entry *e ); -int has_children( Backend *be, Entry *p ); +int id2children_add LDAP_P(( Backend *be, Entry *p, Entry *e )); +int id2children_remove LDAP_P(( Backend *be, Entry *p, Entry *e )); +int has_children LDAP_P(( Backend *be, Entry *p )); /* * id2entry.c */ -int id2entry_add( Backend *be, Entry *e ); -int id2entry_delete( Backend *be, Entry *e ); -Entry * id2entry( Backend *be, ID id ); +int id2entry_add LDAP_P(( Backend *be, Entry *e )); +int id2entry_delete LDAP_P(( Backend *be, Entry *e )); + +Entry * id2entry_rw LDAP_P(( Backend *be, ID id, int rw )); +#define id2entry_r(be, id) id2entry_rw((be), (id), 0) +#define id2entry_w(be, id) id2entry_rw((be), (id), 1) /* * idl.c */ -IDList * idl_alloc( int nids ); -IDList * idl_allids( Backend *be ); -void idl_free( IDList *idl ); -IDList * idl_fetch( Backend *be, struct dbcache *db, Datum key ); -int idl_insert_key( Backend *be, struct dbcache *db, Datum key, ID id ); -int idl_insert( IDList **idl, ID id, int maxids ); -IDList * idl_intersection( Backend *be, IDList *a, IDList *b ); -IDList * idl_union( Backend *be, IDList *a, IDList *b ); -IDList * idl_notin( Backend *be, IDList *a, IDList *b ); -ID idl_firstid( IDList *idl ); -ID idl_nextid( IDList *idl, ID id ); +ID_BLOCK * idl_alloc LDAP_P(( unsigned int nids )); +ID_BLOCK * idl_allids LDAP_P(( Backend *be )); +void idl_free LDAP_P(( ID_BLOCK *idl )); +ID_BLOCK * idl_fetch LDAP_P(( Backend *be, struct dbcache *db, Datum key )); +int idl_insert_key LDAP_P(( Backend *be, struct dbcache *db, Datum key, ID id )); +int idl_insert LDAP_P(( ID_BLOCK **idl, ID id, unsigned int maxids )); +int idl_delete_key LDAP_P(( Backend *be, struct dbcache *db, Datum key, ID id )); +ID_BLOCK * idl_intersection LDAP_P(( Backend *be, ID_BLOCK *a, ID_BLOCK *b )); +ID_BLOCK * idl_union LDAP_P(( Backend *be, ID_BLOCK *a, ID_BLOCK *b )); +ID_BLOCK * idl_notin LDAP_P(( Backend *be, ID_BLOCK *a, ID_BLOCK *b )); +ID idl_firstid LDAP_P(( ID_BLOCK *idl )); +ID idl_nextid LDAP_P(( ID_BLOCK *idl, ID id )); /* * index.c */ -int index_add_entry( Backend *be, Entry *e ); -int index_add_mods( Backend *be, LDAPMod *mods, ID id ); -IDList * index_read( Backend *be, char *type, int indextype, char *val ); -int index_add_values( Backend *be, char *type, struct berval **vals, ID id ); +int index_add_entry LDAP_P(( Backend *be, Entry *e )); +int index_add_mods LDAP_P(( Backend *be, LDAPModList *ml, ID id )); +ID_BLOCK * index_read LDAP_P(( Backend *be, char *type, int indextype, char *val )); +/* Possible operations supported (op) by index_change_values() */ +#define __INDEX_ADD_OP 0x0001 +#define __INDEX_DELETE_OP 0x0002 +int index_change_values LDAP_P(( Backend *be, + char *type, + struct berval **vals, + ID id, + unsigned int op )); + /* * kerberos.c */ -#ifdef KERBEROS -/* krbv4_ldap_auth( Backend *be, struct berval *cred, AUTH_DAT *ad ); */ +#ifdef HAVE_KERBEROS +/* krbv4_ldap_auth LDAP_P(( Backend *be, struct berval *cred, AUTH_DAT *ad )); */ #endif + +/* + * modify.c + * These prototypes are placed here because they are used by modify and + * modify rdn which are implemented in different files. + * + * We need ldbm_internal_modify here because of LDAP modrdn & modify use + * it. If we do not add this, there would be a bunch of code replication + * here and there and of course the likelihood of bugs increases. + * Juan C. Gomez (gomez@engr.sgi.com) 05/18/99 + * + */ + +int add_values LDAP_P(( Entry *e, LDAPMod *mod, char *dn )); +int delete_values LDAP_P(( Entry *e, LDAPMod *mod, char *dn )); +int replace_values LDAP_P(( Entry *e, LDAPMod *mod, char *dn )); +int ldbm_modify_internal LDAP_P((Backend *be, Connection *conn, Operation *op, + char *dn, LDAPModList *mods, Entry *e)); /* * nextid.c */ -ID next_id( Backend *be ); -void next_id_return( Backend *be, ID id ); -ID next_id_get( Backend *be ); +ID next_id LDAP_P(( Backend *be )); +void next_id_return LDAP_P(( Backend *be, ID id )); +ID next_id_get LDAP_P(( Backend *be )); +int next_id_save LDAP_P(( Backend *be )); +LDAP_END_DECL #endif diff --git a/servers/slapd/back-ldbm/search.c b/servers/slapd/back-ldbm/search.c index 6fa1d9b7dc..0fdbe926b9 100644 --- a/servers/slapd/back-ldbm/search.c +++ b/servers/slapd/back-ldbm/search.c @@ -11,9 +11,13 @@ #include "back-ldbm.h" #include "proto-back-ldbm.h" -static ID_BLOCK *base_candidates(Backend *be, Connection *conn, Operation *op, char *base, Filter *filter, char **attrs, int attrsonly, char **matched, int *err); -static ID_BLOCK *onelevel_candidates(Backend *be, Connection *conn, Operation *op, char *base, Filter *filter, char **attrs, int attrsonly, char **matched, int *err); -static ID_BLOCK *subtree_candidates(Backend *be, Connection *conn, Operation *op, char *base, Filter *filter, char **attrs, int attrsonly, char **matched, Entry *e, int *err, int lookupbase); +static ID_BLOCK *base_candidate( + Backend *be, Entry *e ); + +static ID_BLOCK *search_candidates( + Backend *be, Entry *e, Filter *filter, + int scope, int deref, int manageDSAit ); + int ldbm_back_search( @@ -37,13 +41,71 @@ ldbm_back_search( ID_BLOCK *candidates; ID id; Entry *e; - Attribute *ref; - struct berval **refs; - char *matched = NULL; + struct berval **v2refs = NULL; + Entry *matched = NULL; + char *matched_dn = NULL; int nentries = 0; - char *realBase; + int manageDSAit = get_manageDSAit( op ); + + Debug(LDAP_DEBUG_TRACE, "=> ldbm_back_search\n", 0, 0, 0); + + /* get entry with reader lock */ + switch ( deref ) { +#ifdef SLAPD_ALIASES + case LDAP_DEREF_FINDING: + case LDAP_DEREF_ALWAYS: + e = alias_dn2entry_r( be, base, &matched, &err ); + break; +#endif + default: + e = dn2entry_r( be, base, &matched ); + err = e != NULL ? LDAP_SUCCESS : LDAP_REFERRAL; + } + + if ( e == NULL ) { + char *matched_dn = NULL; + struct berval **refs = NULL; + + if ( matched != NULL ) { + matched_dn = ch_strdup( matched->e_dn ); + refs = is_entry_referral( matched ) + ? get_entry_referrals( be, conn, op, matched ) + : NULL; + cache_return_entry_r( &li->li_cache, matched ); + } else { + refs = default_referral; + } + + send_ldap_result( conn, op, err, + matched_dn, NULL, refs, NULL ); + + if( matched != NULL ) { + ber_bvecfree( refs ); + free( matched_dn ); + } + + return 1; + } - Debug(LDAP_DEBUG_ARGS, "=> ldbm_back_search\n", 0, 0, 0); + if (!manageDSAit && is_entry_referral( e ) ) { + /* entry is a referral, don't allow add */ + char *matched_dn = ch_strdup( e->e_dn ); + struct berval **refs = get_entry_referrals( be, + conn, op, e ); + + cache_return_entry_r( &li->li_cache, matched ); + + Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, + 0, 0 ); + + send_ldap_result( conn, op, LDAP_REFERRAL, + matched_dn, NULL, refs, NULL ); + + ber_bvecfree( refs ); + free( matched_dn ); + + return 1; + } if ( tlimit == 0 && be_isroot( be, op->o_ndn ) ) { tlimit = -1; /* allow root to set no limit */ @@ -52,6 +114,7 @@ ldbm_back_search( be->be_timelimit : tlimit; stoptime = op->o_time + tlimit; } + if ( slimit == 0 && be_isroot( be, op->o_ndn ) ) { slimit = -1; /* allow root to set no limit */ } else { @@ -59,68 +122,29 @@ ldbm_back_search( be->be_sizelimit : slimit; } - /* - * check and apply aliasing where the dereferencing applies to - * the subordinates of the base - */ + if ( scope == LDAP_SCOPE_BASE) { + candidates = base_candidate( be, e ); - switch ( deref ) { - case LDAP_DEREF_FINDING: - case LDAP_DEREF_ALWAYS: - realBase = derefDN ( be, conn, op, base ); - break; - default: - realBase = ch_strdup(base); + } else { + candidates = search_candidates( be, e, filter, + scope, deref, manageDSAit ); } - (void) dn_normalize_case( realBase ); - - Debug( LDAP_DEBUG_TRACE, "using base \"%s\"\n", - realBase, 0, 0 ); - - switch ( scope ) { - case LDAP_SCOPE_BASE: - candidates = base_candidates( be, conn, op, realBase, filter, - attrs, attrsonly, &matched, &err ); - break; - - case LDAP_SCOPE_ONELEVEL: - candidates = onelevel_candidates( be, conn, op, realBase, filter, - attrs, attrsonly, &matched, &err ); - break; - - case LDAP_SCOPE_SUBTREE: - candidates = subtree_candidates( be, conn, op, realBase, filter, - attrs, attrsonly, &matched, NULL, &err, 1 ); - break; - - default: - send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, - "", "Bad search scope", NULL ); - if( realBase != NULL) { - free( realBase ); - } - return( -1 ); - } + matched_dn = ch_strdup( e->e_dn ); + cache_return_entry_r( &li->li_cache, e ); /* null candidates means we could not find the base object */ if ( candidates == NULL ) { - send_ldap_result( conn, op, err, - matched, NULL, NULL ); - if ( matched != NULL ) { - free( matched ); - } - if( realBase != NULL) { - free( realBase ); - } - return( -1 ); - } + /* return a NO SUCH OBJECT */ + Debug( LDAP_DEBUG_TRACE, "no candidates\n", 0, + 0, 0 ); - if ( matched != NULL ) { - free( matched ); - } + send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, + matched_dn, "no search candidates", NULL, NULL ); - refs = NULL; + free( matched_dn ); + return 1; + } for ( id = idl_firstid( candidates ); id != NOID; id = idl_nextid( candidates, id ) ) { @@ -130,10 +154,8 @@ ldbm_back_search( if ( op->o_abandon ) { ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex ); idl_free( candidates ); - ber_bvecfree( refs ); - if( realBase != NULL) { - free( realBase ); - } + ber_bvecfree( v2refs ); + free( matched_dn ); return( 0 ); } ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex ); @@ -141,17 +163,27 @@ ldbm_back_search( /* check time limit */ if ( tlimit != -1 && slap_get_time() > stoptime ) { send_search_result( conn, op, LDAP_TIMELIMIT_EXCEEDED, - NULL, NULL, refs, nentries ); + NULL, NULL, v2refs, NULL, nentries ); idl_free( candidates ); - ber_bvecfree( refs ); - if( realBase != NULL) { - free( realBase ); - } + ber_bvecfree( v2refs ); + free( matched_dn ); return( 0 ); } /* get the entry with reader lock */ - if ( (e = id2entry_r( be, id )) == NULL ) { + switch ( deref ) { +#ifdef SLAPD_ALIASES + case LDAP_DEREF_SEARCHING: + case LDAP_DEREF_ALWAYS: + e = alias_id2entry_r( be, id, &matched, &err ); + break; +#endif + default: + e = dn2entry_r( be, base, &matched ); + err = e != NULL ? LDAP_SUCCESS : LDAP_REFERRAL; + } + + if ( e == NULL ) { Debug( LDAP_DEBUG_ARGS, "candidate %ld not found\n", id, 0, 0 ); continue; @@ -162,13 +194,15 @@ ldbm_back_search( * this for subtree searches, and don't check the filter * explicitly here since it's only a candidate anyway. */ - if ( scope == LDAP_SCOPE_SUBTREE && - e->e_ndn != NULL && - strncmp( e->e_ndn, "REF=", 4 ) == 0 && - (ref = attr_find( e->e_attrs, "ref" )) != NULL ) + if ( !manageDSAit && scope != LDAP_SCOPE_BASE && + is_entry_referral( e ) ) { + struct berval **refs = get_entry_referrals( be, conn, op, e ); + send_search_reference( be, conn, op, - e, ref->a_vals, &refs ); + e, refs, NULL, &v2refs ); + + ber_bvecfree( refs ); /* otherwise it's an entry - see if it matches the filter */ } else { @@ -178,21 +212,22 @@ ldbm_back_search( char *dn; /* check scope */ - scopeok = 1; if ( scope == LDAP_SCOPE_ONELEVEL ) { if ( (dn = dn_parent( be, e->e_dn )) != NULL ) { (void) dn_normalize_case( dn ); - scopeok = (dn == realBase) + scopeok = (dn == matched_dn) ? 1 - : (strcmp( dn, realBase ) ? 0 : 1 ); + : (strcmp( dn, matched_dn ) ? 0 : 1 ); free( dn ); } else { - scopeok = (realBase == NULL || *realBase == '\0'); + scopeok = (matched_dn == NULL || *matched_dn == '\0'); } } else if ( scope == LDAP_SCOPE_SUBTREE ) { dn = ch_strdup( e->e_ndn ); - scopeok = dn_issuffix( dn, realBase ); + scopeok = dn_issuffix( dn, matched_dn ); free( dn ); + } else { + scopeok = 1; } if ( scopeok ) { @@ -201,39 +236,16 @@ ldbm_back_search( cache_return_entry_r( &li->li_cache, e ); send_search_result( conn, op, LDAP_SIZELIMIT_EXCEEDED, NULL, NULL, - refs, nentries ); + v2refs, NULL, nentries ); idl_free( candidates ); - ber_bvecfree( refs ); - - if( realBase != NULL) { - free( realBase ); - } + ber_bvecfree( v2refs ); + free( matched_dn ); return( 0 ); } - /* - * check and apply aliasing where the dereferencing applies to - * the subordinates of the base - */ - switch ( deref ) { - case LDAP_DEREF_SEARCHING: - case LDAP_DEREF_ALWAYS: - { - Entry *newe = derefAlias_r( be, conn, op, e ); - if ( newe == NULL ) { /* problem with the alias */ - cache_return_entry_r( &li->li_cache, e ); - e = NULL; - } - else if ( newe != e ) { /* reassign e */ - cache_return_entry_r( &li->li_cache, e ); - e = newe; - } - } - break; - } if (e) { switch ( send_search_entry( be, conn, op, e, - attrs, attrsonly, 0 ) ) { + attrs, attrsonly, 0, NULL ) ) { case 0: /* entry sent ok */ nentries++; break; @@ -242,11 +254,8 @@ ldbm_back_search( case -1: /* connection closed */ cache_return_entry_r( &li->li_cache, e ); idl_free( candidates ); - ber_bvecfree( refs ); - - if( realBase != NULL) { - free( realBase ); - } + ber_bvecfree( v2refs ); + free( matched_dn ); return( 0 ); } } @@ -264,204 +273,120 @@ ldbm_back_search( idl_free( candidates ); send_search_result( conn, op, - refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL, - NULL, NULL, refs, nentries ); + v2refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL, + NULL, NULL, v2refs, NULL, nentries ); - ber_bvecfree( refs ); - - if( realBase != NULL) { - free( realBase ); - } + ber_bvecfree( v2refs ); return( 0 ); } static ID_BLOCK * -base_candidates( +base_candidate( Backend *be, - Connection *conn, - Operation *op, - char *base, - Filter *filter, - char **attrs, - int attrsonly, - char **matched, - int *err + Entry *e ) { - struct ldbminfo *li = (struct ldbminfo *) be->be_private; ID_BLOCK *idl; - Entry *e; - Debug(LDAP_DEBUG_TRACE, "base_candidates: base: \"%s\"\n", base, 0, 0); - - *err = LDAP_SUCCESS; - - /* get entry with reader lock */ - if ( (e = dn2entry_r( be, base, matched )) == NULL ) { - *err = LDAP_NO_SUCH_OBJECT; - return( NULL ); - } - - /* check for deleted */ + Debug(LDAP_DEBUG_TRACE, "base_candidates: base: \"%s\"\n", + e->e_dn, 0, 0); idl = idl_alloc( 1 ); idl_insert( &idl, e->e_id, 1 ); - - /* free reader lock */ - cache_return_entry_r( &li->li_cache, e ); - return( idl ); } static ID_BLOCK * -onelevel_candidates( +search_candidates( Backend *be, - Connection *conn, - Operation *op, - char *base, + Entry *e, Filter *filter, - char **attrs, - int attrsonly, - char **matched, - int *err + int scope, + int deref, + int manageDSAit ) { struct ldbminfo *li = (struct ldbminfo *) be->be_private; - Entry *e = NULL; - Filter *f; - char buf[20]; ID_BLOCK *candidates; + Filter *f, *rf, *af, *lf; - Debug(LDAP_DEBUG_TRACE, "onelevel_candidates: base: \"%s\"\n", base, 0, 0); + Debug(LDAP_DEBUG_TRACE, "search_candidates: base: \"%s\" %s\n", + e->e_dn, 0, 0 ); - *err = LDAP_SUCCESS; + f = NULL; - /* get the base object with reader lock */ - if ( base != NULL && *base != '\0' && - (e = dn2entry_r( be, base, matched )) == NULL ) - { - *err = LDAP_NO_SUCH_OBJECT; - return( NULL ); + if( !manageDSAit ) { + /* match referrals */ + rf = (Filter *) ch_malloc( sizeof(Filter) ); + rf->f_next = NULL; + rf->f_choice = LDAP_FILTER_OR; + rf->f_or = (Filter *) ch_malloc( sizeof(Filter) ); + rf->f_or->f_choice = LDAP_FILTER_EQUALITY; + rf->f_or->f_avtype = ch_strdup( "objectclass" ); + rf->f_or->f_avvalue.bv_val = ch_strdup( "REFERRAL" ); + rf->f_or->f_avvalue.bv_len = sizeof("REFERRAL")-1; + rf->f_or->f_next = filter; + f = rf; + } else { + rf = NULL; + f = filter; } - /* - * modify the filter to be something like this: - * - * parent=baseobject & originalfilter - */ - - f = (Filter *) ch_malloc( sizeof(Filter) ); - f->f_next = NULL; - f->f_choice = LDAP_FILTER_AND; - f->f_and = (Filter *) ch_malloc( sizeof(Filter) ); - f->f_and->f_choice = LDAP_FILTER_EQUALITY; - f->f_and->f_ava.ava_type = ch_strdup( "id2children" ); - sprintf( buf, "%ld", e != NULL ? e->e_id : 0 ); - f->f_and->f_ava.ava_value.bv_val = ch_strdup( buf ); - f->f_and->f_ava.ava_value.bv_len = strlen( buf ); - f->f_and->f_next = filter; - - /* from here, it's just like subtree_candidates */ - candidates = subtree_candidates( be, conn, op, base, f, attrs, - attrsonly, matched, e, err, 0 ); - - /* free up just the filter stuff we allocated above */ - f->f_and->f_next = NULL; - filter_free( f ); - - /* free entry and reader lock */ - if( e != NULL ) { - cache_return_entry_r( &li->li_cache, e ); + if( deref == LDAP_DEREF_SEARCHING || deref == LDAP_DEREF_ALWAYS ) { + /* match aliases */ + af = (Filter *) ch_malloc( sizeof(Filter) ); + af->f_next = NULL; + af->f_choice = LDAP_FILTER_OR; + af->f_or = (Filter *) ch_malloc( sizeof(Filter) ); + af->f_or->f_choice = LDAP_FILTER_EQUALITY; + af->f_or->f_avtype = ch_strdup( "objectclass" ); + af->f_or->f_avvalue.bv_val = ch_strdup( "ALIAS" ); + af->f_or->f_avvalue.bv_len = sizeof("ALIAS")-1; + af->f_or->f_next = f; + f = af; + } else { + af = NULL; } - return( candidates ); -} -static ID_BLOCK * -subtree_candidates( - Backend *be, - Connection *conn, - Operation *op, - char *base, - Filter *filter, - char **attrs, - int attrsonly, - char **matched, - Entry *e, - int *err, - int lookupbase -) -{ - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - Filter *f, **filterarg_ptr; - ID_BLOCK *candidates; + lf = (Filter *) ch_malloc( sizeof(Filter) ); + lf->f_next = NULL; + lf->f_choice = LDAP_FILTER_AND; + lf->f_and = (Filter *) ch_malloc( sizeof(Filter) ); + lf->f_and->f_next = f; - Debug(LDAP_DEBUG_TRACE, "subtree_candidates: base: \"%s\" %s\n", - base ? base : "NULL", lookupbase ? "lookupbase" : "", 0); - - /* - * get the base object - unless we already have it (from one-level). - * also, unless this is a one-level search or a subtree search - * starting at the very top of our subtree, we need to modify the - * filter to be something like this: - * - * dn=*baseobjectdn & (originalfilter | ref=*) - * - * the "objectclass=referral" part is used to select referrals to return - */ - - *err = LDAP_SUCCESS; - f = NULL; - if ( lookupbase ) { - e = NULL; + if ( scope == LDAP_SCOPE_SUBTREE ) { + lf->f_and->f_choice = LDAP_FILTER_SUBSTRINGS; + lf->f_and->f_sub_type = ch_strdup( "dn" ); + lf->f_and->f_sub_initial = NULL; + lf->f_and->f_sub_any = NULL; + lf->f_and->f_sub_final = ch_strdup( e->e_ndn ); + value_normalize( lf->f_and->f_sub_final, SYNTAX_DN|SYNTAX_CIS ); - if ( base != NULL && *base != '\0' && - (e = dn2entry_r( be, base, matched )) == NULL ) - { - *err = LDAP_NO_SUCH_OBJECT; - return( NULL ); - } + } else { + char buf[16]; + lf->f_and->f_choice = LDAP_FILTER_EQUALITY; + lf->f_and->f_ava.ava_type = ch_strdup( "id2children" ); + sprintf( buf, "%ld", e != NULL ? e->e_id : 0 ); + lf->f_and->f_ava.ava_value.bv_val = ch_strdup( buf ); + lf->f_and->f_ava.ava_value.bv_len = strlen( buf ); + } - if (e) { - cache_return_entry_r( &li->li_cache, e ); - } + candidates = filter_candidates( be, lf ); - f = (Filter *) ch_malloc( sizeof(Filter) ); - f->f_next = NULL; - f->f_choice = LDAP_FILTER_OR; - f->f_or = (Filter *) ch_malloc( sizeof(Filter) ); - f->f_or->f_choice = LDAP_FILTER_EQUALITY; - f->f_or->f_avtype = ch_strdup( "objectclass" ); - /* Patch to use normalized uppercase */ - f->f_or->f_avvalue.bv_val = ch_strdup( "REFERRAL" ); - f->f_or->f_avvalue.bv_len = strlen( "REFERRAL" ); - filterarg_ptr = &f->f_or->f_next; - *filterarg_ptr = filter; - filter = f; - - if ( ! be_issuffix( be, base ) ) { - f = (Filter *) ch_malloc( sizeof(Filter) ); - f->f_next = NULL; - f->f_choice = LDAP_FILTER_AND; - f->f_and = (Filter *) ch_malloc( sizeof(Filter) ); - f->f_and->f_choice = LDAP_FILTER_SUBSTRINGS; - f->f_and->f_sub_type = ch_strdup( "dn" ); - f->f_and->f_sub_initial = NULL; - f->f_and->f_sub_any = NULL; - f->f_and->f_sub_final = ch_strdup( base ); - value_normalize( f->f_and->f_sub_final, SYNTAX_CIS ); - f->f_and->f_next = filter; - filter = f; - } - } + /* free up filter additions we allocated above */ + lf->f_and->f_next = NULL; + filter_free( lf ); - candidates = filter_candidates( be, filter ); + if( af != NULL ) { + af->f_or->f_next = NULL; + filter_free( af ); + } - /* free up just the parts we allocated above */ - if ( f != NULL ) { - *filterarg_ptr = NULL; - filter_free( f ); + if( rf != NULL ) { + rf->f_or->f_next = NULL; + filter_free( rf ); } return( candidates ); diff --git a/servers/slapd/backend.c b/servers/slapd/backend.c index 998bfa8c6a..3b5b51fe77 100644 --- a/servers/slapd/backend.c +++ b/servers/slapd/backend.c @@ -1,146 +1,419 @@ /* backend.c - routines for dealing with back-end databases */ +#include "portable.h" + #include -#include -#include -#include + +#include +#include + #include + #include "slap.h" +#include "lutil.h" -#ifdef LDAP_LDBM -extern int ldbm_back_bind(); -extern int ldbm_back_unbind(); -extern int ldbm_back_search(); -extern int ldbm_back_compare(); -extern int ldbm_back_modify(); -extern int ldbm_back_modrdn(); -extern int ldbm_back_add(); -extern int ldbm_back_delete(); -extern int ldbm_back_abandon(); -extern int ldbm_back_config(); -extern int ldbm_back_init(); -extern int ldbm_back_close(); -#endif - -#ifdef LDAP_PASSWD -extern int passwd_back_search(); -extern int passwd_back_config(); -#endif - -#ifdef LDAP_SHELL -extern int shell_back_bind(); -extern int shell_back_unbind(); -extern int shell_back_search(); -extern int shell_back_compare(); -extern int shell_back_modify(); -extern int shell_back_modrdn(); -extern int shell_back_add(); -extern int shell_back_delete(); -extern int shell_back_abandon(); -extern int shell_back_config(); -extern int shell_back_init(); -#endif - -extern int defsize; -extern int deftime; - -#define BACKEND_GRAB_SIZE 10 - -int nbackends; -Backend *backends; -static int maxbackends; +#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 -Backend * -new_backend( +static BackendInfo binfo[] = { +#if defined(SLAPD_LDAP) && !defined(SLAPD_LDAP_DYNAMIC) + {"ldap", ldap_back_initialize}, +#endif +#if defined(SLAPD_LDBM) && !defined(SLAPD_LDBM_DYNAMIC) + {"ldbm", ldbm_back_initialize}, +#endif +#if defined(SLAPD_BDB2) && !defined(SLAPD_BDB2_DYNAMIC) + {"bdb2", bdb2_back_initialize}, +#endif +#if defined(SLAPD_PASSWD) && !defined(SLAPD_PASSWD_DYNAMIC) + {"passwd", passwd_back_initialize}, +#endif +#if defined(SLAPD_PERL) && !defined(SLAPD_PERL_DYNAMIC) + {"perl", perl_back_initialize}, +#endif +#if defined(SLAPD_SHELL) && !defined(SLAPD_SHELL_DYNAMIC) + {"shell", shell_back_initialize}, +#endif +#if defined(SLAPD_TCL) && !defined(SLAPD_LDAP_TCL) + {"tcl", tcl_back_initialize}, +#endif + {NULL} +}; + +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; + } + +#ifdef SLAPD_MODULES + return 0; +#else + Debug( LDAP_DEBUG_ANY, + "backend_init: failed\n", + 0, 0, 0 ); + + return rc; +#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] ); + } + + if(rc != 0) { + 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( + &backendInfo[i] ); + } + } + +#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; - int foundit; + BackendInfo *bi = backend_info(type); + int rc = 0; - if ( nbackends == maxbackends ) { - maxbackends += BACKEND_GRAB_SIZE; - backends = (Backend *) ch_realloc( (char *) backends, - maxbackends * sizeof(Backend) ); - memset( &backends[nbackends], '\0', BACKEND_GRAB_SIZE * - sizeof(Backend) ); + 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; - foundit = 0; - -#ifdef LDAP_LDBM - if ( strcasecmp( type, "ldbm" ) == 0 ) { - be->be_bind = ldbm_back_bind; - be->be_unbind = ldbm_back_unbind; - be->be_search = ldbm_back_search; - be->be_compare = ldbm_back_compare; - be->be_modify = ldbm_back_modify; - be->be_modrdn = ldbm_back_modrdn; - be->be_add = ldbm_back_add; - be->be_delete = ldbm_back_delete; - be->be_abandon = ldbm_back_abandon; - be->be_config = ldbm_back_config; - be->be_init = ldbm_back_init; - be->be_close = ldbm_back_close; - be->be_type = "ldbm"; - foundit = 1; - } -#endif - -#ifdef LDAP_PASSWD - if ( strcasecmp( type, "passwd" ) == 0 ) { - be->be_bind = NULL; - be->be_unbind = NULL; - be->be_search = passwd_back_search; - be->be_compare = NULL; - be->be_modify = NULL; - be->be_modrdn = NULL; - be->be_add = NULL; - be->be_delete = NULL; - be->be_abandon = NULL; - be->be_config = passwd_back_config; - be->be_init = NULL; - be->be_close = NULL; - be->be_type = "passwd"; - foundit = 1; - } -#endif - -#ifdef LDAP_SHELL - if ( strcasecmp( type, "shell" ) == 0 ) { - be->be_bind = shell_back_bind; - be->be_unbind = shell_back_unbind; - be->be_search = shell_back_search; - be->be_compare = shell_back_compare; - be->be_modify = shell_back_modify; - be->be_modrdn = shell_back_modrdn; - be->be_add = shell_back_add; - be->be_delete = shell_back_delete; - be->be_abandon = shell_back_abandon; - be->be_config = shell_back_config; - be->be_init = shell_back_init; - be->be_close = NULL; - be->be_type = "shell"; - foundit = 1; - } -#endif - - if ( be->be_init != NULL ) { - (*be->be_init)( be ); - } - - if ( foundit == 0 ) { - fprintf( stderr, "Unrecognized database type (%s)\n", type ); - exit( 1 ); + + 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++; return( be ); } +void +be_db_close( void ) +{ + int i; + + for ( i = 0; i < nbackends; i++ ) { + if ( backends[i].bd_info->bi_db_close ) { + (*backends[i].bd_info->bi_db_close)( &backends[i] ); + } + } +} + Backend * select_backend( char * dn ) { @@ -148,21 +421,36 @@ select_backend( char * dn ) dnlen = strlen( dn ); for ( i = 0; i < nbackends; i++ ) { - for ( j = 0; backends[i].be_suffix != NULL && - backends[i].be_suffix[j] != NULL; j++ ) { - len = strlen( backends[i].be_suffix[j] ); + for ( j = 0; backends[i].be_nsuffix != NULL && + backends[i].be_nsuffix[j] != NULL; j++ ) + { + len = strlen( backends[i].be_nsuffix[j] ); if ( len > dnlen ) { continue; } - if ( strcasecmp( backends[i].be_suffix[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 ); } @@ -174,8 +462,8 @@ be_issuffix( { int i; - for ( i = 0; be->be_suffix != NULL && be->be_suffix[i] != NULL; i++ ) { - if ( strcasecmp( be->be_suffix[i], suffix ) == 0 ) { + for ( i = 0; be->be_nsuffix != NULL && be->be_nsuffix[i] != NULL; i++ ) { + if ( strcmp( be->be_nsuffix[i], suffix ) == 0 ) { return( 1 ); } } @@ -184,50 +472,126 @@ be_issuffix( } int -be_isroot( Backend *be, char *dn ) +be_isroot( Backend *be, char *ndn ) { - if ( dn == NULL ) { + int rc; + + if ( ndn == NULL || be->be_root_ndn == NULL ) { return( 0 ); } - return( be->be_rootdn ? strcasecmp( be->be_rootdn, dn ) == 0 - : 0 ); + rc = strcmp( be->be_root_ndn, ndn ) ? 0 : 1; + + return(rc); +} + +char * +be_root_dn( Backend *be ) +{ + if ( be->be_root_dn == NULL ) { + return( "" ); + } + + return be->be_root_dn; } int -be_isroot_pw( Backend *be, char *dn, struct berval *cred ) +be_isroot_pw( Backend *be, char *ndn, struct berval *cred ) { - if ( ! be_isroot( be, dn ) || be->be_rootpw == NULL ) { + int result; + + if ( ! be_isroot( be, ndn ) ) { return( 0 ); } - return( strcmp( be->be_rootpw, cred->bv_val ) == 0 ); +#ifdef SLAPD_CRYPT + ldap_pvt_thread_mutex_lock( &crypt_mutex ); +#endif + + result = lutil_passwd( cred->bv_val, be->be_root_pw, NULL ); + +#ifdef SLAPD_CRYPT + ldap_pvt_thread_mutex_unlock( &crypt_mutex ); +#endif + + return result == 0; } -void -be_close() +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; + } +} + +int +backend_unbind( + Connection *conn, + Operation *op +) { int i; for ( i = 0; i < nbackends; i++ ) { - if ( backends[i].be_close != NULL ) { - (*backends[i].be_close)( &backends[i] ); + if ( backends[i].be_unbind ) { + (*backends[i].be_unbind)( &backends[i], conn, op ); } } + + return 0; } +int +backend_connection_init( + Connection *conn +) +{ + int i; -void -be_unbind( - Connection *conn, - Operation *op + 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_unbind != NULL ) { - (*backends[i].be_unbind)( &backends[i], conn, op ); + if ( backends[i].be_connection_destroy ) { + (*backends[i].be_connection_destroy)( &backends[i], conn); } } + + return 0; +} + +int +backend_group( + 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); } diff --git a/servers/slapd/bind.c b/servers/slapd/bind.c index df2a1845de..c8daed7bfe 100644 --- a/servers/slapd/bind.c +++ b/servers/slapd/bind.c @@ -159,7 +159,7 @@ do_bind( if ( version < LDAP_VERSION_MIN || version > LDAP_VERSION_MAX ) { Debug( LDAP_DEBUG_ANY, "unknown version %d\n", version, 0, 0 ); send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, - NULL, "version not supported", NULL ); + NULL, "version not supported", NULL, NULL ); goto cleanup; } @@ -178,7 +178,7 @@ do_bind( "do_bind: no sasl mechanism provided\n", version, 0, 0 ); send_ldap_result( conn, op, rc = LDAP_AUTH_METHOD_NOT_SUPPORTED, - NULL, "no sasl mechanism provided", NULL ); + NULL, "no sasl mechanism provided", NULL, NULL ); goto cleanup; } @@ -187,7 +187,7 @@ do_bind( "do_bind: sasl mechanism \"%s\" not supported.\n", mech, 0, 0 ); send_ldap_result( conn, op, rc = LDAP_AUTH_METHOD_NOT_SUPPORTED, - NULL, "sasl mechanism not supported", NULL ); + NULL, "sasl mechanism not supported", NULL, NULL ); goto cleanup; } @@ -242,7 +242,8 @@ do_bind( * we already forced connection to "anonymous", we just * need to send success */ - send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL ); + send_ldap_result( conn, op, LDAP_SUCCESS, + NULL, NULL, NULL, NULL ); goto cleanup; } @@ -255,15 +256,15 @@ do_bind( if ( (be = select_backend( ndn )) == NULL ) { if ( cred.bv_len == 0 ) { send_ldap_result( conn, op, LDAP_SUCCESS, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); } else if ( default_referral ) { send_ldap_result( conn, op, rc = LDAP_REFERRAL, - NULL, NULL, default_referral ); + NULL, NULL, default_referral, NULL ); } else { send_ldap_result( conn, op, rc = LDAP_INVALID_CREDENTIALS, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); } goto cleanup; @@ -273,8 +274,6 @@ do_bind( /* alias suffix */ char *edn; - ndn = suffixAlias( ndn, op, be ); - if ( (*be->be_bind)( be, conn, op, ndn, method, mech, &cred, &edn ) == 0 ) { ldap_pvt_thread_mutex_lock( &conn->c_mutex ); @@ -295,7 +294,7 @@ do_bind( /* send this here to avoid a race condition */ send_ldap_result( conn, op, LDAP_SUCCESS, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); } else if (edn != NULL) { free( edn ); @@ -303,7 +302,7 @@ do_bind( } else { send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, - NULL, "Function not implemented", NULL ); + NULL, "Function not implemented", NULL, NULL ); } cleanup: diff --git a/servers/slapd/compare.c b/servers/slapd/compare.c index 6430dcf134..29a7c80962 100644 --- a/servers/slapd/compare.c +++ b/servers/slapd/compare.c @@ -35,7 +35,7 @@ do_compare( Debug( LDAP_DEBUG_ANY, "do_compare: SASL bind in progress.\n", 0, 0, 0 ); send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS, - NULL, "SASL bind in progress", NULL ); + NULL, "SASL bind in progress", NULL, NULL ); return LDAP_SASL_BIND_IN_PROGRESS; } @@ -86,18 +86,15 @@ do_compare( ava_free( &ava, 0 ); send_ldap_result( conn, op, rc = LDAP_REFERRAL, - NULL, NULL, default_referral ); + NULL, NULL, default_referral, NULL ); return 1; } - /* alias suffix if approp */ - ndn = suffixAlias( ndn, op, be ); - if ( be->be_compare ) { (*be->be_compare)( be, conn, op, ndn, &ava ); } else { send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, - NULL, "Function not implemented", NULL ); + NULL, "Function not implemented", NULL, NULL ); } free( ndn ); diff --git a/servers/slapd/config.c b/servers/slapd/config.c index 0b169a5c1d..6554f3cf56 100644 --- a/servers/slapd/config.c +++ b/servers/slapd/config.c @@ -127,7 +127,7 @@ read_config( char *fname ) be = backend_db_init( cargv[1] ); /* assign a default depth limit for alias deref */ - be->be_maxDerefDepth = SLAPD_DEFAULT_MAXDEREFDEPTH; + be->be_max_deref_depth = SLAPD_DEFAULT_MAXDEREFDEPTH; /* get pid file name */ } else if ( strcasecmp( cargv[0], "pidfile" ) == 0 ) { @@ -225,54 +225,9 @@ read_config( char *fname ) free( dn ); } - /* set database suffixAlias */ - } else if ( strcasecmp( cargv[0], "suffixAlias" ) == 0 ) { - if ( cargc < 2 ) { - Debug( LDAP_DEBUG_ANY, - "%s: line %d: missing alias and aliased_dn in \"suffixAlias \" line\n", - fname, lineno, 0 ); - return( 1 ); - } else if ( cargc < 3 ) { - Debug( LDAP_DEBUG_ANY, - "%s: line %d: missing aliased_dn in \"suffixAlias \" line\n", - fname, lineno, 0 ); - return( 1 ); - } else if ( cargc > 3 ) { - Debug( LDAP_DEBUG_ANY, - "%s: line %d: extra cruft in suffixAlias line (ignored)\n", - fname, lineno, 0 ); - } - if ( be == NULL ) { - Debug( LDAP_DEBUG_ANY, -"%s: line %d: suffixAlias line must appear inside a database definition (ignored)\n", - fname, lineno, 0 ); - } else { - char *alias, *aliased_dn; - - alias = ch_strdup( cargv[1] ); - (void) dn_normalize( alias ); - - aliased_dn = ch_strdup( cargv[2] ); - (void) dn_normalize( aliased_dn ); - - - if ( strcasecmp( alias, aliased_dn) == 0 ) { - Debug( LDAP_DEBUG_ANY, -"%s: line %d: suffixAlias %s is not different from aliased dn (ignored)\n", - fname, lineno, alias ); - } else { - (void) dn_normalize_case( alias ); - (void) dn_normalize_case( aliased_dn ); - charray_add( &be->be_suffixAlias, alias ); - charray_add( &be->be_suffixAlias, aliased_dn ); - } - - free(alias); - free(aliased_dn); - } - /* set max deref depth */ } else if ( strcasecmp( cargv[0], "maxDerefDepth" ) == 0 ) { + int i; if ( cargc < 2 ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: missing depth in \"maxDerefDepth \" line\n", @@ -283,9 +238,14 @@ read_config( char *fname ) Debug( LDAP_DEBUG_ANY, "%s: line %d: depth line must appear inside a database definition (ignored)\n", fname, lineno, 0 ); + } else if ((i = atoi(cargv[i])) < 0) { + Debug( LDAP_DEBUG_ANY, +"%s: line %d: depth must be positive (ignored)\n", + fname, lineno, 0 ); + } else { - be->be_maxDerefDepth = atoi (cargv[1]); - } + be->be_max_deref_depth = i; + } /* set magic "root" dn for this database */ diff --git a/servers/slapd/configinfo.c b/servers/slapd/configinfo.c index a8051991bb..4d85b2b627 100644 --- a/servers/slapd/configinfo.c +++ b/servers/slapd/configinfo.c @@ -56,8 +56,10 @@ config_info( Connection *conn, Operation *op ) attr_merge( e, "database", vals ); } - send_search_entry( &backends[0], conn, op, e, NULL, 0, 1 ); - send_search_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL, 1 ); + send_search_entry( &backends[0], conn, op, e, + NULL, 0, 1, NULL ); + send_search_result( conn, op, LDAP_SUCCESS, + NULL, NULL, NULL, NULL, 1 ); entry_free( e ); } diff --git a/servers/slapd/controls.c b/servers/slapd/controls.c index 9580ea0fd4..37361cb47c 100644 --- a/servers/slapd/controls.c +++ b/servers/slapd/controls.c @@ -155,9 +155,29 @@ return_results: if( rc == -1 ) { send_ldap_disconnect( conn, op, rc, errmsg ); } else { - send_ldap_result( conn, op, rc, NULL, errmsg, NULL ); + send_ldap_result( conn, op, rc, + NULL, errmsg, NULL, NULL ); } } return rc; } + + +int get_manageDSAit( Operation *op ) +{ + int i; + if( op == NULL || op->o_ctrls == NULL ) { + return 0; + } + + for( i=0; op->o_ctrls[i] != NULL; i++ ) { + if( strcmp( LDAP_CONTROL_MANAGEDSAIT, op->o_ctrls[i]->ldctl_oid ) + == 0 ) + { + return 1; + } + } + + return 0; +} \ No newline at end of file diff --git a/servers/slapd/delete.c b/servers/slapd/delete.c index 53d3f50077..5f13cd90f5 100644 --- a/servers/slapd/delete.c +++ b/servers/slapd/delete.c @@ -35,7 +35,7 @@ do_delete( Debug( LDAP_DEBUG_ANY, "do_delete: SASL bind in progress.\n", 0, 0, 0 ); send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS, - NULL, "SASL bind in progress", NULL ); + NULL, "SASL bind in progress", NULL, NULL ); return LDAP_SASL_BIND_IN_PROGRESS; } @@ -72,13 +72,10 @@ do_delete( if ( (be = select_backend( ndn )) == NULL ) { free( ndn ); send_ldap_result( conn, op, rc = LDAP_REFERRAL, - NULL, NULL, default_referral ); + NULL, NULL, default_referral, NULL ); return rc; } - /* alias suffix if approp */ - ndn = suffixAlias( ndn, op, be ); - /* * do the delete if 1 && (2 || 3) * 1) there is a delete function implemented in this backend; @@ -95,11 +92,11 @@ do_delete( } } else { send_ldap_result( conn, op, rc = LDAP_REFERRAL, - NULL, NULL, default_referral ); + NULL, NULL, default_referral, NULL ); } } else { send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, - NULL, "Function not implemented", NULL ); + NULL, "Function not implemented", NULL, NULL ); } free( ndn ); diff --git a/servers/slapd/extended.c b/servers/slapd/extended.c index 7082448fca..4b38c60c36 100644 --- a/servers/slapd/extended.c +++ b/servers/slapd/extended.c @@ -74,7 +74,7 @@ do_extended( Debug( LDAP_DEBUG_ANY, "do_extended: unsupported operation \"%s\"\n", reqoid, 0 ,0 ); send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, - NULL, "unsuppored extended operation", NULL ); + NULL, "unsuppored extended operation", NULL, NULL ); goto done; } @@ -98,7 +98,7 @@ do_extended( Debug( LDAP_DEBUG_ARGS, "do_extended: oid \"%s\"\n", reqoid, 0 ,0 ); send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, - NULL, "unsupported extended operation", NULL ); + NULL, "unsupported extended operation", NULL, NULL ); done: if ( reqoid != NULL ) { diff --git a/servers/slapd/libslapd.dsp b/servers/slapd/libslapd.dsp new file mode 100644 index 0000000000..9c6ddefdd6 --- /dev/null +++ b/servers/slapd/libslapd.dsp @@ -0,0 +1,290 @@ +# Microsoft Developer Studio Project File - Name="libslapd" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=libslapd - Win32 Single Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libslapd.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libslapd.mak" CFG="libslapd - Win32 Single Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libslapd - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "libslapd - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE "libslapd - Win32 Single Debug" (based on\ + "Win32 (x86) Static Library") +!MESSAGE "libslapd - Win32 Single Release" (based on\ + "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe + +!IF "$(CFG)" == "libslapd - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "libslapd" +# PROP BASE Intermediate_Dir "libslapd" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release\libslapd" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "libslapd - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "libslap0" +# PROP BASE Intermediate_Dir "libslap0" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug\libslapd" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "libslapd - Win32 Single Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "libslap1" +# PROP BASE Intermediate_Dir "libslap1" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "SDebug" +# PROP Intermediate_Dir "SDebug\libslapd" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "libslapd - Win32 Single Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "libslap2" +# PROP BASE Intermediate_Dir "libslap2" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "SRelease" +# PROP Intermediate_Dir "SRelease\libslapd" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ENDIF + +# Begin Target + +# Name "libslapd - Win32 Release" +# Name "libslapd - Win32 Debug" +# Name "libslapd - Win32 Single Debug" +# Name "libslapd - Win32 Single Release" +# Begin Source File + +SOURCE=.\abandon.c +# End Source File +# Begin Source File + +SOURCE=.\acl.c +# End Source File +# Begin Source File + +SOURCE=.\aclparse.c +# End Source File +# Begin Source File + +SOURCE=.\add.c +# End Source File +# Begin Source File + +SOURCE=.\attr.c +# End Source File +# Begin Source File + +SOURCE=.\ava.c +# End Source File +# Begin Source File + +SOURCE=.\backend.c +# End Source File +# Begin Source File + +SOURCE=.\bind.c +# End Source File +# Begin Source File + +SOURCE=.\ch_malloc.c +# End Source File +# Begin Source File + +SOURCE=.\charray.c +# End Source File +# Begin Source File + +SOURCE=.\compare.c +# End Source File +# Begin Source File + +SOURCE=.\config.c +# End Source File +# Begin Source File + +SOURCE=.\configinfo.c +# End Source File +# Begin Source File + +SOURCE=.\connection.c +# End Source File +# Begin Source File + +SOURCE=.\controls.c +# End Source File +# Begin Source File + +SOURCE=.\daemon.c +# End Source File +# Begin Source File + +SOURCE=.\delete.c +# End Source File +# Begin Source File + +SOURCE=.\dn.c +# End Source File +# Begin Source File + +SOURCE=.\entry.c +# End Source File +# Begin Source File + +SOURCE=.\extended.c +# End Source File +# Begin Source File + +SOURCE=.\filter.c +# End Source File +# Begin Source File + +SOURCE=.\filterentry.c +# End Source File +# Begin Source File + +SOURCE=.\init.c +# End Source File +# Begin Source File + +SOURCE=.\lock.c +# End Source File +# Begin Source File + +SOURCE=.\modify.c +# End Source File +# Begin Source File + +SOURCE=.\modrdn.c +# End Source File +# Begin Source File + +SOURCE=.\monitor.c +# End Source File +# Begin Source File + +SOURCE=.\operation.c +# End Source File +# Begin Source File + +SOURCE=.\phonetic.c +# End Source File +# Begin Source File + +SOURCE=".\proto-slap.h" +# End Source File +# Begin Source File + +SOURCE=.\repl.c +# End Source File +# Begin Source File + +SOURCE=.\root_dse.c +# End Source File +# Begin Source File + +SOURCE=.\schema.c +# End Source File +# Begin Source File + +SOURCE=.\schemaparse.c +# End Source File +# Begin Source File + +SOURCE=.\search.c +# End Source File +# Begin Source File + +SOURCE=.\slap.h +# End Source File +# Begin Source File + +SOURCE=.\str2filter.c +# End Source File +# Begin Source File + +SOURCE=.\unbind.c +# End Source File +# Begin Source File + +SOURCE=.\user.c +# End Source File +# Begin Source File + +SOURCE=.\value.c +# End Source File +# Begin Source File + +SOURCE=.\wsa_err.c +# End Source File +# End Target +# End Project diff --git a/servers/slapd/modify.c b/servers/slapd/modify.c index cfc62e8d69..0d475655b8 100644 --- a/servers/slapd/modify.c +++ b/servers/slapd/modify.c @@ -45,8 +45,8 @@ do_modify( if( op->o_bind_in_progress ) { Debug( LDAP_DEBUG_ANY, "do_modify: SASL bind in progress.\n", 0, 0, 0 ); - send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS, NULL, - "SASL bind in progress", NULL ); + send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS, + NULL, "SASL bind in progress", NULL, NULL ); return LDAP_SASL_BIND_IN_PROGRESS; } @@ -112,7 +112,7 @@ do_modify( (*modtail)->ml_op != LDAP_MOD_REPLACE ) { send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, - NULL, "unrecognized modify operation", NULL ); + NULL, "unrecognized modify operation", NULL, NULL ); free( ndn ); modlist_free( modlist ); return LDAP_PROTOCOL_ERROR; @@ -122,7 +122,7 @@ do_modify( && (*modtail)->ml_op != LDAP_MOD_DELETE ) { send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, - NULL, "unrecognized modify operation", NULL ); + NULL, "unrecognized modify operation", NULL, NULL ); free( ndn ); modlist_free( modlist ); return LDAP_PROTOCOL_ERROR; @@ -162,13 +162,10 @@ do_modify( free( ndn ); modlist_free( modlist ); send_ldap_result( conn, op, rc = LDAP_REFERRAL, - NULL, NULL, default_referral ); + NULL, NULL, default_referral, NULL ); return rc; } - /* alias suffix if approp */ - ndn = suffixAlias ( ndn, op, be ); - /* * do the modify if 1 && (2 || 3) * 1) there is a modify function implemented in this backend; @@ -187,11 +184,11 @@ do_modify( /* send a referral */ } else { send_ldap_result( conn, op, rc = LDAP_REFERRAL, - NULL, NULL, default_referral ); + NULL, NULL, default_referral, NULL ); } } else { send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, - NULL, "Function not implemented", NULL ); + NULL, "Function not implemented", NULL, NULL ); } free( ndn ); diff --git a/servers/slapd/modrdn.c b/servers/slapd/modrdn.c index 439fb41452..a09cbb4137 100644 --- a/servers/slapd/modrdn.c +++ b/servers/slapd/modrdn.c @@ -53,8 +53,8 @@ do_modrdn( if( op->o_bind_in_progress ) { Debug( LDAP_DEBUG_ANY, "do_modrdn: SASL bind in progress.\n", 0, 0, 0 ); - send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS, NULL, - "SASL bind in progress", NULL ); + send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS, + NULL, "SASL bind in progress", NULL, NULL ); return LDAP_SASL_BIND_IN_PROGRESS; } @@ -162,7 +162,7 @@ do_modrdn( free( newSuperior ); free( nnewSuperior ); send_ldap_result( conn, op, LDAP_REFERRAL, - NULL, NULL, default_referral ); + NULL, NULL, default_referral, NULL ); return 0; } } @@ -184,7 +184,7 @@ do_modrdn( free( newSuperior ); free( nnewSuperior ); send_ldap_result( conn, op, rc = LDAP_REFERRAL, - NULL, NULL, default_referral ); + NULL, NULL, default_referral, NULL ); return rc; } @@ -203,16 +203,12 @@ do_modrdn( free( nnewSuperior ); send_ldap_result( conn, op, rc = LDAP_AFFECTS_MULTIPLE_DSAS, - NULL, NULL, NULL ); + NULL, NULL, NULL, NULL ); return rc; } - - /* alias suffix if approp */ - ndn = suffixAlias( ndn, op, be ); - /* * do the add if 1 && (2 || 3) * 1) there is an add function implemented in this backend; @@ -232,11 +228,11 @@ do_modrdn( } } else { send_ldap_result( conn, op, rc = LDAP_REFERRAL, - NULL, NULL, default_referral ); + NULL, NULL, default_referral, NULL ); } } else { send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, - NULL, "Function not implemented", NULL ); + NULL, "Function not implemented", NULL, NULL ); } free( ndn ); diff --git a/servers/slapd/monitor.c b/servers/slapd/monitor.c index 251f8b5ec3..855a2e8dc0 100644 --- a/servers/slapd/monitor.c +++ b/servers/slapd/monitor.c @@ -242,8 +242,10 @@ monitor_info( Connection *conn, Operation *op ) attr_merge( e, "concurrency", vals ); #endif - send_search_entry( &backends[0], conn, op, e, NULL, 0, 1 ); - send_search_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL, 1 ); + send_search_entry( &backends[0], conn, op, e, + NULL, 0, 1, NULL ); + send_search_result( conn, op, LDAP_SUCCESS, + NULL, NULL, NULL, NULL, 1 ); entry_free( e ); } diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index 6e29f71056..847f947515 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -129,6 +129,8 @@ int get_ctrls LDAP_P(( Operation *op, int senderrors )); +int get_manageDSAit LDAP_P(( Operation *op )); + /* * config.c */ @@ -258,10 +260,15 @@ void replog LDAP_P(( Backend *be, int optype, char *dn, void *change, int flag ) * result.c */ +struct berval **get_entry_referrals LDAP_P(( + Backend *be, Connection *conn, Operation *op, + Entry *e )); + void send_ldap_result LDAP_P(( Connection *conn, Operation *op, int err, char *matched, char *text, - struct berval **refs )); + struct berval **refs, + LDAPControl **ctrls )); void send_ldap_disconnect LDAP_P(( Connection *conn, Operation *op, @@ -271,16 +278,19 @@ void send_search_result LDAP_P(( Connection *conn, Operation *op, int err, char *matched, char *text, struct berval **refs, + LDAPControl **ctrls, int nentries )); int send_search_reference LDAP_P(( Backend *be, Connection *conn, Operation *op, Entry *e, struct berval **refs, + LDAPControl **ctrls, struct berval ***v2refs )); int send_search_entry LDAP_P(( Backend *be, Connection *conn, Operation *op, - Entry *e, char **attrs, int attrsonly, int opattrs )); + Entry *e, char **attrs, int attrsonly, int opattrs, + LDAPControl **ctrls )); int str2result LDAP_P(( char *s, int *code, char **matched, char **info )); @@ -302,6 +312,10 @@ int mr_add LDAP_P((LDAP_MATCHING_RULE *mr, slap_mr_normalize_func *normalize, sl void schema_info LDAP_P((Connection *conn, Operation *op, char **attrs, int attrsonly)); int schema_init LDAP_P((void)); +int is_entry_objectclass LDAP_P(( Entry *, char* objectclass )); +#define is_entry_alias(e) is_entry_objectclass((e), "ALIAS") +#define is_entry_referral(e) is_entry_objectclass((e), "REFERRAL") + /* * schemaparse.c @@ -330,11 +344,6 @@ int value_cmp LDAP_P(( struct berval *v1, struct berval *v2, int syntax, int value_find LDAP_P(( struct berval **vals, struct berval *v, int syntax, int normalize )); -/* - * suffixAlias.c - */ -char *suffixAlias LDAP_P(( char *dn, Operation *op, Backend *be )); - /* * user.c */ diff --git a/servers/slapd/result.c b/servers/slapd/result.c index 00cbca44d3..32899631df 100644 --- a/servers/slapd/result.c +++ b/servers/slapd/result.c @@ -69,29 +69,19 @@ static ber_tag_t req2res( ber_tag_t tag ) return tag; } -void trim_refs( - struct berval **refs, - int trimurl ) +static void trim_refs_urls( + struct berval **refs ) { - int i; + unsigned i; assert( refs != NULL ); for( i=0; refs[i] != NULL; i++ ) { - unsigned long j; - - /* trim URI label */ - for( j=0; jbv_len; j++ ) { - if( isspace(refs[i]->bv_val[j]) ) { - refs[i]->bv_val[j] = '\0'; - refs[i]->bv_len = j; - break; - } - } - if( trimurl && refs[i]->bv_len > sizeof("ldap://") && + if( refs[i]->bv_len > sizeof("ldap://") && strncasecmp( refs[i]->bv_val, "ldap://", sizeof("ldap://")-1 ) == 0 ) { + unsigned j; for( j=sizeof("ldap://"); jbv_len ; j++ ) { if( refs[i]->bv_val[j] = '/' ) { refs[i]->bv_val[j] = '\0'; @@ -103,7 +93,63 @@ void trim_refs( } } -long send_ldap_ber( +struct berval **get_entry_referrals( + Backend *be, Connection *conn, Operation *op, Entry *e ) +{ + Attribute *attr; + struct berval **refs; + unsigned i, j; + + if( is_entry_referral( e ) ) { + return NULL; + } + + attr = attr_find( e->e_attrs, "ref" ); + + if( attr == NULL ) return NULL; + + for( i=0; attr->a_vals[i] != NULL; i++ ) { + /* count references */ + } + + if( i < 1 ) return NULL; + + refs = ch_malloc( i + 1 ); + + for( i=0, j=0; attr->a_vals[i] != NULL; i++ ) { + unsigned k; + struct berval *ref = ber_bvdup( attr->a_vals[i] ); + + /* trim the label */ + for( k=0; kbv_len; k++ ) { + if( isspace(ref->bv_val[k]) ) { + ref->bv_val[k] = '\0'; + ref->bv_len = k; + break; + } + } + + if( ref->bv_len > 0 ) { + refs[j++] = ref; + + } else { + ber_bvfree( ref ); + } + } + + refs[j] = NULL; + + if( j == 0 ) { + ber_bvecfree( refs ); + refs = NULL; + } + + /* we should check that a referral value exists... */ + + return refs; +} + +static long send_ldap_ber( Connection *conn, BerElement *ber ) { @@ -174,13 +220,16 @@ send_ldap_response( char *text, struct berval **ref, char *resoid, - struct berval *resdata + struct berval *resdata, + LDAPControl **ctrls ) { BerElement *ber; int rc; long bytes; + assert( ctrls == NULL ); /* ctrls not implemented */ + ber = ber_alloc_t( LBER_USE_DER ); Debug( LDAP_DEBUG_TRACE, "send_ldap_response: tag=%ld msgid=%ld err=%ld\n", @@ -290,7 +339,7 @@ send_ldap_disconnect( #endif send_ldap_response( conn, op, tag, msgid, err, NULL, text, NULL, - reqoid, NULL ); + reqoid, NULL, NULL ); Statslog( LDAP_DEBUG_STATS, "conn=%ld op=%ld DISCONNECT err=%ld tag=%lu text=%s\n", @@ -305,7 +354,8 @@ send_ldap_result( ber_int_t err, char *matched, char *text, - struct berval **ref + struct berval **ref, + LDAPControl **ctrls ) { ber_tag_t tag; @@ -319,10 +369,6 @@ send_ldap_result( assert( err != LDAP_PARTIAL_RESULTS ); - if ( ref != NULL ) { - trim_refs( ref, 0 ); - } - if ( err == LDAP_REFERRAL ) { if( ref == NULL ) { err = LDAP_NO_SUCH_OBJECT; @@ -349,7 +395,7 @@ send_ldap_result( send_ldap_response( conn, op, tag, msgid, err, matched, text, ref, - NULL, NULL ); + NULL, NULL, ctrls ); Statslog( LDAP_DEBUG_STATS, "conn=%ld op=%ld RESULT err=%ld tag=%lu text=%s\n", @@ -370,6 +416,7 @@ send_search_result( char *matched, char *text, struct berval **refs, + LDAPControl **ctrls, int nentries ) { @@ -383,9 +430,7 @@ send_search_result( assert( err != LDAP_PARTIAL_RESULTS ); - if ( refs != NULL ) { - trim_refs( refs, 1 ); - } + trim_refs_urls( refs ); if( op->o_protocol < LDAP_VERSION3 ) { /* send references in search results */ @@ -419,7 +464,7 @@ send_search_result( send_ldap_response( conn, op, tag, msgid, err, matched, text, refs, - NULL, NULL ); + NULL, NULL, ctrls ); Statslog( LDAP_DEBUG_STATS, "conn=%ld op=%ld SEARCH RESULT err=%ld tag=%lu text=%s\n", @@ -437,7 +482,8 @@ send_search_entry( Entry *e, char **attrs, int attrsonly, - int opattrs + int opattrs, + LDAPControl **ctrls ) { BerElement *ber; @@ -474,7 +520,7 @@ send_search_entry( if ( ber == NULL ) { Debug( LDAP_DEBUG_ANY, "ber_alloc failed\n", 0, 0, 0 ); send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, "allocating BER error", NULL ); + NULL, "allocating BER error", NULL, NULL ); goto error_return; } @@ -485,7 +531,7 @@ send_search_entry( Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 ); ber_free( ber, 1 ); send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, "encoding dn error", NULL ); + NULL, "encoding dn error", NULL, NULL ); goto error_return; } @@ -520,7 +566,7 @@ send_search_entry( Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 ); ber_free( ber, 1 ); send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, "encoding type error", NULL ); + NULL, "encoding type error", NULL, NULL ); goto error_return; } @@ -538,7 +584,7 @@ send_search_entry( "ber_printf failed\n", 0, 0, 0 ); ber_free( ber, 1 ); send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, "encoding value error", NULL ); + NULL, "encoding value error", NULL, NULL ); goto error_return; } } @@ -548,7 +594,7 @@ send_search_entry( Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 ); ber_free( ber, 1 ); send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, "encode end error", NULL ); + NULL, "encode end error", NULL, NULL ); goto error_return; } } @@ -559,7 +605,7 @@ send_search_entry( Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 ); ber_free( ber, 1 ); send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, "encode entry end error", NULL ); + NULL, "encode entry end error", NULL, NULL ); return( 1 ); } @@ -596,6 +642,7 @@ send_search_reference( Operation *op, Entry *e, struct berval **refs, + LDAPControl **ctrls, struct berval ***v2refs ) { @@ -644,7 +691,7 @@ send_search_reference( Debug( LDAP_DEBUG_ANY, "send_search_reference: ber_alloc failed\n", 0, 0, 0 ); send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, "alloc BER error", NULL ); + NULL, "alloc BER error", NULL, NULL ); return -1; } @@ -656,7 +703,7 @@ send_search_reference( "send_search_reference: ber_printf failed\n", 0, 0, 0 ); ber_free( ber, 1 ); send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, "encode dn error", NULL ); + NULL, "encode dn error", NULL, NULL ); return -1; } diff --git a/servers/slapd/root_dse.c b/servers/slapd/root_dse.c index edb655c24d..25d5f7ddbf 100644 --- a/servers/slapd/root_dse.c +++ b/servers/slapd/root_dse.c @@ -97,8 +97,10 @@ root_dse_info( Connection *conn, Operation *op, char **attrs, int attrsonly ) attr_merge( e, "ref", default_referral ); } - send_search_entry( &backends[0], conn, op, e, attrs, attrsonly, 1 ); - send_search_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL, 1 ); + send_search_entry( &backends[0], conn, op, + e, attrs, attrsonly, 1, NULL ); + send_search_result( conn, op, LDAP_SUCCESS, + NULL, NULL, NULL, NULL, 1 ); entry_free( e ); } diff --git a/servers/slapd/schema.c b/servers/slapd/schema.c index fc2ce4188c..e2e2294d56 100644 --- a/servers/slapd/schema.c +++ b/servers/slapd/schema.c @@ -1143,8 +1143,10 @@ schema_info( Connection *conn, Operation *op, char **attrs, int attrsonly ) return; } - send_search_entry( &backends[0], conn, op, e, attrs, attrsonly, 0 ); - send_search_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL, 1 ); + send_search_entry( &backends[0], conn, op, + e, attrs, attrsonly, 0, NULL ); + send_search_result( conn, op, LDAP_SUCCESS, + NULL, NULL, NULL, NULL, 1 ); entry_free( e ); } @@ -1179,3 +1181,35 @@ oc_print( ObjectClass *oc ) } #endif + + +int is_entry_objectclass( + Entry* e, + char* oc) +{ + Attribute *attr; + struct berval bv; + + if( e == NULL || oc == NULL || *oc == '\0' ) + return 0; + + /* + * find objectClass attribute + */ + attr = attr_find(e->e_attrs, "objectclass"); + + if( attr == NULL ) { + /* no objectClass attribute */ + return 0; + } + + bv.bv_val = oc; + bv.bv_len = strlen( bv.bv_val ); + + if( value_find(attr->a_vals, &bv, attr->a_syntax, 1) != 0) { + /* entry is not of this objectclass */ + return 0; + } + + return 1; +} \ No newline at end of file diff --git a/servers/slapd/search.c b/servers/slapd/search.c index dbdff19a1d..09d1591666 100644 --- a/servers/slapd/search.c +++ b/servers/slapd/search.c @@ -41,8 +41,8 @@ do_search( if( op->o_bind_in_progress ) { Debug( LDAP_DEBUG_ANY, "do_search: SASL bind in progress.\n", 0, 0, 0 ); - send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS, NULL, - "SASL bind in progress", NULL ); + send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS, + NULL, "SASL bind in progress", NULL, NULL ); return LDAP_SASL_BIND_IN_PROGRESS; } @@ -80,10 +80,27 @@ do_search( goto return_results; } - if ( scope != LDAP_SCOPE_BASE && scope != LDAP_SCOPE_ONELEVEL - && scope != LDAP_SCOPE_SUBTREE ) { - send_ldap_disconnect( conn, op, - LDAP_PROTOCOL_ERROR, "decoding error" ); + switch( scope ) { + case LDAP_SCOPE_BASE: + case LDAP_SCOPE_ONELEVEL: + case LDAP_SCOPE_SUBTREE: + break; + default: + send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, + NULL, "invalid scope", NULL, NULL ); + rc = -1; + goto return_results; + } + + switch( deref ) { + case LDAP_DEREF_NEVER: + case LDAP_DEREF_FINDING: + case LDAP_DEREF_SEARCHING: + case LDAP_DEREF_ALWAYS: + break; + default: + send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, + NULL, "invalid deref", NULL, NULL ); rc = -1; goto return_results; } @@ -101,7 +118,7 @@ do_search( LDAP_PROTOCOL_ERROR, "decode error" ); } else { send_ldap_result( conn, op, err, - NULL, "Bad search filter", NULL ); + NULL, "Bad search filter", NULL, NULL ); } goto return_results; } @@ -161,8 +178,14 @@ do_search( } #endif /* monitor or config or schema dn */ - if ( strcmp( base, LDAP_ROOT_DSE ) == 0 && scope == LDAP_SCOPE_BASE ) { - root_dse_info( conn, op, attrs, attrsonly ); + if ( strcmp( base, LDAP_ROOT_DSE ) == 0 ) { + if( scope == LDAP_SCOPE_BASE ) { + root_dse_info( conn, op, attrs, attrsonly ); + + } else { + send_ldap_result( conn, op, rc = LDAP_REFERRAL, + NULL, NULL, default_referral, NULL ); + } goto return_results; } @@ -173,21 +196,18 @@ do_search( */ if ( (be = select_backend( base )) == NULL ) { send_ldap_result( conn, op, rc = LDAP_REFERRAL, - NULL, NULL, default_referral ); + NULL, NULL, default_referral, NULL ); goto return_results; } - /* translate the base if it matches an aliased base part */ - base = suffixAlias ( base, op, be ); - /* actually do the search and send the result(s) */ if ( be->be_search ) { (*be->be_search)( be, conn, op, base, scope, deref, sizelimit, timelimit, filter, fstr, attrs, attrsonly ); } else { send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, - NULL, "Function not implemented", NULL ); + NULL, "Function not implemented", NULL, NULL ); } return_results:; diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index 41438d271d..ea4b6ff4a6 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -193,11 +193,11 @@ typedef struct entry { struct access { #define ACL_NONE 0x0001 -#define ACL_AUTH 0x0002 -#define ACL_COMPARE 0x0004 -#define ACL_SEARCH 0x0008 -#define ACL_READ 0x0010 -#define ACL_WRITE 0x0020 +#define ACL_AUTH 0x0004 +#define ACL_COMPARE 0x0008 +#define ACL_SEARCH 0x0010 +#define ACL_READ 0x0020 +#define ACL_WRITE 0x0040 #define ACL_PRIV_MASK 0x00ff #define ACL_SELF 0x4000 @@ -394,12 +394,11 @@ struct backend_db { /* these should be renamed from be_ to bd_ */ char **be_suffix; /* the DN suffixes of data in this backend */ char **be_nsuffix; /* the normalized DN suffixes in this backend */ - char **be_suffixAlias; /* the DN suffix aliases of data in this backend */ char *be_root_dn; /* the magic "root" dn for this db */ char *be_root_ndn; /* the magic "root" normalized dn for this db */ char *be_root_pw; /* the magic "root" password for this db */ int be_readonly; /* 1 => db is in "read only" mode */ - int be_maxDerefDepth; /* limit for depth of an alias deref */ + unsigned int be_max_deref_depth; /* limit for depth of an alias deref */ int be_sizelimit; /* size limit for this backend */ int be_timelimit; /* time limit for this backend */ struct acl *be_acl; /* access control list for this backend */ diff --git a/servers/slapd/slapd.dsp b/servers/slapd/slapd.dsp new file mode 100644 index 0000000000..ebe7203c0f --- /dev/null +++ b/servers/slapd/slapd.dsp @@ -0,0 +1,165 @@ +# Microsoft Developer Studio Project File - Name="slapd" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=slapd - Win32 Single Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "slapd.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "slapd.mak" CFG="slapd - Win32 Single Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "slapd - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "slapd - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE "slapd - Win32 Single Debug" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "slapd - Win32 Single Release" (based on\ + "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "slapd - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release\slapd" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 hs_regex.lib libdb.lib ws2_32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "slapd - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug\slapd" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 hs_regex.lib libdb.lib ws2_32.lib advapi32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ELSEIF "$(CFG)" == "slapd - Win32 Single Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "slapd___" +# PROP BASE Intermediate_Dir "slapd___" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "SDebug" +# PROP Intermediate_Dir "SDebug\slapd" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 hs_regexd.lib libdbs.lib wsock32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 hs_regex.lib libdb.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ELSEIF "$(CFG)" == "slapd - Win32 Single Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "slapd__0" +# PROP BASE Intermediate_Dir "slapd__0" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "SRelease" +# PROP Intermediate_Dir "SRelease\slapd" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 hs_regex.lib libdb.lib wsock32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 hs_regex.lib libdb.lib ws2_32.lib /nologo /subsystem:console /machine:I386 + +!ENDIF + +# Begin Target + +# Name "slapd - Win32 Release" +# Name "slapd - Win32 Debug" +# Name "slapd - Win32 Single Debug" +# Name "slapd - Win32 Single Release" +# Begin Source File + +SOURCE=.\daemon.c +# End Source File +# Begin Source File + +SOURCE=.\main.c +# End Source File +# Begin Source File + +SOURCE=.\nt_svc.c +# End Source File +# Begin Source File + +SOURCE=".\proto-slap.h" +# End Source File +# Begin Source File + +SOURCE=.\result.c +# End Source File +# Begin Source File + +SOURCE=.\slap.h +# End Source File +# End Target +# End Project diff --git a/servers/slapd/tools/ldbmcat.dsp b/servers/slapd/tools/ldbmcat.dsp new file mode 100644 index 0000000000..e74b773e51 --- /dev/null +++ b/servers/slapd/tools/ldbmcat.dsp @@ -0,0 +1,148 @@ +# Microsoft Developer Studio Project File - Name="ldbmcat" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=ldbmcat - Win32 Single Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ldbmcat.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ldbmcat.mak" CFG="ldbmcat - Win32 Single Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ldbmcat - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "ldbmcat - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE "ldbmcat - Win32 Single Debug" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "ldbmcat - Win32 Single Release" (based on\ + "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ldbmcat - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\Release" +# PROP Intermediate_Dir "..\Release\ldbmcat" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 libdb.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\libraries\Release" + +!ELSEIF "$(CFG)" == "ldbmcat - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "ldbmcat_" +# PROP BASE Intermediate_Dir "ldbmcat_" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\Debug" +# PROP Intermediate_Dir "..\Debug\ldbmcat" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 libdb.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\libraries\Debug" + +!ELSEIF "$(CFG)" == "ldbmcat - Win32 Single Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "ldbmcat_" +# PROP BASE Intermediate_Dir "ldbmcat_" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\Sdebug" +# PROP Intermediate_Dir "..\SDebug\ldbmcat" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 oldbm32.lib libdb.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\libraries\Debug" +# ADD LINK32 libdb.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\libraries\Debug" + +!ELSEIF "$(CFG)" == "ldbmcat - Win32 Single Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "ldbmcat0" +# PROP BASE Intermediate_Dir "ldbmcat0" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\SRelease" +# PROP Intermediate_Dir "..\SRelease\ldbmcat" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib libdb.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\libraries\Release" +# ADD LINK32 libdbs.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\libraries\Release" + +!ENDIF + +# Begin Target + +# Name "ldbmcat - Win32 Release" +# Name "ldbmcat - Win32 Debug" +# Name "ldbmcat - Win32 Single Debug" +# Name "ldbmcat - Win32 Single Release" +# Begin Source File + +SOURCE=.\ldbmcat.c +# End Source File +# Begin Source File + +SOURCE=.\mimic.c +# End Source File +# End Target +# End Project diff --git a/servers/slapd/tools/ldbmtest.c b/servers/slapd/tools/ldbmtest.c index 56513ab5b8..afe0588fca 100644 --- a/servers/slapd/tools/ldbmtest.c +++ b/servers/slapd/tools/ldbmtest.c @@ -1,68 +1,66 @@ +#include "portable.h" + #include -#include -#include -#include -#include -#include -#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_SYS_RESOURCE_H #include -#include +#endif +#ifdef HAVE_SYS_PARAM_H #include +#endif #include -#include -#include "portable.h" -#include "ldapconfig.h" + +#ifdef HAVE_FCNTL_H +#include +#endif + +#ifdef HAVE_IO_H +#include +#endif + +#include "ldap_defaults.h" #include "../slap.h" #include "../back-ldbm/back-ldbm.h" -#define EDITOR "/usr/ucb/vi" - -extern IDList *idl_fetch(); -extern Backend *select_backend(); -extern struct dbcache *ldbm_cache_open(); - -static struct dbcache *openchoice(); -static void print_entry(); -static void free_and_close(); -static void edit_entry(); -static void get_keydata(); - -struct dbcache *dbc; -LDBM dbp; -char *tailorfile; -Backend *be = NULL; -int ldap_debug; -int ldap_syslog; -int ldap_syslog_level; -int global_schemacheck; -int num_entries_sent; -int num_bytes_sent; -int active_threads; -char *default_referral; -struct objclass *global_oc; -time_t currenttime; -pthread_t listener_tid; -pthread_mutex_t num_sent_mutex; -pthread_mutex_t entry2str_mutex; -pthread_mutex_t active_threads_mutex; -pthread_mutex_t new_conn_mutex; -pthread_mutex_t currenttime_mutex; -pthread_mutex_t replog_mutex; -pthread_mutex_t ops_mutex; -pthread_mutex_t regex_mutex; - -main( argc, argv ) - int argc; - char **argv; +static struct dbcache *openchoice(char c, int mode, int verbose, char **fname); +static void print_entry(FILE *fp, char c, Datum *key, char *klabel, Datum *data, char *dlabel); +static void free_and_close(struct dbcache *dbc, Datum key, Datum data); +static void edit_entry(char c, Datum *data); +static void get_keydata(FILE *fp, char c, Datum *key, Datum *data); + +static struct dbcache *dbc; +static LDBM dbp; +static Backend *be = NULL; + +int +main( int argc, char **argv ) { char buf[256]; Datum savekey, key, data, last; char *fname; ID id; - IDList *idl; + ID_BLOCK *idl; Backend *tbe; int i; - extern char *optarg; + char *tailorfile; + +#ifdef HAVE_BERKELEY_DB2 + DBC *cursorp; +#endif + + ldbm_datum_init( savekey ); + ldbm_datum_init( key ); + ldbm_datum_init( data ); + ldbm_datum_init( last ); tailorfile = SLAPD_DEFAULT_CONFIGFILE; while ( (i = getopt( argc, argv, "d:f:" )) != EOF ) { @@ -88,8 +86,9 @@ main( argc, argv ) * initialize stuff and figure out which backend we're dealing with */ - init(); - read_config( tailorfile, &be, NULL ); + slap_init(SLAP_TOOL_MODE, "ldbmtest"); + read_config( tailorfile ); + slap_startup(-1); while ( 1 ) { printf( "dbtest: " ); @@ -135,7 +134,7 @@ main( argc, argv ) get_keydata( stdin, buf[1], &key, NULL ); if ( (idl = idl_fetch( be, dbc, key )) != NULL ) { data.dptr = (char *) idl; - data.dsize = (idl->b_nmax + 1) * sizeof(ID); + data.dsize = (ID_BLOCK_NMAX(idl) + 1) * sizeof(ID); print_entry( stdout, buf[1], &key, "key: ", &data, "data:\n" ); } @@ -151,9 +150,16 @@ main( argc, argv ) } savekey.dptr = NULL; +#ifdef HAVE_BERKELEY_DB2 + for ( key = ldbm_firstkey( dbc->dbc_db, &cursorp ); + key.dptr != NULL; + key = ldbm_nextkey( dbc->dbc_db, key, cursorp ) ) +#else for ( key = ldbm_firstkey( dbc->dbc_db ); key.dptr != NULL; - key = ldbm_nextkey( dbc->dbc_db, key ) ) { + key = ldbm_nextkey( dbc->dbc_db, key ) ) +#endif + { if ( savekey.dptr != NULL ) ldbm_datum_free( dbc->dbc_db, savekey ); savekey = key; @@ -168,7 +174,9 @@ main( argc, argv ) "key: ", NULL, NULL ); } - ldbm_datum_free( dbc->dbc_db, data ); + if ( data.dptr != NULL ) { + ldbm_datum_free( dbc->dbc_db, data ); + } } if ( savekey.dptr != NULL ) ldbm_datum_free( dbc->dbc_db, savekey ); @@ -197,6 +205,7 @@ main( argc, argv ) free_and_close( dbc, key, data ); break; +#ifndef HAVE_WINSOCK case 'e': /* edit an entry */ if ( (dbc = openchoice( buf[1], LDBM_WRITER, 1, NULL )) == NULL ) { @@ -235,6 +244,7 @@ main( argc, argv ) free_and_close( dbc, key, data ); break; +#endif case 'a': /* add an entry */ if ( (dbc = openchoice( buf[1], LDBM_WRITER, 1, NULL )) @@ -265,13 +275,13 @@ main( argc, argv ) get_keydata( stdin, buf[1], &key, &data ); - idl = (IDList *) data.dptr; + idl = (ID_BLOCK *) data.dptr; for ( id = idl_firstid( idl ); id != NOID; id = idl_nextid( idl, id ) ) { if ( idl_insert_key( be, dbc, key, id ) != 0 ) { fprintf( stderr, - "idl_insert_key (%s) %d failed\n", + "idl_insert_key (%s) %ld failed\n", key.dptr, id ); continue; } @@ -288,7 +298,7 @@ main( argc, argv ) } else { buf[strlen( buf ) - 1] = '\0'; } - (void) dn_normalize( buf ); + (void) dn_normalize_case( buf ); if ( (tbe = select_backend( buf )) == NULL ) { fprintf( stderr, "unknown suffix \"%s\"\n", buf ); @@ -313,8 +323,16 @@ main( argc, argv ) } last.dptr = NULL; + +#ifdef HAVE_BERKELEY_DB2 + for ( key = ldbm_firstkey( dbp, &cursorp ); + key.dptr != NULL; + key = ldbm_nextkey( dbp, last, cursorp ) ) +#else for ( key = ldbm_firstkey( dbp ); key.dptr != NULL; - key = ldbm_nextkey( dbp, last ) ) { + key = ldbm_nextkey( dbp, last ) ) +#endif + { if ( last.dptr != NULL ) { ldbm_datum_free( dbp, last ); } @@ -348,14 +366,14 @@ main( argc, argv ) } } + slap_shutdown(-1); + slap_destroy(); + return( 0 ); } static void -free_and_close( dbc, key, data ) - struct dbcache *dbc; - Datum key; - Datum data; +free_and_close( struct dbcache *dbc, Datum key, Datum data ) { ldbm_cache_really_close( be, dbc ); if ( key.dptr != NULL ) @@ -365,17 +383,13 @@ free_and_close( dbc, key, data ) } static int -dnid_cmp( a, b ) - long *a; - long *b; +dnid_cmp( const void *a, const void *b ) { - return( *a - *b ); + return( *(const long int *)a - *(const long int *)b ); } static char * -myrealloc( p, size ) - char *p; - int size; +myrealloc( char *p, int size ) { if ( p == NULL ) return( (char *) malloc( size ) ); @@ -384,15 +398,13 @@ myrealloc( p, size ) } static void -get_idlist( fp, data ) - FILE *fp; - Datum *data; +get_idlist( FILE *fp, Datum *data ) { char buf[20]; - int i, j, fd, tty; - IDList *p; - int psize, pmax; - int nmax, nids; + int i, fd, tty; + ID_BLOCK *p; + unsigned int psize, pmax; + unsigned int nmax, nids; fd = fileno( fp ); tty = isatty( fd ); @@ -415,7 +427,7 @@ get_idlist( fp, data ) if ( psize + sizeof(ID) > pmax ) { pmax += BUFSIZ; - p = (IDList *) myrealloc( (char *) p, pmax ); + p = (ID_BLOCK *) myrealloc( (char *) p, pmax ); } if ( strncmp( buf, "nids=0", 6 ) == 0 ) { @@ -423,7 +435,7 @@ get_idlist( fp, data ) continue; } - p->b_ids[i++] = atol( buf ); + ID_BLOCK_ID(p,i++) = atol( buf ); psize += sizeof(ID); } if ( nmax == 0 ) { @@ -432,7 +444,7 @@ get_idlist( fp, data ) printf( "%d IDs entered. Max number of ids? [%d] ", i, i ); if ( fgets( buf, sizeof(buf), fp ) != NULL && - isdigit( buf[0] ) ) { + isdigit( (unsigned char) buf[0] ) ) { nmax = atol( buf ); } } else { @@ -440,29 +452,27 @@ get_idlist( fp, data ) } } if ( i > 0 ) { - p->b_nmax = nmax; + ID_BLOCK_NMAX(p) = nmax; if ( nids != 0 ) { - p->b_nids = 0; - p->b_ids[i] = NOID; + ID_BLOCK_NIDS(p) = 0; + ID_BLOCK_ID(p,i) = NOID; } else { - p->b_nids = i; + ID_BLOCK_NIDS(p) = i; } - qsort( (void *) p->b_ids, i, sizeof(ID), (void *) dnid_cmp ); + qsort( (void *) &ID_BLOCK_ID(p, 0), i, sizeof(ID), dnid_cmp ); } data->dptr = (char *) p; - data->dsize = (nmax + 2) * sizeof(ID); + data->dsize = (nmax + ID_BLOCK_IDS_OFFSET) * sizeof(ID); } static void -get_entry( fp, data ) - FILE *fp; - Datum *data; +get_entry( FILE *fp, Datum *data ) { char buf[BUFSIZ]; char *p; - int pmax, psize, len; + unsigned int pmax, psize, len; int fd; fd = fileno( fp ); @@ -491,18 +501,19 @@ get_entry( fp, data ) data->dsize = psize + 1; } +#ifndef HAVE_WINSOCK static void -edit_entry( c, data ) - char c; - Datum *data; +edit_entry( char c, Datum *data ) { int fd, pid; char tmpname[20]; FILE *fp; +#ifndef HAVE_WAITPID WAITSTATUSTYPE status; +#endif strcpy( tmpname, "/tmp/dbtestXXXXXX" ); -#ifdef ultrix +#ifndef HAVE_MKSTEMP if ( (fd = open( mktemp( tmpname ), O_RDWR, 0600 )) == -1 ) { perror( tmpname ); return; @@ -527,7 +538,7 @@ edit_entry( c, data ) char *editor; if ( (editor = getenv( "EDITOR" )) == NULL ) { - editor = EDITOR; + editor = LDAP_EDITOR; } execl( editor, editor, tmpname, NULL ); perror( "execl" ); @@ -536,11 +547,12 @@ edit_entry( c, data ) fclose( fp ); -#ifdef USE_WAITPID - if ( waitpid( (pid_t) -1, 0, WAIT_FLAGS ) < 0 ) { +#ifdef HAVE_WAITPID + if ( waitpid( (pid_t) -1, NULL, WAIT_FLAGS ) < 0 ) #else - if ( wait3( &status, WAIT_FLAGS, 0 ) < 0 ) { + if ( wait3( (pid_t) -1, &status, WAIT_FLAGS, 0 ) < 0 ) #endif + { perror( "wait" ); return; } @@ -549,19 +561,17 @@ edit_entry( c, data ) perror( tmpname ); return; } - ldbm_datum_free( NULL, *data ); + if ( data->dptr != NULL ) { + ldbm_datum_free( NULL, *data ); + } get_keydata( fp, c, NULL, data ); fclose( fp ); unlink( tmpname ); } +#endif static struct dbcache * -openfile( name, namesiz, mode, verbose, c ) - char *name; - int namesiz; - int mode; - int verbose; - char c; +openfile( char *name, int namesiz, int mode, int verbose, char c ) { struct dbcache *dbc; @@ -590,11 +600,7 @@ openfile( name, namesiz, mode, verbose, c ) } static struct dbcache * -openchoice( c, mode, verbose, fname ) - char c; - int mode; - int verbose; - char **fname; +openchoice( char c, int mode, int verbose, char **fname ) { static char name[MAXPATHLEN]; @@ -629,17 +635,18 @@ openchoice( c, mode, verbose, fname ) } static void -print_entry( fp, c, key, klabel, data, dlabel ) - FILE *fp; - char c; - Datum *key; - char *klabel; - Datum *data; - char *dlabel; +print_entry( + FILE *fp, + char c, + Datum *key, + char *klabel, + Datum *data, + char *dlabel +) { ID id; - IDList *idl; - int i; + ID_BLOCK *idl; + unsigned int i; char msg[2]; if ( data != NULL && data->dptr == NULL ) { @@ -661,14 +668,14 @@ print_entry( fp, c, key, klabel, data, dlabel ) key->dsize ); if ( data != NULL ) { SAFEMEMCPY( (char *) &id, data->dptr, sizeof(ID) ); - fprintf( fp, "%s%d\n", dlabel ? dlabel : "", id ); + fprintf( fp, "%s%ld\n", dlabel ? dlabel : "", id ); } break; case 'e': /* id2entry - key is dnid, data is entry */ if ( key != NULL ) { SAFEMEMCPY( (char *) &id, key->dptr, sizeof(ID) ); - fprintf( fp, "%s %d\n", klabel, id ); + fprintf( fp, "%s %ld\n", klabel, id ); } if ( data != NULL ) { if ( dlabel ) { @@ -685,22 +692,22 @@ print_entry( fp, c, key, klabel, data, dlabel ) fprintf( fp, "%s%s (len %d)\n", klabel, key->dptr, key->dsize ); if ( data != NULL ) { - idl = (IDList *) data->dptr; + idl = (ID_BLOCK *) data->dptr; if ( dlabel ) - fprintf( fp, "%s\tnmax=%d\n\tncur=%d\n", dlabel, - idl->b_nmax, idl->b_nids ); + fprintf( fp, "%s\tnmax=%ld\n\tncur=%ld\n", dlabel, + ID_BLOCK_NMAX(idl), ID_BLOCK_NIDS(idl) ); - if ( INDIRECT_BLOCK( idl ) ) { - for ( i = 0; idl->b_ids[i] != NOID; i++ ) { - fprintf( fp, "\t%d\n", idl->b_ids[i] ); + if ( ID_BLOCK_INDIRECT( idl ) ) { + for ( i = 0; !ID_BLOCK_NOID(idl, i); i++ ) { + fprintf( fp, "\t%ld\n", ID_BLOCK_ID(idl, i) ); } - } else if ( ALLIDS( idl ) ) { - fprintf( fp, "\tALLIDS (1..%d)\n", - idl->b_nids - 1 ); + } else if ( ID_BLOCK_ALLIDS( idl ) ) { + fprintf( fp, "\tALLIDS (1..%ld)\n", + ID_BLOCK_NIDS(idl) - 1 ); } else { - for ( i = 0; i < idl->b_nids; i++ ) { - fprintf( fp, "\t%d\n", idl->b_ids[i] ); + for ( i = 0; i < ID_BLOCK_NIDS(idl); i++ ) { + fprintf( fp, "\t%ld\n", ID_BLOCK_ID(idl,i) ); } } } @@ -722,11 +729,7 @@ print_entry( fp, c, key, klabel, data, dlabel ) } static void -get_keydata( fp, c, key, data ) - FILE *fp; - char c; - Datum *key; - Datum *data; +get_keydata( FILE *fp, char c, Datum *key, Datum *data ) { static char kbuf[BUFSIZ], dbuf[BUFSIZ]; long n; diff --git a/servers/slapd/tools/ldbmtest.dsp b/servers/slapd/tools/ldbmtest.dsp new file mode 100644 index 0000000000..6bd91f19b9 --- /dev/null +++ b/servers/slapd/tools/ldbmtest.dsp @@ -0,0 +1,148 @@ +# Microsoft Developer Studio Project File - Name="ldbmtest" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=ldbmtest - Win32 Single Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ldbmtest.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ldbmtest.mak" CFG="ldbmtest - Win32 Single Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ldbmtest - Win32 Release" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "ldbmtest - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE "ldbmtest - Win32 Single Debug" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "ldbmtest - Win32 Single Release" (based on\ + "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ldbmtest - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\Release" +# PROP Intermediate_Dir "..\Release\ldbmtest" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\include" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 libdb.lib hs_regex.lib ws2_32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "ldbmtest - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\Debug" +# PROP Intermediate_Dir "..\Debug\ldbmtest" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 libdb.lib hs_regex.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ELSEIF "$(CFG)" == "ldbmtest - Win32 Single Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "ldbmtest" +# PROP BASE Intermediate_Dir "ldbmtest" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\SDebug" +# PROP Intermediate_Dir "..\SDebug\ldbmtest" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 libdbs.lib hs_regex.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ELSEIF "$(CFG)" == "ldbmtest - Win32 Single Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "ldbmtes0" +# PROP BASE Intermediate_Dir "ldbmtes0" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\SRelease" +# PROP Intermediate_Dir "..\SRelease\ldbmtest" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\..\..\include" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 libdbs.lib hs_regex.lib ws2_32.lib /nologo /subsystem:console /machine:I386 + +!ENDIF + +# Begin Target + +# Name "ldbmtest - Win32 Release" +# Name "ldbmtest - Win32 Debug" +# Name "ldbmtest - Win32 Single Debug" +# Name "ldbmtest - Win32 Single Release" +# Begin Source File + +SOURCE=.\ldbmtest.c +# End Source File +# Begin Source File + +SOURCE=.\mimic.c +# End Source File +# End Target +# End Project diff --git a/servers/slapd/tools/mimic.c b/servers/slapd/tools/mimic.c index b5e80c5803..251f0dcb54 100644 --- a/servers/slapd/tools/mimic.c +++ b/servers/slapd/tools/mimic.c @@ -23,6 +23,17 @@ int str2result( return 0; } +void +send_ldap_disconnect( + Connection *conn, + Operation *op, + ber_int_t err, + char *text +) +{ + assert(0); +} + void send_ldap_result( Connection *conn, @@ -30,7 +41,8 @@ send_ldap_result( int err, char *matched, char *text, - struct berval **refs + struct berval **refs, + LDAPControl **ctrls ) { assert(0); @@ -44,6 +56,7 @@ send_search_result( char *matched, char *text, struct berval **refs, + LDAPControl **ctrls, int nentries ) { @@ -58,7 +71,8 @@ send_search_entry( Entry *e, char **attrs, int attrsonly, - int opattrs + int opattrs, + LDAPControl **ctrls ) { assert(0); @@ -71,9 +85,17 @@ int send_search_reference( Operation *op, Entry *e, struct berval **refs, + LDAPControl **ctrls, struct berval ***v2refs ) { assert(0); return -1; } + +struct berval **get_entry_referrals( + Backend *be, Connection *conn, Operation *op, Entry *e ) +{ + assert(0); + return NULL; +} diff --git a/servers/slapd/value.c b/servers/slapd/value.c index c9e6fbb577..7ef0c62cd5 100644 --- a/servers/slapd/value.c +++ b/servers/slapd/value.c @@ -1,12 +1,16 @@ /* value.c - routines for dealing with values */ +#include "portable.h" + #include -#include -#include -#include -#include + +#include +#include +#include +#include + #include -#include "portable.h" + #include "slap.h" int @@ -85,7 +89,7 @@ value_normalize( } if ( syntax & SYNTAX_DN ) { - (void) dn_normalize_case( s ); + (void) dn_normalize( s ); return; } @@ -94,13 +98,11 @@ value_normalize( if ( (syntax & SYNTAX_TEL) && (*s == ' ' || *s == '-') ) { continue; } - *d++ = TOUPPER( *s ); + *d++ = TOUPPER( (unsigned char) *s ); } *d = '\0'; } -#define MIN( a, b ) (a < b ? a : b ) - int value_cmp( struct berval *v1, @@ -110,7 +112,6 @@ value_cmp( ) { int rc; - struct stat st1, st2; if ( normalize & 1 ) { v1 = ber_bvdup( v1 ); @@ -133,8 +134,9 @@ value_cmp( break; case SYNTAX_BIN: - rc = memcmp( v1->bv_val, v2->bv_val, MIN( v1->bv_len, - v2->bv_len ) ); + rc = (v1->bv_len == v2->bv_len + ? memcmp( v1->bv_val, v2->bv_val, v1->bv_len ) + : v1->bv_len > v2->bv_len ? 1 : -1); break; } @@ -148,50 +150,6 @@ value_cmp( return( rc ); } -int -value_ncmp( - struct berval *v1, - struct berval *v2, - int syntax, - int len, - int normalize -) -{ - int rc; - - if ( normalize & 1 ) { - v1 = ber_bvdup( v1 ); - value_normalize( v1->bv_val, syntax ); - } - if ( normalize & 2 ) { - v2 = ber_bvdup( v2 ); - value_normalize( v2->bv_val, syntax ); - } - - switch ( syntax ) { - case SYNTAX_CIS: - case (SYNTAX_CIS | SYNTAX_TEL): - rc = strncasecmp( v1->bv_val, v2->bv_val, len ); - break; - - case SYNTAX_CES: - rc = strncmp( v1->bv_val, v2->bv_val, len ); - break; - - case SYNTAX_BIN: - rc = memcmp( v1->bv_val, v2->bv_val, len ); - } - - if ( normalize & 1 ) { - ber_bvfree( v1 ); - } - if ( normalize & 2 ) { - ber_bvfree( v2 ); - } - - return( rc ); -} - int value_find( struct berval **vals,