mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-27 01:59:38 -05:00
minor naming cleanup; improvements to DN mapping layer; major docs update
This commit is contained in:
parent
c1e4eeb23b
commit
f5936eb7fc
17 changed files with 296 additions and 166 deletions
|
|
@ -41,90 +41,163 @@ 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.
|
||||
.LP
|
||||
This backend is experimental.
|
||||
This backend is \fIexperimental\fP.
|
||||
.SH CONFIGURATION
|
||||
These
|
||||
.B slapd.conf
|
||||
options apply to the SQL backend database.
|
||||
That is, they must follow a "database sql" line and come before any
|
||||
options apply to the SQL backend database, which means that
|
||||
they must follow a "database sql" line and come before any
|
||||
subsequent "backend" or "database" lines.
|
||||
Other database options are described in the
|
||||
Other database options not specific to this backend are described
|
||||
in the
|
||||
.BR slapd.conf (5)
|
||||
manual page.
|
||||
.SH DATA SOURCE CONFIGURATION
|
||||
|
||||
.TP
|
||||
.B dbname <datasource name>
|
||||
The name of the ODBC datasource to use.
|
||||
.LP
|
||||
.B dbhost <hostname>
|
||||
.br
|
||||
.B dbuser <username>
|
||||
.br
|
||||
.B dbpasswd <password>
|
||||
.br
|
||||
.B dbuser <username>
|
||||
.RS
|
||||
These three options are generally unneeded, because this information is already
|
||||
taken from the datasource.
|
||||
Use them if you need to override datasource settings.
|
||||
The three above options are generally unneeded, because this information
|
||||
is taken from the datasource specified by the
|
||||
.B dbname
|
||||
directive.
|
||||
They allow to override datasource settings.
|
||||
Also, several RDBMS' drivers tend to require explicit passing of user/password,
|
||||
even if those are given in datasource (Note:
|
||||
.B dbhost
|
||||
is currently ignored).
|
||||
.RE
|
||||
.SH SCOPING CONFIGURATION
|
||||
These options specify SQL query templates for scoping searches.
|
||||
|
||||
.TP
|
||||
.B subtree_cond <SQL expression>
|
||||
Specifies a where-clause template used to form a subtree search condition
|
||||
(dn=".*<dn>").
|
||||
(dn="(.+,)?<dn>$").
|
||||
It may differ from one SQL dialect to another (see samples).
|
||||
By default, it is constructed based on the knowledge about
|
||||
how to normalize DN values (e.g.
|
||||
\fB"<upper_func>(ldap_entries.dn) LIKE CONCAT('%',?)"\fP).
|
||||
|
||||
.TP
|
||||
.B children_cond <SQL expression>
|
||||
Specifies a where-clause template used to form a children search condition
|
||||
(dn="\.+,<dn>").
|
||||
(dn=".+,<dn>$").
|
||||
It may differ from one SQL dialect to another (see samples).
|
||||
.TP
|
||||
.B oc_query <SQL expression>
|
||||
The default is
|
||||
.B "SELECT id, name, keytbl, keycol, create_proc, delete_proc, expect_return FROM ldap_oc_mappings"
|
||||
.TP
|
||||
.B at_query <SQL expression>
|
||||
The default is
|
||||
.B "SELECT name, sel_expr, from_tbls, join_where, add_proc, delete_proc, param_order, expect_return FROM ldap_attr_mappings WHERE oc_map_id=?"
|
||||
.TP
|
||||
.B insentry_query <SQL expression>
|
||||
The default is
|
||||
.B "INSERT INTO ldap_entries (dn, oc_map_id, parent, keyval) VALUES (?, ?, ?, ?)"
|
||||
.TP
|
||||
.B delentry_query <SQL expression>
|
||||
The default is
|
||||
.B "DELETE FROM ldap_entries WHERE id=?"
|
||||
By default, it is constructed based on the knowledge about
|
||||
how to normalize DN values (e.g.
|
||||
\fB"<upper_func>(ldap_entries.dn) LIKE CONCAT('%,',?)"\fP).
|
||||
|
||||
These four options specify SQL query templates for loading schema mapping
|
||||
.TP
|
||||
.B use_subtree_shortcut { NO | yes }
|
||||
Do not use the subtree condition when the searchBase is the database
|
||||
suffix, and the scope is subtree; rather collect all entries.
|
||||
.RE
|
||||
.SH STAMEMENT CONFIGURATION
|
||||
These options specify SQL query templates for loading schema mapping
|
||||
metainformation, adding and deleting entries to ldap_entries, etc.
|
||||
All these and subtree_cond should have the given default values.
|
||||
For the current value it is recommended to look at the sources,
|
||||
or in the log output when slapd starts with "-d 5" or greater.
|
||||
Note that the parameter number and order must not be changed.
|
||||
|
||||
.TP
|
||||
.B oc_query <SQL expression>
|
||||
The query that is used to collect the objectClass mapping data
|
||||
from table \fIldap_oc_mappings\fP; see "METAINFORMATION USED" for details.
|
||||
The default is
|
||||
\fB"SELECT id, name, keytbl, keycol, create_proc, delete_proc, expect_return
|
||||
FROM ldap_oc_mappings"\fP.
|
||||
|
||||
.TP
|
||||
.B at_query <SQL expression>
|
||||
The query that is used to collect the attributeType mapping data
|
||||
from table \fIldap_attr_mappings\fP; see "METAINFORMATION USED" for details.
|
||||
The default is
|
||||
\fB"SELECT name, sel_expr, from_tbls, join_where, add_proc, delete_proc,
|
||||
param_order, expect_return FROM ldap_attr_mappings WHERE oc_map_id=?"\fP.
|
||||
|
||||
.TP
|
||||
.B id_query <SQL expression>
|
||||
The query that is used to map a DN to an entry
|
||||
in table \fIldap_entries\fP; see "METAINFORMATION USED" for details.
|
||||
The default is
|
||||
\fB"SELECT id,keyval,oc_map_id,dn FROM ldap_entries WHERE <DN match expr>"\fP,
|
||||
where \fB<DN match expr>\fP is constructed based on the knowledge about
|
||||
how to normalize DN values (e.g. \fB"dn=?"\fP if no means to uppercase
|
||||
strings are available; typically, \fB"<upper_func>(dn)=?"\fP
|
||||
is used).
|
||||
|
||||
.TP
|
||||
.B insentry_stmt <SQL expression>
|
||||
The statement that is used to insert a new entry
|
||||
in table \fIldap_entries\fP; see "METAINFORMATION USED" for details.
|
||||
The default is
|
||||
\fB"INSERT INTO ldap_entries (dn, oc_map_id, parent, keyval) VALUES
|
||||
(?, ?, ?, ?)"\fP.
|
||||
|
||||
.TP
|
||||
.B delentry_stmt <SQL expression>
|
||||
The statement that is used to delete an existing entry
|
||||
from table \fIldap_entries\fP; see "METAINFORMATION USED" for details.
|
||||
The default is
|
||||
\fB"DELETE FROM ldap_entries WHERE id=?"\fP.
|
||||
|
||||
.TP
|
||||
.B delobjclasses_stmt <SQL expression>
|
||||
The statement that is used to delete an existing entry's ID
|
||||
from table \fIldap_objclasses\fP; see "METAINFORMATION USED" for details.
|
||||
The default is
|
||||
\fB""DELETE FROM ldap_entry_objclasses WHERE entry_id=?"\fP.
|
||||
|
||||
.TP
|
||||
.B delreferrals_stmt <SQL expression>
|
||||
The statement that is used to delete an existing entry's ID
|
||||
from table \fIldap_referrals\fP; see "METAINFORMATION USED" for details.
|
||||
The default is
|
||||
\fB""DELETE FROM ldap_referrals WHERE entry_id=?"\fP.
|
||||
|
||||
.RE
|
||||
.SH HELPER CONFIGURATION
|
||||
|
||||
.TP
|
||||
.B upper_func <SQL function name>
|
||||
Specifies the name of a function that converts a given value to uppercase.
|
||||
This is used for CIS matching when the RDBMS is case sensitive.
|
||||
This is used for case insensitive matching when the RDBMS is case sensitive.
|
||||
It may differ from one SQL dialect to another (e.g. \fBUCASE\fP, \fBUPPER\fP
|
||||
or whatever; see samples). By default, none is used, i.e. strings are not
|
||||
uppercased, so matches may be case sensitive.
|
||||
|
||||
.TP
|
||||
.B upper_needs_cast { NO | yes}
|
||||
.B upper_needs_cast { NO | yes }
|
||||
Set this directive to
|
||||
.B yes
|
||||
if
|
||||
.B upper_func
|
||||
needs an explicit cast when applied to literal strings. The form
|
||||
needs an explicit cast when applied to literal strings.
|
||||
A cast in the form
|
||||
.B CAST (<arg> AS VARCHAR(<max DN length>))
|
||||
is used, where
|
||||
.B <max DN length>
|
||||
is builtin.
|
||||
This is
|
||||
.B experimental
|
||||
and may change in future releases.
|
||||
is builtin in back-sql; see macro
|
||||
.B BACKSQL_MAX_DN_LEN
|
||||
(currently 255; note that slapd's builtin limit, in macro
|
||||
.BR SLAP_LDAPDN_MAXLEN ,
|
||||
is set to 8192).
|
||||
This is \fIexperimental\fP and may change in future releases.
|
||||
|
||||
.TP
|
||||
.B concat_pattern <pattern>
|
||||
This statement defines the
|
||||
.B pattern
|
||||
to be used to concatenate strings. The
|
||||
that is used to concatenate strings. The
|
||||
.B pattern
|
||||
MUST contain two question marks, '?', that will be replaced
|
||||
by the two strings that must be concatenated. The default value is
|
||||
|
|
@ -135,40 +208,34 @@ but an explicit cast may be required when operating on literal strings:
|
|||
.BR "CAST(?||? AS VARCHAR(<length>))".
|
||||
On some RDBMSes (IBM db2, MSSQL) the form
|
||||
.B "?+?"
|
||||
is known to work.
|
||||
is known to work as well.
|
||||
Carefully check the documentation of your RDBMS or stay with the examples
|
||||
for supported ones.
|
||||
This is
|
||||
.B experimental
|
||||
and may change in future releases.
|
||||
This is \fIexperimental\fP and may change in future releases.
|
||||
|
||||
.TP
|
||||
.B strcast_func <SQL function name>
|
||||
Specifies the name of a function that converts a given value to a string
|
||||
for appropriate ordering. This is used in "SELECT DISTINCT" statements
|
||||
for strongly typed RDBMSes with little implicit casting (like PostgreSQL),
|
||||
when a literal string is specified.
|
||||
This is
|
||||
.B experimental
|
||||
and may change in future releases.
|
||||
This is \fIexperimental\fP and may change in future releases.
|
||||
|
||||
.TP
|
||||
.B has_ldapinfo_dn_ru { NO | yes }
|
||||
Explicitly inform the backend whether the SQL schema has dn_ru column
|
||||
(dn in reverse uppercased form) or not.
|
||||
Overrides automatic check (required by PostgreSQL/unixODBC).
|
||||
This is
|
||||
.B experimental
|
||||
and may change in future releases.
|
||||
Explicitly inform the backend whether the dn_ru column
|
||||
(DN in reverse uppercased form) is present in table \fIldap_entries\fP.
|
||||
Overrides automatic check (this is required, ofr instance,
|
||||
by PostgreSQL/unixODBC).
|
||||
This is \fIexperimental\fP and may change in future releases.
|
||||
|
||||
.TP
|
||||
.B fail_if_no_mapping { NO | yes }
|
||||
When set to
|
||||
.B yes
|
||||
it forces
|
||||
.I attribute
|
||||
write operations to fail if no appropriate mapping between LDAP attributes
|
||||
and SQL data is available.
|
||||
The default behavior is to ignore those changes that cannot be mapped
|
||||
correctly.
|
||||
it forces \fIattribute\fP write operations to fail if no appropriate
|
||||
mapping between LDAP attributes and SQL data is available.
|
||||
The default behavior is to ignore those changes that cannot be mapped.
|
||||
It has no impact on objectClass mapping, i.e. if the
|
||||
.I structuralObjectClass
|
||||
of an entry cannot be mapped to SQL by looking up its name
|
||||
|
|
@ -177,9 +244,7 @@ in ldap_oc_mappings, an
|
|||
operation will fail regardless of the
|
||||
.B fail_if_no_mapping
|
||||
switch; see section "METAINFORMATION USED" for details.
|
||||
This is
|
||||
.B experimental
|
||||
and may change in future releases.
|
||||
This is \fIexperimental\fP and may change in future releases.
|
||||
|
||||
.TP
|
||||
.B allow_orphans { NO | yes }
|
||||
|
|
@ -196,21 +261,31 @@ Instructs the database to create and manage an in-memory baseObject
|
|||
entry instead of looking for one in the RDBMS.
|
||||
If the (optional)
|
||||
.B filename
|
||||
argument is given, the entry is read from file
|
||||
.B filename
|
||||
in
|
||||
argument is given, the entry is read from that file in
|
||||
.BR LDIF (5)
|
||||
form.
|
||||
This is particularly useful when
|
||||
.B ldap_entries
|
||||
form; otherwise, an entry with objectClass \fBextensibleObject\fP
|
||||
is created based on the contents of the RDN of the \fIbaseObject\fP.
|
||||
This is particularly useful when \fIldap_entries\fP
|
||||
information is stored in a view rather than in a table, and
|
||||
.B union
|
||||
is not supported for views, so that the view can only specify
|
||||
one rule to compute the entry structure for one objectClass.
|
||||
This topic is discussed further in section "METAINFORMATION USED".
|
||||
This is
|
||||
.B experimental
|
||||
and may change in future releases.
|
||||
This is \fIexperimental\fP and may change in future releases.
|
||||
|
||||
.TP
|
||||
.B create_needs_select { NO | yes }
|
||||
Instructs the database whether entry creation in table \fIldap_entries\fP
|
||||
needs a subsequent select to collect the automatically assigned ID,
|
||||
instead of being returned by a stored procedure.
|
||||
|
||||
.TP
|
||||
.B sqllayer <name> [...]
|
||||
Loads the layer \fB<name>\fP onto a stack of helpers that are used
|
||||
to map DNs from LDAP to SQL representation and vice-versa.
|
||||
Subsequent args are passed to the layer configuration routine.
|
||||
This is \fIhighly experimental\fP and should be used with extreme care.
|
||||
The API of the layers is not frozen yet, so it is unpublished.
|
||||
|
||||
.SH METAINFORMATION USED
|
||||
.LP
|
||||
|
|
@ -280,7 +355,7 @@ for telephoneNumber we can use:
|
|||
.LP
|
||||
.nf
|
||||
SELECT phones.phone AS telephoneNumber FROM persons,phones
|
||||
WHERE persons.id=phones.pers_id AND persons.id=?
|
||||
WHERE persons.id=phones.pers_id AND persons.id=?
|
||||
.fi
|
||||
.LP
|
||||
If we wanted to service LDAP requests with filters like
|
||||
|
|
@ -288,11 +363,15 @@ If we wanted to service LDAP requests with filters like
|
|||
.LP
|
||||
.nf
|
||||
SELECT ... FROM persons,phones
|
||||
WHERE persons.id=phones.pers_id
|
||||
AND persons.id=?
|
||||
AND phones.phone like '123%'
|
||||
WHERE persons.id=phones.pers_id
|
||||
AND persons.id=?
|
||||
AND phones.phone like '%1%2%3%'
|
||||
.fi
|
||||
.LP
|
||||
(note how the telephoneNumber match is expanded in multiple wildcards
|
||||
to account for interspersed ininfluential chars like spaces, dashes
|
||||
and so; this occurs by design because telephoneNumber is defined after
|
||||
a specially recognized syntax).
|
||||
So, if we had information about what tables contain values for each
|
||||
attribute, how to join these tables and arrange these values, we could
|
||||
try to automatically generate such statements, and translate search
|
||||
|
|
@ -402,13 +481,15 @@ like this (by Robin Elfrink):
|
|||
CREATE VIEW ldap_entries (id, dn, oc_map_id, parent, keyval)
|
||||
AS
|
||||
SELECT 0, UPPER('o=MyCompany,c=NL'),
|
||||
3, 0, 'baseObject' FROM unixusers WHERE userid='root' UNION
|
||||
3, 0, 'baseObject' FROM unixusers WHERE userid='root'
|
||||
UNION
|
||||
SELECT (1000000000+userid),
|
||||
UPPER(CONCAT(CONCAT('cn=',gecos),',o=MyCompany,c=NL')),
|
||||
1, 0, userid FROM unixusers UNION
|
||||
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;
|
||||
UPPER(CONCAT(CONCAT('cn=',groupnaam),',o=MyCompany,c=NL')),
|
||||
2, 0, groupnummer FROM groups;
|
||||
.fi
|
||||
|
||||
.LP
|
||||
|
|
@ -439,7 +520,7 @@ query generated (which loads candidate IDs)
|
|||
AND ldap_entries.objclass=?
|
||||
AND ldap_entries.parent=?
|
||||
AND phones.pers_id=persons.id
|
||||
AND (phones.phone LIKE '123%')
|
||||
AND (phones.phone LIKE '%1%2%3%')
|
||||
.fi
|
||||
.LP
|
||||
(for ONELEVEL search)
|
||||
|
|
@ -465,15 +546,15 @@ ADD, DELETE, MODIFY and MODRDN operations are 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 values of a given attribute, using
|
||||
the given entry keyval (see examples -- mostly ORACLE and MSSQL - since
|
||||
there're no stored procs in mySQL).
|
||||
the given entry keyval (see examples -- mostly PostgreSQL, ORACLE and MSSQL
|
||||
- since as of this writing there are no stored procs in MySQL).
|
||||
.LP
|
||||
We just add more columns to oc_mappings and attr_mappings, holding
|
||||
We just add more columns to ldap_oc_mappings and ldap_attr_mappings, holding
|
||||
statements to execute (like create_proc, add_proc, del_proc etc.), and
|
||||
flags governing the 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.
|
||||
with the concepts expressed above.
|
||||
.LP
|
||||
.SH Common techniques (referrals, multiclassing etc.)
|
||||
First of all, let's remember that among other major differences to the
|
||||
|
|
@ -505,16 +586,24 @@ As previously stated, this backend should not be considered
|
|||
a replacement of other data storage backends, but rather a gateway
|
||||
to existing RDBMS storages that need to be published in LDAP form.
|
||||
.LP
|
||||
The hasSubordintes operational attribute is honored by back-sql
|
||||
The \fBhasSubordintes\fP operational attribute is honored by back-sql
|
||||
in search results and in compare operations; it is partially honored
|
||||
also in filtering. Owing to design limitations, a (braindead) filter
|
||||
also in filtering. Owing to design limitations, a (braindead?) filter
|
||||
of the form
|
||||
\fB(!(hasSubordinates=TRUE))\fP
|
||||
will give no results instead of returning all the leaf entries.
|
||||
will give no results instead of returning all the leaf entries, because
|
||||
it actually expands into \fB... AND NOT (1=1)\fP.
|
||||
If you need to find all the leaf entries, please use
|
||||
\fB(hasSubordinates=FALSE)\fP
|
||||
instead.
|
||||
.LP
|
||||
A directoryString value of the form "__First___Last_"
|
||||
(where underscores should be replaced by spaces) corresponds
|
||||
to its prettified counterpart "First_Last"; this is not currently
|
||||
honored by back-sql if non-prettified data is written via RDBMS;
|
||||
when non-prettified data is written thru back-sql, the prettified
|
||||
values are actually used instead.
|
||||
.LP
|
||||
.SH PROXY CACHE OVERLAY
|
||||
The proxy cache overlay
|
||||
allows caching of LDAP search requests (queries) in a local database.
|
||||
|
|
@ -525,6 +614,7 @@ for details.
|
|||
There are example SQL modules in the slapd/back-sql/rdbms_depend/
|
||||
directory in the OpenLDAP source tree.
|
||||
.SH FILES
|
||||
|
||||
.TP
|
||||
ETCDIR/slapd.conf
|
||||
default slapd configuration file
|
||||
|
|
|
|||
|
|
@ -1348,7 +1348,7 @@ backsql_add( Operation *op, SlapReply *rs )
|
|||
}
|
||||
}
|
||||
|
||||
rc = backsql_Prepare( dbh, &sth, bi->sql_insentry_query, 0 );
|
||||
rc = backsql_Prepare( dbh, &sth, bi->sql_insentry_stmt, 0 );
|
||||
if ( rc != SQL_SUCCESS ) {
|
||||
rs->sr_err = LDAP_OTHER;
|
||||
rs->sr_text = "SQL-backend error";
|
||||
|
|
@ -1416,7 +1416,7 @@ backsql_add( Operation *op, SlapReply *rs )
|
|||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, " backsql_add(): executing \"%s\" for dn \"%s\"\n",
|
||||
bi->sql_insentry_query, op->oq_add.rs_e->e_name.bv_val, 0 );
|
||||
bi->sql_insentry_stmt, op->oq_add.rs_e->e_name.bv_val, 0 );
|
||||
#ifdef BACKSQL_ARBITRARY_KEY
|
||||
Debug( LDAP_DEBUG_TRACE, " for oc_map_id=%ld, "
|
||||
"parent_id=%s, keyval=%ld\n",
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
static backsql_api *backsqlapi;
|
||||
|
||||
int
|
||||
backsql_api_config( backsql_info *bi, const char *name )
|
||||
backsql_api_config( backsql_info *bi, const char *name, int argc, char *argv[] )
|
||||
{
|
||||
backsql_api *ba;
|
||||
|
||||
|
|
@ -44,6 +44,14 @@ backsql_api_config( backsql_info *bi, const char *name )
|
|||
|
||||
ba2 = ch_malloc( sizeof( backsql_api ) );
|
||||
*ba2 = *ba;
|
||||
|
||||
if ( ba2->ba_config ) {
|
||||
if ( ( *ba2->ba_config )( ba2, argc, argv ) ) {
|
||||
ch_free( ba2 );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
ba2->ba_next = bi->sql_api;
|
||||
bi->sql_api = ba2;
|
||||
return 0;
|
||||
|
|
@ -53,12 +61,35 @@ backsql_api_config( backsql_info *bi, const char *name )
|
|||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
backsql_api_destroy( backsql_info *bi )
|
||||
{
|
||||
backsql_api *ba;
|
||||
|
||||
assert( bi );
|
||||
|
||||
ba = bi->sql_api;
|
||||
|
||||
if ( ba == NULL ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for ( ; ba; ba = ba->ba_next ) {
|
||||
if ( ba->ba_destroy ) {
|
||||
(void)( *ba->ba_destroy )( ba );
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
backsql_api_register( backsql_api *ba )
|
||||
{
|
||||
backsql_api *ba2;
|
||||
|
||||
assert( ba );
|
||||
assert( ba->ba_private == NULL );
|
||||
|
||||
if ( ba->ba_name == NULL ) {
|
||||
fprintf( stderr, "API module has no name\n" );
|
||||
|
|
|
|||
|
|
@ -238,9 +238,14 @@ typedef struct {
|
|||
*/
|
||||
typedef struct backsql_api {
|
||||
char *ba_name;
|
||||
int (*ba_config)( struct backsql_api *self, int argc, char *argv[] );
|
||||
int (*ba_destroy)( struct backsql_api *self );
|
||||
|
||||
int (*ba_dn2odbc)( Operation *op, SlapReply *rs, struct berval *dn );
|
||||
int (*ba_odbc2dn)( Operation *op, SlapReply *rs, struct berval *dn );
|
||||
struct backsql_api *ba_next;
|
||||
|
||||
void *ba_private;
|
||||
struct backsql_api *ba_next;
|
||||
} backsql_api;
|
||||
|
||||
/*
|
||||
|
|
@ -437,10 +442,10 @@ typedef struct {
|
|||
struct berval sql_children_cond;
|
||||
char *sql_oc_query,
|
||||
*sql_at_query;
|
||||
char *sql_insentry_query,
|
||||
*sql_delentry_query,
|
||||
*sql_delobjclasses_query,
|
||||
*sql_delreferrals_query;
|
||||
char *sql_insentry_stmt,
|
||||
*sql_delentry_stmt,
|
||||
*sql_delobjclasses_stmt,
|
||||
*sql_delreferrals_stmt;
|
||||
char *sql_id_query;
|
||||
char *sql_has_children_query;
|
||||
|
||||
|
|
|
|||
|
|
@ -100,26 +100,15 @@ backsql_bind( Operation *op, SlapReply *rs )
|
|||
}
|
||||
e = &user_entry;
|
||||
|
||||
if ( ! access_allowed( op, e, password, NULL, ACL_AUTH, NULL ) ) {
|
||||
#if 1
|
||||
rs->sr_err = LDAP_INVALID_CREDENTIALS;
|
||||
#else
|
||||
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
||||
#endif
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
a = attr_find( e->e_attrs, password );
|
||||
if ( a == NULL ) {
|
||||
#if 1
|
||||
rs->sr_err = LDAP_INVALID_CREDENTIALS;
|
||||
#else
|
||||
rs->sr_err = LDAP_INAPPROPRIATE_AUTH;
|
||||
#endif
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
if ( slap_passwd_check( op->o_conn, a, &op->oq_bind.rb_cred, &rs->sr_text ) != 0 ) {
|
||||
if ( slap_passwd_check( op, e, a, &op->oq_bind.rb_cred,
|
||||
&rs->sr_text ) != 0 )
|
||||
{
|
||||
rs->sr_err = LDAP_INVALID_CREDENTIALS;
|
||||
goto error_return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -176,18 +176,20 @@ backsql_db_config(
|
|||
Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
|
||||
"at_query=%s\n", bi->sql_at_query, 0, 0 );
|
||||
|
||||
} else if ( !strcasecmp( argv[ 0 ], "insentry_query" ) ) {
|
||||
} else if ( !strcasecmp( argv[ 0 ], "insentry_stmt" ) ||
|
||||
!strcasecmp( argv[ 0 ], "insentry_query" ) )
|
||||
{
|
||||
if ( argc < 2 ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<==backsql_db_config (%s line %d): "
|
||||
"missing SQL statement "
|
||||
"in \"insentry_query\" directive\n",
|
||||
"in \"insentry_stmt\" directive\n",
|
||||
fname, lineno, 0 );
|
||||
return 1;
|
||||
}
|
||||
bi->sql_insentry_query = ch_strdup( argv[ 1 ] );
|
||||
bi->sql_insentry_stmt = ch_strdup( argv[ 1 ] );
|
||||
Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
|
||||
"insentry_query=%s\n", bi->sql_insentry_query, 0, 0 );
|
||||
"insentry_stmt=%s\n", bi->sql_insentry_stmt, 0, 0 );
|
||||
|
||||
} else if ( !strcasecmp( argv[ 0 ], "create_needs_select" ) ) {
|
||||
if ( argc < 2 ) {
|
||||
|
|
@ -274,44 +276,50 @@ backsql_db_config(
|
|||
Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
|
||||
"strcast_func=%s\n", bi->sql_strcast_func.bv_val, 0, 0 );
|
||||
|
||||
} else if ( !strcasecmp( argv[ 0 ], "delentry_query" ) ) {
|
||||
} else if ( !strcasecmp( argv[ 0 ], "delentry_stmt" ) ||
|
||||
!strcasecmp( argv[ 0 ], "delentry_query" ) )
|
||||
{
|
||||
if ( argc < 2 ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<==backsql_db_config (%s line %d): "
|
||||
"missing SQL statement "
|
||||
"in \"delentry_query\" directive\n",
|
||||
"in \"delentry_stmt\" directive\n",
|
||||
fname, lineno, 0 );
|
||||
return 1;
|
||||
}
|
||||
bi->sql_delentry_query = ch_strdup( argv[ 1 ] );
|
||||
bi->sql_delentry_stmt = ch_strdup( argv[ 1 ] );
|
||||
Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
|
||||
"delentry_query=%s\n", bi->sql_delentry_query, 0, 0 );
|
||||
"delentry_stmt=%s\n", bi->sql_delentry_stmt, 0, 0 );
|
||||
|
||||
} else if ( !strcasecmp( argv[ 0 ], "delobjclasses_query" ) ) {
|
||||
} else if ( !strcasecmp( argv[ 0 ], "delobjclasses_stmt" ) ||
|
||||
!strcasecmp( argv[ 0 ], "delobjclasses_query" ) )
|
||||
{
|
||||
if ( argc < 2 ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<==backsql_db_config (%s line %d): "
|
||||
"missing SQL statement "
|
||||
"in \"delobjclasses_query\" directive\n",
|
||||
"in \"delobjclasses_stmt\" directive\n",
|
||||
fname, lineno, 0 );
|
||||
return 1;
|
||||
}
|
||||
bi->sql_delobjclasses_query = ch_strdup( argv[ 1 ] );
|
||||
bi->sql_delobjclasses_stmt = ch_strdup( argv[ 1 ] );
|
||||
Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
|
||||
"delobjclasses_query=%s\n", bi->sql_delobjclasses_query, 0, 0 );
|
||||
"delobjclasses_stmt=%s\n", bi->sql_delobjclasses_stmt, 0, 0 );
|
||||
|
||||
} else if ( !strcasecmp( argv[ 0 ], "delreferrals_query" ) ) {
|
||||
} else if ( !strcasecmp( argv[ 0 ], "delreferrals_stmt" ) ||
|
||||
!strcasecmp( argv[ 0 ], "delreferrals_query" ) )
|
||||
{
|
||||
if ( argc < 2 ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<==backsql_db_config (%s line %d): "
|
||||
"missing SQL statement "
|
||||
"in \"delreferrals_query\" directive\n",
|
||||
"in \"delreferrals_stmt\" directive\n",
|
||||
fname, lineno, 0 );
|
||||
return 1;
|
||||
}
|
||||
bi->sql_delreferrals_query = ch_strdup( argv[ 1 ] );
|
||||
bi->sql_delreferrals_stmt = ch_strdup( argv[ 1 ] );
|
||||
Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
|
||||
"delreferrals_query=%s\n", bi->sql_delreferrals_query, 0, 0 );
|
||||
"delreferrals_stmt=%s\n", bi->sql_delreferrals_stmt, 0, 0 );
|
||||
|
||||
} else if ( !strcasecmp( argv[ 0 ], "has_ldapinfo_dn_ru") ) {
|
||||
if ( argc < 2 ) {
|
||||
|
|
@ -436,7 +444,8 @@ backsql_db_config(
|
|||
}
|
||||
|
||||
} else if ( !strcasecmp( argv[ 0 ], "sqllayer") ) {
|
||||
if ( backsql_api_config( bi, argv[ 1 ] ) ) {
|
||||
if ( backsql_api_config( bi, argv[ 1 ], argc - 2, &argv[ 2 ] ) )
|
||||
{
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<==backsql_db_config (%s line %d): "
|
||||
"unable to load sqllayer \"%s\"\n",
|
||||
|
|
|
|||
|
|
@ -246,7 +246,7 @@ backsql_delete( Operation *op, SlapReply *rs )
|
|||
SQLFreeStmt( sth, SQL_DROP );
|
||||
|
||||
/* delete "auxiliary" objectClasses, if any... */
|
||||
rc = backsql_Prepare( dbh, &sth, bi->sql_delobjclasses_query, 0 );
|
||||
rc = backsql_Prepare( dbh, &sth, bi->sql_delobjclasses_stmt, 0 );
|
||||
if ( rc != SQL_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
" backsql_delete(): "
|
||||
|
|
@ -296,7 +296,7 @@ backsql_delete( Operation *op, SlapReply *rs )
|
|||
SQLFreeStmt( sth, SQL_DROP );
|
||||
|
||||
/* delete referrals, if any... */
|
||||
rc = backsql_Prepare( dbh, &sth, bi->sql_delreferrals_query, 0 );
|
||||
rc = backsql_Prepare( dbh, &sth, bi->sql_delreferrals_stmt, 0 );
|
||||
if ( rc != SQL_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
" backsql_delete(): "
|
||||
|
|
@ -346,7 +346,7 @@ backsql_delete( Operation *op, SlapReply *rs )
|
|||
SQLFreeStmt( sth, SQL_DROP );
|
||||
|
||||
/* delete entry... */
|
||||
rc = backsql_Prepare( dbh, &sth, bi->sql_delentry_query, 0 );
|
||||
rc = backsql_Prepare( dbh, &sth, bi->sql_delentry_stmt, 0 );
|
||||
if ( rc != SQL_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
" backsql_delete(): "
|
||||
|
|
|
|||
|
|
@ -135,10 +135,10 @@ backsql_db_destroy(
|
|||
free( bi->sql_subtree_cond.bv_val );
|
||||
free( bi->sql_oc_query );
|
||||
free( bi->sql_at_query );
|
||||
free( bi->sql_insentry_query );
|
||||
free( bi->sql_delentry_query );
|
||||
free( bi->sql_delobjclasses_query );
|
||||
free( bi->sql_delreferrals_query );
|
||||
free( bi->sql_insentry_stmt );
|
||||
free( bi->sql_delentry_stmt );
|
||||
free( bi->sql_delobjclasses_stmt );
|
||||
free( bi->sql_delreferrals_stmt );
|
||||
|
||||
if ( bi->sql_baseObject ) {
|
||||
entry_free( bi->sql_baseObject );
|
||||
|
|
@ -343,48 +343,48 @@ backsql_db_open(
|
|||
bi->sql_at_query = ch_strdup( backsql_def_at_query );
|
||||
}
|
||||
|
||||
if ( bi->sql_insentry_query == NULL ) {
|
||||
if ( bi->sql_insentry_stmt == NULL ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
|
||||
"entry insertion SQL statement not specified "
|
||||
"(use \"insentry_query\" directive in slapd.conf)\n",
|
||||
"(use \"insentry_stmt\" directive in slapd.conf)\n",
|
||||
0, 0, 0 );
|
||||
Debug(LDAP_DEBUG_TRACE, "backsql_db_open(): "
|
||||
"setting \"%s\" by default\n",
|
||||
backsql_def_insentry_query, 0, 0 );
|
||||
bi->sql_insentry_query = ch_strdup( backsql_def_insentry_query );
|
||||
backsql_def_insentry_stmt, 0, 0 );
|
||||
bi->sql_insentry_stmt = ch_strdup( backsql_def_insentry_stmt );
|
||||
}
|
||||
|
||||
if ( bi->sql_delentry_query == NULL ) {
|
||||
if ( bi->sql_delentry_stmt == NULL ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
|
||||
"entry deletion SQL statement not specified "
|
||||
"(use \"delentry_query\" directive in slapd.conf)\n",
|
||||
"(use \"delentry_stmt\" directive in slapd.conf)\n",
|
||||
0, 0, 0 );
|
||||
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
|
||||
"setting \"%s\" by default\n",
|
||||
backsql_def_delentry_query, 0, 0 );
|
||||
bi->sql_delentry_query = ch_strdup( backsql_def_delentry_query );
|
||||
backsql_def_delentry_stmt, 0, 0 );
|
||||
bi->sql_delentry_stmt = ch_strdup( backsql_def_delentry_stmt );
|
||||
}
|
||||
|
||||
if ( bi->sql_delobjclasses_query == NULL ) {
|
||||
if ( bi->sql_delobjclasses_stmt == NULL ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
|
||||
"objclasses deletion SQL statement not specified "
|
||||
"(use \"delobjclasses_query\" directive in slapd.conf)\n",
|
||||
"(use \"delobjclasses_stmt\" directive in slapd.conf)\n",
|
||||
0, 0, 0 );
|
||||
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
|
||||
"setting \"%s\" by default\n",
|
||||
backsql_def_delobjclasses_query, 0, 0 );
|
||||
bi->sql_delobjclasses_query = ch_strdup( backsql_def_delobjclasses_query );
|
||||
backsql_def_delobjclasses_stmt, 0, 0 );
|
||||
bi->sql_delobjclasses_stmt = ch_strdup( backsql_def_delobjclasses_stmt );
|
||||
}
|
||||
|
||||
if ( bi->sql_delreferrals_query == NULL ) {
|
||||
if ( bi->sql_delreferrals_stmt == NULL ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
|
||||
"referrals deletion SQL statement not specified "
|
||||
"(use \"delreferrals_query\" directive in slapd.conf)\n",
|
||||
"(use \"delreferrals_stmt\" directive in slapd.conf)\n",
|
||||
0, 0, 0 );
|
||||
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
|
||||
"setting \"%s\" by default\n",
|
||||
backsql_def_delreferrals_query, 0, 0 );
|
||||
bi->sql_delreferrals_query = ch_strdup( backsql_def_delreferrals_query );
|
||||
backsql_def_delreferrals_stmt, 0, 0 );
|
||||
bi->sql_delreferrals_stmt = ch_strdup( backsql_def_delreferrals_stmt );
|
||||
}
|
||||
|
||||
op->o_hdr = (Opheader *)&op[ 1 ];
|
||||
|
|
|
|||
|
|
@ -232,13 +232,13 @@ backsql_modrdn( Operation *op, SlapReply *rs )
|
|||
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
|
||||
"executing delentry_query\n", 0, 0, 0 );
|
||||
"executing delentry_stmt\n", 0, 0, 0 );
|
||||
|
||||
rc = backsql_Prepare( dbh, &sth, bi->sql_delentry_query, 0 );
|
||||
rc = backsql_Prepare( dbh, &sth, bi->sql_delentry_stmt, 0 );
|
||||
if ( rc != SQL_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
" backsql_modrdn(): "
|
||||
"error preparing delentry_query\n", 0, 0, 0 );
|
||||
"error preparing delentry_stmt\n", 0, 0, 0 );
|
||||
backsql_PrintErrors( bi->sql_db_env, dbh,
|
||||
sth, rc );
|
||||
|
||||
|
|
@ -279,13 +279,13 @@ backsql_modrdn( Operation *op, SlapReply *rs )
|
|||
SQLFreeStmt( sth, SQL_DROP );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
|
||||
"executing insentry_query\n", 0, 0, 0 );
|
||||
"executing insentry_stmt\n", 0, 0, 0 );
|
||||
|
||||
rc = backsql_Prepare( dbh, &sth, bi->sql_insentry_query, 0 );
|
||||
rc = backsql_Prepare( dbh, &sth, bi->sql_insentry_stmt, 0 );
|
||||
if ( rc != SQL_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
" backsql_modrdn(): "
|
||||
"error preparing insentry_query\n", 0, 0, 0 );
|
||||
"error preparing insentry_stmt\n", 0, 0, 0 );
|
||||
backsql_PrintErrors( bi->sql_db_env, dbh,
|
||||
sth, rc );
|
||||
|
||||
|
|
|
|||
|
|
@ -96,7 +96,9 @@ int backsql_modify_internal(
|
|||
/*
|
||||
* api.c
|
||||
*/
|
||||
int backsql_api_config( backsql_info *si, const char *name );
|
||||
int backsql_api_config( backsql_info *bi, const char *name,
|
||||
int argc, char *argv[] );
|
||||
int backsql_api_destroy( backsql_info *bi );
|
||||
int backsql_api_register( backsql_api *ba );
|
||||
int backsql_api_dn2odbc( Operation *op, SlapReply *rs, struct berval *dn );
|
||||
int backsql_api_odbc2dn( Operation *op, SlapReply *rs, struct berval *dn );
|
||||
|
|
@ -221,10 +223,10 @@ extern char
|
|||
backsql_def_oc_query[],
|
||||
backsql_def_needs_select_oc_query[],
|
||||
backsql_def_at_query[],
|
||||
backsql_def_delentry_query[],
|
||||
backsql_def_insentry_query[],
|
||||
backsql_def_delobjclasses_query[],
|
||||
backsql_def_delreferrals_query[],
|
||||
backsql_def_delentry_stmt[],
|
||||
backsql_def_insentry_stmt[],
|
||||
backsql_def_delobjclasses_stmt[],
|
||||
backsql_def_delreferrals_stmt[],
|
||||
backsql_def_subtree_cond[],
|
||||
backsql_def_upper_subtree_cond[],
|
||||
backsql_id_query[],
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ dbname ldap_db2
|
|||
dbuser db2inst1
|
||||
dbpasswd ibmdb2
|
||||
subtree_cond "upper(ldap_entries.dn) LIKE CONCAT('%',?)"
|
||||
insentry_query "insert into ldap_entries (id,dn,oc_map_id,parent,keyval) values ((select max(id)+1 from ldap_entries),?,?,?,?)"
|
||||
insentry_stmt "insert into ldap_entries (id,dn,oc_map_id,parent,keyval) values ((select max(id)+1 from ldap_entries),?,?,?,?)"
|
||||
upper_func "upper"
|
||||
upper_needs_cast "yes"
|
||||
create_needs_select "yes"
|
||||
|
|
|
|||
|
|
@ -28,5 +28,5 @@ dbname ldap_mysql
|
|||
dbuser root
|
||||
dbpasswd
|
||||
subtree_cond "ldap_entries.dn LIKE CONCAT('%',?)"
|
||||
insentry_query "INSERT INTO ldap_entries (dn,oc_map_id,parent,keyval) VALUES (?,?,?,?)"
|
||||
insentry_stmt "INSERT INTO ldap_entries (dn,oc_map_id,parent,keyval) VALUES (?,?,?,?)"
|
||||
has_ldapinfo_dn_ru no
|
||||
|
|
|
|||
|
|
@ -28,5 +28,5 @@ dbname ldap_ora8
|
|||
dbuser ldap
|
||||
dbpasswd ldap
|
||||
subtree_cond "UPPER(ldap_entries.dn) LIKE CONCAT('%',UPPER(?))"
|
||||
insentry_query "INSERT INTO ldap_entries (id,dn,oc_map_id,parent,keyval) VALUES (ldap_entry_ids.nextval,?,?,?,?)"
|
||||
insentry_stmt "INSERT INTO ldap_entries (id,dn,oc_map_id,parent,keyval) VALUES (ldap_entry_ids.nextval,?,?,?,?)"
|
||||
upper_func UPPER
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ rootpw secret
|
|||
dbname PostgreSQL
|
||||
dbuser postgres
|
||||
dbpasswd postgres
|
||||
insentry_query "insert into ldap_entries (id,dn,oc_map_id,parent,keyval) values ((select max(id)+1 from ldap_entries),?,?,?,?)"
|
||||
insentry_stmt "insert into ldap_entries (id,dn,oc_map_id,parent,keyval) values ((select max(id)+1 from ldap_entries),?,?,?,?)"
|
||||
upper_func "upper"
|
||||
strcast_func "text"
|
||||
concat_pattern "?||?"
|
||||
|
|
|
|||
|
|
@ -28,4 +28,4 @@ dbname ldap_tt
|
|||
dbuser root
|
||||
dbpasswd
|
||||
subtree_cond "ldap_entries.dn LIKE ?"
|
||||
insentry_query "INSERT INTO ldap_entries (dn,oc_map_id,parent,keyval) VALUES (?,?,?,?)"
|
||||
insentry_stmt "INSERT INTO ldap_entries (dn,oc_map_id,parent,keyval) VALUES (?,?,?,?)"
|
||||
|
|
|
|||
|
|
@ -958,6 +958,10 @@ equality_match:;
|
|||
casefold = 1;
|
||||
}
|
||||
|
||||
/* FIXME: directoryString filtering should use a similar
|
||||
* approach to deal with non-prettified values like
|
||||
* " A non prettified value ", by using a LIKE
|
||||
* filter with all whitespaces collapsed to a single '%' */
|
||||
if ( SLAP_MR_ASSOCIATED( matching_rule,
|
||||
bi->sql_telephoneNumberMatch ) )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -47,13 +47,13 @@ char backsql_def_at_query[] =
|
|||
"SELECT name,sel_expr,from_tbls,join_where,add_proc,delete_proc,"
|
||||
"param_order,expect_return,sel_expr_u FROM ldap_attr_mappings "
|
||||
"WHERE oc_map_id=?";
|
||||
char backsql_def_delentry_query[] = "DELETE FROM ldap_entries WHERE id=?";
|
||||
char backsql_def_insentry_query[] =
|
||||
char backsql_def_delentry_stmt[] = "DELETE FROM ldap_entries WHERE id=?";
|
||||
char backsql_def_insentry_stmt[] =
|
||||
"INSERT INTO ldap_entries (dn,oc_map_id,parent,keyval) "
|
||||
"VALUES (?,?,?,?)";
|
||||
char backsql_def_delobjclasses_query[] = "DELETE FROM ldap_entry_objclasses "
|
||||
char backsql_def_delobjclasses_stmt[] = "DELETE FROM ldap_entry_objclasses "
|
||||
"WHERE entry_id=?";
|
||||
char backsql_def_delreferrals_query[] = "DELETE FROM ldap_referrals "
|
||||
char backsql_def_delreferrals_stmt[] = "DELETE FROM ldap_referrals "
|
||||
"WHERE entry_id=?";
|
||||
char backsql_def_subtree_cond[] = "ldap_entries.dn LIKE CONCAT('%',?)";
|
||||
char backsql_def_upper_subtree_cond[] = "(ldap_entries.dn) LIKE CONCAT('%',?)";
|
||||
|
|
|
|||
Loading…
Reference in a new issue