First commit of Hallvard's backend documentation effort

Backend documentation patch, version 1

================
Most of this text is taken from OpenLDAP.  The work of rewriting it
to manual pages is done by by Hallvard B. Furuseth and placed into
the public domain.  This software is not subject to any license of
the University of Oslo.
================

Hallvard B. Furuseth <h.b.furuseth@usit.uio.no>, April 2002.
This commit is contained in:
Pierangelo Masarati 2002-04-29 20:24:29 +00:00
parent 6b8828ed28
commit d019bff7b8
15 changed files with 1792 additions and 1217 deletions

99
doc/man/man5/slapd-bdb.5 Normal file
View File

@ -0,0 +1,99 @@
.TH SLAPD-BDB 5 "28 April 2002" "OpenLDAP LDVERSION"
.\" Copyright 1998-2002 The OpenLDAP Foundation All Rights Reserved.
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.\" $OpenLDAP$
.SH NAME
slapd-bdb \- BDB backend to slapd
.SH SYNOPSIS
ETCDIR/slapd.conf
.SH DESCRIPTION
The BDB backend to
.BR slapd (8)
is the recommended backend for a normal slapd database.
It uses the Sleepycat BerkelyDB package to store data.
It makes extensive use of indexing and caching to speed data access.
.SH CONFIGURATION
The
.BR slapd.conf (5)
options in this category apply to the BDB databases.
That is, they must follow a "database bdb" line and come before any
subsequent "backend" or "database" lines.
.TP
.B cachesize <integer>
Specify the size in entries of the in-memory cache maintained
by the BDB backend database instance.
The default is 1000 entries.
.TP
.B checkpoint <kbyte> <min>
Specify the frequency for checkpointing the database transaction log.
A checkpoint operation flushes the database buffers to disk and writes
a checkpoint record in the log.
The checkpoint will occur if either <kbyte> data has been written or
<min> minutes have passed since the last checkpoint.
Both arguments default to zero, in which case they are ignored.
See the Berkeley DB reference guide for more details.
.TP
.B dbnosync
Specify that on-disk database contents should not be immediately
synchronized with in memory changes.
Enabling this option may improve performance at the expense of data
security.
.TP
.B directory <directory>
Specify the directory where the BDB files containing this database and
associated indexes live.
A separate directory must be specified for each database.
The default is
.BR LOCALSTATEDIR/openldap-data .
.TP
.B dirtyread
Allow reads of modified but not yet committed data.
Usually transactions are isolated to prevent other operations from
accessing uncommitted data.
This option may improve performance, but may also return inconsistent
results if the data comes from a transaction that is later aborted.
In this case, the modified data is discarded and a subsequent search
will return a different result.
.TP
.B
index {<attrlist>|default} [pres,eq,approx,sub,<special>]
Specify the indexes to maintain for the given attribute (or
list of attributes).
Some attributes only support a subset of indexes.
If only an <attr> is given, the indices specified for \fBdefault\fR
are maintained.
Note that setting a default does not imply that all attributes will be
indexed.
A number of special index parameters may be specified.
The index type
.B sub
can be decomposed into
.BR subinitial ,
.BR subany ,\ and
.B subfinal
indices.
The special type
.B nolang
may be specified to disallow use of this index by language subtypes.
The special type
.B nosubtypes
may be specified to disallow use of this index by named subtypes.
Note: changing index settings requires rebuilding indices, see
.BR slapindex (8).
.TP
.B lockdetect {oldest|youngest|fewest|random|default}
Specify which transaction to abort when a deadlock is detected.
The default is the same as
.BR random .
.TP
.B mode <integer>
Specify the file protection mode that newly created database
index files should have.
The default is 0600.
.SH SEE ALSO
.BR slapd.conf (5),
.BR slapd (8),
.BR slapadd (8),
.BR slapcat (8),
.BR slapindex (8).

122
doc/man/man5/slapd-ldbm.5 Normal file
View File

@ -0,0 +1,122 @@
.TH SLAPD-LDBM 5 "28 April 2002" "OpenLDAP LDVERSION"
.\" Copyright 1998-2002 The OpenLDAP Foundation All Rights Reserved.
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.\" $OpenLDAP$
.SH NAME
slapd-ldbm \- LDBM backend to slapd
.SH SYNOPSIS
ETCDIR/slapd.conf
.SH DESCRIPTION
The LDBM backend to
.BR slapd (8)
is a database that makes
extensive use of indexing and caching to speed data access.
.\" .SH LDBM BACKEND-SPECIFIC OPTIONS
.\" Options in this category only apply to the LDBM backend.
.\" That is, they must follow "backend ldbm" line and come before
.\" any subsequent "backend" or "database" lines.
.SH CONFIGURATION
The
.BR slapd.conf (5)
options in this category apply to the LDBM databases.
That is, they must follow a "database ldbm" line and come before any
subsequent "backend" or "database" lines.
.TP
.B cachesize <integer>
Specify the size in entries of the in-memory cache maintained
by the LDBM backend database instance.
The default is 1000 entries.
.TP
.B dbcachesize <integer>
Specify the size in bytes of the in-memory cache associated with each
open index file.
If not supported by the underlying database method, this option is
ignored without comment.
The default is 100000 bytes.
.TP
.B dbnolocking
Specify that no database locking should be performed.
Enabling this option may improve performance at the expense of data security.
Do NOT run any slap tools while slapd is running.
.TP
.B dbnosync
Specify that on-disk database contents should not be immediately
synchronized with in memory changes.
Enabling this option may improve performance at the expense of data
security.
.TP
.B dbsync <frequency> <maxdelays> <delayinterval>
Flush dirty database buffers to disk every
.B <seconds>
seconds.
Implies
.B dbnosync
(ie. indvidual updates are no longer written to disk).
It attempts to avoid syncs during periods of peak activity by waiting
.B <delayinterval>
seconds if the server is busy, repeating this delay up to
.B <maxdelays>
times before proceeding.
It is an attempt to provide higher write performance with some amount
of data security.
Note that it may still be possible to get an inconsistent database if
the underlying engine fills its cache and writes out individual pages
and slapd crashes or is killed before the next sync.
.B <maxdelays>
and
.B <delayinterval>
are optional and default to
.B 12
and
.B 5
respectively, giving a total elapsed delay of 60 seconds before a sync
will occur.
.B <maxdelays>
may be zero, and
.B <delayinterval>
must be 1 or greater.
.TP
.B directory <directory>
Specify the directory where the LDBM files containing this database and
associated indexes live.
A separate directory must be specified for each database.
The default is
.BR LOCALSTATEDIR/openldap-data .
.TP
.B
index {<attrlist>|default} [pres,eq,approx,sub,<special>]
Specify the indexes to maintain for the given attribute (or
list of attributes).
Some attributes only support a subset of indexes.
If only an <attr> is given, the indices specified for \fBdefault\fR
are maintained.
Note that setting a default does not imply that all attributes will be
indexed.
A number of special index parameters may be specified.
The index type
.B sub
can be decomposed into
.BR subinitial ,
.BR subany ,\ and
.B subfinal
indices.
The special type
.B nolang
may be specified to disallow use of this index by language subtypes.
The special type
.B nosubtypes
may be specified to disallow use of this index by named subtypes.
Note: changing index settings requires rebuilding indices, see
.BR slapindex (8).
.TP
.B mode <integer>
Specify the file protection mode that newly created database
index files should have.
The default is 0600.
.SH SEE ALSO
.BR slapd.conf (5),
.BR slapd (8),
.BR slapadd (8),
.BR slapcat (8),
.BR slapindex (8).

657
doc/man/man5/slapd-meta.5 Normal file
View File

@ -0,0 +1,657 @@
.TH SLAPD_META 5 "28 April 2002" "OpenLDAP LDVERSION"
.\" Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
.\" Copying restrictions apply. See the COPYRIGHT file.
.\" Copyright 2001, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
.\" $OpenLDAP$
.\"
.\" Portions of this document should probably be moved to slapd-ldap(5)
.\" and maybe manual pages for librewrite.
.\"
.SH NAME
slapd_meta \- metadirectory backend
.SH SYNOPSIS
ETCDIR/slapd.conf
.SH DESCRIPTION
The
.B meta
backend to
.BR slapd (8)
performs basic LDAP proxying with respect to a set of remote LDAP
servers, called "targets".
The information contained in these servers can be presented as
belonging to a single Directory Information Tree (DIT).
.LP
A basic knowledge of the functionality of the
.BR slapd_ldap (5)
backend is recommended.
This backend has been designed as an enhancement of the ldap backend.
The two backends share many features (actually they also share
portions of code).
While the
.B ldap
backend is intended to proxy operations directed to a single server, the
.B meta
backend is mainly intended for proxying of multiple servers and possibly
naming context masquerading.
These features, although useful in many scenarios, may result in
excessive overhead for some applications, so its use should be
carefully considered.
In the examples section, some typical scenarios will be discussed.
.SH EXAMPLES
There are examples various places in this document, as well as in the
slapd/back-meta/data/ directory in the OpenLDAP source tree.
.SH CONFIGURATION
The
.BR slapd.conf (5)
options in this category apply to the META backend database.
That is, they must follow a "database meta" line and come before any
subsequent "backend" or "database" lines.
.LP
Note: as with the
.B ldap
backend, operational attributes related to entry creation/modification
should not be used, as they would be passed to the target servers,
generating an error.
Moreover, it makes little sense to use such attributes in proxying, as
the proxy server doesn't actually store data, so it should have no
knowledge of such attributes.
While code to strip the modification attributes has been put in place
(and #ifdef'd), it implies unmotivated overhead.
So it is strongly recommended to set
.LP
.nf
lastmod off
.fi
.LP
for every
.B ldap
and
.B meta
backend.
.SH "SPECIAL CONFIGURATION DIRECTIVES"
Target configuration starts with the "uri" directive.
All the configuration directives that are not specific to targets
should be defined first for clarity, including those that are common
to all backends.
They are:
.TP
.B default-target none
This directive forces the backend to reject all those operations
that must resolve to a single target in case none or multiple
targets are selected.
They include: add, delete, modify, modrdn; compare is not included, as
well as bind since, as they don't alter entries, in case of multiple
matches an attempt is made to perform the operation on any candidate
target, with the constraint that at most on must succeed.
This directive can also be used when processing targets to mark a
specific target as default.
.TP
.B dncache-ttl {forever|disabled|<ttl>}
This directive sets the time-to-live of the dn cache.
This caches the target that holds a given dn to speed up target
selection in case multiple targets would result from an uncached
search; forever means cache never expires; disabled means no dn
caching; otherwise a valid ( > 0 ) ttl in seconds is required.
.SH "TARGET SPECIFICATION"
Target specification starts with a "uri" directive:
.TP
.B uri <protocol>://[<host>[:<port>]]/<naming context>
The "server" directive that was allowed in the LDAP backend (although
deprecated) has been discarded in the Meta backend.
The <protocol> part can be anything ldap_initialize(3) accepts
({ldap|ldaps|ldapi} and variants); <host> and <port> may be omitted,
defaulting to whatever is set in /etc/ldap.conf (correct me!?!).
The <naming context> part is mandatory.
It must end with one of the naming contexts defined for the backend,
e.g.:
.LP
.nf
suffix "dc=foo,dc=com"
uri "ldap://x.foo.com/dc=x,dc=foo,dc=com"
.fi
.LP
The <naming context> part doesn't need to be unique across the targets;
it may also match one of the values of the "suffix" directive.
.TP
.B default-target [<target>]
The "default-target" directive can also be used during target specification.
With no arguments it marks the current target as the default.
The optional number marks target <target> as the default one, starting
from 1.
Target <target> must be defined.
.TP
.B binddn <administrative dn for ac purposes>
This directive, as in the LDAP backend, allows to define the dn that is
used to query the target server for acl checking; it should have read
access on the target server to attributes used on the proxy for acl
checking.
There is no risk of giving away such values; they are only used to
check permissions.
.TP
.B bindpw <password for ac purposes>
This directive sets the password for acl checking in conjunction
with the above mentioned "binddn" directive.
.TP
.B pseudorootdn <substitute dn in case of rootdn bind>
This directive, if present, sets the dn that will be substituted to
the bind dn if a bind with the backend's "rootdn" succeeds.
The true "rootdn" of the target server ought not be used; an arbitrary
administrative dn should used instead.
.TP
.B pseudorootpw <substitute password in case of rootdn bind>
This directive sets the credential that will be used in case a bind
with the backend's "rootdn" succeeds, and the bind is propagated to
the target using the "pseudorootdn" dn.
.TP
.B rewrite* ...
The rewrite options are described in the "REWRITING" section.
.TP
.B suffixmassage <virtual naming context> <real naming context>
All the directives starting with "rewrite" refer to the rewrite engine
that has been added to slapd.
The "suffixmassage" directive was introduced in the LDAP backend to
allow suffix massaging while proxying.
It has been obsoleted by the rewriting tools.
However, both for backward compatibility and for ease of configuration
when simple suffix massage is required, it has been preserved.
It wraps the basic rewriting instructions that perform suffix
massaging.
.LP
Note: this also fixes a flaw in suffix massaging, which operated
on (case insensitive) DNs instead of normalized DNs,
so "dc=foo, dc=com" would not match "dc=foo,dc=com".
.LP
See the "REWRITING" section.
.TP
.B map {objectClass|attribute} {<source>|*} [<dest>|*]
This maps object classes and attributes as in the LDAP backend.
See
.BR slapd-ldap (5).
.SH "SCENARIOS"
A powerful (and in some sense dangerous) rewrite engine has been added
to both the LDAP and Meta backends.
While the former can gain limited beneficial effects from rewriting
stuff, the latter can become an amazingly powerful tool.
.LP
Consider a couple of scenarios first.
.LP
1) Two directory servers share two levels of naming context;
say "dc=a,dc=foo,dc=com" and "dc=b,dc=foo,dc=com".
Then, an unambiguous Meta database can be configured as:
.LP
.nf
database meta
suffix "dc=foo,dc=com"
uri "ldap://a.foo.com/dc=a,dc=foo,dc=com"
uri "ldap://b.foo.com/dc=b,dc=foo,dc=com"
.fi
.LP
Operations directed to a specific target can be easily resolved
because there are no ambiguities.
The only operation that may resolve to multiple targets is a search
with base "dc=foo,dc=com" and scope at least "one", which results in
spawning two searches to the targets.
.LP
2a) Two directory servers don't share any portion of naming context,
but they'd present as a single DIT.
[Caveat: uniqueness of (massaged) entries among the two servers is
assumed; integrity checks risk to incur in excessive overhead and have
not been implemented.] Say we have "dc=bar,dc=org" and "o=Foo,c=US",
and we'd like them to appear as branches of "dc=foo,dc=com", say
"dc=a,dc=foo,dc=com" and "dc=b,dc=foo,dc=com".
Then we need to configure our Meta backend as:
.LP
.nf
database meta
suffix "dc=foo,dc=com"
uri "ldap://a.bar.com/dc=a,dc=foo,dc=com"
suffixmassage "dc=a,dc=foo,dc=com" "dc=bar,dc=org"
uri "ldap://b.foo.com/dc=b,dc=foo,dc=com"
suffixmassage "dc=b,dc=foo,dc=com" "o=Foo,c=US"
.fi
.LP
Again, operations can be resolved without ambiguity, although
some rewriting is required.
Notice that the virtual naming context of each target is a branch of
the database's naming context; it is rewritten back and forth when
operations are performed towards the target servers.
What "back and forth" means will be clarified later.
.LP
When a search with base "dc=foo,dc=com" is attempted, if the
scope is "base" it fails with "no such object"; in fact, the
common root of the two targets (prior to massaging) does not
exist.
If the scope is "one", both targets are contacted with the base
replaced by each target's base; the scope is derated to "base".
In general, a scope "one" search is honored, and the scope is derated,
only when the incoming base is at most one level lower of a target's
naming context (prior to massaging).
.LP
Finally, if the scope is "sub" the incoming base is replaced
by each target's unmassaged naming context, and the scope
is not altered.
.LP
2b) Consider the above reported scenario with the two servers
sharing the same naming context:
.LP
.nf
database meta
suffix "dc=foo,dc=com"
uri "ldap://a.bar.com/dc=foo,dc=com"
suffixmassage "dc=foo,dc=com" "dc=bar,dc=org"
uri "ldap://b.foo.com/dc=foo,dc=com"
suffixmassage "dc=foo,dc=com" "o=Foo,c=US"
.fi
.LP
All the previous considerations hold, except that now there is
no way to unambiguously resolve a DN.
In this case, all the operations that require an unambiguous target
selection will fail unless the dn is already cached or a default
target has been set.
.SH ACLs
Note on ACLs: at present you may add whatever ACL rule you desire
to to the Meta (and LDAP) backends.
However, the meaning of an ACL on a proxy may require some
considerations.
Two philosophies may be considered:
.LP
a) the remote server dictates the permissions; the proxy simply passes
back what it gets from the remote server.
.LP
b) the remote server unveils "everything"; the proxy is responsible
for protecting data from unauthorized access.
.LP
Of course the latter sounds unreasonable, but it is not.
It is possible to imagine scenarios in which a remote host discloses
data that can be considered "public" inside an intranet, and a proxy
that connects it to the internet may impose additional constraints.
To this purpose, the proxy should be able to comply with all the ACL
matching criteria that the server supports.
This has been achieved with regard to all the criteria supported by
slapd except a special subtle case (please drop me a note if you can
find other exceptions: <ando@openldap.org>).
The rule
.LP
.nf
access to dn="<dn>" attr=<attr>
by dnattr=<dnattr> read
by * none
.fi
.LP
cannot be matched iff the attribute that is being requested, <attr>,
is NOT <dnattr>, and the attribute that determines membership,
<dnattr>, has not been requested (e.g. in a search)
.LP
In fact this ACL is resolved by slapd using the portion of entry it
retrieved from the remote server without requiring any further
intervention of the backend, so, if the <dnattr> attribute has not
been fetched, the match cannot be assessed because the attribute is
not present, not because no value matches the requirement!
.LP
Note on ACLs and attribute mapping: ACLs are applied to the mapped
attributes; for instance, if the attribute locally known as "foo" is
mapped to "bar" on a remote server, then local ACLs apply to attribute
"foo" and are totally unaware of its remote name.
The remote server will check permissions for "bar", and the local
server will possibly enforce additional restrictions to "foo".
.\"
.\" If this section is moved, also update the reference in
.\" libraries/librewrite/RATIONALE.
.\"
.SH REWRITING
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.
.LP
The underlying concept is to build a lightweight rewrite module
for the slapd server (initially dedicated to the LDAP backend).
.SH 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.
.SH "Pattern Matching Flags"
.TP
.B `C'
honors case in matching (default is case insensitive)
.TP
.B `R'
use POSIX Basic Regular Expressions (default is Extended)
.SH "Action Flags"
.TP
.B `:'
apply the rule once only (default is recursive)
.TP
.B `@'
stop applying rules in case of match.
.TP
.B `#'
stop current operation if the rule matches, and issue an `unwilling to
perform' error.
.TP
.B `G{n}'
jump n rules back and forth (watch for loops!).
Note that `G{1}' is implicit in every rule.
.TP
.B `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.
.LP
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.
.LP
More flags (mainly Action Flags) will be added as needed.
.SH "Pattern matching:"
See
.BR regex (7).
.SH "String Substitution:"
The string substitution happens according to a substitution pattern.
.TP
.B -
substring 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.
.TP
.B -
variable substitution will be allowed (at least when I figure out
which kind of variable could be proficiently substituted)
.TP
.B -
map lookup will be allowed (map lookup of substring matches in gdbm,
ldap(!), math(?) and so on maps `a la sendmail'.
.TP
.B -
subroutine invocation will make it possible to rewrite a submatch in
terms of the output of another rewriteContext.
.Sh "Old syntax:"
.TP
.B `\\' {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:
.TP
.B \\n{xpasswd}
maps the n-th substring match as uid to the gecos field in
/etc/passwd;
.TP
.B \\n{xfile(/absolute/path)}
maps the n-th substring match to a `key value' style plain text file.
.TP
.B \\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.)
.SH "New scheme:"
everything starting with `\\' requires substitution;
.LP
the only obvious exception is `\\\\', which is left as is;
.LP
the basic substitution is `\\d', where `d' is a digit;
0 means the whole string, while 1-9 is a submatch;
.LP
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 `}';
.LP
the output of the map is used instead of the submatch;
.LP
in the new schema, a `\\' followed by a `{' invokes an
advanced substitution scheme.
The pattern is:
.LP
.nf
`\\' `{' [{ <op> }] <name> `(' <substitution schema> `)' `}'
.fi
.LP
where <name> must be a legal name for the map, i.e.
.LP
.nf
<name> ::= [a-z][a-z0-9]* (case insensitive)
<op> ::= `>' `|' `&' `&&' `*' `**' `$'
.fi
.LP
and <substitution schema> must be a legal substitution
schema, with no limits on the nesting level.
.LP
The operators are:
.TP
.B >
sub context invocation; <name> must be a legal, already defined
rewrite context name
.TP
.B |
external command invocation; <name> must refer to a legal, already
defined command name (NOT IMPL.)
.TP
.B &
variable assignment; <name> defines a variable in the running
operation structure which can be dereferenced later (NOT IMPL.)
.TP
.B *
variable dereferencing; <name> must refer to a variable that is
defined and assigned for the running operation (NOT IMPL.)
.TP
.B $
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.)
.LP
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.
.SH "Rewrite context:"
A rewrite context is a set of rules which are applied in sequence.
The basic idea is to have an application initialize a rewrite
engine (think of Apache's mod_rewrite ...) with a set of rewrite
contexts; when string rewriting is required, one invokes the
appropriate rewrite context with the input string and obtains the
newly rewritten one if no errors occur.
.LP
An interesting application, in the LDAP backend or in slapd itself,
could associate each basic server operation to a rewrite context
(most of them possibly aliasing the default one).
Then, DN rewriting could take place at any invocation of a backend
operation.
.LP
client -> server:
.LP
.nf
default if defined and no specific
context is available
bindDn bind
searchBase search
searchFilter search
compareDn compare
addDn add
modifyDn modify
modrDn modrdn
newSuperiorDn modrdn
deleteDn delete
.fi
.LP
server -> client:
.LP
.nf
searchResult search (only if defined; no default)
.fi
.LP
.SH "Basic configuration syntax"
.TP
.B rewriteEngine { on | off }
If `on', the requested rewriting is performed; if `off', no
rewriting takes place (an easy way to stop rewriting without
altering too much the configuration file).
.TP
.B rewriteContext <context name> [ alias <aliased context name> ]
<Context name> is the name that identifies the context, i.e. the name
used by the application to refer to the set of rules it contains.
It is used also to reference sub contexts in string rewriting.
A context may aliase another one.
In this case the alias context contains no rule, and any reference to
it will result in accessing the aliased one.
.TP
.B rewriteRule <regex pattern> <substitution pattern> [ <flags> ]
Determines how a tring can be rewritten if a pattern is matched.
Examples are reported below.
.SH "Additional configuration syntax:"
.TP
.B rewriteMap <map name> <map type> [ <map attrs> ]
Allows to define a map that transforms substring rewriting into
something else.
The map is referenced inside the substitution pattern of a rule.
.TP
.B rewriteParam <param name> <param value>
Sets a value with global scope, that can be dereferenced by the
command `\\{$paramName}'.
.TP
.B rewriteMaxPasses <number of passes>
Sets the maximum number of total rewriting passes taht can be
performed in a signle rewriting operation (to avoid loops).
.SH "Configuration examples:"
.nf
# set to `off' to disable rewriting
rewriteEngine on
# Everything defined here goes into the `default' context.
# This rule changes the naming context of anything sent
# to `dc=home,dc=net' to `dc=OpenLDAP, dc=org'
rewriteRule "(.*)dc=home,[ ]?dc=net"
"\\1dc=OpenLDAP, dc=org" ":"
# Start a new context (ends input of the previous one).
# This rule adds blancs between dn parts if not present.
rewriteContext addBlancs
rewriteRule "(.*),([^ ].*)" "\\1, \\2"
# This one eats blancs
rewriteContext eatBlancs
rewriteRule "(.*),[ ](.*)" "\\1,\\2"
# Here control goes back to the default rewrite
# context; rules are appended to the existing ones.
# anything that gets here is piped into rule `addBlancs'
rewriteContext default
rewriteRule ".*" "\\{>addBlancs(\\0)}" ":"
# Anything with `uid=username' is looked up in
# /etc/passwd for gecos (I know it's nearly useless,
# but it is there just to test something fancy!). Note
# the `I' flag that leaves `uid=username' in place if
# `username' does not have a valid account, and the
# `:' that forces the rule to be processed exactly once.
rewriteContext uid2Gecos
rewriteRule "(.*)uid=([a-z0-9]+),(.+)"
"\\1cn=\\2{xpasswd},\\3" "I:"
# Finally, in a bind, if one uses a `uid=username' dn,
# it is rewritten in `cn=name surname' if possible.
rewriteContext bindDn
rewriteRule ".*" "\\{>addBlancs(\\{>uid2Gecos(\\0)})}" ":"
# Rewrite the search base according to `default' rules.
rewriteContext searchBase alias default
# Search results with OpenLDAP dn are rewritten back with
# `dc=home,dc=net' naming context, with spaces eaten.
rewriteContext searchResult
rewriteRule "(.*[^ ]?)[ ]?dc=OpenLDAP,[ ]?dc=org"
"\\{>eatBlancs(\\1)}dc=home,dc=net" ":"
# Bind with email instead of full dn: we first need
# an ldap map that turns attributes into a dn (the
# filter is provided by the substitution string):
rewriteMap ldap attr2dn "ldap://host/dc=my,dc=org?dn?sub"
# Then we need to detect emails; note that the rule
# in case of match stops rewriting; in case of error,
# it is ignored. In case we are mapping virtual
# to real naming contexts, we also need to rewrite
# regular DNs, because the definition of a bindDn
# rewrite context overrides the default definition.
rewriteContext bindDn
rewriteRule "(mail=[^,]+@[^,]+)" "\\{attr2dn(\\1)}" "@I"
# This is a rather sophisticate example. It massages a
# search filter in case who performs the search has
# administrative privileges. First we need to keep
# track of the bind dn of the incoming request:
rewriteContext bindDn
rewriteRule ".+" "\\{**&binddn(\\0)}" ":"
# A search filter containing `uid=' is rewritten only
# if an appropriate dn is bound.
# To do this, in the first rule the bound dn is
# dereferenced, while the filter is decomposed in a
# prefix, the argument of the `uid=', and in a
# suffix. A tag `<>' is appended to the DN. If the DN
# refers to an entry in the `ou=admin' subtree, the
# filter is rewritten OR-ing the `uid=<arg>' with
# `cn=<arg>'; otherwise it is left as is. This could be
# useful, for instance, to allow apache's auth_ldap-1.4
# module to authenticate users with both `uid' and
# `cn', but only if the request comes from a possible
# `dn: cn=Web auth, ou=admin, dc=home, dc=net' user.
rewriteContext searchFilter
rewriteRule "(.*\\()uid=([a-z0-9_]+)(\\).*)"
"\\{**binddn}<>\\{&prefix(\\1)}\\{&arg(\\2)}\\{&suffix(\\3)}"
":I"
rewriteRule "[^,]+,[ ]?ou=admin,[ ]?dc=home,[ ]?dc=net"
"\\{*prefix}|(uid=\\{*arg})(cn=\\{*arg})\\{*suffix}" "@I"
rewriteRule ".*<>" "\\{*prefix}uid=\\{*arg}\\{*suffix}"
.fi
.SH "LDAP Proxy resolution (a possible evolution of slapd-ldap(5):"
In case the rewritten dn is an LDAP URL, the operation is initiated
towards the host[:port] indicated in the url, if it does not refer
to the local server.
E.g.:
.LP
.nf
rewriteRule \'^cn=root,.*\' \'\\0\' \'G{3}\'
rewriteRule \'^cn=[a-l].*\' \'ldap://ldap1.my.org/\\0\' \'@\'
rewriteRule \'^cn=[m-z].*\' \'ldap://ldap2.my.org/\\0\' \'@\'
rewriteRule \'.*\' \'ldap://ldap3.my.org/\\0\' \'@\'
.fi
.LP
(Rule 1 is simply there to illustrate the `G{n}' action; it could have
been written:
.LP
.nf
rewriteRule \'^cn=root,.*\' \'ldap://ldap3.my.org/\\0\' \'@\'
.fi
.LP
with the advantage of saving one rewrite pass ...)
.SH "SEE ALSO"
.BR slapd.conf (5),
.BR slapd (8),
.BR regex (7).

46
doc/man/man5/slapd-null.5 Normal file
View File

@ -0,0 +1,46 @@
.TH SLAPD-NULL 5 "25 April 2002" "OpenLDAP LDVERSION"
.\" $OpenLDAP$
.SH NAME
slapd-null \- Null backend to slapd
.SH SYNOPSIS
ETCDIR/slapd.conf
.SH DESCRIPTION
The Null backend to
.BR slapd (8)
is surely the most useful part of
.BR slapd :
.br
- Searches return success but no entries.
.br
- Compares return compareFalse.
.br
- Updates return success (unless readonly is on) but do nothing.
.br
- Binds fail unless the database option "bind on" is given.
.br
Inspired by the /dev/null device.
.SH CONFIGURATION
The
.BR slapd.conf (5)
option in this category applies to the NULL backend database.
That is, it must follow a "database null" line and come before
any subsequent "database" lines.
Other database options are described in the
.BR slapd.conf (5)
manual page.
.TP
.B bind <on/off>
Allow binds as DNs in this backend's suffix.
The default is "off".
.SH EXAMPLE
Here is a possible slapd.conf extract using the Null backend:
.LP
.nf
database null
suffix "cn=Nothing"
bind on
.fi
.LP
.SH SEE ALSO
.BR slapd.conf (5),
.BR slapd (8).

View File

@ -0,0 +1,32 @@
.TH SLAPD-PASSWD 5 "25 April 2002" "OpenLDAP LDVERSION"
.\" Copyright 1998-2002 The OpenLDAP Foundation All Rights Reserved.
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.\" $OpenLDAP$
.SH NAME
slapd-passwd \- /etc/passwd backend to slapd
.SH SYNOPSIS
ETCDIR/slapd.conf
.SH DESCRIPTION
The PASSWD backend to
.BR slapd (8)
serves up the user account information listed in the system
.BR passwd (5)
file.
.SH CONFIGURATION
The
.BR slapd.conf (5)
options in this category apply to the PASSWD backend database.
That is, they must follow a "database passwd" line and come before any
subsequent "backend" or "database" lines.
Other database options are described in the
.BR slapd.conf (5)
manual page.
.TP
.B file <filename>
Specifies an alternate passwd file to use.
The default is
.BR /etc/passwd .
.SH SEE ALSO
.BR slapd.conf (5),
.BR slapd (8),
.BR passwd (5).

170
doc/man/man5/slapd-perl.5 Normal file
View File

@ -0,0 +1,170 @@
.TH SLAPD-PERL 5 "25 April 2002" "OpenLDAP LDVERSION"
.\" $OpenLDAP$
.SH NAME
slapd-perl \- Perl backend to slapd
.SH SYNOPSIS
ETCDIR/slapd.conf
.SH DESCRIPTION
The Perl backend to
.BR slapd (8)
works by embedding a
.BR perl (1)
interpreter into
.BR slapd (8).
Any perl database section of the configuration file
.BR slapd.conf (5)
must then specify what Perl module to use.
.B Slapd
then creates a new Perl object that handles all the requests for that
particular instance of the backend.
.LP
You will need to create a method for each one of the
following actions:
.LP
.nf
* new # creates a new object,
* search # performs the ldap search,
* compare # does a compare,
* modify # modifies an entry,
* add # adds an entry to backend,
* modrdn # modifies an entry's rdn,
* delete # deletes an ldap entry,
* config # process unknown config file lines,
* init # called after backend is initialized.
.fi
.LP
Unless otherwise specified, the methods return the result code
which will be returned to the client. Unimplemented actions
can just return unwillingToPerform (53).
.TP
.B new
This method is called when the configuration file encounters a
.B perlmod
line.
The module in that line is then effectively `use'd into the perl
interpreter, then the \fBnew\fR method is called to create a new
object.
Note that multiple instances of that object may be instantiated, as
with any perl object.
.\" .LP
The
.B new
method receives the class name as argument.
.TP
.B search
This method is called when a search request comes from a client.
It arguments are as follows:
.nf
* object reference
* base DN
* scope
* alias deferencing policy
* size limit
* time limit
* filter string
* attributes only flag (1 for yes)
* list of attributes that are to be returned (may be empty).
.fi
.LP
Return value: (resultcode, ldif-entry, ldif-entry, ...)
.TP
.B compare
This method is called when a compare request comes from a client.
Its arguments are as follows.
.nf
* object reference
* dn
* attribute assertion string
.fi
.LP
.TP
.B modify
This method is called when a modify request comes from a client.
Its arguments are as follows.
.nf
* object reference
* dn
* a list formatted as follows
{ "ADD" | "DELETE" | "REPLACE" }, attributetype, value..., ...
.fi
.LP
.TP
.B add
This method is called when a add request comes from a client.
Its arguments are as follows.
.nf
* object reference
* entry in string format.
.fi
.LP
.TP
.B modrdn
This method is called when a modrdn request comes from a client.
Its arguments are as follows.
.nf
* object reference
* dn
* new rdn
* delete old dn flag (1 means yes)
.fi
.LP
.TP
.B delete
This method is called when a delete request comes from a client.
Its arguments are as follows.
.nf
* object reference
* dn
.fi
.LP
.TP
.B config
This method is called with unknown
.BR slapd.conf (5)
configuration file lines.
Its arguments are as follows.
.nf
* object reference
* array of arguments on line
.fi
.LP
Return value: nonzero if this is not a valid option.
.TP
.B init
This method is called after backend is initialized.
Its argument is as follows.
.nf
* object reference
.fi
.LP
Return value: nonzero if initialization failed.
.SH CONFIGURATION
The
.BR slapd.conf (5)
options in this category apply to the PERL backend database.
That is, they must follow a "database perl" line and come before any
subsequent "backend" or "database" lines.
Other database options are described in the
.BR slapd.conf (5)
manual page.
.TP
.B perlModulePath /path/to/libs
Add the path to the @INC variable.
.TP
.B perlModule ModName
`Use' the module name ModName from ModName.pm
.TP
.B filterSearchResults
Search results are candidates that need to be filtered (with the
filter in the search request), rather than search results to be
returned directly to the client.
.SH EXAMPLE
There is an example Perl module `SampleLDAP' in the slapd/back-perl/
direcetory in the OpenLDAP source tree.
.SH WARNING
The interface of this backend to the perl module MAY change.
Any suggestions would greatly be appreciated.
.SH SEE ALSO
.BR slapd.conf (5),
.BR slapd (8),
.BR perl (1).

View File

@ -0,0 +1,53 @@
.TH SLAPD-SHELL 5 "25 April 2002" "OpenLDAP LDVERSION"
.\" Copyright 1998-2002 The OpenLDAP Foundation All Rights Reserved.
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.\" $OpenLDAP$
.SH NAME
slapd-shell \- Shell backend to slapd
.SH SYNOPSIS
ETCDIR/slapd.conf
.SH DESCRIPTION
The Shell backend to
.BR slapd (8)
executes external programs to implement operations, and is designed to
make it easy to tie an existing database to the
.B slapd
front-end.
.SH CONFIGURATION
The
.BR slapd.conf (5)
options in this category apply to the SHELL backend database.
That is, they must follow a "database shell" line and come before any
subsequent "backend" or "database" lines.
.LP
These options specify the pathname of the command to execute in response
to the given LDAP operation.
Note that you need only supply configuration lines for those commands you
want the backend to handle.
Operations for which a command is not supplied will be refused with an
"unwilling to perform" error.
.TP
.B bind <pathname>
.TP
.B unbind <pathname>
.TP
.B search <pathname>
.TP
.B compare <pathname>
.TP
.B modify <pathname>
.TP
.B modrdn <pathname>
.TP
.B add <pathname>
.TP
.B delete <pathname>
.TP
.B abandon <pathname>
.SH EXAMPLE
There is a skeleton search script in the slapd/back-shell/ directory
in the OpenLDAP source tree.
.SH SEE ALSO
.BR slapd.conf (5),
.BR slapd (8),
.BR sh (1).

324
doc/man/man5/slapd-sql.5 Normal file
View File

@ -0,0 +1,324 @@
.TH SLAPD-SQL 5 "25 April 2002" "OpenLDAP LDVERSION"
.\" $OpenLDAP$
.SH NAME
slapd-sql \- SQL backend to slapd
.SH SYNOPSIS
ETCDIR/slapd.conf
.SH PURPOSE
The primary purpose of this backend (8) to
.BR slapd (8)
is to PRESENT information stored in some RDBMS as an LDAP subtree
without any programming (some SQL and maybe stored procedures can't be
considered programming, anyway ;).
.LP
That is, for example, when you (some ISP) have account information you
use in RDBMS, and want to use modern solutions that expect such
information in LDAP (to authenticate users, make email lookups etc.).
Or you want to synchronize or distribute information between different
sites/applications that use RDBMSes and/or LDAP.
Or whatever else...
.LP
It is NOT designed as general-purpose backend that uses RDBMS instead
of BerkeleyDB (as the standard LDBM backend does), though it can be
used as such with several limitations.
You can take a look at
.B http://www.openldap.org/faq/index.cgi?file=378
(OpenLDAP FAQ-O-Matic/General LDAP FAQ/Directories vs. conventional
databases) to find out more on this point.
.LP
The idea (detailed below) is to use some metainformation to translate
LDAP queries to SQL queries, leaving relational schema untouched, so
that old applications can continue using it without any
modifications.
This allows SQL and LDAP applications to inter-operate without
replication, and exchange data as needed.
.LP
The SQL backend is designed to be tunable to virtually any relational
schema without having to change source (through that metainformation
mentioned).
Also, it uses ODBC to connect to RDBMSes, and is highly configurable
for SQL dialects RDBMSes may use, so it may be used for integration
and distribution of data on different RDBMSes, OSes, hosts etc., in
other words, in highly heterogeneous environment.
.SH "METAINFORMATION USED"
.LP
Almost everything mentioned later is illustrated in examples located
in the
.B slapd/back-sql/rdbms_depend/
directory in the OpenLDAP source tree, and contains scripts for
generating sample database for Oracle,MS SQL Server and mySQL.
.LP
First thing that one must arrange for himself is what set of LDAP
object classes can present your RDBMS information.
.LP
The easiest way is to create an objectclass for each entity you had in
ER-diagram when designing your relational schema.
Any relational schema, no matter how normalized it is, was designed
after some model of your application's domain (for instance, accounts,
services etc. in ISP), and is used in terms of its entities, not just
tables of normalized schema.
It means that for every attribute of every such instance there is an
effective SQL query that loads its values.
.LP
Also you might want your object classes to conform to some of standard
schemas like inetOrgPerson etc.
.LP
Nevertheless, when you think it out, we must define a way to translate
LDAP operation requests to (series of) SQL queries.
Let us deal with the SEARCH operation.
.LP
Example:
Let's suppose that we store information about persons working in our
organization in two tables:
.LP
.nf
PERSONS PHONES
---------- -------------
id integer id integer
first_name varchar pers_id integer references persons(id)
last_name varchar phone
middle_name varchar
...
.fi
.LP
(PHONES contains telephone numbers associated with persons).
A person can have several numbers, then PHONES contains several
records with corresponding pers_id, or no numbers (and no records in
PHONES with such pers_id).
An LDAP objectclass to present such information could look like this:
.LP
.nf
person
-------
MUST cn
MAY telephoneNumber
MAY firstName
MAY lastName
...
.fi
.LP
To fetch all values for cn attribute given person ID, we construct the
query:
.LP
.nf
SELECT CONCAT(persons.first_name,\' \',persons.last_name)
AS cn FROM persons WHERE persons.id=?
.fi
.LP
for telephoneNumber we can use:
.LP
.nf
SELECT phones.phone AS telephoneNumber FROM persons,phones
WHERE persons.id=phones.pers.id AND persons.id=?
.fi
.LP
If we wanted to service LDAP requests with filters like
(telephoneNumber=123*), we would construct something like:
.LP
.nf
SELECT ... FROM persons,phones
WHERE persons.id=phones.pers.id
AND persons.id=?
AND phones.phone like \'123%\'
.fi
.LP
So, if we had information about what tables contain values for each
attribute, how to join this tables and arrange these values, we could
try to automatically generate such statements, and translate search
filters to SQL WHERE clauses.
.LP
To store such information, we add three more tables to our schema, so
that and fill it with data (see samples):
.LP
.nf
ldap_oc_mappings (some columns are not listed for clarity)
---------------
id=1
name="person"
keytbl="persons"
keycol="id"
.fi
.LP
This table defines a mapping between objectclass (its name held in the
"name" column), and a table that holds primary key for corresponding
entities.
For instance, in our example, the person entity, which we are trying
to present as "person" objectclass, resides in two tables (persons and
phones), and is identified by persons.id column (that we will call
primary key for this entity).
Keytbl and keycol thus contain "persons" (name of the table), and "id"
(name of the column).
.LP
.nf
ldap_attr_mappings (some columns are not listed for clarity)
-----------
id=1
oc_id=1
name="cn"
sel_expr="CONCAT(persons.first_name,\' \',persons.last_name)"
from_tbls="persons"
join_where=NULL
************
id=<n>
oc_map_id=1
name="telephoneNumber"
sel_expr="phones.phone"
from_tbls="persons,phones"
join_where="phones.pers_id=persons.id"
.fi
.LP
This table defines mappings between LDAP attributes and SQL queries
that load their values.
Note that, unlike LDAP schema, these are not
.B attribute types
- attribute "cn" for "person" objectclass can well
have its values in different table than "cn" for other objectclass,
so attribute mappings depend on objectclass mappings (unlike attribute
types in LDAP schema, which are indifferent to objectclasses).
Thus, we have oc_map_id column with link to oc_mappings table.
.LP
Now we cut the SQL query that loads values for given attribute into 3 parts.
First goes into sel_expr column - this is the expression we had
between SELECT and FROM keywords, which defines WHAT to load.
Next is table list - text between FROM and WHERE keywords.
It may contain aliases for convenience (see exapmles).
The last is part of where clause, which (if exists at all) express the
condition for joining the table containing values wich table
containing primary key (foreign key equality and such).
If values are in the same table with primary key, then this column is
left NULL (as for cn attribute above).
.LP
Having this information in parts, we are able to not only construct
queries that load attribute values by id of entry (for this we could
store SQL query as a whole), but to construct queries that load id's
of objects that correspond to given search filter (or at least part of
it).
See below for examples.
.LP
.nf
ldap_entries
------------
id=1
dn=<dn you choose>
oc_map_id=...
parent=<parent record id>
keyval=<value of primary key>
.fi
.LP
This table defines mappings between DNs of entries in your LDAP tree,
and values of primary keys for corresponding relational data.
It has recursive structure (parent column references id column of the
same table), which allows you to add any tree structure(s) to your
flat relational data.
Having id of objectclass mapping, we can determine table and column
for primary key, and keyval stores value of it, thus defining exact
tuple corresponding to LDAP entry with this DN.
.LP
Note that such design (see exact SQL table creation query) implies one
important constraint - the key must be integer.
But all that I know about well-designed schemas makes me think that it
s not very narrow ;) If anyone needs support for different types for
keys - he may want to write a patch, and submit it to OpenLDAP ITS,
then I'll include it.
.LP
Also, several people complained that they don't really need very
structured tree, and they don't want to update one more table every
time they add or delete instance in relational schema.
Those can use a view instead of real table for ldap_entries, something
like this (by Robin Elfrink):
.LP
.nf
CREATE VIEW ldap_entries (id, dn, oc_map_id, parent, keyval)
AS SELECT (1000000000+userid),
UPPER(CONCAT(CONCAT(\'cn=\',gecos),\',o=MyCompany,c=NL\')),
1, 0, userid FROM unixusers UNION
SELECT (2000000000+groupnummer),
UPPER(CONCAT(CONCAT(\'cn=\',groupnaam),\',o=MyCompany,c=NL\')),
2, 0, groupnummer FROM groups;
.fi
.LP
.SH "Typical SQL backend operation"
Having metainformation loaded, the SQL backend uses these tables to
determine a set of primary keys of candidates (depending on search
scope and filter).
It tries to do it for each objectclass registered in ldap_objclasses.
.LP
Example:
for our query with filter (telephoneNumber=123*) we would get following
query generated (which loads candidate IDs)
.LP
.nf
SELECT ldap_entries.id,persons.id, \'person\' AS objectClass,
ldap_entries.dn AS dn
FROM ldap_entries,persons,phones
WHERE persons.id=ldap_entries.keyval
AND ldap_entries.objclass=?
AND ldap_entries.parent=?
AND phones.pers_id=persons.id
AND (phones.phone LIKE \'123%\')
.fi
.LP
(for ONELEVEL search)
or "... AND dn=?" (for BASE search)
or "... AND dn LIKE \'%?\'" (for SUBTREE)
.LP
Then, for each candidate, we load attributes requested using
per-attribute queries like
.LP
.nf
SELECT phones.phone AS telephoneNumber
FROM persons,phones
WHERE persons.id=? AND phones.pers_id=persons.id
.fi
.LP
Then, we use test_filter() from frontend API to test entry for full
LDAP search filter match (since we cannot effectively make sense of
SYNTAX of corresponding LDAP schema attribute, we translate the filter
into most relaxed SQL condition to filter candidates), and send it to
user.
.LP
ADD, DELETE, MODIFY operations also performed on per-attribute
metainformation (add_proc etc.).
In those fields one can specify an SQL statement or stored procedure
call which can add, or delete given value of given attribute, using
given entry keyval (see examples -- mostly ORACLE and MSSQL - since
there're no stored procs in mySQL).
.LP
We just add more columns to oc_mappings and attr_mappings, holding
statements to execute (like create_proc, add_proc, del_proc etc.), and
flags governing order of parameters passed to those statements.
Please see samples to find out what are the parameters passed, and other
information on this matter - they are self-explanatory for those familiar
with concept expressed above.
.LP
.SH "common techniques (referrals, multiclassing etc.)"
First of all, lets remember that among other major differences to
complete LDAP data model, the concept above does not directly support
such things as multiple objectclasses for entry, and referrals.
Fortunately, they are easy to adopt in this scheme.
The SQL backend suggests two more tables being added to schema -
ldap_entry_objectclasses(entry_id,oc_name), and
ldap_referrals(entry_id,url).
.LP
First contains any number of objectclass names that corresponding
entries will be found by, in addition to that mentioned in
mapping.
The SQL backend automatically adds attribute mapping for "objectclass"
attribute to each objectclass mapping, that loads values from this table.
So, you may, for instance, have mapping for inetOrgPerson, and use it
for queries for "person" objectclass...
.LP
Second table contains any number of referrals associated with given entry.
The SQL backend automatically adds attribute mapping for "ref" attribute
to each objectclass mapping, that loads values from this table.
So, if you add objectclass "referral" to this entry, and make one or
more tuples in ldap_referrals for this entry (they will be seen as
values of "ref" attribute), you will have slapd return referral, as
described in Administrators Guide.
.LP
.SH EXAMPLES
There are example SQL modules in the slapd/back-sql/rdbms_depend/
direcetory in the OpenLDAP source tree.
.SH SEE ALSO
.BR slapd.conf (5),
.BR slapd (8).

243
doc/man/man5/slapd-tcl.5 Normal file
View File

@ -0,0 +1,243 @@
.TH SLAPD-TCL 5 "28 April 2002" "OpenLDAP LDVERSION"
.\" $OpenLDAP$
.SH NAME
slapd-tcl \- Tcl backend to slapd
.SH SYNOPSIS
ETCDIR/slapd.conf
.SH DESCRIPTION
The Tcl backend to
.BR slapd (8)
works by embedding a
.BR Tcl (3tcl)
interpreter into
.BR slapd (8).
Any tcl database section of the configuration file
.BR slapd.conf (5)
must then specify what Tcl script to use.
.SH CONFIGURATION
The
.BR slapd.conf (5)
options in this category apply to the TCL backend database.
That is, they must follow a "database tcl" line and come before any
subsequent "backend" or "database" lines.
Other database options are described in the
.BR slapd.conf (5)
manual page.
.TP
.B scriptpath <filename.tcl>
The full path to the tcl script used for this database
.TP
.B search <proc>
.TP
.B add <proc>
.TP
.B delete <proc>
.TP
.B modify <proc>
.TP
.B bind <proc>
.TP
.B unbind <proc>
.TP
.B modrdn <proc>
.TP
.B compare <proc>
.TP
.B abandon <proc>
The procs for each ldap function.
This is similar to how the
.BR slapd-shell (5)
backend setup works, but these refer to the tcl procs in the
`scriptpath' script that handle them.
.TP
.B tclrealm <interpreter name>
This is one of the biggest pluses of using the tcl backend.
The realm lets you group several databases to the same interpreter.
This basically means they share the same global variables and proc space.
So global variables, as well as all the procs, are callable between databases.
If no tclrealm is specified, it is put into the "default" realm.
.SH "Variables passed to the procs"
.TP
.B abandon { action msgid suffix }
.nf
action - Always equal to ABANDON.
msgid - The msgid of this ldap operation.
suffix - List of suffix(es) associated with the
call. Each one is an entry in a tcl
formatted list (surrounded by {}'s).
.fi
.TP
.B add { action msgid suffix entry }
.nf
action - Always equal to ADD.
msgid - The msgid of this ldap operation.
suffix - List of suffix(es), as above.
entry - Full entry to add. Each "type: val" is
an element in a tcl formatted list.
.fi
.TP
.B bind { action msgid suffix dn method cred_len cred }
.nf
action - Always equal to BIND.
msgid - The msgid of this ldap operation.
suffix - List of suffix(es), as above.
dn - DN being bound to.
method - One of the ldap authentication methods.
cred_len - Length of cred.
cred - Credentials being used to authenticate,
according to RFC. If this value is empty,
then it should be considered an anonymous
bind (??)
.fi
.TP
.B compare { action msgid suffix dn ava_type ava_value }
.nf
action - Always equal to COMPARE.
msgid - The msgid of this ldap operation.
suffix - List of suffix(es), as above.
dn - DN for compare.
ava_type - Type for comparison.
ava_value - Value to compare.
.fi
.TP
.B delete { action msgid suffix dn }
.nf
action - Always equal to DELETE.
msgid - The msgid of this ldap operation.
suffix - List of suffix(es), as above.
dn - DN to delete.
.fi
.TP
.B modify { action msgid suffix dn mods }
.nf
action - Always equal to MODIFY.
msgid - The msgid of this ldap operation.
suffix - List of suffix(es), as above.
dn - DN to modify.
mods - Tcl list of modifications.
The list is formatted in this way:
{
{ {op: type} {type: val} }
{ {op: type} {type: val} {type: val} }
...
}
Newlines are not present in the actual var,
they are present here for clarification.
"op" is the type of modification
(ADD, DELETE, REPLACE).
.fi
.TP
.B modrdn { action msgid suffix dn newrdn deleteoldrdn }
.nf
action - Always equal to MODRDN.
msgid - The msgid of this ldap operation.
suffix - List of suffix(es), as above.
dn - DN whose RDN is being renamed.
newrdn - New RDN.
deleteoldrdn - Boolean stating whether or not the
old RDN should be removed after being renamed.
.fi
.TP
.B search { action msgid suffix base scope deref sizelimit timelimit filterstr attrsonly attrlist }
.nf
action - Always equal to SEARCH.
msgid - The msgid of this ldap operation.
suffix - List of suffix(es), as above.
base - Base for this search.
scope - Scope of search, ( 0 | 1 | 2 ).
deref - Alias dereferencing ( 0 | 1 | 2 | 3 ).
sizelimit - Maximum number of entries to return.
timelimit - Time limit for search.
filterstr - Filter string as sent by the requester.
attrsonly - Boolean for whether to list only the
attributes, and not values as well.
attrlist - Tcl list if to retrieve.
.fi
.TP
.B unbind { action msgid suffix dn }
.nf
action - Always equal to UNBIND.
msgid - The msgid of this ldap operation.
suffix - List of suffix(es), as above.
dn - DN to unbind.
.fi
.LP
.SH "Return Method and Syntax"
There are only 2 return types.
All procs must return a result to show status of the operation.
The result is in this form:
.LP
.nf
{ RESULT {code: <integer>} {matched: <partialdn>}
{info: <string>} {} }
.fi
.LP
This is best accomplished with this type of tcl code
.LP
.nf
lappend ret_val "RESULT"
lappend ret_val "code: 0"
lappend ret_val ""
return $ret_val
.fi
.LP
The final empty string (item in list) is necessary to point to the end
of list.
The `code', `matched', and `info' values are not necessary, and
default values are given if not specified.
The `code' value is usually an LDAP error in decimal notation from
ldap.h.
The `info', may be sent back to the client, depending on the
function.
In the bind proc, LDAP uses the value of `code' to indicate whether or
not the authentication is acceptable.
.LP
The other type of return is for searches.
It is similar format to the shell backend return (as is most of the
syntax here).
Its format follows:
.LP
.nf
{dn: o=Company, c=US} {attr: val} {objectclass: val} {}
{dn: o=CompanyB, c=US} {attr: val} {objectclass: val} {}
.fi
.LP
Again, newlines are for visual purposes here.
Also note the {} marking the end of the entry (same effect as a
newline in ldif format).
Here is some example code again, showing a full search proc example.
.LP
.nf
# Note that `args' lets you lump all possible args
# into one var, used here for simplicity of example
proc ldap:search { args } {
# ...perform some operations...
lappend ret_val "dn: $rdn,$base"
lappend ret_val "objectclass: $objcl"
lappend ret_val "sn: $rdn"
lappend ret_val "mail: $email"
lappend ret_val ""
# Now setup the result
lappend ret_val "RESULT"
lappend ret_val "code: 0"
lappend ret_val ""
return $ret_val
}
.fi
.LP
NOTE: Newlines in the return value is acceptable in search entries
(i.e. when returning base64 encoded binary entries).
.LP
.SH "Builtin Commands and Variables"
.TP
.B ldap:debug <msg>
Allows you to send debug messages through OpenLDAP's native debugging
system, this is sent as a LDAP_DEBUG_ANY and will be logged.
Useful for debugging scripts or logging bind failures.
.SH SEE ALSO
.BR slapd.conf (5),
.BR slapd (8),
.BR Tcl (3tcl).

View File

@ -1,4 +1,4 @@
.TH SLAPD.CONF 5 "26 January 2002" "OpenLDAP LDVERSION"
.TH SLAPD.CONF 5 "28 April 2002" "OpenLDAP LDVERSION"
.\" Copyright 1998-2002 The OpenLDAP Foundation All Rights Reserved.
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.\" $OpenLDAP$
@ -56,12 +56,11 @@ backslash character (`\\'), the character should be preceded by a
backslash character.
.LP
The specific configuration options available are discussed below in the
Global Configuration Options, General Backend Options, General Database
Options, LDBM Database-Specific Options,
Shell Database-Specific Options, and Password
Database-Specific Options sections. Refer to the "OpenLDAP
Administrator's Guide" for more details on the slapd configuration
file.
Global Configuration Options, General Backend Options, and General Database
Options. Backend-specific options are discussed in the
.B slapd-<backend>(5)
manual pages. Refer to the "OpenLDAP Administrator's Guide" for more
details on the slapd configuration file.
.SH GLOBAL CONFIGURATION OPTIONS
Options described in this section apply to all backends, unless specifically
overridden in a backend definition. Arguments that should be replaced by
@ -787,7 +786,11 @@ depending on which backend will serve the database.
.SH GENERAL DATABASE OPTIONS
Options in this section only apply to the configuration file section
for the database in which they are defined. They are supported by every
type of backend.
type of backend. Note that the
.B database
and at least one
.B suffix
option are mandatory for each database.
.TP
.B database <databasetype>
Mark the beginning of a new database instance definition. <databasetype>
@ -941,195 +944,11 @@ Specify the referral to pass back when
.BR slapd (8)
is asked to modify a replicated local database.
If specified multiple times, each url is provided.
.\" .SH LDBM BACKEND-SPECIFIC OPTIONS
.\" Options in this category only apply to the LDBM backend. That is,
.\" they must follow "backend ldbm" line and come before any subsequent
.\" "backend" or "database" lines. The LDBM backend is a high-performance
.\" database that makes extensive use of indexing and caching to speed
.\" data access.
.SH BDB DATABASE-SPECIFIC OPTIONS
Options in this category only apply to the BDB databases. That is,
they must follow "database bdb" line and come before any subsequent
"backend" or "database" lines.
.TP
.B cachesize <integer>
Specify the size in entries of the in-memory cache maintained
by the BDB backend database instance. The default is 1000 entries.
.TP
.B checkpoint <kbyte> <min>
Specify the frequency for checkpointing the database transaction log.
A checkpoint operation flushes the database buffers to disk and writes
a checkpoint record in the log. The checkpoint will occur if either
<kbyte> data has been written or <min> minutes have passed since the
last checkpoint. Both arguments default to zero, in which case they are ignored.
See the Berkeley DB reference guide for more details.
.TP
.B dbnosync
Specify that on-disk database contents should not be immediately
synchronized with in memory changes. Enabling this option may improve
performance at the expense of data security.
.TP
.B directory <directory>
Specify the directory where the BDB files containing this database and
associated indexes live. A separate directory must be specified for
each database. The default is
.BR LOCALSTATEDIR/openldap-data .
.TP
.B dirtyread
Allow reads of modified but not yet committed data. Usually transactions
are isolated to prevent other operations from accessing uncommitted data.
This option may improve performance, but may also return inconsistent
results if the data comes from a transaction that is later aborted. In
this case, the modified data is discarded and a subsequent search will
return a different result.
.TP
.B
index {<attrlist>|default} [pres,eq,approx,sub,<special>]
See the description for LDBM.
.TP
.B lockdetect {oldest|youngest|fewest|random|default}
Specify which transaction to abort when a deadlock is detected. The
default is the same as
.BR random .
.TP
.B mode <integer>
Specify the file protection mode that newly created database
index files should have. The default is 0600.
.SH LDBM DATABASE-SPECIFIC OPTIONS
Options in this category only apply to the LDBM databases. That is,
they must follow "database ldbm" line and come before any subsequent
"backend" or "database" lines.
.TP
.B cachesize <integer>
Specify the size in entries of the in-memory cache maintained
by the LDBM backend database instance. The default is 1000 entries.
.TP
.B dbcachesize <integer>
Specify the size in bytes of the in-memory cache associated
with each open index file. If not supported by the underlying database
method, this option is ignored without comment. The default is 100000 bytes.
.TP
.B dbnolocking
Specify that no database locking should be performed.
Enabling this option may improve performance at the expense of data security.
Do NOT run any slap tools while slapd is running.
.TP
.B dbnosync
Specify that on-disk database contents should not be immediately
synchronized with in memory changes. Enabling this option may improve
performance at the expense of data security.
.TP
.B dbsync <frequency> <maxdelays> <delayinterval>
Flush dirty database buffers to disk every
.B <seconds>
seconds. Implies
.B dbnosync
(ie. indvidual updates are no longer written to disk). It attempts to avoid
syncs during periods of peak activity by waiting
.B <delayinterval>
seconds if the server is busy, repeating this delay up to
.B <maxdelays>
times before proceeding.
It is an attempt to provide higher write performance with some amount of data
security. Note that it may still be possible to get an inconsistent
database if the underlying engine fills its cache and writes out individual
pages and slapd crashes or is killed before the next sync.
.B <maxdelays>
and
.B <delayinterval>
are optional and default to
.B 12
and
.B 5
respectively, giving a total elapsed delay of 60 seconds before a sync
will occur.
.B <maxdelays>
may be zero, and
.B <delayinterval>
must be 1 or greater.
.TP
.B directory <directory>
Specify the directory where the LDBM files containing this database and
associated indexes live. A separate directory must be specified for
each database. The default is
.BR LOCALSTATEDIR/openldap-data .
.TP
.B
index {<attrlist>|default} [pres,eq,approx,sub,<special>]
Specify the indexes to maintain for the given attribute (or
list of attributes). Some attributes only support a subset
of indexes. If only an <attr> is given, the indices specified
for \fBdefault\fR are maintained. Note that setting a default
does not imply that all attributes will be indexed.
A number of special index parameters may be
specified.
The index type
.B sub
can be decomposed into
.BR subinitial ,
.BR subany ,\ and
.B subfinal
indices.
The special type
.B nolang
may be specified to disallow use of this index by language subtypes.
The special type
.B nosubtypes
may be specified to disallow use of this index by named subtypes.
Note: changing index settings requires rebuilding indices, see
.BR slapindex (8).
.TP
.B mode <integer>
Specify the file protection mode that newly created database
index files should have. The default is 0600.
.SH SHELL DATABASE-SPECIFIC OPTIONS
Options in this category only apply to the SHELL backend database. That is,
they must follow a "database shell" line and come before any subsequent
"backend" or "database" lines. The Shell backend executes external programs to
implement operations, and is designed to make it easy to tie an existing
database to the
.B slapd
front-end.
.TP
.B bind <pathname>
.TP
.B unbind <pathname>
.TP
.B search <pathname>
.TP
.B compare <pathname>
.TP
.B modify <pathname>
.TP
.B modrdn <pathname>
.TP
.B add <pathname>
.TP
.B delete <pathname>
.TP
.B abandon <pathname>
These options specify the pathname of the command to execute in response
to the given LDAP operation.
Note that you need only supply configuration lines for those commands you
want the backend to handle. Operations for which a command is not
supplied will be refused with an "unwilling to perform" error.
.SH PASSWORD DATABASE-SPECIFIC OPTIONS
Options in this category only apply to the PASSWD backend database.
That is, they must follow a "database passwd" line and come before any
subsequent "backend" or "database" lines. The PASSWD database serves up the user
account information listed in the system
.BR passwd (5)
file.
.TP
.B file <filename>
Specifies an alternate passwd file to use. The default is
.B /etc/passwd.
.SH OTHER DATABASE-SPECIFIC OPTIONS
Other databases may allow specific configuration options; they will be
documented separately since most of these databases are very specific
.SH DATABASE-SPECIFIC OPTIONS
Each database may allow specific configuration options; they will be
documented separately in the
.B slapd-<backend>(5)
manual pakges since most of these databases are very specific
or experimental.
.SH EXAMPLE
"OpenLDAP Administrator's Guide" contains an annotated
@ -1138,10 +957,18 @@ example of a configuration file.
ETCDIR/slapd.conf
.SH SEE ALSO
.BR ldap (3),
.BR slapd-bdb (5),
.BR slapd-ldbm (5),
.BR slapd-meta (5),
.BR slapd-null (5),
.BR slapd-passwd (5),
.BR slapd-perl (5),
.BR slapd-shell (5),
.BR slapd-sql (5),
.BR slapd-tcl (5),
.BR slapd.replog (5),
.BR slapd.access (5),
.BR locale (5),
.BR passwd (5),
.BR slapd (8),
.BR slapadd (8),
.BR slapcat (8),

View File

@ -169,7 +169,7 @@ on voluminous debugging which will be printed on standard error, type:
.LP
.nf
.ft tt
LIBEXECDIR/slapd -f ETCDIR/slapd.conf -d 255
LIBEXECDIR/slapd -f /var/tmp/slapd.conf -d 255
.ft
.fi
.LP

View File

@ -1,397 +1,2 @@
/******************************************************************************
*
* 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
* example file, the working syntax is used.
*
*
*
* Rewrite context:
*
* a rewrite context is a set of rules which are applied in sequence.
* The basic idea is to have an application initialize a rewrite
* engine (think of Apache's mod_rewrite ...) with a set of rewrite
* contexts; when string rewriting is required, one invokes the
* appropriate rewrite context with the input string and obtains the
* newly rewritten one if no errors occur.
*
* An interesting application, in back-ldap or in slapd itself,
* could associate each basic server operation to a rewrite context
* (most of them possibly aliasing the default one). Then, DN rewriting
+ could take place at any invocation of a backend operation.
*
* client -> server:
* default if defined and no specific context is available
* bindDn bind
* searchBase search
* searchFilter search
* compareDn compare
* addDn add
* modifyDn modify
* modrDn modrdn
* newSuperiorDn modrdn
* deleteDn delete
*
* server -> client:
* searchResult search (only if defined; no default)
*
*
* Configuration syntax:
*
* Basics:
*
* rewriteEngine { on | off }
*
* rewriteContext <context name> [ alias <aliased context name> ]
*
* rewriteRule <regex pattern> <substitution pattern> [ <flags> ]
*
*
* Additional:
*
* rewriteMap <map name> <map type> [ <map attrs> ]
*
* rewriteParam <param name> <param value>
*
* rewriteMaxPasses <number of passes>
*
*
*
* rewriteEngine:
*
* if 'on', the requested rewriting is performed; if 'off', no
* rewriting takes place (an easy way to stop rewriting without
* altering too much the configuration file)
*
* rewriteContext:
*
* <context name> is the name that identifies the context, i.e.
* the name used by the application to refer to the set of rules
* it contains. It is used also to reference sub contexts in
* string rewriting. A context may aliase another one. In this
* case the alias context contains no rule, and any reference to
* it will result in accessing the aliased one.
*
* rewriteRule:
*
* determines how a tring can be rewritten if a pattern is matched.
* Examples are reported below.
*
* rewriteMap:
*
* allows to define a map that transforms substring rewriting into
* something else. The map is referenced inside the substitution
* pattern of a rule.
*
* rewriteParam:
*
* sets a value with global scope, that can be dereferenced by the
* command '\{$paramName}'.
*
* rewriteMaxPasses:
*
* sets the maximum number of total rewriting passes taht can be
* performed in a signle rewriting operation (to avoid loops).
*
*
* Configuration examples:
*
* # set to 'off' to disable rewriting
*
* rewriteEngine on
*
*
* # everything defined here goes into the 'default' context
* # this rule changes the naming context of anything sent to
* # 'dc=home,dc=net' to 'dc=OpenLDAP, dc=org'
*
* rewriteRule "(.*)dc=home,[ ]?dc=net" "\1dc=OpenLDAP, dc=org" ":"
*
*
* # start a new context (ends input of the previous one)
* # this rule adds blancs between dn parts if not present.
*
* rewriteContext addBlancs
* rewriteRule "(.*),([^ ].*)" "\1, \2"
*
*
* # this one eats blancs
*
* rewriteContext eatBlancs
* rewriteRule "(.*),[ ](.*)" "\1,\2"
*
*
* # here control goes back to the default rewrite context; rules are
* # appended to the existing ones.
* # anything that gets here is piped into rule 'addBlancs'
*
* rewriteContext default
* rewriteRule ".*" "\{>addBlancs(\0)}" ":"
*
*
* # anything with 'uid=username' gets looked up in /etc/passwd for
* # gecos (I know it's nearly useless, but it is there just to
* # test something fancy!). Note the 'I' flag that leaves
* # 'uid=username' in place if 'username' does not have a valid
* # account. Note also the ':' that forces the rule to be processed
* # exactly once.
*
* rewriteContext uid2Gecos
* rewriteRule "(.*)uid=([a-z0-9]+),(.+)" "\1cn=\2{xpasswd},\3" "I:"
*
*
* # finally, in case of bind, if one uses a 'uid=username' dn,
* # it is rewritten in 'cn=name surname' if possible.
*
* rewriteContext bindDn
* rewriteRule ".*" "\{>addBlancs(\{>uid2Gecos(\0)})}" ":"
*
*
* # the search base is rewritten according to 'default' rules
*
* rewriteContext searchBase alias default
*
*
* # search results with OpenLDAP dn are rewritten back with
* # 'dc=home,dc=net' naming context, with spaces eaten.
*
* rewriteContext searchResult
* rewriteRule "(.*[^ ]?)[ ]?dc=OpenLDAP,[ ]?dc=org"
* "\{>eatBlancs(\1)}dc=home,dc=net" ":"
*
* # bind with email instead of full dn: we first need an ldap map
* # that turns attributes into a dn (the filter is provided by the
* # substitution string):
*
* rewriteMap ldap attr2dn "ldap://host/dc=my,dc=org?dn?sub"
*
* # then we need to detect emails; note that the rule in case of match
* # stops rewriting; in case of error, it is ignored.
* # In case we are mapping virtual to real naming contexts, we also
* # need to rewrite regular dns, because the definition of a bindDn
* # rewrite context overrides the default definition.
*
* rewriteContext bindDn
* rewriteRule "(mail=[^,]+@[^,]+)" "\{attr2dn(\1)}" "@I"
*
* # This is a rather sophisticate example. It massages a search filter
* # in case who performs the search has administrative privileges.
* # First we need to keep track of the bind dn of the incoming request:
*
* rewriteContext bindDn
* rewriteRule ".+" "\{**&binddn(\0)}" ":"
*
* # a search filter containing 'uid=' is rewritten only if an
* # appropriate dn is bound.
* # to do this, in the first rule the bound dn is dereferenced, while
* # the filter is decomposed in a prefix, the argument of the 'uid=',
* # and in a suffix. A tag '<>' is appended to the dn. If the dn
* # refers to an entry in the 'ou=admin' subtree, the filter is
* # rewritten OR-ing the 'uid=<arg>' with 'cn=<arg>'; otherwise
* # it is left as is. This could be useful, for instance, to allow
* # apache's auth_ldap-1.4 module to authenticate users with both
* # 'uid' and 'cn', but only if the request comes from a possible
* # 'dn: cn=Web auth, ou=admin, dc=home, dc=net' user.
*
* rewriteContext searchFilter
* rewriteRule "(.*\()uid=([a-z0-9_]+)(\).*)"
* "\{**binddn}<>\{&prefix(\1)}\{&arg(\2)}\{&suffix(\3)}" ":I"
* rewriteRule "[^,]+,[ ]?ou=admin,[ ]?dc=home,[ ]?dc=net"
* "\{*prefix}|(uid=\{*arg})(cn=\{*arg})\{*suffix}" "@I"
* rewriteRule ".*<>" "\{*prefix}uid=\{*arg}\{*suffix}"
*
*
* LDAP Proxy resolution (a possible evolution of the back-ldap):
*
* in case the rewritten dn is an LDAP URL, the operation is initiated
* towards the host[:port] indicated in the url, if it does not refer
* to the local server.
*
* e.g.:
*
* rewriteRule '^cn=root,.*' '\0' 'G{3}'
* rewriteRule '^cn=[a-l].*' 'ldap://ldap1.my.org/\0' '@'
* rewriteRule '^cn=[m-z].*' 'ldap://ldap2.my.org/\0' '@'
* rewriteRule '.*' 'ldap://ldap3.my.org/\0' '@'
*
* (rule 1 is simply there to illustrate the 'G{n}' action; it could
* have been written:
*
* rewriteRule '^cn=root,.*' 'ldap://ldap3.my.org/\0' '@'
*
* with the advantage of saving one rewrite pass ...)
*/
The workings of the rewrite library are described in the
REWRITING section of the slapd-meta(5) manual page.

View File

@ -1,158 +1,13 @@
=head1 Introduction
This is a sample Perl module for the OpenLDAP server slapd.
It also contains the documentation that you will need to
get up and going.
WARNING: the interfaces of this backen to the perl module
MAY change. Any suggestions would greatly be appreciated.
=head1 Overview
The Perl back end works by embedding a Perl interpreter into
the slapd backend. Then when the configuration file indicates
that we are going to be using a Perl backend it will get an
option that tells it what module to use. It then creates a
new Perl object that handles all the request for that particular
instance of the back end.
=head1 Interface
You will need to create a method for each one of the
following actions that you wish to handle.
* new # Creates a new object.
* search # Performs the ldap search
* compare # does a compare
* modify # modify's and entry
* add # adds an entry to back end
* modrdn # modifies a an entries rdn
* delete # deletes an ldap entry
* config # process unknown config file lines
* init # called after backend is initialized
=head2 new
This method is called when the config file encounters a
B<perlmod> line. The module in that line is then effectively
used into the perl interpreter, then the new method is called
to create a new object. Note that multiple instances of that
object may be instantiated, as with any perl object.
The new method doesn't receive any arguments other than the
class name.
RETURN:
=head2 search
This method is called when a search request comes from a client.
It arguments are as follow.
* obj reference
* base DN
* scope
* alias deferencing policy
* size limit
* time limit
* filter string
* attributes only flag ( 1 for yes )
* list of attributes that are to be returned. (could be empty)
RETURN:
=head2 compare
This method is called when a compare request comes from a client.
Its arguments are as follows.
* obj reference
* dn
* attribute assertion string
RETURN:
=head2 modify
This method is called when a modify request comes from a client.
Its arguments are as follows.
* obj reference
* dn
* lists formatted as follows
{ ADD | DELETE | REPLACE }, key, value
RETURN:
=head2 add
This method is called when a add request comes from a client.
Its arguments are as follows.
* obj reference
* entry in string format.
RETURN:
=head2 modrdn
This method is called when a modrdn request comes from a client.
Its arguments are as follows.
* obj reference
* dn
* new rdn
* delete old dn flage ( 1 means yes )
RETURN:
=head2 delete
This method is called when a delete request comes from a client.
Its arguments are as follows.
* obj reference
* dn
RETURN:
=head2 config
* obj reference
* arrray of arguments on line
RETURN: non zero value if this is not a valid option.
=head2 init
* obj reference
RETURN: non zero value if initialization failed.
=head1 Configuration
The perl section of the config file recognizes the following
options. It should also be noted that any option not recoginized
will be sent to the B<config> method of the perl module as noted
above.
database perl # startn section for the perl database
suffix "o=AnyOrg, c=US"
perlModulePath /path/to/libs # addes the path to @INC variable same
# as "use lib '/path/to/libs'"
perlModule ModName # use the module name ModName from ModName.pm
filterSearchResults # search results are candidates that need to be
# filtered, rather than search results to be
# returned directly to the client
=cut
# This is a sample Perl module for the OpenLDAP server slapd.
#
# $OpenLDAP$
#
# Usage: Add something this to slapd.conf:
#
# database perl
# suffix "o=AnyOrg, c=US"
# perlModulePath /path/to/this/file
# perlModule SampleLDAP
package SampleLDAP;
@ -169,6 +24,11 @@ sub new
return $this;
}
sub init
{
return 0;
}
sub search
{
my $this = shift;
@ -247,7 +107,7 @@ sub add
my ( $dn ) = ( $entryStr =~ /dn:\s(.*)$/m );
#
# This needs to be here untill a normalize dn is
# This needs to be here until a normalized dn is
# passed to this routine.
#
$dn = uc( $dn );
@ -296,5 +156,3 @@ sub config
}
1;

View File

@ -1,257 +1 @@
CONTENT
1. Purpose
2. Metainformation used
3. Typical back-sql operation
4. Several important common techniques (referrals, multiclassing)
1. Purpose
Primary purpose of this backend is to PRESENT information stored in some RDBMS
as an LDAP subtree without any programming (some SQL and maybe stored
procedures can't be considered programming, anyway ;).
That is, for example, when you (some ISP) have account
information you use in RDBMS, and want to use modern solutions that expect such
information in LDAP (to authenticate users, make email lookups etc.).
Or you want to syncronize or distribute information between different
sites/applications that use RDBMSes and/or LDAP. Or whatever else...
It is NOT designed as general-purpose backend that uses RDBMS instead of
BerkeleyDB (as standard back-ldbm does), though it can be used as such
with several limitations. You can take a look at
http://www.openldap.org/faq/index.cgi?file=378
(OpenLDAP FAQ-O-Matic/General LDAP FAQ/Directories vs. conventional databases)
to find out more on this point.
The idea (detailed below) is to use some metainformation to translate
LDAP queries to SQL queries, leaving relational schema untouched, so that
old applications can continue using it without any modifications. This allows
SQL and LDAP applications to interoperate without replication, and exchange
data as needed.
Back-sql is designed to be tunable to virtually any relational schema without
having to change source (through that metainformation mentioned).
Also, it uses ODBC to connect to RDBMSes, and is highly configurable for
SQL dialects RDBMSes may use, so it may be used for integration and
distribution of data on different RDBMSes, OSes, hosts etc., in other words,
in highly heterogeneous environment.
2. Metainformation used
***
Almost everything mentioned later is illustrated in example, which is located
in backsql/rdbms_depend directory, and contains scripts for generating sample
database for Oracle,MS SQL Server and mySQL.
***
First thing that one must arrange for himself is what set of LDAP
objectclasses can present your RDBMS information.
The easiest way is to create objectclass for each entity you had
in ER-diagram when designing your relational schema.
Any relational schema, no matter how normalized it is, was designed after
some model of your applications domain (for instance, accounts, services etc.
in ISP), and is used in terms of its entities, not just tables of normalized
schema.
It means that for every attribute of every such instance there is an effective
SQL query that loads it's values.
Also you might want your objectclasses to conform to some of standard schemas
like inetOrgPerson etc..
Nevertheless, when you think it out, we must define a way to translate LDAP
operation requests to (series of) SQL queries. Let us deal with SEARCH
operation.
Example:
Lets suppose that we store information about persons working in our
organization in two tables:
PERSONS PHONES
---------- -------------
id integer id integer
first_name varchar pers_id integer references persons(id)
last_name varchar phone
middle_name varchar
...
(PHONES contains telephone numbers associated with persons). A person can have
several numbers, then PHONES contains several records with corresponding
pers_id, or no numbers (and no records in PHONES with such pers_id). LDAP
objectclass to present such information could look like this:
person
-------
MUST cn
MAY telephoneNumber
MAY firstName
MAY lastName
...
To fetch all values for cn attribute given person ID, we construct the query:
SELECT CONCAT(persons.first_name,' ',persons.last_name) as cn FROM persons WHERE persons.id=?
for telephoneNumber we can use:
SELECT phones.phone as telephoneNumber FROM persons,phones WHERE persons.id=phones.pers.id and persons.id=?
If we wanted to service LDAP request with filter like (telephoneNumber=123*),
we would construct something like:
SELECT ... FROM persons,phones WHERE persons.id=phones.pers.id and persons.id=? and phones.phone like '123%'
So, if we had information about what tables contain values for each
attribute, how to join this tables and arrange these values, we could try
to automatically generate such statements, and translate search filters
to SQL WHERE clauses.
To store such information, we add three more tables to our schema, so that
and fill it with data (see samples):
ldap_oc_mappings (some columns are not listed for clarity)
---------------
id=1
name="person"
keytbl="persons"
keycol="id"
This table defines mapping between objectclass (its name held in "name" column),
and table that holds primary key for corresponding entities. For instance,
in our example, the person entity, which we are trying to present as "person"
objectclass, resides in two tables (persons and phones), and is identified
by persons.id column (that we will call primary key for this entity).
keytbl and keycol thus contain "persons" (name of the table), and "id" (name
of the column).
ldap_attr_mappings (some columns are not listed for clarity)
-----------
id=1
oc_id=1
name="cn"
sel_expr="CONCAT(persons.first_name,' ',persons.last_name)"
from_tbls="persons"
join_where=NULL
************
id=<n>
oc_map_id=1
name="telephoneNumber"
sel_expr="phones.phone"
from_tbls="persons,phones"
join_where="phones.pers_id=persons.id"
This table defines mappings between LDAP attributes and SQL queries that
load their values. Note that, unlike LDAP schema, these are not *attribute types*
- attribute "cn" for "person" objectclass can well have it's values in different
table than "cn" for other objectclass, so attribute mappings depend on
objectclass mappings (unlike attribute types in LDAP schema, which are
indifferent to objectclasses). Thus, we have oc_map_id column with link to
oc_mappings table.
Now we cut the SQL query that loads values for given attribute into 3 parts.
First goes into sel_expr column - this is the expression we had between
SELECT and FROM keywords, which defines WHAT to load.
Next is table list - text between FROM and WHERE keywords. It may contain
aliases for convenience (see exapmles).
The last is part of where clause, which (if exists at all) express the
condition for joining the table containing values wich table containing
primary key (foreign key equality and such). If values are in the same table
with primary key, then this column is left NULL (as for cn attribute above).
Having this information in parts, we are able to not only construct queries
that load attribute values by id of entry (for this we could store SQL query
as a whole), but to construct queries that load id's of objects that
correspond to given search filter (or at least part of it).
See below for examples.
ldap_entries
------------
id=1
dn=<dn you choose>
oc_map_id=...
parent=<parent record id>
keyval=<value of primary key>
This table defines mappings between DNs of entries in your LDAP tree,
and values of primary keys for corresponding relational data. It has
recursive structure (parent column references id column of the same table),
which allows you to add any tree structure(s) to your flat relational data.
Having id of objectclass mapping, we can determine table and column for
primary key, and keyval stores value of it, thus defining exact tuple
corresponding to LDAP entry with this DN.
Note that such design (see exact SQL table creation query) implies one
important constraint - the key must be integer. But all that I know about
well-designed schemas makes me think that it s not very narrow ;)
If anyone needs support for different types for keys - he may want to write
a patch, and submit it to OpenLDAP ITS, then I'll include it.
Also, several people complained that they don't really need very structured
tree, and they don't want to update one more table every time they add or
delete instance in relational schema. Those can use a view instead of real
table, something like this:
Robin Elfrink wrote:
> About using a view for ldap_entries...
>
> This is what I came up with this morning:
>
> CREATE VIEW ldap_entries (id, dn, oc_map_id, parent, keyval) AS
> SELECT (1000000000+userid),
> UPPER(CONCAT(CONCAT('cn=',gecos),',o=MyCompany,c=NL'))
> , 1, 0, userid FROM unixusers UNION
> SELECT (2000000000+groupnummer),
> UPPER(CONCAT(CONCAT('cn=',groupnaam),',o=MyCompany,c=NL')), 2, 0,
> groupnummer FROM groups;
>
3. Typical back-sql operation
Having metainformation loaded, back-sql uses these tables to determine a set
of primary keys of candidates (depending on search scope and filter). It tries
to do it for each objectclass registered in ldap_objclasses.
Exapmle:
for our query with filter (telephoneNumber=123*) we would get following
query generated (which loads candidate IDs)
SELECT ldap_entries.id,persons.id, 'person' AS objectClass, ldap_entries.dn AS dn FROM ldap_entries,persons,phones WHERE persons.id=ldap_entries.keyval AND ldap_entries.objclass=? AND ldap_entries.parent=? AND phones.pers_id=persons.id AND (phones.phone LIKE '123%')
(for ONELEVEL search)
or "... AND dn=?" (for BASE search)
or "... AND dn LIKE '%?'" (for SUBTREE)
Then, for each candidate, we load attributes requested using per-attribute queries
like
SELECT phones.phone AS telephoneNumber FROM persons,phones WHERE persons.id=? AND phones.pers_id=persons.id
Then, we use test_filter() from frontend API to test entry for full
LDAP search filter match (since we cannot effectively make sense of SYNTAX
of corresponding LDAP schema attribute, we translate the filter into most relaxed
SQL condition to filter candidates), and send it to user.
ADD,DELETE,MODIFY operations also performed on per-attribute metainformation
(add_proc etc.). In those fields one can specify an SQL statement or stored procedure
call which can add, or delete given value of given attribute, using given entry
keyval (see examples -- mostly ORACLE and MSSQL - since there're no stored procs in mySQL).
We just add more columns to oc_m,appings and attr_mappings, holding statements
to execute (like create_proc, add_proc, del_proc etc.), and flags governing
order of parameters passed to those statements.
Please see samples to find out what are the parameters passed, and other
information on this matter - they are self-explanatory for those familiar
with concept expressed above.
4. Several common techniques (referrals, multiclassing etc.)
First of all, lets remember that among other major differences to complete
LDAP data model, the concept above does not directly support such things
as multiple objectclasses for entry, and referrals.
Fortunately, they are easy to adopt in this scheme. Back-sql suggests two more
tables being added to schema -
ldap_entry_objectclasses(entry_id, oc_name), and ldap_referrals (entry_id,url).
First contains any number of objectclass names that corresponding entries
will be found by, in addition to that mentioned in mapping. Back-sql
automatically adds attribute mapping for "objectclass" attribute to each objectclass
mapping, that loads values from this table. So, you may, for instance, have
mapping for inetOrgPerson, and use it for queries for "person" objectclass...
Second table contains any number of referrals associated with given entry.
Back-sql automatically adds attribute mapping for "ref" attribute to each
objectclass mapping, that loads values from this table.
So, if you add objectclass "referral" to this entry, and make one or more
tuples in ldap_referrals for this entry (they will be seen as values of "ref"
attribute), you will have slapd return referral, as described in Administrators
Guide.
The SQL backend is described in the slapd-sql(5) manual page.

View File

@ -1,206 +1 @@
Tcl Backend Interface for OpenLDAP
----------------------------
Synopsis of slapd.conf setup
----------------------------
database tcl
suffix o=Suffix
# The full path to the tcl script used for this database
scriptpath /usr/lib/ldap/database.tcl
# The procs for each ldap function. This is similar to how
# the shell backend setup works, but these refer to
# the tcl procs in the 'scriptpath' script that handle them
search <proc>
add <proc>
delete <proc>
modify <proc>
bind <proc>
unbind <proc>
modrdn <proc>
compare <proc>
abandon <proc>
# This is one of the biggest pluses of using the tcl backend.
# The realm lets you group several databases to the same interpreter.
# This basically means they share the same global variables and proc
# space. So global variables, as well as all the procs, are callable
# between databases. If no tclrealm is specified, it is put into the
# "default" realm.
tclrealm <interpreter name>
-----------------------------------------
Synopsis of variables passed to the procs
-----------------------------------------
abandon { action msgid suffix }
action - Always equal to ABANDON
msgid - The msgid of this ldap session
suffix - List of suffix(es) associated with the call. Each one is
an entry in a tcl formatted list (surrounded by {}'s)
add { action msgid suffix entry }
action - Always equal to ADD
msgid - The msgid of this ldap session
suffix - List of suffix(es) associated with the call. Each one is
an entry in a tcl formatted list (surrounded by {}'s)
entry - Full entry to add. Each "type: val" is an element in a
tcl formatted list.
bind { action msgid suffix dn method cred_len cred }
action - Always equal to BIND
msgid - The msgid of this ldap session
suffix - List of suffix(es) associated with the call. Each one
is an entry in a tcl formatted list (surrounded by {}'s)
dn - DN being bound to
method - One of the ldap authentication methods
cred_len - Length of cred
cred - Credentials being used to authenticate, according to
RFC, if this value is empty, then it should be
considered an anonomous bind (??)
compare { action msgid suffix dn ava_type ava_value }
action - Always equal to COMPARE
msgid - The msgid of this ldap session
suffix - List of suffix(es) associated with the call. Each one
is and entry in a tcl formatted list (surrounded by {}'s)
dn - DN for compare
ava_type - Type for comparison
ava_value - Value to compare
delete { action msgid suffix dn }
action - Always equal to DELETE
msgid - The msgid of this ldap session
suffix - List of suffix(es) associated with the call. Each one
is and entry in a tcl formatted list (surrounded by {}'s)
dn - DN to delete
modify { action msgid suffix dn mods }
action - Always equal to MODIFY
msgid - The msgid of this ldap session
suffix - List of suffix(es) associated with the call. Each one
is and entry in a tcl formatted list (surrounded by {}'s)
dn - DN to modify
mods - Tcl list of modifications. List is formatted in this way:
{
{ {op: type} {type: val} }
{ {op: type} {type: val} {type: val} }
...
}
Newlines are not present in the actual var, they are
present here for clarification. "op" is the type of
modification (add, delete, replace).
modrdn { action msgid suffix dn newrdn deleteoldrdn }
action - Always equal to MODRDN
msgid - The msgid of this ldap session
suffix - List of suffix(es) associated with the call. Each one
is and entry in a tcl formatted list (surrounded by {}'s)
dn - DN whose RDN is being renamed
newrdn - New RDN
deleteoldrdn - Boolean stating whether or not the old RDN should
be removed after being renamed
search { action msgid suffix base scope deref sizelimit timelimit
filterstr attrsonly attrlist }
action - Always equal to SEARCH
msgid - The msgid of this ldap session
suffix - List of suffix(es) associated with the call. Each one
is and entry in a tcl formatted list (surrounded by {}'s)
base - Base for this search
scope - Scope of search, ( 0 | 1 | 2 )
deref - Alias dereferencing ( 0 | 1 | 2 | 3 )
sizelimit - Script should try not to return more data that this
timelimit - Time limit for search
filterstr - Filter string as sent by the requestor.
attrsonly - Boolean for whether to list only the attributes
instead of attributes and their values.
attrlist - Tcl list if to retrieve.
unbind { action msgid suffix dn }
action - Always equal to UNBIND
msgid - The msgid of this ldap session
suffix - List of suffix(es) associated with the call. Each one
is and entry in a tcl formatted list (surrounded by {}'s)
dn - DN to unbind
------------------------------------
Synopsis of Return Method and Syntax
------------------------------------
There are only 2 return types. All procs must return a result to show
status of the operation. The result is in this form:
{ RESULT {code: <integer>} {matched: <partialdn>} {info: <string>} {} }
This is best accomplished with this type of tcl code
lappend ret_val "RESULT"
lappend ret_val "code: 0"
lappend ret_val ""
return $ret_val
The final empty string (item in list) is necessary to point to the end of
list. The 'code', 'matched', and 'info' values are not necessary, and
default values are given if not specified. The 'code' value is usually an
LDAP error in decimal notation from ldap.h. The 'info', may be sent back
to the client, depending on the function. LDAP uses the value of 'code' to
indicate whether or not the authentication is acceptible in the bind proc.
The other type of return is for searches. It is similar format to the
shell backend return (as is most of the syntax here). Its format follows:
{dn: o=Company, c=US} {attr: val} {objectclass: val} {}
{dn: o=CompanyB, c=US} {attr: val} {objectclass: val} {}
Again, newlines are for visual purposes here. Also note the {} marking the
end of the entry (same effect as a newline in ldif format). Here is some
example code again, showing a full search proc example.
# Note that 'args' lets you lump all possible args into one var, used
# here for simplicity of example
proc ldap:search { args } {
# perform some operations
lappend ret_val "dn: $rdn,$base"
lappend ret_val "objectclass: $objcl"
lappend ret_val "sn: $rdn"
lappend ret_val "mail: $email"
lappend ret_val ""
# Now setup the result
lappend ret_val "RESULT"
lappend ret_val "code: 0"
lappend ret_val ""
return $ret_val
}
NOTE: Newlines in the return value is acceptable in search entries (i.e.
when returning base64 encoded binary entries).
-------------------------------------
Synopsis of Builtin Commands and Vars
-------------------------------------
ldap:debug <msg>
Allows you to send debug messages through OpenLDAP's native debugging
system, this is sent as a LDAP_DEBUG_ANY and will be logged. Useful for
debugging scripts or logging bind failures.
The Tcl Backend is described in the slapd-tcl(5) manual page.