mirror of
https://github.com/samba-team/samba.git
synced 2025-09-16 01:44:21 +03:00
committed by
Gerald (Jerry) Carter
parent
22ae788666
commit
f08fafc492
@@ -1,7 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
ldb database library
|
ldb database library
|
||||||
|
|
||||||
Copyright (C) Andrew Tridgell 2004
|
|
||||||
Copyright (C) Derrell Lipman 2005
|
Copyright (C) Derrell Lipman 2005
|
||||||
|
|
||||||
** NOTE! The following LGPL license applies to the ldb
|
** NOTE! The following LGPL license applies to the ldb
|
||||||
@@ -37,6 +36,7 @@
|
|||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
#include "ldb/include/ldb.h"
|
#include "ldb/include/ldb.h"
|
||||||
#include "ldb/include/ldb_private.h"
|
#include "ldb/include/ldb_private.h"
|
||||||
|
#include "ldb/include/ldb_parse.h"
|
||||||
#include "ldb/ldb_sqlite3/ldb_sqlite3.h"
|
#include "ldb/ldb_sqlite3/ldb_sqlite3.h"
|
||||||
|
|
||||||
#ifndef FALSE
|
#ifndef FALSE
|
||||||
@@ -294,124 +294,314 @@ lsqlite3_add_msg_attr(struct ldb_context *ldb,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static char *
|
||||||
|
lsqlite3_parsetree_to_sql(struct ldb_module *module,
|
||||||
|
char * hTalloc,
|
||||||
|
const struct ldb_parse_tree *t)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char * child;
|
||||||
|
char * p;
|
||||||
|
char * ret = NULL;
|
||||||
|
char * pAttrName;
|
||||||
|
|
||||||
|
|
||||||
|
switch(t->operation) {
|
||||||
|
case LDB_OP_SIMPLE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LDB_OP_AND:
|
||||||
|
ret = lsqlite3_parsetree_to_sql(module,
|
||||||
|
hTalloc,
|
||||||
|
t->u.list.elements[0]);
|
||||||
|
|
||||||
|
for (i = 1; i < t->u.list.num_elements; i++) {
|
||||||
|
child =
|
||||||
|
lsqlite3_parsetree_to_sql(
|
||||||
|
module,
|
||||||
|
hTalloc,
|
||||||
|
t->u.list.elements[i]);
|
||||||
|
ret = talloc_asprintf_append(ret,
|
||||||
|
"INTERSECT\n"
|
||||||
|
"%s\n",
|
||||||
|
child);
|
||||||
|
talloc_free(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
child = ret;
|
||||||
|
ret = talloc_asprintf("(\n"
|
||||||
|
"%s\n"
|
||||||
|
")\n",
|
||||||
|
child);
|
||||||
|
talloc_free(child);
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
case LDB_OP_OR:
|
||||||
|
child =
|
||||||
|
lsqlite3_parsetree_to_sql(
|
||||||
|
module,
|
||||||
|
hTalloc,
|
||||||
|
t->u.list.elements[0]);
|
||||||
|
|
||||||
|
for (i = 1; i < t->u.list.num_elements; i++) {
|
||||||
|
child =
|
||||||
|
lsqlite3_parsetree_to_sql(
|
||||||
|
module,
|
||||||
|
hTalloc,
|
||||||
|
t->u.list.elements[i]);
|
||||||
|
ret = talloc_asprintf_append(ret,
|
||||||
|
"UNION\n"
|
||||||
|
"%s\n",
|
||||||
|
child);
|
||||||
|
talloc_free(child);
|
||||||
|
}
|
||||||
|
child = ret;
|
||||||
|
ret = talloc_asprintf("(\n"
|
||||||
|
"%s\n"
|
||||||
|
")\n",
|
||||||
|
child);
|
||||||
|
talloc_free(child);
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
case LDB_OP_NOT:
|
||||||
|
child =
|
||||||
|
lsqlite3_parsetree_to_sql(
|
||||||
|
module,
|
||||||
|
hTalloc,
|
||||||
|
t->u.not.child);
|
||||||
|
ret = talloc_asprintf(hTalloc,
|
||||||
|
"(\n"
|
||||||
|
" SELECT eid\n"
|
||||||
|
" FROM ldb_entry\n"
|
||||||
|
" WHERE eid NOT IN %s\n"
|
||||||
|
")\n",
|
||||||
|
child);
|
||||||
|
talloc_free(child);
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* should never occur */
|
||||||
|
abort();
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Get a case-folded copy of the attribute name */
|
||||||
|
pAttrName = ldb_casefold((struct ldb_context *) module,
|
||||||
|
t->u.simple.attr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For simple searches, we want to retrieve the list of EIDs that
|
||||||
|
* match the criteria. We accomplish this by searching the
|
||||||
|
* appropriate table, ldb_attr_<attributeName>, for the eid
|
||||||
|
* corresponding to all matching values.
|
||||||
|
*/
|
||||||
|
if (t->u.simple.value.length == 1 &&
|
||||||
|
(*(const char *) t->u.simple.value.data) == '*') {
|
||||||
|
/*
|
||||||
|
* Special case for "attr_name=*". In this case, we want the
|
||||||
|
* eid corresponding to all values in the specified attribute
|
||||||
|
* table.
|
||||||
|
*/
|
||||||
|
if ((p = sqlite3_mprintf("(\n"
|
||||||
|
" SELECT eid\n"
|
||||||
|
" FROM ldb_attr_%q\n"
|
||||||
|
")\n",
|
||||||
|
pAttrName)) == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = talloc_strdup(hTalloc, p);
|
||||||
|
sqlite3_free(p);
|
||||||
|
|
||||||
|
} else if (strcasecmp(t->u.simple.attr, "objectclass") == 0) {
|
||||||
|
/*
|
||||||
|
* For object classes, we want to search for all objectclasses
|
||||||
|
* that are subclasses as well.
|
||||||
|
*/
|
||||||
|
if ((p = sqlite3_mprintf(
|
||||||
|
"(\n"
|
||||||
|
" SELECT eid\n"
|
||||||
|
" FROM ldb_attr_objectclass\n"
|
||||||
|
" WHERE attr_name IN\n"
|
||||||
|
" (SELECT class_name\n"
|
||||||
|
" FROM ldb_objectclasses\n"
|
||||||
|
" WHERE tree_key GLOB\n"
|
||||||
|
" (SELECT tree_key\n"
|
||||||
|
" FROM ldb_objectclasses\n"
|
||||||
|
" WHERE class_name = %Q) || '*')\n"
|
||||||
|
")\n",
|
||||||
|
t->u.simple.value.data)) == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = talloc_strdup(hTalloc, p);
|
||||||
|
sqlite3_free(p);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* A normal query. */
|
||||||
|
if ((p = sqlite3_mprintf("(\n"
|
||||||
|
" SELECT eid\n"
|
||||||
|
" FROM ldb_attr_%q\n"
|
||||||
|
" WHERE attr_value = %Q\n"
|
||||||
|
")\n",
|
||||||
|
pAttrName,
|
||||||
|
t->u.simple.value.data)) == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = talloc_strdup(hTalloc, p);
|
||||||
|
sqlite3_free(p);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char *
|
||||||
|
lsqlite3_parsetree_to_tablelist(struct ldb_module *module,
|
||||||
|
char * hTalloc,
|
||||||
|
const struct ldb_parse_tree *t)
|
||||||
|
{
|
||||||
|
#warning "obtain talloc'ed array of attribute names for table list"
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* search for matching records
|
* search for matching records
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
lsqlite3_search(struct ldb_module *module,
|
lsqlite3_search(struct ldb_module * module,
|
||||||
const char *base,
|
const char * pBaseDN,
|
||||||
enum ldb_scope scope,
|
enum ldb_scope scope,
|
||||||
const char *expression,
|
const char * pExpression,
|
||||||
const char * const attrs[],
|
const char * const attrs[],
|
||||||
struct ldb_message ***res)
|
struct ldb_message *** res)
|
||||||
{
|
{
|
||||||
#warning "lsqlite3_search() not yet implemented"
|
int ret;
|
||||||
#if 0
|
int bLoop;
|
||||||
int count;
|
long long eid;
|
||||||
int msg_count;
|
char * sql;
|
||||||
struct ldb_context * ldb = module->ldb;
|
char * sql_constraints;
|
||||||
struct lsqlite3_private * lsqlite3 = module->private_data;
|
char * table_list;
|
||||||
|
char * hTalloc;
|
||||||
if (base == NULL) {
|
const char * pTail;
|
||||||
base = "";
|
sqlite3_stmt * pStmt;
|
||||||
|
struct ldb_parse_tree * pTree;
|
||||||
|
struct lsqlite3_private * lsqlite3 = module->private_data;
|
||||||
|
|
||||||
|
if (pBaseDN == NULL) {
|
||||||
|
pBaseDN = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
lsqlite3->last_rc = ldap_search_s(lsqlite3->ldap, base, (int)scope,
|
/*
|
||||||
expression,
|
* Obtain the eid of the base DN
|
||||||
discard_const_p(char *, attrs),
|
*/
|
||||||
0, &ldapres);
|
if ((pTail = sqlite3_mprintf("SELECT eid "
|
||||||
if (lsqlite3->last_rc != LDAP_SUCCESS) {
|
" FROM ldb_attr_dn "
|
||||||
|
" WHERE attr_value = %Q;",
|
||||||
|
pBaseDN)) == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (bLoop = TRUE; bLoop; ) {
|
||||||
|
|
||||||
|
/* Compile the SQL statement into sqlite virtual machine */
|
||||||
|
if ((ret = sqlite3_prepare(lsqlite3->sqlite,
|
||||||
|
pTail,
|
||||||
|
-1,
|
||||||
|
&pStmt,
|
||||||
|
&pTail)) != SQLITE_OK) {
|
||||||
|
ret = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* One row expected */
|
||||||
|
if ((ret = sqlite3_step(pStmt)) == SQLITE_SCHEMA) {
|
||||||
|
(void) sqlite3_finalize(pStmt);
|
||||||
|
continue;
|
||||||
|
} else if (ret != SQLITE_ROW) {
|
||||||
|
(void) sqlite3_finalize(pStmt);
|
||||||
|
ret = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Retrieve the EID */
|
||||||
|
eid = sqlite3_column_int64(pStmt, 0);
|
||||||
|
|
||||||
|
/* Free the virtual machine */
|
||||||
|
if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) {
|
||||||
|
(void) sqlite3_finalize(pStmt);
|
||||||
|
continue;
|
||||||
|
} else if (ret != SQLITE_OK) {
|
||||||
|
(void) sqlite3_finalize(pStmt);
|
||||||
|
ret = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Normal condition is only one time through loop. Loop is
|
||||||
|
* rerun in error conditions, via "continue", above.
|
||||||
|
*/
|
||||||
|
ret = 0;
|
||||||
|
bLoop = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse the filter expression into a tree we can work with */
|
||||||
|
if ((pTree = ldb_parse_tree(module->ldb, pExpression)) == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Allocate a temporary talloc context */
|
||||||
|
hTalloc = talloc_new(module);
|
||||||
|
|
||||||
count = ldap_count_entries(lsqlite3->ldap, ldapres);
|
/* Move the parse tree to our temporary context */
|
||||||
if (count == -1 || count == 0) {
|
talloc_steal(hTalloc, pTree);
|
||||||
ldap_msgfree(ldapres);
|
|
||||||
return count;
|
/* Convert filter into a series of SQL statements (constraints) */
|
||||||
}
|
sql_constraints = lsqlite3_parsetree_to_sql(module, hTalloc, pTree);
|
||||||
|
|
||||||
|
/* Get the list of attribute names to use as our extra table list */
|
||||||
|
table_list = lsqlite3_parsetree_to_tablelist(module, hTalloc, pTree);
|
||||||
|
|
||||||
(*res) = talloc_array(lsqlite3, struct ldb_message *, count+1);
|
switch(scope) {
|
||||||
if (! *res) {
|
case LDB_SCOPE_DEFAULT:
|
||||||
ldap_msgfree(ldapres);
|
case LDB_SCOPE_SUBTREE:
|
||||||
errno = ENOMEM;
|
sql = sqlite3_mprintf(
|
||||||
return -1;
|
"SELECT entry.entry_data\n"
|
||||||
}
|
" FROM ldb_entry AS entry\n"
|
||||||
|
" WHERE entry.eid IN\n"
|
||||||
|
" (SELECT ldb_entry.eid\n"
|
||||||
|
" FROM ldb_entry,\n"
|
||||||
|
" ldb_descendants,\n"
|
||||||
|
" %q\n"
|
||||||
|
" WHERE ldb_descendants.aeid = %lld\n"
|
||||||
|
" AND ldb_entry.eid = ldb_descendants.deid\n"
|
||||||
|
" AND ldap_entry.eid IN\n"
|
||||||
|
"%s);",
|
||||||
|
table_list,
|
||||||
|
sql_constraints);
|
||||||
|
break;
|
||||||
|
|
||||||
(*res)[0] = NULL;
|
#warning "scope BASE and ONLEVEL not yet implemented"
|
||||||
|
case LDB_SCOPE_BASE:
|
||||||
|
break;
|
||||||
|
|
||||||
msg_count = 0;
|
case LDB_SCOPE_ONELEVEL:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* loop over all messages */
|
return ret;
|
||||||
for (msg=ldap_first_entry(lsqlite3->ldap, ldapres);
|
|
||||||
msg;
|
|
||||||
msg=ldap_next_entry(lsqlite3->ldap, msg)) {
|
|
||||||
BerElement *berptr = NULL;
|
|
||||||
char *attr, *dn;
|
|
||||||
|
|
||||||
if (msg_count == count) {
|
|
||||||
/* hmm, got too many? */
|
|
||||||
ldb_debug(ldb, LDB_DEBUG_FATAL, "Fatal: ldap message count inconsistent\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
(*res)[msg_count] = talloc(*res, struct ldb_message);
|
|
||||||
if (!(*res)[msg_count]) {
|
|
||||||
goto failed;
|
|
||||||
}
|
|
||||||
(*res)[msg_count+1] = NULL;
|
|
||||||
|
|
||||||
dn = ldap_get_dn(lsqlite3->ldap, msg);
|
|
||||||
if (!dn) {
|
|
||||||
goto failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
(*res)[msg_count]->dn = talloc_strdup((*res)[msg_count], dn);
|
|
||||||
ldap_memfree(dn);
|
|
||||||
if (!(*res)[msg_count]->dn) {
|
|
||||||
goto failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
(*res)[msg_count]->num_elements = 0;
|
|
||||||
(*res)[msg_count]->elements = NULL;
|
|
||||||
(*res)[msg_count]->private_data = NULL;
|
|
||||||
|
|
||||||
/* loop over all attributes */
|
|
||||||
for (attr=ldap_first_attribute(lsqlite3->ldap, msg, &berptr);
|
|
||||||
attr;
|
|
||||||
attr=ldap_next_attribute(lsqlite3->ldap, msg, berptr)) {
|
|
||||||
struct berval **bval;
|
|
||||||
bval = ldap_get_values_len(lsqlite3->ldap, msg, attr);
|
|
||||||
|
|
||||||
if (bval) {
|
|
||||||
lsqlite3_add_msg_attr(ldb, (*res)[msg_count], attr, bval);
|
|
||||||
ldap_value_free_len(bval);
|
|
||||||
}
|
|
||||||
|
|
||||||
ldap_memfree(attr);
|
|
||||||
}
|
|
||||||
if (berptr) ber_free(berptr, 0);
|
|
||||||
|
|
||||||
msg_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
ldap_msgfree(ldapres);
|
|
||||||
|
|
||||||
return msg_count;
|
|
||||||
|
|
||||||
failed:
|
|
||||||
if (*res) lsqlite3_search_free(module, *res);
|
|
||||||
return -1;
|
|
||||||
#else
|
|
||||||
return -1;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
lsqlite3_new_attr(struct lsqlite3_private * lsqlite3,
|
lsqlite3_new_attr(struct ldb_module * module,
|
||||||
char * pAttrName)
|
char * pAttrName)
|
||||||
{
|
{
|
||||||
|
struct lsqlite3_private * lsqlite3 = module->private_data;
|
||||||
|
|
||||||
|
/* Get a case-folded copy of the attribute name */
|
||||||
|
pAttrName = ldb_casefold((struct ldb_context *) module, pAttrName);
|
||||||
|
|
||||||
QUERY_NOROWS(lsqlite3,
|
QUERY_NOROWS(lsqlite3,
|
||||||
FALSE,
|
FALSE,
|
||||||
"CREATE TABLE ldb_attr_%q "
|
"CREATE TABLE ldb_attr_%q "
|
||||||
@@ -429,12 +619,13 @@ lsqlite3_new_attr(struct lsqlite3_private * lsqlite3,
|
|||||||
* requests in the ldb_message
|
* requests in the ldb_message
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
lsqlite3_msg_to_sql(struct ldb_module *module,
|
lsqlite3_msg_to_sql(struct ldb_module * module,
|
||||||
const struct ldb_message *msg,
|
const struct ldb_message * msg,
|
||||||
long long eid,
|
long long eid,
|
||||||
int use_flags)
|
int use_flags)
|
||||||
{
|
{
|
||||||
int flags;
|
int flags;
|
||||||
|
char * pAttrName;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
unsigned int j;
|
unsigned int j;
|
||||||
struct lsqlite3_private * lsqlite3 = module->private_data;
|
struct lsqlite3_private * lsqlite3 = module->private_data;
|
||||||
@@ -450,7 +641,7 @@ lsqlite3_msg_to_sql(struct ldb_module *module,
|
|||||||
|
|
||||||
if (flags == LDB_FLAG_MOD_ADD) {
|
if (flags == LDB_FLAG_MOD_ADD) {
|
||||||
/* Create the attribute table if it doesn't exist */
|
/* Create the attribute table if it doesn't exist */
|
||||||
if (lsqlite3_new_attr(lsqlite3, el->name) != 0) {
|
if (lsqlite3_new_attr(module, el->name) != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -458,6 +649,10 @@ lsqlite3_msg_to_sql(struct ldb_module *module,
|
|||||||
/* For each value of the specified attribute name... */
|
/* For each value of the specified attribute name... */
|
||||||
for (j = 0; j < el->num_values; j++) {
|
for (j = 0; j < el->num_values; j++) {
|
||||||
|
|
||||||
|
/* Get a case-folded copy of the attribute name */
|
||||||
|
pAttrName = ldb_casefold((struct ldb_context *) module,
|
||||||
|
el->name);
|
||||||
|
|
||||||
/* ... bind the attribute value, if necessary */
|
/* ... bind the attribute value, if necessary */
|
||||||
switch (flags) {
|
switch (flags) {
|
||||||
case LDB_FLAG_MOD_ADD:
|
case LDB_FLAG_MOD_ADD:
|
||||||
@@ -467,6 +662,7 @@ lsqlite3_msg_to_sql(struct ldb_module *module,
|
|||||||
" (eid, attr_value) "
|
" (eid, attr_value) "
|
||||||
" VALUES "
|
" VALUES "
|
||||||
" (%lld, %Q);",
|
" (%lld, %Q);",
|
||||||
|
pAttrName,
|
||||||
eid, el->values[j].data);
|
eid, el->values[j].data);
|
||||||
QUERY_NOROWS(lsqlite3,
|
QUERY_NOROWS(lsqlite3,
|
||||||
FALSE,
|
FALSE,
|
||||||
@@ -486,6 +682,7 @@ lsqlite3_msg_to_sql(struct ldb_module *module,
|
|||||||
"UPDATE ldb_attr_%q "
|
"UPDATE ldb_attr_%q "
|
||||||
" SET attr_value = %Q "
|
" SET attr_value = %Q "
|
||||||
" WHERE eid = %lld;",
|
" WHERE eid = %lld;",
|
||||||
|
pAttrName,
|
||||||
el->values[j].data,
|
el->values[j].data,
|
||||||
eid);
|
eid);
|
||||||
QUERY_NOROWS(lsqlite3,
|
QUERY_NOROWS(lsqlite3,
|
||||||
@@ -506,6 +703,7 @@ lsqlite3_msg_to_sql(struct ldb_module *module,
|
|||||||
"DELETE FROM ldb_attr_%q "
|
"DELETE FROM ldb_attr_%q "
|
||||||
" WHERE eid = %lld "
|
" WHERE eid = %lld "
|
||||||
" AND attr_value = %Q;",
|
" AND attr_value = %Q;",
|
||||||
|
pAttrName,
|
||||||
eid,
|
eid,
|
||||||
el->values[j].data);
|
el->values[j].data);
|
||||||
QUERY_NOROWS(lsqlite3,
|
QUERY_NOROWS(lsqlite3,
|
||||||
@@ -903,16 +1101,11 @@ lsqlite3_initialize(struct lsqlite3_private *lsqlite3,
|
|||||||
;
|
;
|
||||||
|
|
||||||
/* Skip protocol indicator of url */
|
/* Skip protocol indicator of url */
|
||||||
if (strchr(url, ':')) {
|
if ((p = strchr(url, ':')) == NULL) {
|
||||||
if (strncmp(url, "sqlite://", 9) != 0) {
|
return SQLITE_MISUSE;
|
||||||
errno = EINVAL;
|
} else {
|
||||||
return SQLITE_MISUSE;
|
++p;
|
||||||
}
|
}
|
||||||
p = url + 9;
|
|
||||||
} else {
|
|
||||||
p = url;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* See if we'll be creating a new database, or opening an existing one
|
* See if we'll be creating a new database, or opening an existing one
|
||||||
|
Reference in New Issue
Block a user