Commit 74fa239a authored by Pierangelo Masarati's avatar Pierangelo Masarati
Browse files

This is the commit of:

  - librewrite, for string rewriting; it may be used in back-ldap
    by configuring with '--enable-rewrite'. It must be used in
    back-meta. There's a text file, 'libraries/librewrite/RATIONALE',
    that explains the usage and the features. More comprehensive
    documentation will follow.
  - enhancements of back-ldap (ITS#989,ITS#998,ITS#1002,ITS#1054 and ITS#1137)
    including dn rewriting, a fix to group acl matching and so
  - back-meta: a new backend that proxies a set of remote servers
    by spawning queries. It uses portions of back-ldap and the rewrite
    capabilities of librewrite. It can be compiled by configuring
    with `--enable-ldap --enable-rewrite --enable-meta'.
    There's a text file, 'servers/slapd/back-meta/Documentation', that
    describes the main features and config statements.

Note: someone (Kurt?) should run 'autoconf' and commit 'configure' as
my autoconf version must be different: my configures contain a number
of differences and I didn't feel comfortable in adding them :)
parent cabeec26
......@@ -116,6 +116,7 @@ OL_ARG_ENABLE(referrals,[ --enable-referrals enable V2 Referrals (experimenta
OL_ARG_ENABLE(kbind,[ --enable-kbind enable V2 Kerberos IV bind (deprecated)], no)dnl
OL_ARG_ENABLE(ipv6,[ --enable-ipv6 enable IPv6 support], auto)dnl
OL_ARG_ENABLE(local,[ --enable-local enable AF_LOCAL (AF_UNIX) socket support], auto)dnl
OL_ARG_ENABLE(rewrite,[ --enable-rewrite enable rewrite], no)dnl
OL_ARG_ENABLE(x_compile,[ --enable-x-compile enable cross compiling],
no, [yes no])dnl
......@@ -177,6 +178,9 @@ OL_ARG_WITH(ldbm_module,[ --with-ldbm-module module type], static,
[static dynamic])
OL_ARG_WITH(ldbm_type,[ --with-ldbm-type use LDBM type], auto,
[auto btree hash])
OL_ARG_ENABLE(meta,[ --enable-meta enable metadirectory backend], no)dnl
OL_ARG_WITH(meta_module,[ --with-meta-module module type], static,
[static dynamic])
OL_ARG_ENABLE(passwd,[ --enable-passwd enable passwd backend], no)dnl
OL_ARG_WITH(passwd_module,[ --with-passwd-module module type], static,
[static dynamic])
......@@ -222,6 +226,9 @@ if test $ol_enable_slapd = no ; then
if test $ol_enable_ldbm = yes ; then
AC_MSG_WARN([slapd disabled, ignoring --enable-ldbm argument])
fi
if test $ol_enable_meta = yes ; then
AC_MSG_WARN([slapd disabled, ignoring --enable-meta argument])
fi
if test $ol_enable_passwd = yes ; then
AC_MSG_WARN([slapd disabled, ignoring --enable-passwd argument])
fi
......@@ -273,6 +280,9 @@ dnl fi
if test $ol_with_ldbm_module != static ; then
AC_MSG_WARN([slapd disabled, ignoring --with-ldbm-module argument])
fi
if test $ol_with_meta_module != static ; then
AC_MSG_WARN([slapd disabled, ignoring --with-meta-module argument])
fi
if test $ol_with_passwd_module != static ; then
AC_MSG_WARN([slapd disabled, ignoring --with-passwd-module argument])
fi
......@@ -291,12 +301,16 @@ dnl fi
if test $ol_enable_slurpd = yes ; then
AC_MSG_ERROR([slurpd requires slapd])
fi
if test $ol_enable_rewrite = yes ; then
AC_MSG_WARN([slapd disabled, ignoring --enable-rewrite argument])
fi
# force settings to no
ol_enable_bdb=no
ol_enable_dnssrv=no
ol_enable_ldap=no
ol_enable_ldbm=no
ol_enable_meta=no
ol_enable_passwd=no
ol_enable_perl=no
ol_enable_shell=no
......@@ -318,6 +332,7 @@ dnl ol_enable_multimaster=no
ol_with_dnssrv_module=static
ol_with_ldap_module=static
ol_with_ldbm_module=static
ol_with_meta_module=static
ol_with_passwd_module=static
ol_with_perl_module=static
ol_with_shell_module=static
......@@ -326,6 +341,8 @@ dnl ol_enable_multimaster=no
ol_enable_slurpd=no
ol_enable_rewrite=no
elif test $ol_enable_ldbm = no ; then
dnl SLAPD without LDBM
......@@ -345,6 +362,7 @@ elif test $ol_enable_ldbm = no ; then
$ol_enable_bdb = no -a \
$ol_enable_dnssrv = no -a \
$ol_enable_ldap = no -a \
$ol_enable_meta = no -a \
$ol_enable_passwd = no -a \
$ol_enable_perl = no -a \
$ol_enable_shell = no -a \
......@@ -427,6 +445,7 @@ BUILD_BDB=no
BUILD_DNSSRV=no
BUILD_LDAP=no
BUILD_LDBM=no
BUILD_META=no
BUILD_PASSWD=no
BUILD_PERL=no
BUILD_SHELL=no
......@@ -437,6 +456,7 @@ BUILD_BDB_DYNAMIC=static
BUILD_DNSSRV_DYNAMIC=static
BUILD_LDAP_DYNAMIC=static
BUILD_LDBM_DYNAMIC=static
BUILD_META_DYNAMIC=static
BUILD_PASSWD_DYNAMIC=static
BUILD_PERL_DYNAMIC=static
BUILD_SHELL_DYNAMIC=static
......@@ -650,6 +670,7 @@ else
ol_with_dnssrv_module=static
ol_with_ldap_module=static
ol_with_ldbm_module=static
ol_with_meta_module=static
ol_with_passwd_module=static
ol_with_perl_module=static
ol_with_shell_module=static
......@@ -2342,6 +2363,25 @@ if test "$ol_link_ldbm" != no ; then
fi
fi
if test "$ol_enable_meta" != no ; then
if test "$ol_enable_ldap" = no ; then
AC_MSG_ERROR([need --enable-ldap to use --enable-meta])
fi
if test "$ol_enable_rewrite" = no ; then
AC_MSG_ERROR([need --enable-rewrite to use --enable-meta])
fi
AC_DEFINE(SLAPD_META,1,[define to support LDAP Metadirectory backend])
BUILD_SLAPD=yes
BUILD_META=yes
if test "$ol_with_meta_module" != static ; then
AC_DEFINE(SLAPD_META_DYNAMIC,1,
[define to support dynamic LDAP Metadirectory backend])
BUILD_META=mod
BUILD_META_DYNAMIC=shared
SLAPD_MODULES_LIST="$SLAPD_MODULES_LIST -dlopen \$(SLAP_DIR)back-meta/back_meta.la"
fi
fi
if test "$ol_enable_passwd" != no ; then
AC_DEFINE(SLAPD_PASSWD,1,[define to support PASSWD backend])
BUILD_SLAPD=yes
......@@ -2412,6 +2452,12 @@ if test "$ol_enable_slurpd" != no -a "$ol_link_threads" != no -a \
BUILD_SLURPD=yes
fi
if test "$ol_enable_rewrite" != no ; then
AC_DEFINE(ENABLE_REWRITE,1,[define to enable rewriting in back-ldap and back-meta])
BUILD_REWRITE=yes
SLAPD_LIBS="$SLAPD_LIBS -lrewrite"
fi
dnl ----------------------------------------------------------------
if test "$LINK_BINS_DYNAMIC" = yes; then
......@@ -2442,6 +2488,7 @@ AC_SUBST(BUILD_SLAPD)
AC_SUBST(BUILD_DNSSRV)
AC_SUBST(BUILD_LDAP)
AC_SUBST(BUILD_LDBM)
AC_SUBST(BUILD_META)
AC_SUBST(BUILD_PASSWD)
AC_SUBST(BUILD_PERL)
AC_SUBST(BUILD_SHELL)
......@@ -2451,6 +2498,7 @@ AC_SUBST(BUILD_SLAPD)
AC_SUBST(BUILD_DNSSRV_DYNAMIC)
AC_SUBST(BUILD_LDAP_DYNAMIC)
AC_SUBST(BUILD_LDBM_DYNAMIC)
AC_SUBST(BUILD_META_DYNAMIC)
AC_SUBST(BUILD_PASSWD_DYNAMIC)
AC_SUBST(BUILD_PERL_DYNAMIC)
AC_SUBST(BUILD_SHELL_DYNAMIC)
......@@ -2523,12 +2571,14 @@ libraries/libldbm/Makefile:build/top.mk:libraries/libldbm/Makefile.in:build/lib.
libraries/libldif/Makefile:build/top.mk:libraries/libldif/Makefile.in:build/lib.mk:build/lib-static.mk \
libraries/liblunicode/Makefile:build/top.mk:libraries/liblunicode/Makefile.in:build/lib.mk:build/lib-static.mk \
libraries/liblutil/Makefile:build/top.mk:libraries/liblutil/Makefile.in:build/lib.mk:build/lib-static.mk \
libraries/librewrite/Makefile:build/top.mk:libraries/librewrite/Makefile.in:build/lib.mk:build/lib-static.mk \
servers/Makefile:build/top.mk:servers/Makefile.in:build/dir.mk \
servers/slapd/Makefile:build/top.mk:servers/slapd/Makefile.in:build/srv.mk \
servers/slapd/back-bdb/Makefile:build/top.mk:servers/slapd/back-bdb/Makefile.in:build/mod.mk \
servers/slapd/back-dnssrv/Makefile:build/top.mk:servers/slapd/back-dnssrv/Makefile.in:build/mod.mk \
servers/slapd/back-ldap/Makefile:build/top.mk:servers/slapd/back-ldap/Makefile.in:build/mod.mk \
servers/slapd/back-ldbm/Makefile:build/top.mk:servers/slapd/back-ldbm/Makefile.in:build/mod.mk \
servers/slapd/back-meta/Makefile:build/top.mk:servers/slapd/back-meta/Makefile.in:build/mod.mk \
servers/slapd/back-passwd/Makefile:build/top.mk:servers/slapd/back-passwd/Makefile.in:build/mod.mk \
servers/slapd/back-perl/Makefile:build/top.mk:servers/slapd/back-perl/Makefile.in:build/mod.mk \
servers/slapd/back-shell/Makefile:build/top.mk:servers/slapd/back-shell/Makefile.in:build/mod.mk \
......
......@@ -930,6 +930,12 @@
/* define to support dynamic LDBM backend */
#undef SLAPD_LDBM_DYNAMIC
/* define to support LDAP Metadirectory backend */
#undef SLAPD_META
/* define to support dynamic LDAP Metadirectory backend */
#undef SLAPD_META_DYNAMIC
/* define to support PASSWD backend */
#undef SLAPD_PASSWD
......@@ -960,6 +966,9 @@
/* define to support dynamic SQL backend */
#undef SLAPD_SQL_DYNAMIC
/* define to enable rewriting in back-ldap and back-meta */
#undef ENABLE_REWRITE
/* begin of postamble */
......
/******************************************************************************
*
* Copyright (C) 2000 Pierangelo Masarati, <ando@sys-net.it>
* All rights reserved.
*
* Permission is granted to anyone to use this software for any purpose
* on any computer system, and to alter it and redistribute it, subject
* to the following restrictions:
*
* 1. The author is not responsible for the consequences of use of this
* software, no matter how awful, even if they arise from flaws in it.
*
* 2. The origin of this software must not be misrepresented, either by
* explicit claim or by omission. Since few users ever read sources,
* credits should appear in the documentation.
*
* 3. Altered versions must be plainly marked as such, and must not be
* misrepresented as being the original software. Since few users
* ever read sources, credits should appear in the documentation.
*
* 4. This notice may not be removed or altered.
*
******************************************************************************/
#ifndef REWRITE_H
#define REWRITE_H
LDAP_BEGIN_DECL
/*
* Default rewrite context
*/
#define REWRITE_DEFAULT_CONTEXT "default"
/*
* Rewrite engine states
*/
#define REWRITE_OFF 0x0000
#define REWRITE_ON 0x0001
#define REWRITE_DEFAULT REWRITE_OFF
/*
* Rewrite internal status returns
*/
#define REWRITE_SUCCESS LDAP_SUCCESS
#define REWRITE_ERR LDAP_OPERATIONS_ERROR
#define REWRITE_NO_SUCH_OBJECT LDAP_NO_SUCH_OBJECT
/*
* Rewrite modes (input values for rewrite_info_init); determine the
* behavior in case a null or non existent context is required:
*
* REWRITE_MODE_ERR error
* REWRITE_MODE_OK no error but no rewrite
* REWRITE_MODE_COPY_INPUT a copy of the input is returned
* REWRITE_MODE_USE_DEFAULT the default context is used.
*/
#define REWRITE_MODE_ERR 0x0010
#define REWRITE_MODE_OK 0x0011
#define REWRITE_MODE_COPY_INPUT 0x0012
#define REWRITE_MODE_USE_DEFAULT 0x0013
/*
* Rewrite status returns
*
* REWRITE_REGEXEC_OK success (result may be empty in case
* of no match)
* REWRITE_REGEXEC_ERR error (internal error,
* misconfiguration, map not working ...)
* REWRITE_REGEXEC_STOP internal use; never returned
* REWRITE_REGEXEC_UNWILLING the server should issue an 'unwilling
* to perform' error
*/
#define REWRITE_REGEXEC_OK 0x0000
#define REWRITE_REGEXEC_ERR 0x0001
#define REWRITE_REGEXEC_STOP 0x0002
#define REWRITE_REGEXEC_UNWILLING 0x0004
/*
* Rewrite info
*/
struct rewrite_info;
struct berval;
/*
* Inits the info
*/
extern struct rewrite_info *
rewrite_info_init(
int mode
);
/*
* Cleans up the info structure
*/
extern int
rewrite_info_delete(
struct rewrite_info *info
);
/*
* Parses a config line and takes actions to fit content in rewrite structure;
* lines handled are of the form:
*
* rewriteEngine {on|off}
* rewriteMaxPasses numPasses
* rewriteContext contextName [alias aliasedRewriteContex]
* rewriteRule pattern substPattern [ruleFlags]
* rewriteMap mapType mapName [mapArgs]
* rewriteParam paramName paramValue
*/
extern int
rewrite_parse(
struct rewrite_info *info,
const char *fname,
int lineno,
int argc,
char **argv
);
/*
* Rewrites a string according to context.
* If the engine is off, OK is returned, but the return string will be NULL.
* In case of 'unwilling to perform', UNWILLING is returned, and the
* return string will also be null. The same in case of error.
* Otherwise, OK is returned, and result will hold a newly allocated string
* with the rewriting.
*
* What to do in case of non-existing rewrite context is still an issue.
* Four possibilities:
* - error,
* - ok with NULL result,
* - ok with copy of string as result,
* - use the default rewrite context.
*/
extern int
rewrite(
struct rewrite_info *info,
const char *rewriteContext,
const char *string,
char **result
);
/*
* Same as above; the cookie relates the rewrite to a session
*/
extern int
rewrite_session(
struct rewrite_info *info,
const char *rewriteContext,
const char *string,
const void *cookie,
char **result
);
/*
* Inits a session
*/
extern struct rewrite_session *
rewrite_session_init(
struct rewrite_info *info,
const void *cookie
);
/*
* Defines and inits a variable with session scope
*/
extern int
rewrite_session_var_set(
struct rewrite_info *info,
const void *cookie,
const char *name,
const char *value
);
/*
* Deletes a session
*/
extern int
rewrite_session_delete(
struct rewrite_info *info,
const void *cookie
);
/*
* Params
*/
/*
* Defines and inits a variable with global scope
*/
extern int
rewrite_param_set(
struct rewrite_info *info,
const char *name,
const char *value
);
/*
* Gets a var with global scope
*/
extern int
rewrite_param_get(
struct rewrite_info *info,
const char *name,
struct berval *value
);
/*
* Destroys the parameter tree
*/
extern int
rewrite_param_destroy(
struct rewrite_info *info
);
LDAP_END_DECL
#endif /* REWRITE_H */
......@@ -6,5 +6,5 @@
SUBDIRS= liblunicode liblutil libldif \
liblber libldap libldap_r \
libavl libldbm
libavl libldbm librewrite
/******************************************************************************
*
* Copyright (C) 2000 Pierangelo Masarati, <ando@sys-net.it>
* All rights reserved.
*
* Permission is granted to anyone to use this software for any purpose
* on any computer system, and to alter it and redistribute it, subject
* to the following restrictions:
*
* 1. The author is not responsible for the consequences of use of this
* software, no matter how awful, even if they arise from flaws in it.
*
* 2. The origin of this software must not be misrepresented, either by
* explicit claim or by omission. Since few users ever read sources,
* credits should appear in the documentation.
*
* 3. Altered versions must be plainly marked as such, and must not be
* misrepresented as being the original software. Since few users
* ever read sources, credits should appear in the documentation.
*
* 4. This notice may not be removed or altered.
*
******************************************************************************/
# $OpenLDAP$
## Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
## COPYING RESTRICTIONS APPLY, see COPYRIGHT file
##
## LIBREWRITE
##
## Copyright 2000-2001 Pierangelo Masarati <ando@sys-net.it>
##
SRCS = config.c context.c info.c ldapmap.c map.c params.c rule.c \
session.c subst.c var.c \
parse.c rewrite.c
XSRCS = version.c
OBJS = config.o context.o info.o ldapmap.o map.o params.o rule.o \
session.o subst.o var.o
LDAP_INCDIR= ../../include
LDAP_LIBDIR= ../../libraries
LIBRARY = librewrite.a
PROGRAMS = rewrite
XLIBS = -lrewrite -lavl -llutil -lldap_r -llber
XXLIBS = $(SECURITY_LIBS) $(LDIF_LIBS) $(LUTIL_LIBS)
XXXLIBS = $(LTHREAD_LIBS)
rewrite: $(LIBRARY) rewrite.o parse.o
$(LTLINK) -o $@ rewrite.o parse.o $(LIBS)
/******************************************************************************
*
* Copyright (C) 2000 Pierangelo Masarati, <ando@sys-net.it>
* All rights reserved.
*
* Permission is granted to anyone to use this software for any purpose
* on any computer system, and to alter it and redistribute it, subject
* to the following restrictions:
*
* 1. The author is not responsible for the consequences of use of this
* software, no matter how awful, even if they arise from flaws in it.
*
* 2. The origin of this software must not be misrepresented, either by
* explicit claim or by omission. Since few users ever read sources,
* credits should appear in the documentation.
*
* 3. Altered versions must be plainly marked as such, and must not be
* misrepresented as being the original software. Since few users
* ever read sources, credits should appear in the documentation.
*
* 4. This notice may not be removed or altered.
*
******************************************************************************/
/*
* Description
*
* A string is rewritten according to a set of rules, called
* a `rewrite context'.
* The rules are based on Regular Expressions (POSIX regex) with
* substring matching; extensions are planned to allow basic variable
* substitution and map resolution of substrings.
* The behavior of pattern matching/substitution can be altered by a
* set of flags.
*
* The underlying concept is to build a lightweight rewrite module
* for the slapd server (initially dedicated to the back-ldap module).
*
*
* Passes
*
* An incoming string is matched agains a set of rules. Rules are made
* of a match pattern, a substitution pattern and a set of actions.
* In case of match a string rewriting is performed according to the
* substitution pattern that allows to refer to substrings matched
* in the incoming string. The actions, if any, are finally performed.
* The substitution pattern allows map resolution of substrings.
* A map is a generic object that maps a substitution pattern to a
* value.
*
*
* Pattern Matching Flags
*
* 'C' honors case in matching (default is case insensitive)
* 'R' use POSIX Basic Regular Expressions (default is Extended)
*
*
* Action Flags
*
* ':' apply the rule once only (default is recursive)
* '@' stop applying rules in case of match.
* '#' stop current operation if the rule matches, and issue an
* `unwilling to perform' error.
* 'G{n}' jump n rules back and forth (watch for loops!). Note that
* 'G{1}' is implicit in every rule.
* 'I' ignores errors in rule; this means, in case of error, e.g.
* issued by a map, the error is treated as a missed match.
* The 'unwilling to perform' is not overridden.
*
* the ordering of the flags is significant. For instance:
*
* 'IG{2}' means ignore errors and jump two lines ahead both in case
* of match and in case of error, while
* 'G{2}I' means ignore errors, but jump thwo lines ahead only in case
* of match.
*
* More flags (mainly Action Flags) will be added as needed.
*
*
* Pattern matching:
*
* see regex(7)
*
*
* String Substitution:
*
* the string substitution happens according to a substitution pattern.
* - susbtring substitution is allowed with the syntax '\d'
* where 'd' is a digit ranging 0-9 (0 is the full match).
* I see that 0-9 digit expansion is a widely accepted
* practise; however there is no technical reason to use
* such a strict limit. A syntax of the form '\{ddd}'
* should be fine if there is any need to use a higher
* number of possible submatches.
* - variable substitution will be allowed (at least when I
* figure out which kind of variable could be proficiently
* substituted)
* - map lookup will be allowed (map lookup of substring matches
* in gdbm, ldap(!), math(?) and so on maps 'a la sendmail'.
* - subroutine invocation will make it possible to rewrite a
* submatch in terms of the output of another rewriteContext
*
* Old syntax:
*
* '\' {0-9} [ '{' <name> [ '(' <args> ')' ] '}' ]
*
* where <name> is the name of a built-in map, and
* <args> are optional arguments to the map, if
* the map <name> requires them.
* The following experimental maps have been implemented:
*
* \n{xpasswd}
* maps the n-th substring match as uid to
* the gecos field in /etc/passwd;
*
* \n{xfile(/absolute/path)}
* maps the n-th substring match
* to a 'key value' style plain text file.
*
* \n{xldap(ldap://url/with?%0?in?filter)
* maps the n-th substring match to an
* attribute retrieved by means of an LDAP
* url with substitution of %0 in the filter
* (NOT IMPL.)
*
* New scheme:
*
* - everything starting with '\' requires substitution;
* - the only obvious exception is '\\', which is left as is;
* - the basic substitution is '\d', where 'd' is a digit;
* 0 means the whole string, while 1-9 is a submatch;
* - in the outdated schema, the digit may be optionally
* followed by a '{', which means pipe the submatch into
* the map described by the string up to the following '}';
* - the output of the map is used instead of the submatch;
* - in the new schema, a '\' followed by a '{' invokes an
* advanced substitution scheme. The pattern is:
*
* '\' '{' [{ <op> }] <name> '(' <substitution schema> ')' '}'
*
* where <name> must be a legal name for the map, i.e.
*
* <name> ::= [a-z][a-z0-9]* (case insensitive)
* <op> ::= '>' '|' '&' '&&' '*' '**' '$'
*
* and <substitution schema> must be a legal substitution
* schema, with no limits on the nesting level.
* The operators are:
* > sub context invocation; <name> must be a legal,
* already defined rewrite context name
* | external command invocation; <name> must refer
* to a legal, already defined command name (NOT IMPL.)
* & variable assignment; <name> defines a variable
* in the running operation structure which can be
* dereferenced later (NOT IMPL.)
* * variable dereferencing; <name> must refer to a
* variable that is defined and assigned for the
* running operation (NOT IMPL.)
* $ parameter dereferencing; <name> must refer to
* an existing parameter; the idea is to make
* some run-time parameters set by the system
* available to the rewrite engine, as the client
* host name, the bind dn if any, constant
* parameters initialized at config time, and so
* on (NOT IMPL.)
*
* Note: as the slapd parsing routines escape backslashes ('\'),
* a double backslash is required inside substitution patterns.
* To overcome the resulting heavy notation, the substitution escaping
* has been delegated to the '%' symbol, which should be used
* instead of '\' in string substitution patterns. The symbol can
* be altered at will by redefining the related macro in "rewrite-int.h".
* In the current snapshot, all the '\' on the left side of each rule
* (the regex pattern) must be converted in '\\'; all the '\' on the
* right side of the rule (the substitution pattern) must be turned
* into '%'. In the following examples, the original (more readable)
* syntax is used; however, in the servers/slapd/back-ldap/slapd.conf