1
0
mirror of https://github.com/samba-team/samba.git synced 2025-07-23 20:59:10 +03:00

r23560: - Activate metze's schema modules (from metze's schema-loading-13 patch).

- samba3sam.js: rework the samba3sam test to not use objectCategory,
  as it's has special rules (dnsName a simple match)
- ldap.js: Test the ordering of the objectClass attributes for the baseDN
- schema_init.c: Load the mayContain and mustContain (and system...) attributes when
  reading the schema from ldb
- To make the schema load not suck in terms of performance, write the
  schema into a static global variable
- ldif_handlers.c: Match objectCategory for equality and canonicolisation
  based on the loaded schema, not simple tring manipuation
- ldb_msg.c: don't duplicate attributes when adding attributes to a list
- kludge_acl.c: return allowedAttributesEffective based on schema results
  and privilages

Andrew Bartlett
(This used to be commit dcff83ebe4)
This commit is contained in:
Andrew Bartlett
2007-06-21 10:18:20 +00:00
committed by Gerald (Jerry) Carter
parent b3f3a4b529
commit e9d19477e4
13 changed files with 403 additions and 166 deletions

View File

@ -37,6 +37,7 @@
#include "ldb/include/ldb_private.h" #include "ldb/include/ldb_private.h"
#include "auth/auth.h" #include "auth/auth.h"
#include "libcli/security/security.h" #include "libcli/security/security.h"
#include "dsdb/samdb/samdb.h"
/* Kludge ACL rules: /* Kludge ACL rules:
* *
@ -105,13 +106,74 @@ struct kludge_acl_context {
int (*up_callback)(struct ldb_context *, void *, struct ldb_reply *); int (*up_callback)(struct ldb_context *, void *, struct ldb_reply *);
enum user_is user_type; enum user_is user_type;
bool allowedAttributes;
bool allowedAttributesEffective;
const char **attrs;
}; };
/* read all objectClasses */
static int kludge_acl_allowedAttributes(struct ldb_context *ldb, struct ldb_message *msg,
const char *attrName)
{
struct ldb_message_element *oc_el = ldb_msg_find_element(msg, "objectClass");
struct ldb_message_element *allowedAttributes;
const struct dsdb_schema *schema = dsdb_get_schema(ldb);
const struct dsdb_class *class;
int i, j, ret;
ret = ldb_msg_add_empty(msg, attrName, 0, &allowedAttributes);
if (ret != LDB_SUCCESS) {
return ret;
}
for (i=0; i < oc_el->num_values; i++) {
class = dsdb_class_by_lDAPDisplayName(schema, (const char *)oc_el->values[i].data);
if (!class) {
/* We don't know this class? what is going on? */
continue;
}
for (j=0; class->mayContain && class->mayContain[j]; j++) {
ldb_msg_add_string(msg, attrName, class->mayContain[j]);
}
for (j=0; class->mustContain && class->mustContain[j]; j++) {
ldb_msg_add_string(msg, attrName, class->mustContain[j]);
}
for (j=0; class->systemMayContain && class->systemMayContain[j]; j++) {
ldb_msg_add_string(msg, attrName, class->systemMayContain[j]);
}
for (j=0; class->systemMustContain && class->systemMustContain[j]; j++) {
ldb_msg_add_string(msg, attrName, class->systemMustContain[j]);
}
}
if (allowedAttributes->num_values > 1) {
qsort(allowedAttributes->values,
allowedAttributes->num_values,
sizeof(*allowedAttributes->values),
data_blob_cmp);
for (i=1 ; i < allowedAttributes->num_values; i++) {
struct ldb_val *val1 = &allowedAttributes->values[i-1];
struct ldb_val *val2 = &allowedAttributes->values[i];
if (data_blob_cmp(val1, val2) == 0) {
memmove(val1, val2, (allowedAttributes->num_values - i) * sizeof( struct ldb_val));
allowedAttributes->num_values--;
i--;
}
}
}
return 0;
}
/* find all attributes allowed by all these objectClasses */
static int kludge_acl_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares) static int kludge_acl_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
{ {
struct kludge_acl_context *ac; struct kludge_acl_context *ac;
struct kludge_private_data *data; struct kludge_private_data *data;
int i; int i, ret;
if (!context || !ares) { if (!context || !ares) {
ldb_set_errstring(ldb, "NULL Context or Result in callback"); ldb_set_errstring(ldb, "NULL Context or Result in callback");
@ -121,12 +183,28 @@ static int kludge_acl_callback(struct ldb_context *ldb, void *context, struct ld
ac = talloc_get_type(context, struct kludge_acl_context); ac = talloc_get_type(context, struct kludge_acl_context);
data = talloc_get_type(ac->module->private_data, struct kludge_private_data); data = talloc_get_type(ac->module->private_data, struct kludge_private_data);
if (ares->type == LDB_REPLY_ENTRY if (ares->type != LDB_REPLY_ENTRY) {
&& data && data->password_attrs) /* if we are not initialized just get through */ return ac->up_callback(ldb, ac->up_context, ares);
}
if (ac->allowedAttributes) {
ret = kludge_acl_allowedAttributes(ldb, ares->message, "allowedAttributes");
if (ret != LDB_SUCCESS) {
return ret;
}
}
if (data && data->password_attrs) /* if we are not initialized just get through */
{ {
switch (ac->user_type) { switch (ac->user_type) {
case SYSTEM: case SYSTEM:
case ADMINISTRATOR: case ADMINISTRATOR:
if (ac->allowedAttributesEffective) {
ret = kludge_acl_allowedAttributes(ldb, ares->message, "allowedAttributesEffective");
if (ret != LDB_SUCCESS) {
return ret;
}
}
break; break;
default: default:
/* remove password attributes */ /* remove password attributes */
@ -136,6 +214,12 @@ static int kludge_acl_callback(struct ldb_context *ldb, void *context, struct ld
} }
} }
if ((ac->allowedAttributes || ac->allowedAttributesEffective) &&
(!ldb_attr_in_list(ac->attrs, "objectClass") &&
!ldb_attr_in_list(ac->attrs, "*"))) {
ldb_msg_remove_attr(ares->message, "objectClass");
}
return ac->up_callback(ldb, ac->up_context, ares); return ac->up_callback(ldb, ac->up_context, ares);
error: error:
@ -163,6 +247,7 @@ static int kludge_acl_search(struct ldb_module *module, struct ldb_request *req)
ac->up_context = req->context; ac->up_context = req->context;
ac->up_callback = req->callback; ac->up_callback = req->callback;
ac->user_type = what_is_user(module); ac->user_type = what_is_user(module);
ac->attrs = req->op.search.attrs;
down_req = talloc_zero(req, struct ldb_request); down_req = talloc_zero(req, struct ldb_request);
if (down_req == NULL) { if (down_req == NULL) {
@ -174,7 +259,15 @@ static int kludge_acl_search(struct ldb_module *module, struct ldb_request *req)
down_req->op.search.scope = req->op.search.scope; down_req->op.search.scope = req->op.search.scope;
down_req->op.search.tree = req->op.search.tree; down_req->op.search.tree = req->op.search.tree;
down_req->op.search.attrs = req->op.search.attrs; down_req->op.search.attrs = req->op.search.attrs;
ac->allowedAttributes = ldb_attr_in_list(req->op.search.attrs, "allowedAttributes");
ac->allowedAttributesEffective = ldb_attr_in_list(req->op.search.attrs, "allowedAttributesEffective");
if (ac->allowedAttributes || ac->allowedAttributesEffective) {
down_req->op.search.attrs
= ldb_attr_list_copy_add(down_req, down_req->op.search.attrs, "objectClass");
}
/* FIXME: I hink we should copy the tree and keep the original /* FIXME: I hink we should copy the tree and keep the original
* unmodified. SSS */ * unmodified. SSS */

View File

@ -54,6 +54,10 @@ static int schema_fsmo_init(struct ldb_module *module)
NULL NULL
}; };
if (dsdb_get_schema(module->ldb)) {
return ldb_next_init(module);
}
schema_dn = samdb_schema_dn(module->ldb); schema_dn = samdb_schema_dn(module->ldb);
if (!schema_dn) { if (!schema_dn) {
ldb_debug(module->ldb, LDB_DEBUG_WARNING, ldb_debug(module->ldb, LDB_DEBUG_WARNING,

View File

@ -50,6 +50,7 @@ struct ldb_context *samdb_connect(TALLOC_CTX *mem_ctx,
if (!ldb) { if (!ldb) {
return NULL; return NULL;
} }
dsdb_make_schema_global(ldb);
return ldb; return ldb;
} }

View File

@ -323,6 +323,34 @@ WERROR dsdb_map_int2oid(const struct dsdb_schema *schema, uint32_t in, TALLOC_CT
talloc_steal(mem_ctx, (p)->elem); \ talloc_steal(mem_ctx, (p)->elem); \
} while (0) } while (0)
#define GET_STRING_LIST_LDB(msg, attr, mem_ctx, p, elem, strict) do { \
int get_string_list_counter; \
struct ldb_message_element *get_string_list_el = ldb_msg_find_element(msg, attr); \
if (get_string_list_el == NULL) { \
if (strict) { \
d_printf("%s: %s == NULL\n", __location__, attr); \
return WERR_INVALID_PARAM; \
} else { \
(p)->elem = NULL; \
break; \
} \
} \
(p)->elem = talloc_array(mem_ctx, const char *, get_string_list_el->num_values + 1); \
for (get_string_list_counter=0; \
get_string_list_counter < get_string_list_el->num_values; \
get_string_list_counter++) { \
(p)->elem[get_string_list_counter] = talloc_strndup((p)->elem, \
(const char *)get_string_list_el->values[get_string_list_counter].data, \
get_string_list_el->values[get_string_list_counter].length); \
if (!(p)->elem[get_string_list_counter]) { \
d_printf("%s: talloc_strndup failed for %s\n", __location__, attr); \
return WERR_NOMEM; \
} \
(p)->elem[get_string_list_counter+1] = NULL; \
} \
talloc_steal(mem_ctx, (p)->elem); \
} while (0)
#define GET_BOOL_LDB(msg, attr, p, elem, strict) do { \ #define GET_BOOL_LDB(msg, attr, p, elem, strict) do { \
const char *str; \ const char *str; \
str = samdb_result_string(msg, attr, NULL);\ str = samdb_result_string(msg, attr, NULL);\
@ -466,13 +494,14 @@ WERROR dsdb_class_from_ldb(const struct dsdb_schema *schema,
obj->systemAuxiliaryClass = NULL; obj->systemAuxiliaryClass = NULL;
obj->systemPossSuperiors = NULL; obj->systemPossSuperiors = NULL;
obj->systemMustContain = NULL;
obj->systemMayContain = NULL;
obj->auxiliaryClass = NULL; obj->auxiliaryClass = NULL;
obj->possSuperiors = NULL; obj->possSuperiors = NULL;
obj->mustContain = NULL;
obj->mayContain = NULL; GET_STRING_LIST_LDB(msg, "systemMustContain", mem_ctx, obj, systemMustContain, False);
GET_STRING_LIST_LDB(msg, "systemMayContain", mem_ctx, obj, systemMayContain, False);
GET_STRING_LIST_LDB(msg, "mustContain", mem_ctx, obj, mustContain, False);
GET_STRING_LIST_LDB(msg, "mayContain", mem_ctx, obj, mayContain, False);
GET_STRING_LDB(msg, "defaultSecurityDescriptor", mem_ctx, obj, defaultSecurityDescriptor, False); GET_STRING_LDB(msg, "defaultSecurityDescriptor", mem_ctx, obj, defaultSecurityDescriptor, False);
@ -930,6 +959,23 @@ const struct dsdb_class *dsdb_class_by_lDAPDisplayName(const struct dsdb_schema
return NULL; return NULL;
} }
const struct dsdb_class *dsdb_class_by_cn(const struct dsdb_schema *schema,
const char *cn)
{
struct dsdb_class *cur;
if (!cn) return NULL;
/* TODO: add binary search */
for (cur = schema->classes; cur; cur = cur->next) {
if (strcasecmp(cur->cn, cn) != 0) continue;
return cur;
}
return NULL;
}
const char *dsdb_lDAPDisplayName_by_id(const struct dsdb_schema *schema, const char *dsdb_lDAPDisplayName_by_id(const struct dsdb_schema *schema,
uint32_t id) uint32_t id)
{ {
@ -964,6 +1010,22 @@ int dsdb_set_schema(struct ldb_context *ldb, struct dsdb_schema *schema)
return LDB_SUCCESS; return LDB_SUCCESS;
} }
static struct dsdb_schema *global_schema;
int dsdb_set_global_schema(struct ldb_context *ldb)
{
int ret;
if (!global_schema) {
return LDB_SUCCESS;
}
ret = ldb_set_opaque(ldb, "dsdb_schema", global_schema);
if (ret != LDB_SUCCESS) {
return ret;
}
return LDB_SUCCESS;
}
const struct dsdb_schema *dsdb_get_schema(struct ldb_context *ldb) const struct dsdb_schema *dsdb_get_schema(struct ldb_context *ldb)
{ {
const void *p; const void *p;
@ -983,6 +1045,26 @@ const struct dsdb_schema *dsdb_get_schema(struct ldb_context *ldb)
return schema; return schema;
} }
void dsdb_make_schema_global(struct ldb_context *ldb)
{
const void *p;
const struct dsdb_schema *schema;
/* see if we have a cached copy */
p = ldb_get_opaque(ldb, "dsdb_schema");
if (!p) {
return;
}
schema = talloc_get_type(p, struct dsdb_schema);
if (!schema) {
return;
}
talloc_steal(NULL, schema);
global_schema = schema;
}
WERROR dsdb_attach_schema_from_ldif_file(struct ldb_context *ldb, const char *pf, const char *df) WERROR dsdb_attach_schema_from_ldif_file(struct ldb_context *ldb, const char *pf, const char *df)
{ {
struct ldb_ldif *ldif; struct ldb_ldif *ldif;

View File

@ -35,6 +35,7 @@
#include "lib/ldb/include/ldb_errors.h" #include "lib/ldb/include/ldb_errors.h"
#include "lib/ldb/samba/ldif_handlers.h" #include "lib/ldb/samba/ldif_handlers.h"
#include "db_wrap.h" #include "db_wrap.h"
#include "dsdb/samdb/samdb.h"
static struct tdb_wrap *tdb_list; static struct tdb_wrap *tdb_list;
@ -126,6 +127,10 @@ struct ldb_context *ldb_wrap_connect(TALLOC_CTX *mem_ctx,
talloc_free(ldb); talloc_free(ldb);
return NULL; return NULL;
} }
if (strcmp(lp_sam_url(), url) == 0) {
dsdb_set_global_schema(ldb);
}
ret = ldb_register_samba_handlers(ldb); ret = ldb_register_samba_handlers(ldb);
if (ret == -1) { if (ret == -1) {

View File

@ -666,7 +666,15 @@ const char **ldb_attr_list_copy_add(TALLOC_CTX *mem_ctx, const char * const *att
{ {
const char **ret; const char **ret;
int i; int i;
for (i=0;attrs[i];i++) /* noop */ ; bool found = false;
for (i=0;attrs[i];i++) {
if (ldb_attr_cmp(attrs[i], new_attr) == 0) {
found = true;
}
}
if (found) {
return ldb_attr_list_copy(mem_ctx, attrs);
}
ret = talloc_array(mem_ctx, const char *, i+2); ret = talloc_array(mem_ctx, const char *, i+2);
if (ret == NULL) { if (ret == NULL) {
return NULL; return NULL;
@ -686,7 +694,7 @@ const char **ldb_attr_list_copy_add(TALLOC_CTX *mem_ctx, const char * const *att
int ldb_attr_in_list(const char * const *attrs, const char *attr) int ldb_attr_in_list(const char * const *attrs, const char *attr)
{ {
int i; int i;
for (i=0;attrs[i];i++) { for (i=0;attrs && attrs[i];i++) {
if (ldb_attr_cmp(attrs[i], attr) == 0) { if (ldb_attr_cmp(attrs[i], attr) == 0) {
return 1; return 1;
} }

View File

@ -299,66 +299,53 @@ static int ldif_canonicalise_objectCategory(struct ldb_context *ldb, void *mem_c
const struct ldb_val *in, struct ldb_val *out) const struct ldb_val *in, struct ldb_val *out)
{ {
struct ldb_dn *dn1 = NULL; struct ldb_dn *dn1 = NULL;
char *oc1, *oc2; const struct dsdb_schema *schema = dsdb_get_schema(ldb);
const struct dsdb_class *class;
if (!schema) {
*out = data_blob_talloc(mem_ctx, in->data, in->length);
return LDB_SUCCESS;
}
dn1 = ldb_dn_new(mem_ctx, ldb, (char *)in->data); dn1 = ldb_dn_new(mem_ctx, ldb, (char *)in->data);
if ( ! ldb_dn_validate(dn1)) { if ( ! ldb_dn_validate(dn1)) {
oc1 = talloc_strndup(mem_ctx, (char *)in->data, in->length); const char *lDAPDisplayName = talloc_strndup(mem_ctx, (char *)in->data, in->length);
} else if (ldb_dn_get_comp_num(dn1) >= 1 && strcasecmp(ldb_dn_get_rdn_name(dn1), "cn") == 0) { class = dsdb_class_by_lDAPDisplayName(schema, lDAPDisplayName);
talloc_free(lDAPDisplayName);
} else if (ldb_dn_get_comp_num(dn1) >= 1 && ldb_attr_cmp(ldb_dn_get_rdn_name(dn1), "cn") == 0) {
const struct ldb_val *val = ldb_dn_get_rdn_val(dn1); const struct ldb_val *val = ldb_dn_get_rdn_val(dn1);
oc1 = talloc_strndup(mem_ctx, (char *)val->data, val->length); const char *cn = talloc_strndup(mem_ctx, (char *)val->data, val->length);
class = dsdb_class_by_cn(schema, cn);
talloc_free(cn);
} else { } else {
talloc_free(dn1);
return -1; return -1;
} }
oc2 = ldb_casefold(ldb, mem_ctx, oc1);
out->data = (void *)oc2;
out->length = strlen(oc2);
talloc_free(oc1);
talloc_free(dn1); talloc_free(dn1);
return 0;
if (!class) {
return -1;
}
*out = data_blob_string_const(talloc_strdup(mem_ctx, class->lDAPDisplayName));
return LDB_SUCCESS;
} }
static int ldif_comparison_objectCategory(struct ldb_context *ldb, void *mem_ctx, static int ldif_comparison_objectCategory(struct ldb_context *ldb, void *mem_ctx,
const struct ldb_val *v1, const struct ldb_val *v1,
const struct ldb_val *v2) const struct ldb_val *v2)
{ {
struct ldb_dn *dn1 = NULL, *dn2 = NULL;
const char *oc1, *oc2;
dn1 = ldb_dn_new(mem_ctx, ldb, (char *)v1->data); int ret1, ret2;
if ( ! ldb_dn_validate(dn1)) { struct ldb_val v1_canon, v2_canon;
oc1 = talloc_strndup(mem_ctx, (char *)v1->data, v1->length); ret1 = ldif_canonicalise_objectCategory(ldb, mem_ctx, v1, &v1_canon);
} else if (ldb_dn_get_comp_num(dn1) >= 1 && strcasecmp(ldb_dn_get_rdn_name(dn1), "cn") == 0) { ret2 = ldif_canonicalise_objectCategory(ldb, mem_ctx, v2, &v2_canon);
const struct ldb_val *val = ldb_dn_get_rdn_val(dn1);
oc1 = talloc_strndup(mem_ctx, (char *)val->data, val->length); if (ret1 == LDB_SUCCESS && ret2 == LDB_SUCCESS) {
return ldb_attr_cmp(v1_canon.data, v2_canon.data);
} else { } else {
oc1 = NULL; return strcasecmp(v1->data, v2->data);
} }
dn2 = ldb_dn_new(mem_ctx, ldb, (char *)v2->data);
if ( ! ldb_dn_validate(dn2)) {
oc2 = talloc_strndup(mem_ctx, (char *)v2->data, v2->length);
} else if (ldb_dn_get_comp_num(dn2) >= 2 && strcasecmp(ldb_dn_get_rdn_name(dn2), "cn") == 0) {
const struct ldb_val *val = ldb_dn_get_rdn_val(dn2);
oc2 = talloc_strndup(mem_ctx, (char *)val->data, val->length);
} else {
oc2 = NULL;
}
oc1 = ldb_casefold(ldb, mem_ctx, oc1);
oc2 = ldb_casefold(ldb, mem_ctx, oc2);
if (!oc1 && oc2) {
return -1;
}
if (oc1 && !oc2) {
return 1;
}
if (!oc1 && !oc2) {
return -1;
}
return strcmp(oc1, oc2);
} }
#define LDB_SYNTAX_SAMBA_SID "LDB_SYNTAX_SAMBA_SID" #define LDB_SYNTAX_SAMBA_SID "LDB_SYNTAX_SAMBA_SID"

View File

@ -611,7 +611,7 @@ function provision(subobj, message, blank, paths, session_info, credentials, lda
var modify_ok = setup_ldb_modify("provision_schema_basedn_modify.ldif", info, samdb); var modify_ok = setup_ldb_modify("provision_schema_basedn_modify.ldif", info, samdb);
if (!modify_ok) { if (!modify_ok) {
if (!add_ok) { if (!add_ok) {
message("Failed to both add and modify schema dn: + samdb.errstring() + "\n"); message("Failed to both add and modify schema dn:" + samdb.errstring() + "\n");
message("Perhaps you need to run the provision script with the --ldap-base-dn option, and add this record to the backend manually\n"); message("Perhaps you need to run the provision script with the --ldap-base-dn option, and add this record to the backend manually\n");
assert(modify_ok); assert(modify_ok);
} }
@ -744,7 +744,7 @@ function provision_schema(subobj, message, tmp_schema_path, paths)
var modify_ok = setup_ldb_modify("provision_schema_basedn_modify.ldif", info, samdb); var modify_ok = setup_ldb_modify("provision_schema_basedn_modify.ldif", info, samdb);
if (!modify_ok) { if (!modify_ok) {
if (!add_ok) { if (!add_ok) {
message("Failed to both add and modify schema dn: + samdb.errstring() + "\n"); message("Failed to both add and modify schema dn: " + samdb.errstring() + "\n");
message("Perhaps you need to run the provision script with the --ldap-base-dn option, and add this record to the backend manually\n"); message("Perhaps you need to run the provision script with the --ldap-base-dn option, and add this record to the backend manually\n");
assert(modify_ok); assert(modify_ok);
} }
@ -882,16 +882,18 @@ function provision_guess()
"extended_dn", "extended_dn",
"asq", "asq",
"samldb", "samldb",
"password_hash",
"operational", "operational",
"objectclass", "objectclass",
"rdn_name", "rdn_name",
"show_deleted", "show_deleted",
"partition"); "partition");
subobj.MODULES_LIST = join(",", modules_list); subobj.MODULES_LIST = join(",", modules_list);
subobj.DOMAINDN_MOD = "objectguid"; subobj.DOMAINDN_MOD = "pdc_fsmo,password_hash";
subobj.CONFIGDN_MOD = "objectguid"; subobj.CONFIGDN_MOD = "naming_fsmo";
subobj.SCHEMADN_MOD = "objectguid"; subobj.SCHEMADN_MOD = "schema_fsmo";
subobj.DOMAINDN_MOD2 = ",objectguid";
subobj.CONFIGDN_MOD2 = ",objectguid";
subobj.SCHEMADN_MOD2 = ",objectguid";
subobj.EXTENSIBLEOBJECT = "# no objectClass: extensibleObject for local ldb"; subobj.EXTENSIBLEOBJECT = "# no objectClass: extensibleObject for local ldb";
subobj.ACI = "# no aci for local ldb"; subobj.ACI = "# no aci for local ldb";

View File

@ -132,11 +132,11 @@ if (ldapbackend) {
subobj["LDAPMODULE"] = "entryUUID"; subobj["LDAPMODULE"] = "entryUUID";
} }
subobj["DOMAINDN_LDB"] = subobj["LDAPBACKEND"]; subobj["DOMAINDN_LDB"] = subobj["LDAPBACKEND"];
subobj["DOMAINDN_MOD"] = subobj["LDAPMODULE"] + ",paged_searches"; subobj["DOMAINDN_MOD2"] = subobj["LDAPMODULE"] + ",paged_searches";
subobj["CONFIGDN_LDB"] = subobj["LDAPBACKEND"]; subobj["CONFIGDN_LDB"] = subobj["LDAPBACKEND"];
subobj["CONFIGDN_MOD"] = subobj["LDAPMODULE"] + ",paged_searches"; subobj["CONFIGDN_MOD2"] = subobj["LDAPMODULE"] + ",paged_searches";
subobj["SCHEMADN_LDB"] = subobj["LDAPBACKEND"]; subobj["SCHEMADN_LDB"] = subobj["LDAPBACKEND"];
subobj["SCHEMADN_MOD"] = subobj["LDAPMODULE"] + ",paged_searches"; subobj["SCHEMADN_MOD2"] = subobj["LDAPMODULE"] + ",paged_searches";
} }
if (!provision_validate(subobj, message)) { if (!provision_validate(subobj, message)) {

View File

@ -5,9 +5,9 @@ partition: ${DOMAINDN}:${DOMAINDN_LDB}
replicateEntries: @SUBCLASSES replicateEntries: @SUBCLASSES
replicateEntries: @ATTRIBUTES replicateEntries: @ATTRIBUTES
replicateEntries: @INDEXLIST replicateEntries: @INDEXLIST
modules:${SCHEMADN}:${SCHEMADN_MOD} modules:${SCHEMADN}:${SCHEMADN_MOD}${SCHEMADN_MOD2}
modules:${CONFIGDN}:${CONFIGDN_MOD} modules:${CONFIGDN}:${CONFIGDN_MOD}${CONFIGDN_MOD2}
modules:${DOMAINDN}:${DOMAINDN_MOD} modules:${DOMAINDN}:${DOMAINDN_MOD}${DOMAINDN_MOD2}
dn: @MODULES dn: @MODULES
@LIST: ${MODULES_LIST} @LIST: ${MODULES_LIST}

View File

@ -23,3 +23,21 @@ fSMORoleOwner: CN=NTDS Settings,CN=${NETBIOSNAME},CN=Servers,CN=${DEFAULTSITE},C
- -
replace: objectVersion replace: objectVersion
objectVersion: 30 objectVersion: 30
-
replace: prefixMap
prefixMap:: QkRTRAAAAAAiAAAAAAACACIAAAAAAAAAAgAAAAQAAgABAAAAAgAAAAgAAgACAAAACA
AAAAwAAgADAAAACAAAABAAAgAEAAAACAAAABQAAgAFAAAACAAAABgAAgAGAAAACAAAABwAAgAHAAA
ACAAAACAAAgAIAAAAAgAAACQAAgAJAAAACAAAACgAAgAKAAAACAAAACwAAgATAAAACAAAADAAAgAU
AAAACAAAADQAAgAVAAAACQAAADgAAgAWAAAACQAAADwAAgAXAAAACgAAAEAAAgAYAAAAAgAAAEQAA
gAZAAAAAgAAAEgAAgAaAAAAAgAAAEwAAgALAAAACgAAAFAAAgAMAAAACQAAAFQAAgANAAAACgAAAF
gAAgAOAAAACQAAAFwAAgAPAAAACgAAAGAAAgAQAAAACQAAAGQAAgARAAAACQAAAGgAAgASAAAACgA
AAGwAAgAbAAAACQAAAHAAAgAcAAAACQAAAHQAAgAdAAAACAAAAHgAAgAeAAAACAAAAHwAAgAfAAAA
CQAAAIAAAgAgAAAACQAAAIQAAgAhAAAACQAAAIgAAgACAAAAVQQAAAIAAABVBgAACAAAACqGSIb3F
AECCAAAACqGSIb3FAEDCAAAAGCGSAFlAgIBCAAAAGCGSAFlAgIDCAAAAGCGSAFlAgEFCAAAAGCGSA
FlAgEEAgAAAFUFAAAIAAAAKoZIhvcUAQQIAAAAKoZIhvcUAQUIAAAACZImiZPyLGQIAAAAYIZIAYb
4QgMJAAAACZImiZPyLGQBAAAACQAAAGCGSAGG+EIDAQAAAAoAAAAqhkiG9xQBBbZYAAACAAAAVRUA
AAIAAABVEgAAAgAAAFUUAAAKAAAAKoZIhvcUAQSCBAAACQAAACqGSIb3FAEFOAAAAAoAAAAqhkiG9
xQBBIIGAAAJAAAAKoZIhvcUAQU5AAAACgAAACqGSIb3FAEEggcAAAkAAAAqhkiG9xQBBToAAAAJAA
AAKoZIhvcUAQVJAAAACgAAACqGSIb3FAEEgjEAAAkAAAArBgEEAYs6ZXcAAAAJAAAAYIZIAYb4QgM
CAAAACAAAACsGAQQBgXoBCAAAACqGSIb3DQEJCQAAAAmSJomT8ixkBAAAAAkAAAArBgEEAbd9BAEA
AAAJAAAAKwYBBAG3fQQC

View File

@ -25,7 +25,7 @@ if (options.ARGV.length != 1) {
var host = options.ARGV[0]; var host = options.ARGV[0];
function basic_tests(ldb, gc_ldb, base_dn, configuration_dn) function basic_tests(ldb, gc_ldb, base_dn, configuration_dn, schema_dn)
{ {
println("Running basic tests"); println("Running basic tests");
@ -473,6 +473,33 @@ objectClass: user
assert(res.error == 0); assert(res.error == 0);
assert (res.msgs.length > 0); assert (res.msgs.length > 0);
println("Testing objectCategory canonacolisation");
var attrs = new Array("cn");
var res = ldb.search("objectCategory=ntDsDSA", configuration_dn, ldb.SCOPE_SUBTREE, attrs);
assert(res.error == 0);
if (res.msgs.length == 0) {
println("Didn't find any records with objectCategory=ntDsDSA");
}
assert(res.msgs.length != 0);
var attrs = new Array("cn");
var res = ldb.search("objectCategory=CN=ntDs-DSA," + schema_dn, configuration_dn, ldb.SCOPE_SUBTREE, attrs);
assert(res.error == 0);
if (res.msgs.length == 0) {
println("Didn't find any records with objectCategory=CN=ntDs-DSA," + schema_dn);
}
assert(res.msgs.length != 0);
println("Testing objectClass attribute order on "+ base_dn);
var attrs = new Array("objectclass");
var res = ldb.search("objectClass=domain", base_dn, ldb.SCOPE_BASE, attrs);
assert(res.error == 0);
assert(res.msgs.length == 1);
assert(res.msgs[0].objectClass[0] == "top");
assert(res.msgs[0].objectClass[1] == "domain");
assert(res.msgs[0].objectClass[2] == "domainDNS");
} }
function basedn_tests(ldb, gc_ldb) function basedn_tests(ldb, gc_ldb)
@ -522,6 +549,15 @@ function find_configurationdn(ldb)
return res.msgs[0].configurationNamingContext; return res.msgs[0].configurationNamingContext;
} }
function find_schemadn(ldb)
{
var attrs = new Array("schemaNamingContext");
var res = ldb.search("", "", ldb.SCOPE_BASE, attrs);
assert(res.error == 0);
assert(res.msgs.length == 1);
return res.msgs[0].schemaNamingContext;
}
/* use command line creds if available */ /* use command line creds if available */
ldb.credentials = options.get_credentials(); ldb.credentials = options.get_credentials();
gc_ldb.credentials = options.get_credentials(); gc_ldb.credentials = options.get_credentials();
@ -529,6 +565,7 @@ gc_ldb.credentials = options.get_credentials();
var ok = ldb.connect("ldap://" + host); var ok = ldb.connect("ldap://" + host);
var base_dn = find_basedn(ldb); var base_dn = find_basedn(ldb);
var configuration_dn = find_configurationdn(ldb); var configuration_dn = find_configurationdn(ldb);
var schema_dn = find_schemadn(ldb);
printf("baseDN: %s\n", base_dn); printf("baseDN: %s\n", base_dn);
@ -537,7 +574,7 @@ if (!ok) {
gc_ldb = undefined; gc_ldb = undefined;
} }
basic_tests(ldb, gc_ldb, base_dn, configuration_dn) basic_tests(ldb, gc_ldb, base_dn, configuration_dn, schema_dn)
basedn_tests(ldb, gc_ldb) basedn_tests(ldb, gc_ldb)

View File

@ -270,7 +270,7 @@ objectClass: user
cn: X cn: X
codePage: x codePage: x
revision: x revision: x
objectCategory: x dnsHostName: x
nextRid: y nextRid: y
lastLogon: x lastLogon: x
description: x description: x
@ -282,7 +282,7 @@ objectClass: top
cn: Y cn: Y
codePage: x codePage: x
revision: x revision: x
objectCategory: y dnsHostName: y
nextRid: y nextRid: y
lastLogon: y lastLogon: y
description: x description: x
@ -292,7 +292,7 @@ objectClass: top
cn: Z cn: Z
codePage: x codePage: x
revision: y revision: y
objectCategory: z dnsHostName: z
nextRid: y nextRid: y
lastLogon: z lastLogon: z
description: y description: y
@ -342,86 +342,86 @@ description: y
/* Search remote record by local DN */ /* Search remote record by local DN */
dn = s4.dn("cn=A"); dn = s4.dn("cn=A");
attrs = new Array("objectCategory", "lastLogon"); attrs = new Array("dnsHostName", "lastLogon");
res = ldb.search("", dn, ldb.SCOPE_BASE, attrs); res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
assert(res.error == 0); assert(res.error == 0);
assert(res.msgs.length == 1); assert(res.msgs.length == 1);
assert(res.msgs[0].dn == dn); assert(res.msgs[0].dn == dn);
assert(res.msgs[0].objectCategory == undefined); assert(res.msgs[0].dnsHostName == undefined);
assert(res.msgs[0].lastLogon == "x"); assert(res.msgs[0].lastLogon == "x");
/* Search remote record by remote DN */ /* Search remote record by remote DN */
dn = s3.dn("cn=A"); dn = s3.dn("cn=A");
attrs = new Array("objectCategory", "lastLogon", "sambaLogonTime"); attrs = new Array("dnsHostName", "lastLogon", "sambaLogonTime");
res = s3.db.search("", dn, ldb.SCOPE_BASE, attrs); res = s3.db.search("", dn, ldb.SCOPE_BASE, attrs);
assert(res.error == 0); assert(res.error == 0);
assert(res.msgs.length == 1); assert(res.msgs.length == 1);
assert(res.msgs[0].dn == dn); assert(res.msgs[0].dn == dn);
assert(res.msgs[0].objectCategory == undefined); assert(res.msgs[0].dnsHostName == undefined);
assert(res.msgs[0].lastLogon == undefined); assert(res.msgs[0].lastLogon == undefined);
assert(res.msgs[0].sambaLogonTime == "x"); assert(res.msgs[0].sambaLogonTime == "x");
/* Search split record by local DN */ /* Search split record by local DN */
dn = s4.dn("cn=X"); dn = s4.dn("cn=X");
attrs = new Array("objectCategory", "lastLogon"); attrs = new Array("dnsHostName", "lastLogon");
res = ldb.search("", dn, ldb.SCOPE_BASE, attrs); res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
assert(res.error == 0); assert(res.error == 0);
assert(res.msgs.length == 1); assert(res.msgs.length == 1);
assert(res.msgs[0].dn == dn); assert(res.msgs[0].dn == dn);
assert(res.msgs[0].objectCategory == "x"); assert(res.msgs[0].dnsHostName == "x");
assert(res.msgs[0].lastLogon == "x"); assert(res.msgs[0].lastLogon == "x");
/* Search split record by remote DN */ /* Search split record by remote DN */
dn = s3.dn("cn=X"); dn = s3.dn("cn=X");
attrs = new Array("objectCategory", "lastLogon", "sambaLogonTime"); attrs = new Array("dnsHostName", "lastLogon", "sambaLogonTime");
res = s3.db.search("", dn, ldb.SCOPE_BASE, attrs); res = s3.db.search("", dn, ldb.SCOPE_BASE, attrs);
assert(res.error == 0); assert(res.error == 0);
assert(res.msgs.length == 1); assert(res.msgs.length == 1);
assert(res.msgs[0].dn == dn); assert(res.msgs[0].dn == dn);
assert(res.msgs[0].objectCategory == undefined); assert(res.msgs[0].dnsHostName == undefined);
assert(res.msgs[0].lastLogon == undefined); assert(res.msgs[0].lastLogon == undefined);
assert(res.msgs[0].sambaLogonTime == "x"); assert(res.msgs[0].sambaLogonTime == "x");
println("Testing search by attribute"); println("Testing search by attribute");
/* Search by ignored attribute */ /* Search by ignored attribute */
attrs = new Array("objectCategory", "lastLogon"); attrs = new Array("dnsHostName", "lastLogon");
res = ldb.search("(revision=x)", NULL, ldb. SCOPE_DEFAULT, attrs); res = ldb.search("(revision=x)", NULL, ldb. SCOPE_DEFAULT, attrs);
assert(res.error == 0); assert(res.error == 0);
assert(res.msgs.length == 2); assert(res.msgs.length == 2);
assert(res.msgs[0].dn == s4.dn("cn=Y")); assert(res.msgs[0].dn == s4.dn("cn=Y"));
assert(res.msgs[0].objectCategory == "y"); assert(res.msgs[0].dnsHostName == "y");
assert(res.msgs[0].lastLogon == "y"); assert(res.msgs[0].lastLogon == "y");
assert(res.msgs[1].dn == s4.dn("cn=X")); assert(res.msgs[1].dn == s4.dn("cn=X"));
assert(res.msgs[1].objectCategory == "x"); assert(res.msgs[1].dnsHostName == "x");
assert(res.msgs[1].lastLogon == "x"); assert(res.msgs[1].lastLogon == "x");
/* Search by kept attribute */ /* Search by kept attribute */
attrs = new Array("objectCategory", "lastLogon"); attrs = new Array("dnsHostName", "lastLogon");
res = ldb.search("(description=y)", NULL, ldb. SCOPE_DEFAULT, attrs); res = ldb.search("(description=y)", NULL, ldb. SCOPE_DEFAULT, attrs);
assert(res.error == 0); assert(res.error == 0);
assert(res.msgs.length == 2); assert(res.msgs.length == 2);
assert(res.msgs[0].dn == s4.dn("cn=Z")); assert(res.msgs[0].dn == s4.dn("cn=Z"));
assert(res.msgs[0].objectCategory == "z"); assert(res.msgs[0].dnsHostName == "z");
assert(res.msgs[0].lastLogon == "z"); assert(res.msgs[0].lastLogon == "z");
assert(res.msgs[1].dn == s4.dn("cn=C")); assert(res.msgs[1].dn == s4.dn("cn=C"));
assert(res.msgs[1].objectCategory == undefined); assert(res.msgs[1].dnsHostName == undefined);
assert(res.msgs[1].lastLogon == "z"); assert(res.msgs[1].lastLogon == "z");
/* Search by renamed attribute */ /* Search by renamed attribute */
attrs = new Array("objectCategory", "lastLogon"); attrs = new Array("dnsHostName", "lastLogon");
res = ldb.search("(badPwdCount=x)", NULL, ldb. SCOPE_DEFAULT, attrs); res = ldb.search("(badPwdCount=x)", NULL, ldb. SCOPE_DEFAULT, attrs);
assert(res.error == 0); assert(res.error == 0);
assert(res.msgs.length == 2); assert(res.msgs.length == 2);
assert(res.msgs[0].dn == s4.dn("cn=B")); assert(res.msgs[0].dn == s4.dn("cn=B"));
assert(res.msgs[0].objectCategory == undefined); assert(res.msgs[0].dnsHostName == undefined);
assert(res.msgs[0].lastLogon == "y"); assert(res.msgs[0].lastLogon == "y");
assert(res.msgs[1].dn == s4.dn("cn=A")); assert(res.msgs[1].dn == s4.dn("cn=A"));
assert(res.msgs[1].objectCategory == undefined); assert(res.msgs[1].dnsHostName == undefined);
assert(res.msgs[1].lastLogon == "x"); assert(res.msgs[1].lastLogon == "x");
/* Search by converted attribute */ /* Search by converted attribute */
attrs = new Array("objectCategory", "lastLogon", "objectSid"); attrs = new Array("dnsHostName", "lastLogon", "objectSid");
/* TODO: /* TODO:
Using the SID directly in the parse tree leads to conversion Using the SID directly in the parse tree leads to conversion
errors, letting the search fail with no results. errors, letting the search fail with no results.
@ -431,23 +431,23 @@ description: y
assert(res.error == 0); assert(res.error == 0);
assert(res.msgs.length == 2); assert(res.msgs.length == 2);
assert(res.msgs[0].dn == s4.dn("cn=X")); assert(res.msgs[0].dn == s4.dn("cn=X"));
assert(res.msgs[0].objectCategory == "x"); assert(res.msgs[0].dnsHostName == "x");
assert(res.msgs[0].lastLogon == "x"); assert(res.msgs[0].lastLogon == "x");
assert(res.msgs[0].objectSid == "S-1-5-21-4231626423-2410014848-2360679739-552"); assert(res.msgs[0].objectSid == "S-1-5-21-4231626423-2410014848-2360679739-552");
assert(res.msgs[1].dn == s4.dn("cn=A")); assert(res.msgs[1].dn == s4.dn("cn=A"));
assert(res.msgs[1].objectCategory == undefined); assert(res.msgs[1].dnsHostName == undefined);
assert(res.msgs[1].lastLogon == "x"); assert(res.msgs[1].lastLogon == "x");
assert(res.msgs[1].objectSid == "S-1-5-21-4231626423-2410014848-2360679739-552"); assert(res.msgs[1].objectSid == "S-1-5-21-4231626423-2410014848-2360679739-552");
/* Search by generated attribute */ /* Search by generated attribute */
/* In most cases, this even works when the mapping is missing /* In most cases, this even works when the mapping is missing
* a `convert_operator' by enumerating the remote db. */ * a `convert_operator' by enumerating the remote db. */
attrs = new Array("objectCategory", "lastLogon", "primaryGroupID"); attrs = new Array("dnsHostName", "lastLogon", "primaryGroupID");
res = ldb.search("(primaryGroupID=512)", NULL, ldb. SCOPE_DEFAULT, attrs); res = ldb.search("(primaryGroupID=512)", NULL, ldb. SCOPE_DEFAULT, attrs);
assert(res.error == 0); assert(res.error == 0);
assert(res.msgs.length == 1); assert(res.msgs.length == 1);
assert(res.msgs[0].dn == s4.dn("cn=A")); assert(res.msgs[0].dn == s4.dn("cn=A"));
assert(res.msgs[0].objectCategory == undefined); assert(res.msgs[0].dnsHostName == undefined);
assert(res.msgs[0].lastLogon == "x"); assert(res.msgs[0].lastLogon == "x");
assert(res.msgs[0].primaryGroupID == "512"); assert(res.msgs[0].primaryGroupID == "512");
@ -468,23 +468,23 @@ description: y
*/ */
/* Search by remote name of renamed attribute */ /* Search by remote name of renamed attribute */
attrs = new Array("objectCategory", "lastLogon"); attrs = new Array("dnsHostName", "lastLogon");
res = ldb.search("(sambaBadPasswordCount=*)", "", ldb. SCOPE_DEFAULT, attrs); res = ldb.search("(sambaBadPasswordCount=*)", "", ldb. SCOPE_DEFAULT, attrs);
assert(res.error == 0); assert(res.error == 0);
assert(res.msgs.length == 0); assert(res.msgs.length == 0);
/* Search by objectClass */ /* Search by objectClass */
attrs = new Array("objectCategory", "lastLogon", "objectClass"); attrs = new Array("dnsHostName", "lastLogon", "objectClass");
res = ldb.search("(objectClass=user)", NULL, ldb. SCOPE_DEFAULT, attrs); res = ldb.search("(objectClass=user)", NULL, ldb. SCOPE_DEFAULT, attrs);
assert(res.error == 0); assert(res.error == 0);
assert(res.msgs.length == 2); assert(res.msgs.length == 2);
assert(res.msgs[0].dn == s4.dn("cn=X")); assert(res.msgs[0].dn == s4.dn("cn=X"));
assert(res.msgs[0].objectCategory == "x"); assert(res.msgs[0].dnsHostName == "x");
assert(res.msgs[0].lastLogon == "x"); assert(res.msgs[0].lastLogon == "x");
assert(res.msgs[0].objectClass != undefined); assert(res.msgs[0].objectClass != undefined);
assert(res.msgs[0].objectClass[3] == "user"); assert(res.msgs[0].objectClass[3] == "user");
assert(res.msgs[1].dn == s4.dn("cn=A")); assert(res.msgs[1].dn == s4.dn("cn=A"));
assert(res.msgs[1].objectCategory == undefined); assert(res.msgs[1].dnsHostName == undefined);
assert(res.msgs[1].lastLogon == "x"); assert(res.msgs[1].lastLogon == "x");
assert(res.msgs[1].objectClass != undefined); assert(res.msgs[1].objectClass != undefined);
assert(res.msgs[1].objectClass[0] == "user"); assert(res.msgs[1].objectClass[0] == "user");
@ -494,19 +494,19 @@ description: y
assert(res.error == 0); assert(res.error == 0);
assert(res.msgs.length == 3); assert(res.msgs.length == 3);
assert(res.msgs[0].dn == s4.dn("cn=B")); assert(res.msgs[0].dn == s4.dn("cn=B"));
assert(res.msgs[0].objectCategory == undefined); assert(res.msgs[0].dnsHostName == undefined);
assert(res.msgs[0].lastLogon == "y"); assert(res.msgs[0].lastLogon == "y");
assert(res.msgs[0].objectClass != undefined); assert(res.msgs[0].objectClass != undefined);
for (i=0;i<res.msgs[0].objectClass.length;i++) { for (i=0;i<res.msgs[0].objectClass.length;i++) {
assert(res.msgs[0].objectClass[i] != "user"); assert(res.msgs[0].objectClass[i] != "user");
} }
assert(res.msgs[1].dn == s4.dn("cn=X")); assert(res.msgs[1].dn == s4.dn("cn=X"));
assert(res.msgs[1].objectCategory == "x"); assert(res.msgs[1].dnsHostName == "x");
assert(res.msgs[1].lastLogon == "x"); assert(res.msgs[1].lastLogon == "x");
assert(res.msgs[1].objectClass != undefined); assert(res.msgs[1].objectClass != undefined);
assert(res.msgs[1].objectClass[3] == "user"); assert(res.msgs[1].objectClass[3] == "user");
assert(res.msgs[2].dn == s4.dn("cn=A")); assert(res.msgs[2].dn == s4.dn("cn=A"));
assert(res.msgs[2].objectCategory == undefined); assert(res.msgs[2].dnsHostName == undefined);
assert(res.msgs[2].lastLogon == "x"); assert(res.msgs[2].lastLogon == "x");
assert(res.msgs[2].objectClass != undefined); assert(res.msgs[2].objectClass != undefined);
assert(res.msgs[2].objectClass[0] == "user"); assert(res.msgs[2].objectClass[0] == "user");
@ -514,43 +514,43 @@ description: y
println("Testing search by parse tree"); println("Testing search by parse tree");
/* Search by conjunction of local attributes */ /* Search by conjunction of local attributes */
attrs = new Array("objectCategory", "lastLogon"); attrs = new Array("dnsHostName", "lastLogon");
res = ldb.search("(&(codePage=x)(revision=x))", NULL, ldb.SCOPE_DEFAULT, attrs); res = ldb.search("(&(codePage=x)(revision=x))", NULL, ldb.SCOPE_DEFAULT, attrs);
assert(res.error == 0); assert(res.error == 0);
assert(res.msgs.length == 2); assert(res.msgs.length == 2);
assert(res.msgs[0].dn == s4.dn("cn=Y")); assert(res.msgs[0].dn == s4.dn("cn=Y"));
assert(res.msgs[0].objectCategory == "y"); assert(res.msgs[0].dnsHostName == "y");
assert(res.msgs[0].lastLogon == "y"); assert(res.msgs[0].lastLogon == "y");
assert(res.msgs[1].dn == s4.dn("cn=X")); assert(res.msgs[1].dn == s4.dn("cn=X"));
assert(res.msgs[1].objectCategory == "x"); assert(res.msgs[1].dnsHostName == "x");
assert(res.msgs[1].lastLogon == "x"); assert(res.msgs[1].lastLogon == "x");
/* Search by conjunction of remote attributes */ /* Search by conjunction of remote attributes */
attrs = new Array("objectCategory", "lastLogon"); attrs = new Array("dnsHostName", "lastLogon");
res = ldb.search("(&(lastLogon=x)(description=x))", NULL, ldb.SCOPE_DEFAULT, attrs); res = ldb.search("(&(lastLogon=x)(description=x))", NULL, ldb.SCOPE_DEFAULT, attrs);
assert(res.error == 0); assert(res.error == 0);
assert(res.msgs.length == 2); assert(res.msgs.length == 2);
assert(res.msgs[0].dn == s4.dn("cn=X")); assert(res.msgs[0].dn == s4.dn("cn=X"));
assert(res.msgs[0].objectCategory == "x"); assert(res.msgs[0].dnsHostName == "x");
assert(res.msgs[0].lastLogon == "x"); assert(res.msgs[0].lastLogon == "x");
assert(res.msgs[1].dn == s4.dn("cn=A")); assert(res.msgs[1].dn == s4.dn("cn=A"));
assert(res.msgs[1].objectCategory == undefined); assert(res.msgs[1].dnsHostName == undefined);
assert(res.msgs[1].lastLogon == "x"); assert(res.msgs[1].lastLogon == "x");
/* Search by conjunction of local and remote attribute */ /* Search by conjunction of local and remote attribute */
attrs = new Array("objectCategory", "lastLogon"); attrs = new Array("dnsHostName", "lastLogon");
res = ldb.search("(&(codePage=x)(description=x))", NULL, ldb.SCOPE_DEFAULT, attrs); res = ldb.search("(&(codePage=x)(description=x))", NULL, ldb.SCOPE_DEFAULT, attrs);
assert(res.error == 0); assert(res.error == 0);
assert(res.msgs.length == 2); assert(res.msgs.length == 2);
assert(res.msgs[0].dn == s4.dn("cn=Y")); assert(res.msgs[0].dn == s4.dn("cn=Y"));
assert(res.msgs[0].objectCategory == "y"); assert(res.msgs[0].dnsHostName == "y");
assert(res.msgs[0].lastLogon == "y"); assert(res.msgs[0].lastLogon == "y");
assert(res.msgs[1].dn == s4.dn("cn=X")); assert(res.msgs[1].dn == s4.dn("cn=X"));
assert(res.msgs[1].objectCategory == "x"); assert(res.msgs[1].dnsHostName == "x");
assert(res.msgs[1].lastLogon == "x"); assert(res.msgs[1].lastLogon == "x");
/* Search by conjunction of local and remote attribute w/o match */ /* Search by conjunction of local and remote attribute w/o match */
attrs = new Array("objectCategory", "lastLogon"); attrs = new Array("dnsHostName", "lastLogon");
res = ldb.search("(&(codePage=x)(nextRid=x))", NULL, ldb.SCOPE_DEFAULT, attrs); res = ldb.search("(&(codePage=x)(nextRid=x))", NULL, ldb.SCOPE_DEFAULT, attrs);
assert(res.error == 0); assert(res.error == 0);
assert(res.msgs.length == 0); assert(res.msgs.length == 0);
@ -559,203 +559,203 @@ description: y
assert(res.msgs.length == 0); assert(res.msgs.length == 0);
/* Search by disjunction of local attributes */ /* Search by disjunction of local attributes */
attrs = new Array("objectCategory", "lastLogon"); attrs = new Array("dnsHostName", "lastLogon");
res = ldb.search("(|(revision=x)(objectCategory=x))", NULL, ldb.SCOPE_DEFAULT, attrs); res = ldb.search("(|(revision=x)(dnsHostName=x))", NULL, ldb.SCOPE_DEFAULT, attrs);
assert(res.error == 0); assert(res.error == 0);
assert(res.msgs.length == 2); assert(res.msgs.length == 2);
assert(res.msgs[0].dn == s4.dn("cn=Y")); assert(res.msgs[0].dn == s4.dn("cn=Y"));
assert(res.msgs[0].objectCategory == "y"); assert(res.msgs[0].dnsHostName == "y");
assert(res.msgs[0].lastLogon == "y"); assert(res.msgs[0].lastLogon == "y");
assert(res.msgs[1].dn == s4.dn("cn=X")); assert(res.msgs[1].dn == s4.dn("cn=X"));
assert(res.msgs[1].objectCategory == "x"); assert(res.msgs[1].dnsHostName == "x");
assert(res.msgs[1].lastLogon == "x"); assert(res.msgs[1].lastLogon == "x");
/* Search by disjunction of remote attributes */ /* Search by disjunction of remote attributes */
attrs = new Array("objectCategory", "lastLogon"); attrs = new Array("dnsHostName", "lastLogon");
res = ldb.search("(|(badPwdCount=x)(lastLogon=x))", NULL, ldb.SCOPE_DEFAULT, attrs); res = ldb.search("(|(badPwdCount=x)(lastLogon=x))", NULL, ldb.SCOPE_DEFAULT, attrs);
assert(res.error == 0); assert(res.error == 0);
assert(res.msgs.length == 3); assert(res.msgs.length == 3);
assert(res.msgs[0].dn == s4.dn("cn=B")); assert(res.msgs[0].dn == s4.dn("cn=B"));
assert(res.msgs[0].objectCategory == undefined); assert(res.msgs[0].dnsHostName == undefined);
assert(res.msgs[0].lastLogon == "y"); assert(res.msgs[0].lastLogon == "y");
assert(res.msgs[1].dn == s4.dn("cn=X")); assert(res.msgs[1].dn == s4.dn("cn=X"));
assert(res.msgs[1].objectCategory == "x"); assert(res.msgs[1].dnsHostName == "x");
assert(res.msgs[1].lastLogon == "x"); assert(res.msgs[1].lastLogon == "x");
assert(res.msgs[2].dn == s4.dn("cn=A")); assert(res.msgs[2].dn == s4.dn("cn=A"));
assert(res.msgs[2].objectCategory == undefined); assert(res.msgs[2].dnsHostName == undefined);
assert(res.msgs[2].lastLogon == "x"); assert(res.msgs[2].lastLogon == "x");
/* Search by disjunction of local and remote attribute */ /* Search by disjunction of local and remote attribute */
attrs = new Array("objectCategory", "lastLogon"); attrs = new Array("dnsHostName", "lastLogon");
res = ldb.search("(|(revision=x)(lastLogon=y))", NULL, ldb.SCOPE_DEFAULT, attrs); res = ldb.search("(|(revision=x)(lastLogon=y))", NULL, ldb.SCOPE_DEFAULT, attrs);
assert(res.error == 0); assert(res.error == 0);
assert(res.msgs.length == 3); assert(res.msgs.length == 3);
assert(res.msgs[0].dn == s4.dn("cn=Y")); assert(res.msgs[0].dn == s4.dn("cn=Y"));
assert(res.msgs[0].objectCategory == "y"); assert(res.msgs[0].dnsHostName == "y");
assert(res.msgs[0].lastLogon == "y"); assert(res.msgs[0].lastLogon == "y");
assert(res.msgs[1].dn == s4.dn("cn=B")); assert(res.msgs[1].dn == s4.dn("cn=B"));
assert(res.msgs[1].objectCategory == undefined); assert(res.msgs[1].dnsHostName == undefined);
assert(res.msgs[1].lastLogon == "y"); assert(res.msgs[1].lastLogon == "y");
assert(res.msgs[2].dn == s4.dn("cn=X")); assert(res.msgs[2].dn == s4.dn("cn=X"));
assert(res.msgs[2].objectCategory == "x"); assert(res.msgs[2].dnsHostName == "x");
assert(res.msgs[2].lastLogon == "x"); assert(res.msgs[2].lastLogon == "x");
/* Search by disjunction of local and remote attribute w/o match */ /* Search by disjunction of local and remote attribute w/o match */
attrs = new Array("objectCategory", "lastLogon"); attrs = new Array("dnsHostName", "lastLogon");
res = ldb.search("(|(codePage=y)(nextRid=z))", NULL, ldb.SCOPE_DEFAULT, attrs); res = ldb.search("(|(codePage=y)(nextRid=z))", NULL, ldb.SCOPE_DEFAULT, attrs);
assert(res.error == 0); assert(res.error == 0);
assert(res.msgs.length == 0); assert(res.msgs.length == 0);
/* Search by negated local attribute */ /* Search by negated local attribute */
attrs = new Array("objectCategory", "lastLogon"); attrs = new Array("dnsHostName", "lastLogon");
res = ldb.search("(!(revision=x))", NULL, ldb.SCOPE_DEFAULT, attrs); res = ldb.search("(!(revision=x))", NULL, ldb.SCOPE_DEFAULT, attrs);
assert(res.error == 0); assert(res.error == 0);
assert(res.msgs.length == 4); assert(res.msgs.length == 4);
assert(res.msgs[0].dn == s4.dn("cn=B")); assert(res.msgs[0].dn == s4.dn("cn=B"));
assert(res.msgs[0].objectCategory == undefined); assert(res.msgs[0].dnsHostName == undefined);
assert(res.msgs[0].lastLogon == "y"); assert(res.msgs[0].lastLogon == "y");
assert(res.msgs[1].dn == s4.dn("cn=A")); assert(res.msgs[1].dn == s4.dn("cn=A"));
assert(res.msgs[1].objectCategory == undefined); assert(res.msgs[1].dnsHostName == undefined);
assert(res.msgs[1].lastLogon == "x"); assert(res.msgs[1].lastLogon == "x");
assert(res.msgs[2].dn == s4.dn("cn=Z")); assert(res.msgs[2].dn == s4.dn("cn=Z"));
assert(res.msgs[2].objectCategory == "z"); assert(res.msgs[2].dnsHostName == "z");
assert(res.msgs[2].lastLogon == "z"); assert(res.msgs[2].lastLogon == "z");
assert(res.msgs[3].dn == s4.dn("cn=C")); assert(res.msgs[3].dn == s4.dn("cn=C"));
assert(res.msgs[3].objectCategory == undefined); assert(res.msgs[3].dnsHostName == undefined);
assert(res.msgs[3].lastLogon == "z"); assert(res.msgs[3].lastLogon == "z");
/* Search by negated remote attribute */ /* Search by negated remote attribute */
attrs = new Array("objectCategory", "lastLogon"); attrs = new Array("dnsHostName", "lastLogon");
res = ldb.search("(!(description=x))", NULL, ldb.SCOPE_DEFAULT, attrs); res = ldb.search("(!(description=x))", NULL, ldb.SCOPE_DEFAULT, attrs);
assert(res.error == 0); assert(res.error == 0);
assert(res.msgs.length == 2); assert(res.msgs.length == 2);
assert(res.msgs[0].dn == s4.dn("cn=Z")); assert(res.msgs[0].dn == s4.dn("cn=Z"));
assert(res.msgs[0].objectCategory == "z"); assert(res.msgs[0].dnsHostName == "z");
assert(res.msgs[0].lastLogon == "z"); assert(res.msgs[0].lastLogon == "z");
assert(res.msgs[1].dn == s4.dn("cn=C")); assert(res.msgs[1].dn == s4.dn("cn=C"));
assert(res.msgs[1].objectCategory == undefined); assert(res.msgs[1].dnsHostName == undefined);
assert(res.msgs[1].lastLogon == "z"); assert(res.msgs[1].lastLogon == "z");
/* Search by negated conjunction of local attributes */ /* Search by negated conjunction of local attributes */
attrs = new Array("objectCategory", "lastLogon"); attrs = new Array("dnsHostName", "lastLogon");
res = ldb.search("(!(&(codePage=x)(revision=x)))", NULL, ldb.SCOPE_DEFAULT, attrs); res = ldb.search("(!(&(codePage=x)(revision=x)))", NULL, ldb.SCOPE_DEFAULT, attrs);
assert(res.error == 0); assert(res.error == 0);
assert(res.msgs.length == 4); assert(res.msgs.length == 4);
assert(res.msgs[0].dn == s4.dn("cn=B")); assert(res.msgs[0].dn == s4.dn("cn=B"));
assert(res.msgs[0].objectCategory == undefined); assert(res.msgs[0].dnsHostName == undefined);
assert(res.msgs[0].lastLogon == "y"); assert(res.msgs[0].lastLogon == "y");
assert(res.msgs[1].dn == s4.dn("cn=A")); assert(res.msgs[1].dn == s4.dn("cn=A"));
assert(res.msgs[1].objectCategory == undefined); assert(res.msgs[1].dnsHostName == undefined);
assert(res.msgs[1].lastLogon == "x"); assert(res.msgs[1].lastLogon == "x");
assert(res.msgs[2].dn == s4.dn("cn=Z")); assert(res.msgs[2].dn == s4.dn("cn=Z"));
assert(res.msgs[2].objectCategory == "z"); assert(res.msgs[2].dnsHostName == "z");
assert(res.msgs[2].lastLogon == "z"); assert(res.msgs[2].lastLogon == "z");
assert(res.msgs[3].dn == s4.dn("cn=C")); assert(res.msgs[3].dn == s4.dn("cn=C"));
assert(res.msgs[3].objectCategory == undefined); assert(res.msgs[3].dnsHostName == undefined);
assert(res.msgs[3].lastLogon == "z"); assert(res.msgs[3].lastLogon == "z");
/* Search by negated conjunction of remote attributes */ /* Search by negated conjunction of remote attributes */
attrs = new Array("objectCategory", "lastLogon"); attrs = new Array("dnsHostName", "lastLogon");
res = ldb.search("(!(&(lastLogon=x)(description=x)))", NULL, ldb.SCOPE_DEFAULT, attrs); res = ldb.search("(!(&(lastLogon=x)(description=x)))", NULL, ldb.SCOPE_DEFAULT, attrs);
assert(res.error == 0); assert(res.error == 0);
assert(res.msgs.length == 4); assert(res.msgs.length == 4);
assert(res.msgs[0].dn == s4.dn("cn=Y")); assert(res.msgs[0].dn == s4.dn("cn=Y"));
assert(res.msgs[0].objectCategory == "y"); assert(res.msgs[0].dnsHostName == "y");
assert(res.msgs[0].lastLogon == "y"); assert(res.msgs[0].lastLogon == "y");
assert(res.msgs[1].dn == s4.dn("cn=B")); assert(res.msgs[1].dn == s4.dn("cn=B"));
assert(res.msgs[1].objectCategory == undefined); assert(res.msgs[1].dnsHostName == undefined);
assert(res.msgs[1].lastLogon == "y"); assert(res.msgs[1].lastLogon == "y");
assert(res.msgs[2].dn == s4.dn("cn=Z")); assert(res.msgs[2].dn == s4.dn("cn=Z"));
assert(res.msgs[2].objectCategory == "z"); assert(res.msgs[2].dnsHostName == "z");
assert(res.msgs[2].lastLogon == "z"); assert(res.msgs[2].lastLogon == "z");
assert(res.msgs[3].dn == s4.dn("cn=C")); assert(res.msgs[3].dn == s4.dn("cn=C"));
assert(res.msgs[3].objectCategory == undefined); assert(res.msgs[3].dnsHostName == undefined);
assert(res.msgs[3].lastLogon == "z"); assert(res.msgs[3].lastLogon == "z");
/* Search by negated conjunction of local and remote attribute */ /* Search by negated conjunction of local and remote attribute */
attrs = new Array("objectCategory", "lastLogon"); attrs = new Array("dnsHostName", "lastLogon");
res = ldb.search("(!(&(codePage=x)(description=x)))", NULL, ldb.SCOPE_DEFAULT, attrs); res = ldb.search("(!(&(codePage=x)(description=x)))", NULL, ldb.SCOPE_DEFAULT, attrs);
assert(res.error == 0); assert(res.error == 0);
assert(res.msgs.length == 4); assert(res.msgs.length == 4);
assert(res.msgs[0].dn == s4.dn("cn=B")); assert(res.msgs[0].dn == s4.dn("cn=B"));
assert(res.msgs[0].objectCategory == undefined); assert(res.msgs[0].dnsHostName == undefined);
assert(res.msgs[0].lastLogon == "y"); assert(res.msgs[0].lastLogon == "y");
assert(res.msgs[1].dn == s4.dn("cn=A")); assert(res.msgs[1].dn == s4.dn("cn=A"));
assert(res.msgs[1].objectCategory == undefined); assert(res.msgs[1].dnsHostName == undefined);
assert(res.msgs[1].lastLogon == "x"); assert(res.msgs[1].lastLogon == "x");
assert(res.msgs[2].dn == s4.dn("cn=Z")); assert(res.msgs[2].dn == s4.dn("cn=Z"));
assert(res.msgs[2].objectCategory == "z"); assert(res.msgs[2].dnsHostName == "z");
assert(res.msgs[2].lastLogon == "z"); assert(res.msgs[2].lastLogon == "z");
assert(res.msgs[3].dn == s4.dn("cn=C")); assert(res.msgs[3].dn == s4.dn("cn=C"));
assert(res.msgs[3].objectCategory == undefined); assert(res.msgs[3].dnsHostName == undefined);
assert(res.msgs[3].lastLogon == "z"); assert(res.msgs[3].lastLogon == "z");
/* Search by negated disjunction of local attributes */ /* Search by negated disjunction of local attributes */
attrs = new Array("objectCategory", "lastLogon"); attrs = new Array("dnsHostName", "lastLogon");
res = ldb.search("(!(|(revision=x)(objectCategory=x)))", NULL, ldb.SCOPE_DEFAULT, attrs); res = ldb.search("(!(|(revision=x)(dnsHostName=x)))", NULL, ldb.SCOPE_DEFAULT, attrs);
assert(res.error == 0); assert(res.error == 0);
assert(res.msgs[0].dn == s4.dn("cn=B")); assert(res.msgs[0].dn == s4.dn("cn=B"));
assert(res.msgs[0].objectCategory == undefined); assert(res.msgs[0].dnsHostName == undefined);
assert(res.msgs[0].lastLogon == "y"); assert(res.msgs[0].lastLogon == "y");
assert(res.msgs[1].dn == s4.dn("cn=A")); assert(res.msgs[1].dn == s4.dn("cn=A"));
assert(res.msgs[1].objectCategory == undefined); assert(res.msgs[1].dnsHostName == undefined);
assert(res.msgs[1].lastLogon == "x"); assert(res.msgs[1].lastLogon == "x");
assert(res.msgs[2].dn == s4.dn("cn=Z")); assert(res.msgs[2].dn == s4.dn("cn=Z"));
assert(res.msgs[2].objectCategory == "z"); assert(res.msgs[2].dnsHostName == "z");
assert(res.msgs[2].lastLogon == "z"); assert(res.msgs[2].lastLogon == "z");
assert(res.msgs[3].dn == s4.dn("cn=C")); assert(res.msgs[3].dn == s4.dn("cn=C"));
assert(res.msgs[3].objectCategory == undefined); assert(res.msgs[3].dnsHostName == undefined);
assert(res.msgs[3].lastLogon == "z"); assert(res.msgs[3].lastLogon == "z");
/* Search by negated disjunction of remote attributes */ /* Search by negated disjunction of remote attributes */
attrs = new Array("objectCategory", "lastLogon"); attrs = new Array("dnsHostName", "lastLogon");
res = ldb.search("(!(|(badPwdCount=x)(lastLogon=x)))", NULL, ldb.SCOPE_DEFAULT, attrs); res = ldb.search("(!(|(badPwdCount=x)(lastLogon=x)))", NULL, ldb.SCOPE_DEFAULT, attrs);
assert(res.error == 0); assert(res.error == 0);
assert(res.msgs.length == 3); assert(res.msgs.length == 3);
assert(res.msgs[0].dn == s4.dn("cn=Y")); assert(res.msgs[0].dn == s4.dn("cn=Y"));
assert(res.msgs[0].objectCategory == "y"); assert(res.msgs[0].dnsHostName == "y");
assert(res.msgs[0].lastLogon == "y"); assert(res.msgs[0].lastLogon == "y");
assert(res.msgs[1].dn == s4.dn("cn=Z")); assert(res.msgs[1].dn == s4.dn("cn=Z"));
assert(res.msgs[1].objectCategory == "z"); assert(res.msgs[1].dnsHostName == "z");
assert(res.msgs[1].lastLogon == "z"); assert(res.msgs[1].lastLogon == "z");
assert(res.msgs[2].dn == s4.dn("cn=C")); assert(res.msgs[2].dn == s4.dn("cn=C"));
assert(res.msgs[2].objectCategory == undefined); assert(res.msgs[2].dnsHostName == undefined);
assert(res.msgs[2].lastLogon == "z"); assert(res.msgs[2].lastLogon == "z");
/* Search by negated disjunction of local and remote attribute */ /* Search by negated disjunction of local and remote attribute */
attrs = new Array("objectCategory", "lastLogon"); attrs = new Array("dnsHostName", "lastLogon");
res = ldb.search("(!(|(revision=x)(lastLogon=y)))", NULL, ldb.SCOPE_DEFAULT, attrs); res = ldb.search("(!(|(revision=x)(lastLogon=y)))", NULL, ldb.SCOPE_DEFAULT, attrs);
assert(res.error == 0); assert(res.error == 0);
assert(res.msgs.length == 3); assert(res.msgs.length == 3);
assert(res.msgs[0].dn == s4.dn("cn=A")); assert(res.msgs[0].dn == s4.dn("cn=A"));
assert(res.msgs[0].objectCategory == undefined); assert(res.msgs[0].dnsHostName == undefined);
assert(res.msgs[0].lastLogon == "x"); assert(res.msgs[0].lastLogon == "x");
assert(res.msgs[1].dn == s4.dn("cn=Z")); assert(res.msgs[1].dn == s4.dn("cn=Z"));
assert(res.msgs[1].objectCategory == "z"); assert(res.msgs[1].dnsHostName == "z");
assert(res.msgs[1].lastLogon == "z"); assert(res.msgs[1].lastLogon == "z");
assert(res.msgs[2].dn == s4.dn("cn=C")); assert(res.msgs[2].dn == s4.dn("cn=C"));
assert(res.msgs[2].objectCategory == undefined); assert(res.msgs[2].dnsHostName == undefined);
assert(res.msgs[2].lastLogon == "z"); assert(res.msgs[2].lastLogon == "z");
/* Search by complex parse tree */ /* Search by complex parse tree */
attrs = new Array("objectCategory", "lastLogon"); attrs = new Array("dnsHostName", "lastLogon");
res = ldb.search("(|(&(revision=x)(objectCategory=x))(!(&(description=x)(nextRid=y)))(badPwdCount=y))", NULL, ldb.SCOPE_DEFAULT, attrs); res = ldb.search("(|(&(revision=x)(dnsHostName=x))(!(&(description=x)(nextRid=y)))(badPwdCount=y))", NULL, ldb.SCOPE_DEFAULT, attrs);
assert(res.error == 0); assert(res.error == 0);
assert(res.msgs.length == 5); assert(res.msgs.length == 5);
assert(res.msgs[0].dn == s4.dn("cn=B")); assert(res.msgs[0].dn == s4.dn("cn=B"));
assert(res.msgs[0].objectCategory == undefined); assert(res.msgs[0].dnsHostName == undefined);
assert(res.msgs[0].lastLogon == "y"); assert(res.msgs[0].lastLogon == "y");
assert(res.msgs[1].dn == s4.dn("cn=X")); assert(res.msgs[1].dn == s4.dn("cn=X"));
assert(res.msgs[1].objectCategory == "x"); assert(res.msgs[1].dnsHostName == "x");
assert(res.msgs[1].lastLogon == "x"); assert(res.msgs[1].lastLogon == "x");
assert(res.msgs[2].dn == s4.dn("cn=A")); assert(res.msgs[2].dn == s4.dn("cn=A"));
assert(res.msgs[2].objectCategory == undefined); assert(res.msgs[2].dnsHostName == undefined);
assert(res.msgs[2].lastLogon == "x"); assert(res.msgs[2].lastLogon == "x");
assert(res.msgs[3].dn == s4.dn("cn=Z")); assert(res.msgs[3].dn == s4.dn("cn=Z"));
assert(res.msgs[3].objectCategory == "z"); assert(res.msgs[3].dnsHostName == "z");
assert(res.msgs[3].lastLogon == "z"); assert(res.msgs[3].lastLogon == "z");
assert(res.msgs[4].dn == s4.dn("cn=C")); assert(res.msgs[4].dn == s4.dn("cn=C"));
assert(res.msgs[4].objectCategory == undefined); assert(res.msgs[4].dnsHostName == undefined);
assert(res.msgs[4].lastLogon == "z"); assert(res.msgs[4].lastLogon == "z");
/* Clean up */ /* Clean up */