summaryrefslogtreecommitdiff
path: root/source4/dsdb
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2009-10-17 10:36:33 -0700
committerJeremy Allison <jra@samba.org>2009-10-17 10:36:33 -0700
commit7c51fa6d699a653cafa90df8e44911b576118ebd (patch)
tree543bf9ca698e03eff81104898b33e77f1abed319 /source4/dsdb
parentcc3a6770c77ec8fe1cd63bf4c682853c56201f0c (diff)
parent3e3214fd91471bca5b6c4d3782e922d252d588fb (diff)
downloadsamba-7c51fa6d699a653cafa90df8e44911b576118ebd.tar.gz
samba-7c51fa6d699a653cafa90df8e44911b576118ebd.tar.bz2
samba-7c51fa6d699a653cafa90df8e44911b576118ebd.zip
Merge branch 'master' of ssh://jra@git.samba.org/data/git/samba
Diffstat (limited to 'source4/dsdb')
-rw-r--r--source4/dsdb/common/sidmap.c612
-rw-r--r--source4/dsdb/common/util.c241
-rw-r--r--source4/dsdb/config.mk4
-rw-r--r--source4/dsdb/kcc/kcc_periodic.c2
-rw-r--r--source4/dsdb/repl/drepl_out_helpers.c5
-rw-r--r--source4/dsdb/repl/replicated_objects.c63
-rw-r--r--source4/dsdb/samdb/cracknames.c8
-rw-r--r--source4/dsdb/samdb/ldb_modules/acl.c3
-rw-r--r--source4/dsdb/samdb/ldb_modules/anr.c14
-rw-r--r--source4/dsdb/samdb/ldb_modules/config.mk32
-rw-r--r--source4/dsdb/samdb/ldb_modules/extended_dn_out.c6
-rw-r--r--source4/dsdb/samdb/ldb_modules/extended_dn_store.c6
-rw-r--r--source4/dsdb/samdb/ldb_modules/instancetype.c38
-rw-r--r--source4/dsdb/samdb/ldb_modules/kludge_acl.c2
-rw-r--r--source4/dsdb/samdb/ldb_modules/lazy_commit.c132
-rw-r--r--source4/dsdb/samdb/ldb_modules/local_password.c5
-rw-r--r--source4/dsdb/samdb/ldb_modules/naming_fsmo.c26
-rw-r--r--source4/dsdb/samdb/ldb_modules/objectclass.c101
-rw-r--r--source4/dsdb/samdb/ldb_modules/objectguid.c4
-rw-r--r--source4/dsdb/samdb/ldb_modules/partition.c20
-rw-r--r--source4/dsdb/samdb/ldb_modules/password_hash.c53
-rw-r--r--source4/dsdb/samdb/ldb_modules/pdc_fsmo.c20
-rw-r--r--source4/dsdb/samdb/ldb_modules/repl_meta_data.c100
-rw-r--r--source4/dsdb/samdb/ldb_modules/rootdse.c4
-rw-r--r--source4/dsdb/samdb/ldb_modules/samldb.c21
-rw-r--r--source4/dsdb/samdb/ldb_modules/schema_fsmo.c113
-rw-r--r--source4/dsdb/samdb/ldb_modules/subtree_delete.c2
-rw-r--r--source4/dsdb/samdb/ldb_modules/tests/samba3sam.py26
-rw-r--r--source4/dsdb/samdb/ldb_modules/util.c128
-rw-r--r--source4/dsdb/samdb/ldb_modules/util.h22
-rw-r--r--source4/dsdb/samdb/samdb_privilege.c31
-rw-r--r--source4/dsdb/schema/prefixmap.h45
-rw-r--r--source4/dsdb/schema/schema.h1
-rw-r--r--source4/dsdb/schema/schema_inferiors.c47
-rw-r--r--source4/dsdb/schema/schema_init.c281
-rw-r--r--source4/dsdb/schema/schema_prefixmap.c22
-rw-r--r--source4/dsdb/schema/schema_set.c5
-rw-r--r--source4/dsdb/schema/schema_syntax.c136
38 files changed, 1228 insertions, 1153 deletions
diff --git a/source4/dsdb/common/sidmap.c b/source4/dsdb/common/sidmap.c
deleted file mode 100644
index 3111a78e51..0000000000
--- a/source4/dsdb/common/sidmap.c
+++ /dev/null
@@ -1,612 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
-
- mapping routines for SID <-> unix uid/gid
-
- Copyright (C) Andrew Tridgell 2004
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "includes.h"
-#include "system/passwd.h"
-#include "../libds/common/flags.h"
-#include "dsdb/samdb/samdb.h"
-#include "auth/auth.h"
-#include "libcli/ldap/ldap_ndr.h"
-#include "lib/ldb/include/ldb.h"
-#include "../lib/util/util_ldb.h"
-#include "libcli/security/security.h"
-#include "param/param.h"
-
-/*
- these are used for the fallback local uid/gid to sid mapping
- code.
-*/
-#define SIDMAP_LOCAL_USER_BASE 0x80000000
-#define SIDMAP_LOCAL_GROUP_BASE 0xC0000000
-#define SIDMAP_MAX_LOCAL_UID 0x3fffffff
-#define SIDMAP_MAX_LOCAL_GID 0x3fffffff
-
-/*
- private context for sid mapping routines
-*/
-struct sidmap_context {
- struct ldb_context *samctx;
-};
-
-/*
- open a sidmap context - use talloc_free to close
-*/
-struct sidmap_context *sidmap_open(TALLOC_CTX *mem_ctx, struct tevent_context *ev_ctx,
- struct loadparm_context *lp_ctx)
-{
- struct sidmap_context *sidmap;
- sidmap = talloc(mem_ctx, struct sidmap_context);
- if (sidmap == NULL) {
- return NULL;
- }
- sidmap->samctx = samdb_connect(sidmap, ev_ctx, lp_ctx, system_session(sidmap, lp_ctx));
- if (sidmap->samctx == NULL) {
- talloc_free(sidmap);
- return NULL;
- }
-
- return sidmap;
-}
-
-
-/*
- check the sAMAccountType field of a search result to see if
- the account is a user account
-*/
-static bool is_user_account(struct ldb_message *res)
-{
- uint_t atype = samdb_result_uint(res, "sAMAccountType", 0);
- if (atype && (!(atype & ATYPE_ACCOUNT))) {
- return false;
- }
- return true;
-}
-
-/*
- check the sAMAccountType field of a search result to see if
- the account is a group account
-*/
-static bool is_group_account(struct ldb_message *res)
-{
- uint_t atype = samdb_result_uint(res, "sAMAccountType", 0);
- if (atype && atype == ATYPE_NORMAL_ACCOUNT) {
- return false;
- }
- return true;
-}
-
-
-
-/*
- return the dom_sid of our primary domain
-*/
-static NTSTATUS sidmap_primary_domain_sid(struct sidmap_context *sidmap,
- TALLOC_CTX *mem_ctx, struct dom_sid **sid)
-{
- const char *attrs[] = { "objectSid", NULL };
- int ret;
- struct ldb_message **res = NULL;
-
- ret = gendb_search_dn(sidmap->samctx, mem_ctx, NULL, &res, attrs);
- if (ret != 1) {
- talloc_free(res);
- return NT_STATUS_NO_SUCH_DOMAIN;
- }
-
- *sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
- talloc_free(res);
- if (*sid == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- return NT_STATUS_OK;
-}
-
-
-/*
- map a sid to a unix uid
-*/
-NTSTATUS sidmap_sid_to_unixuid(struct sidmap_context *sidmap,
- const struct dom_sid *sid, uid_t *uid)
-{
- const char *attrs[] = { "sAMAccountName", "uidNumber",
- "sAMAccountType", "unixName", NULL };
- int ret;
- const char *s;
- TALLOC_CTX *tmp_ctx;
- struct ldb_message **res;
- struct dom_sid *domain_sid;
- NTSTATUS status;
-
- tmp_ctx = talloc_new(sidmap);
-
- ret = gendb_search(sidmap->samctx, tmp_ctx, NULL, &res, attrs,
- "objectSid=%s",
- ldap_encode_ndr_dom_sid(tmp_ctx, sid));
-
- if (ret != 1) {
- goto allocated_sid;
- }
-
- /* make sure its a user, not a group */
- if (!is_user_account(res[0])) {
- DEBUG(0,("sid_to_unixuid: sid %s is not an account!\n",
- dom_sid_string(tmp_ctx, sid)));
- talloc_free(tmp_ctx);
- return NT_STATUS_INVALID_SID;
- }
-
- /* first try to get the uid directly */
- s = samdb_result_string(res[0], "uidNumber", NULL);
- if (s != NULL) {
- *uid = strtoul(s, NULL, 0);
- talloc_free(tmp_ctx);
- return NT_STATUS_OK;
- }
-
- /* next try via the UnixName attribute */
- s = samdb_result_string(res[0], "unixName", NULL);
- if (s != NULL) {
- struct passwd *pwd = getpwnam(s);
- if (!pwd) {
- DEBUG(0,("unixName %s for sid %s does not exist as a local user\n", s,
- dom_sid_string(tmp_ctx, sid)));
- talloc_free(tmp_ctx);
- return NT_STATUS_NO_SUCH_USER;
- }
- *uid = pwd->pw_uid;
- talloc_free(tmp_ctx);
- return NT_STATUS_OK;
- }
-
- /* finally try via the sAMAccountName attribute */
- s = samdb_result_string(res[0], "sAMAccountName", NULL);
- if (s != NULL) {
- struct passwd *pwd = getpwnam(s);
- if (!pwd) {
- DEBUG(0,("sAMAccountName '%s' for sid %s does not exist as a local user\n",
- s, dom_sid_string(tmp_ctx, sid)));
- talloc_free(tmp_ctx);
- return NT_STATUS_NO_SUCH_USER;
- }
- *uid = pwd->pw_uid;
- talloc_free(tmp_ctx);
- return NT_STATUS_OK;
- }
-
-
-allocated_sid:
- status = sidmap_primary_domain_sid(sidmap, tmp_ctx, &domain_sid);
- if (!NT_STATUS_IS_OK(status)) {
- talloc_free(tmp_ctx);
- return NT_STATUS_NO_SUCH_DOMAIN;
- }
-
- if (dom_sid_in_domain(domain_sid, sid)) {
- uint32_t rid = sid->sub_auths[sid->num_auths-1];
- if (rid >= SIDMAP_LOCAL_USER_BASE &&
- rid < SIDMAP_LOCAL_GROUP_BASE) {
- *uid = rid - SIDMAP_LOCAL_USER_BASE;
- talloc_free(tmp_ctx);
- return NT_STATUS_OK;
- }
- }
-
-
- DEBUG(0,("sid_to_unixuid: no uidNumber, unixName or sAMAccountName for sid %s\n",
- dom_sid_string(tmp_ctx, sid)));
-
- talloc_free(tmp_ctx);
- return NT_STATUS_NONE_MAPPED;
-}
-
-
-/*
- see if a sid is a group - very inefficient!
-*/
-bool sidmap_sid_is_group(struct sidmap_context *sidmap, struct dom_sid *sid)
-{
- const char *attrs[] = { "sAMAccountType", NULL };
- int ret;
- TALLOC_CTX *tmp_ctx;
- struct ldb_message **res;
- NTSTATUS status;
- struct dom_sid *domain_sid;
- bool is_group;
-
- tmp_ctx = talloc_new(sidmap);
-
- ret = gendb_search(sidmap->samctx, tmp_ctx, NULL, &res, attrs,
- "objectSid=%s", ldap_encode_ndr_dom_sid(tmp_ctx, sid));
- if (ret == 1) {
- is_group = is_group_account(res[0]);
- talloc_free(tmp_ctx);
- return is_group;
- }
-
- status = sidmap_primary_domain_sid(sidmap, tmp_ctx, &domain_sid);
- if (!NT_STATUS_IS_OK(status)) {
- talloc_free(tmp_ctx);
- return false;
- }
-
- if (dom_sid_in_domain(domain_sid, sid)) {
- uint32_t rid = sid->sub_auths[sid->num_auths-1];
- if (rid >= SIDMAP_LOCAL_GROUP_BASE) {
- talloc_free(tmp_ctx);
- return true;
- }
- }
-
- talloc_free(tmp_ctx);
- return false;
-}
-
-/*
- map a sid to a unix gid
-*/
-NTSTATUS sidmap_sid_to_unixgid(struct sidmap_context *sidmap,
- const struct dom_sid *sid, gid_t *gid)
-{
- const char *attrs[] = { "sAMAccountName", "gidNumber",
- "unixName", "sAMAccountType", NULL };
- int ret;
- const char *s;
- TALLOC_CTX *tmp_ctx;
- struct ldb_message **res;
- NTSTATUS status;
- struct dom_sid *domain_sid;
-
- tmp_ctx = talloc_new(sidmap);
-
- ret = gendb_search(sidmap->samctx, tmp_ctx, NULL, &res, attrs,
- "objectSid=%s", ldap_encode_ndr_dom_sid(tmp_ctx, sid));
- if (ret != 1) {
- goto allocated_sid;
- }
-
- /* make sure its not a user */
- if (!is_group_account(res[0])) {
- DEBUG(0,("sid_to_unixgid: sid %s is a ATYPE_NORMAL_ACCOUNT\n",
- dom_sid_string(tmp_ctx, sid)));
- talloc_free(tmp_ctx);
- return NT_STATUS_INVALID_SID;
- }
-
- /* first try to get the gid directly */
- s = samdb_result_string(res[0], "gidNumber", NULL);
- if (s != NULL) {
- *gid = strtoul(s, NULL, 0);
- talloc_free(tmp_ctx);
- return NT_STATUS_OK;
- }
-
- /* next try via the UnixName attribute */
- s = samdb_result_string(res[0], "unixName", NULL);
- if (s != NULL) {
- struct group *grp = getgrnam(s);
- if (!grp) {
- DEBUG(0,("unixName '%s' for sid %s does not exist as a local group\n",
- s, dom_sid_string(tmp_ctx, sid)));
- talloc_free(tmp_ctx);
- return NT_STATUS_NO_SUCH_GROUP;
- }
- *gid = grp->gr_gid;
- talloc_free(tmp_ctx);
- return NT_STATUS_OK;
- }
-
- /* finally try via the sAMAccountName attribute */
- s = samdb_result_string(res[0], "sAMAccountName", NULL);
- if (s != NULL) {
- struct group *grp = getgrnam(s);
- if (!grp) {
- DEBUG(0,("sAMAccountName '%s' for sid %s does not exist as a local group\n", s, dom_sid_string(tmp_ctx, sid)));
- talloc_free(tmp_ctx);
- return NT_STATUS_NO_SUCH_GROUP;
- }
- *gid = grp->gr_gid;
- talloc_free(tmp_ctx);
- return NT_STATUS_OK;
- }
-
-allocated_sid:
- status = sidmap_primary_domain_sid(sidmap, tmp_ctx, &domain_sid);
- if (!NT_STATUS_IS_OK(status)) {
- talloc_free(tmp_ctx);
- return NT_STATUS_NO_SUCH_DOMAIN;
- }
-
- if (dom_sid_in_domain(domain_sid, sid)) {
- uint32_t rid = sid->sub_auths[sid->num_auths-1];
- if (rid >= SIDMAP_LOCAL_GROUP_BASE) {
- *gid = rid - SIDMAP_LOCAL_GROUP_BASE;
- talloc_free(tmp_ctx);
- return NT_STATUS_OK;
- }
- }
-
- DEBUG(0,("sid_to_unixgid: no gidNumber, unixName or sAMAccountName for sid %s\n",
- dom_sid_string(tmp_ctx, sid)));
-
- talloc_free(tmp_ctx);
- return NT_STATUS_NONE_MAPPED;
-}
-
-
-/*
- map a unix uid to a dom_sid
- the returned sid is allocated in the supplied mem_ctx
-*/
-NTSTATUS sidmap_uid_to_sid(struct sidmap_context *sidmap,
- TALLOC_CTX *mem_ctx,
- const uid_t uid, struct dom_sid **sid)
-{
- const char *attrs[] = { "sAMAccountName", "objectSid", "sAMAccountType", NULL };
- int ret, i;
- TALLOC_CTX *tmp_ctx;
- struct ldb_message **res;
- struct passwd *pwd;
- struct dom_sid *domain_sid;
- NTSTATUS status;
-
- /*
- we search for the mapping in the following order:
-
- - check if the uid is in the dynamic uid range assigned for winbindd
- use. If it is, then look in winbindd sid mapping
- database (not implemented yet)
- - look for a user account in samdb that has uidNumber set to the
- given uid
- - look for a user account in samdb that has unixName or
- sAMAccountName set to the name given by getpwuid()
- - assign a SID by adding the uid to SIDMAP_LOCAL_USER_BASE in the local
- domain
- */
-
-
- tmp_ctx = talloc_new(mem_ctx);
-
-
- /*
- step 2: look for a user account in samdb that has uidNumber set to the
- given uid
- */
-
- ret = gendb_search(sidmap->samctx, tmp_ctx, NULL, &res, attrs,
- "uidNumber=%u", (unsigned int)uid);
- for (i=0;i<ret;i++) {
- if (!is_user_account(res[i])) continue;
-
- *sid = samdb_result_dom_sid(mem_ctx, res[i], "objectSid");
- talloc_free(tmp_ctx);
- NT_STATUS_HAVE_NO_MEMORY(*sid);
- return NT_STATUS_OK;
- }
-
- /*
- step 3: look for a user account in samdb that has unixName
- or sAMAccountName set to the name given by getpwuid()
- */
- pwd = getpwuid(uid);
- if (pwd == NULL) {
- goto allocate_sid;
- }
-
- ret = gendb_search(sidmap->samctx, tmp_ctx, NULL, &res, attrs,
- "(|(unixName=%s)(sAMAccountName=%s))",
- pwd->pw_name, pwd->pw_name);
- for (i=0;i<ret;i++) {
- if (!is_user_account(res[i])) continue;
-
- *sid = samdb_result_dom_sid(mem_ctx, res[i], "objectSid");
- talloc_free(tmp_ctx);
- NT_STATUS_HAVE_NO_MEMORY(*sid);
- return NT_STATUS_OK;
- }
-
-
- /*
- step 4: assign a SID by adding the uid to
- SIDMAP_LOCAL_USER_BASE in the local domain
- */
-allocate_sid:
- if (uid > SIDMAP_MAX_LOCAL_UID) {
- return NT_STATUS_NONE_MAPPED;
- }
-
- status = sidmap_primary_domain_sid(sidmap, tmp_ctx, &domain_sid);
- if (!NT_STATUS_IS_OK(status)) {
- talloc_free(tmp_ctx);
- return status;
- }
-
- *sid = dom_sid_add_rid(mem_ctx, domain_sid, SIDMAP_LOCAL_USER_BASE + uid);
- talloc_free(tmp_ctx);
-
- if (*sid == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- return NT_STATUS_OK;
-}
-
-
-/*
- map a unix gid to a dom_sid
- the returned sid is allocated in the supplied mem_ctx
-*/
-NTSTATUS sidmap_gid_to_sid(struct sidmap_context *sidmap,
- TALLOC_CTX *mem_ctx,
- const gid_t gid, struct dom_sid **sid)
-{
- const char *attrs[] = { "sAMAccountName", "objectSid", "sAMAccountType", NULL };
- int ret, i;
- TALLOC_CTX *tmp_ctx;
- struct ldb_message **res;
- struct group *grp;
- struct dom_sid *domain_sid;
- NTSTATUS status;
-
- /*
- we search for the mapping in the following order:
-
- - check if the gid is in the dynamic gid range assigned for winbindd
- use. If it is, then look in winbindd sid mapping
- database (not implemented yet)
- - look for a group account in samdb that has gidNumber set to the
- given gid
- - look for a group account in samdb that has unixName or
- sAMAccountName set to the name given by getgrgid()
- - assign a SID by adding the gid to SIDMAP_LOCAL_GROUP_BASE in the local
- domain
- */
-
-
- tmp_ctx = talloc_new(sidmap);
-
-
- /*
- step 2: look for a group account in samdb that has gidNumber set to the
- given gid
- */
-
- ret = gendb_search(sidmap->samctx, tmp_ctx, NULL, &res, attrs,
- "gidNumber=%u", (unsigned int)gid);
- for (i=0;i<ret;i++) {
- if (!is_group_account(res[i])) continue;
-
- *sid = samdb_result_dom_sid(mem_ctx, res[i], "objectSid");
- talloc_free(tmp_ctx);
- NT_STATUS_HAVE_NO_MEMORY(*sid);
- return NT_STATUS_OK;
- }
-
- /*
- step 3: look for a group account in samdb that has unixName
- or sAMAccountName set to the name given by getgrgid()
- */
- grp = getgrgid(gid);
- if (grp == NULL) {
- goto allocate_sid;
- }
-
- ret = gendb_search(sidmap->samctx, tmp_ctx, NULL, &res, attrs,
- "(|(unixName=%s)(sAMAccountName=%s))",
- grp->gr_name, grp->gr_name);
- for (i=0;i<ret;i++) {
- if (!is_group_account(res[i])) continue;
-
- *sid = samdb_result_dom_sid(mem_ctx, res[i], "objectSid");
- talloc_free(tmp_ctx);
- NT_STATUS_HAVE_NO_MEMORY(*sid);
- return NT_STATUS_OK;
- }
-
-
- /*
- step 4: assign a SID by adding the gid to
- SIDMAP_LOCAL_GROUP_BASE in the local domain
- */
-allocate_sid:
- if (gid > SIDMAP_MAX_LOCAL_GID) {
- return NT_STATUS_NONE_MAPPED;
- }
-
- status = sidmap_primary_domain_sid(sidmap, tmp_ctx, &domain_sid);
- if (!NT_STATUS_IS_OK(status)) {
- talloc_free(tmp_ctx);
- return status;
- }
-
- *sid = dom_sid_add_rid(mem_ctx, domain_sid, SIDMAP_LOCAL_GROUP_BASE + gid);
- talloc_free(tmp_ctx);
-
- if (*sid == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- return NT_STATUS_OK;
-}
-
-/*
- check if a sid is in the range of auto-allocated SIDs from our primary domain,
- and if it is, then return the name and atype
-*/
-NTSTATUS sidmap_allocated_sid_lookup(struct sidmap_context *sidmap,
- TALLOC_CTX *mem_ctx,
- const struct dom_sid *sid,
- const char **name,
- enum lsa_SidType *rtype)
-{
- NTSTATUS status;
- struct dom_sid *domain_sid;
- TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
- uint32_t rid, atype;
-
- status = sidmap_primary_domain_sid(sidmap, tmp_ctx, &domain_sid);
- if (!NT_STATUS_IS_OK(status)) {
- return NT_STATUS_NO_SUCH_DOMAIN;
- }
-
- if (!dom_sid_in_domain(domain_sid, sid)) {
- talloc_free(tmp_ctx);
- return NT_STATUS_NONE_MAPPED;
- }
-
- talloc_free(tmp_ctx);
-
- rid = sid->sub_auths[sid->num_auths-1];
- if (rid < SIDMAP_LOCAL_USER_BASE) {
- return NT_STATUS_NONE_MAPPED;
- }
-
- if (rid < SIDMAP_LOCAL_GROUP_BASE) {
- struct passwd *pwd;
- uid_t uid = rid - SIDMAP_LOCAL_USER_BASE;
- atype = ATYPE_NORMAL_ACCOUNT;
- *rtype = ds_atype_map(atype);
-
- pwd = getpwuid(uid);
- if (pwd == NULL) {
- *name = talloc_asprintf(mem_ctx, "uid%u", uid);
- } else {
- *name = talloc_strdup(mem_ctx, pwd->pw_name);
- }
- } else {
- struct group *grp;
- gid_t gid = rid - SIDMAP_LOCAL_GROUP_BASE;
- atype = ATYPE_LOCAL_GROUP;
- *rtype = ds_atype_map(atype);
- grp = getgrgid(gid);
- if (grp == NULL) {
- *name = talloc_asprintf(mem_ctx, "gid%u", gid);
- } else {
- *name = talloc_strdup(mem_ctx, grp->gr_name);
- }
- }
-
- if (*name == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- return NT_STATUS_OK;
-}
diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c
index 45f19e93bb..c9562b0de7 100644
--- a/source4/dsdb/common/util.c
+++ b/source4/dsdb/common/util.c
@@ -1433,63 +1433,6 @@ struct ldb_dn *samdb_server_site_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx
}
/*
- * This works out if we are running on a supported forest/domain function
- * level. Basically this means that we don't support mixed/interim (NT 4 DC
- * support) levels.
- * If errmsg isn't NULL we write in an adequate error message for printing out
- * to the screen.
- */
-bool samdb_is_capable_dc(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
- char **errmsg)
-{
- int32_t level_forest, level_domain, level_domain_mixed;
- bool ret = true;
-
- level_forest = (int32_t) samdb_search_int64(ldb, mem_ctx, -1,
- samdb_partitions_dn(ldb, mem_ctx), "msDS-Behavior-Version",
- NULL);
- level_domain = (int32_t) samdb_search_int64(ldb, mem_ctx, -1,
- samdb_base_dn(ldb), "msDS-Behavior-Version", NULL);
- level_domain_mixed = (int32_t) samdb_search_int64(ldb, mem_ctx, -1,
- samdb_base_dn(ldb), "nTMixedDomain", NULL);
-
- if (errmsg != NULL)
- *errmsg = talloc_strdup(mem_ctx, "");
-
- if (level_forest == -1 || level_domain == -1 || level_domain_mixed == -1) {
- ret = false;
- if (errmsg != NULL)
- *errmsg = talloc_strdup_append(*errmsg,
- "\nATTENTION: Invalid values for forest and/or domain function level!"
- );
- }
-
- if (level_forest == DS_DOMAIN_FUNCTION_2003_MIXED) {
- ret = false;
- if (errmsg != NULL)
- *errmsg = talloc_strdup_append(*errmsg,
- "\nATTENTION: You run SAMBA 4 on the 2003 with mixed domains (NT4 DC support) forest level. This isn't supported!"
- );
- }
- if ((level_domain == DS_DOMAIN_FUNCTION_2000 && level_domain_mixed != 0)
- || level_domain == DS_DOMAIN_FUNCTION_2003_MIXED) {
- ret = false;
- if (errmsg != NULL)
- *errmsg = talloc_strdup_append(*errmsg,
- "\nATTENTION: You run SAMBA 4 on a mixed/interim (NT4 DC support) domain level. This isn't supported!"
- );
- }
-
- if ((!ret) && (errmsg != NULL)) {
- *errmsg = talloc_strdup_append(*errmsg,
- "\nPlease raise the domain and/or forest level to an adequate value. Use for this the 'domainlevel' tool, the MS AD MMC tools or manipulate the needed attributes directly."
- );
- }
-
- return ret;
-}
-
-/*
work out if we are the PDC for the domain of the current open ldb
*/
bool samdb_is_pdc(struct ldb_context *ldb)
@@ -1588,7 +1531,7 @@ int samdb_search_for_parent_domain(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
while ((sdn = ldb_dn_get_parent(local_ctx, sdn))) {
ret = ldb_search(ldb, local_ctx, &res, sdn, LDB_SCOPE_BASE, attrs,
- "(|(|(objectClass=domain)(objectClass=builtinDomain))(objectClass=samba4LocalDomain))");
+ "(|(objectClass=domain)(objectClass=builtinDomain))");
if (ret == LDB_SUCCESS) {
if (res->count == 1) {
break;
@@ -1640,21 +1583,22 @@ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
struct samr_Password *param_lmNewHash,
struct samr_Password *param_ntNewHash,
bool user_change,
- enum samr_RejectReason *reject_reason,
+ enum samPwdChangeReason *reject_reason,
struct samr_DomInfo1 **_dominfo)
{
- const char * const user_attrs[] = { "userAccountControl", "lmPwdHistory",
+ const char * const user_attrs[] = { "userAccountControl",
+ "lmPwdHistory",
"ntPwdHistory",
"dBCSPwd", "unicodePwd",
"objectSid",
"pwdLastSet", NULL };
- const char * const domain_attrs[] = { "pwdProperties", "pwdHistoryLength",
- "maxPwdAge", "minPwdAge",
- "minPwdLength", NULL };
+ const char * const domain_attrs[] = { "minPwdLength", "pwdProperties",
+ "pwdHistoryLength",
+ "maxPwdAge", "minPwdAge", NULL };
NTTIME pwdLastSet;
- int64_t minPwdAge;
- uint_t minPwdLength, pwdProperties, pwdHistoryLength;
- uint_t userAccountControl;
+ uint32_t minPwdLength, pwdProperties, pwdHistoryLength;
+ int64_t maxPwdAge, minPwdAge;
+ uint32_t userAccountControl;
struct samr_Password *sambaLMPwdHistory, *sambaNTPwdHistory,
*lmPwdHash, *ntPwdHash, *lmNewHash, *ntNewHash;
struct samr_Password local_lmNewHash, local_ntNewHash;
@@ -1675,14 +1619,14 @@ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
if (count != 1) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
- userAccountControl = samdb_result_uint(res[0], "userAccountControl", 0);
- sambaLMPwdHistory_len = samdb_result_hashes(mem_ctx, res[0],
- "lmPwdHistory", &sambaLMPwdHistory);
- sambaNTPwdHistory_len = samdb_result_hashes(mem_ctx, res[0],
- "ntPwdHistory", &sambaNTPwdHistory);
- lmPwdHash = samdb_result_hash(mem_ctx, res[0], "dBCSPwd");
- ntPwdHash = samdb_result_hash(mem_ctx, res[0], "unicodePwd");
- pwdLastSet = samdb_result_uint64(res[0], "pwdLastSet", 0);
+ userAccountControl = samdb_result_uint(res[0], "userAccountControl", 0);
+ sambaLMPwdHistory_len = samdb_result_hashes(mem_ctx, res[0],
+ "lmPwdHistory", &sambaLMPwdHistory);
+ sambaNTPwdHistory_len = samdb_result_hashes(mem_ctx, res[0],
+ "ntPwdHistory", &sambaNTPwdHistory);
+ lmPwdHash = samdb_result_hash(mem_ctx, res[0], "dBCSPwd");
+ ntPwdHash = samdb_result_hash(mem_ctx, res[0], "unicodePwd");
+ pwdLastSet = samdb_result_uint64(res[0], "pwdLastSet", 0);
/* Copy parameters */
lmNewHash = param_lmNewHash;
@@ -1695,9 +1639,10 @@ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
|UF_WORKSTATION_TRUST_ACCOUNT
|UF_SERVER_TRUST_ACCOUNT));
- if (domain_dn) {
+ if (domain_dn != NULL) {
/* pull the domain parameters */
- count = gendb_search_dn(ctx, mem_ctx, domain_dn, &res, domain_attrs);
+ count = gendb_search_dn(ctx, mem_ctx, domain_dn, &res,
+ domain_attrs);
if (count != 1) {
DEBUG(2, ("samdb_set_password: Domain DN %s is invalid, for user %s\n",
ldb_dn_get_linearized(domain_dn),
@@ -1706,14 +1651,15 @@ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
}
} else {
/* work out the domain sid, and pull the domain from there */
- domain_sid = samdb_result_sid_prefix(mem_ctx, res[0], "objectSid");
+ domain_sid = samdb_result_sid_prefix(mem_ctx, res[0],
+ "objectSid");
if (domain_sid == NULL) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
count = gendb_search(ctx, mem_ctx, NULL, &res, domain_attrs,
- "(objectSid=%s)",
- ldap_encode_ndr_dom_sid(mem_ctx, domain_sid));
+ "(objectSid=%s)",
+ ldap_encode_ndr_dom_sid(mem_ctx, domain_sid));
if (count != 1) {
DEBUG(2, ("samdb_set_password: Could not find domain to match SID: %s, for user %s\n",
dom_sid_string(mem_ctx, domain_sid),
@@ -1722,17 +1668,18 @@ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
}
}
- pwdProperties = samdb_result_uint(res[0], "pwdProperties", 0);
- pwdHistoryLength = samdb_result_uint(res[0], "pwdHistoryLength", 0);
- minPwdLength = samdb_result_uint(res[0], "minPwdLength", 0);
- minPwdAge = samdb_result_int64(res[0], "minPwdAge", 0);
+ minPwdLength = samdb_result_uint(res[0], "minPwdLength", 0);
+ pwdProperties = samdb_result_uint(res[0], "pwdProperties", 0);
+ pwdHistoryLength = samdb_result_uint(res[0], "pwdHistoryLength", 0);
+ maxPwdAge = samdb_result_int64(res[0], "maxPwdAge", 0);
+ minPwdAge = samdb_result_int64(res[0], "minPwdAge", 0);
- if (userAccountControl & UF_PASSWD_NOTREQD) {
+ if ((userAccountControl & UF_PASSWD_NOTREQD) != 0) {
/* see [MS-ADTS] 2.2.15 */
minPwdLength = 0;
}
- if (_dominfo) {
+ if (_dominfo != NULL) {
struct samr_DomInfo1 *dominfo;
/* on failure we need to fill in the reject reasons */
dominfo = talloc(mem_ctx, struct samr_DomInfo1);
@@ -1742,24 +1689,27 @@ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
dominfo->min_password_length = minPwdLength;
dominfo->password_properties = pwdProperties;
dominfo->password_history_length = pwdHistoryLength;
- dominfo->max_password_age = minPwdAge;
+ dominfo->max_password_age = maxPwdAge;
dominfo->min_password_age = minPwdAge;
*_dominfo = dominfo;
}
- if (restrictions && new_password) {
+ if ((restrictions != 0) && (new_password != 0)) {
char *new_pass;
- /* check the various password restrictions */
- if (restrictions && minPwdLength > utf16_len_n(new_password->data, new_password->length) / 2) {
+ /* checks if the "minPwdLength" property is satisfied */
+ if ((restrictions != 0)
+ && (minPwdLength > utf16_len_n(
+ new_password->data, new_password->length)/2)) {
if (reject_reason) {
- *reject_reason = SAMR_REJECT_TOO_SHORT;
+ *reject_reason = SAM_PWD_CHANGE_PASSWORD_TOO_SHORT;
}
return NT_STATUS_PASSWORD_RESTRICTION;
}
/* Create the NT hash */
- mdfour(local_ntNewHash.hash, new_password->data, new_password->length);
+ mdfour(local_ntNewHash.hash, new_password->data,
+ new_password->length);
ntNewHash = &local_ntNewHash;
@@ -1770,11 +1720,13 @@ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
new_password->data, new_password->length,
(void **)&new_pass, NULL, false)) {
- /* possibly check password complexity */
- if (restrictions && (pwdProperties & DOMAIN_PASSWORD_COMPLEX) &&
- !check_password_quality(new_pass)) {
+ /* checks the password complexity */
+ if ((restrictions != 0)
+ && ((pwdProperties
+ & DOMAIN_PASSWORD_COMPLEX) != 0)
+ && (!check_password_quality(new_pass))) {
if (reject_reason) {
- *reject_reason = SAMR_REJECT_COMPLEXITY;
+ *reject_reason = SAM_PWD_CHANGE_NOT_COMPLEX;
}
return NT_STATUS_PASSWORD_RESTRICTION;
}
@@ -1786,63 +1738,69 @@ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
}
}
- if (restrictions && user_change) {
+ if ((restrictions != 0) && user_change) {
/* are all password changes disallowed? */
- if (pwdProperties & DOMAIN_REFUSE_PASSWORD_CHANGE) {
+ if ((pwdProperties & DOMAIN_REFUSE_PASSWORD_CHANGE) != 0) {
if (reject_reason) {
- *reject_reason = SAMR_REJECT_OTHER;
+ *reject_reason = SAM_PWD_CHANGE_NO_ERROR;
}
return NT_STATUS_PASSWORD_RESTRICTION;
}
- /* can this user change password? */
- if (userAccountControl & UF_PASSWD_CANT_CHANGE) {
+ /* can this user change the password? */
+ if ((userAccountControl & UF_PASSWD_CANT_CHANGE) != 0) {
if (reject_reason) {
- *reject_reason = SAMR_REJECT_OTHER;
+ *reject_reason = SAM_PWD_CHANGE_NO_ERROR;
}
return NT_STATUS_PASSWORD_RESTRICTION;
}
- /* yes, this is a minus. The ages are in negative 100nsec units! */
+ /* Password minimum age: yes, this is a minus. The ages are in negative 100nsec units! */
if (pwdLastSet - minPwdAge > now_nt) {
if (reject_reason) {
- *reject_reason = SAMR_REJECT_OTHER;
+ *reject_reason = SAM_PWD_CHANGE_NO_ERROR;
}
return NT_STATUS_PASSWORD_RESTRICTION;
}
/* check the immediately past password */
if (pwdHistoryLength > 0) {
- if (lmNewHash && lmPwdHash && memcmp(lmNewHash->hash, lmPwdHash->hash, 16) == 0) {
+ if (lmNewHash && lmPwdHash && memcmp(lmNewHash->hash,
+ lmPwdHash->hash, 16) == 0) {
if (reject_reason) {
- *reject_reason = SAMR_REJECT_IN_HISTORY;
+ *reject_reason = SAM_PWD_CHANGE_PWD_IN_HISTORY;
}
return NT_STATUS_PASSWORD_RESTRICTION;
}
- if (ntNewHash && ntPwdHash && memcmp(ntNewHash->hash, ntPwdHash->hash, 16) == 0) {
+ if (ntNewHash && ntPwdHash && memcmp(ntNewHash->hash,
+ ntPwdHash->hash, 16) == 0) {
if (reject_reason) {
- *reject_reason = SAMR_REJECT_IN_HISTORY;
+ *reject_reason = SAM_PWD_CHANGE_PWD_IN_HISTORY;
}
return NT_STATUS_PASSWORD_RESTRICTION;
}
}
/* check the password history */
- sambaLMPwdHistory_len = MIN(sambaLMPwdHistory_len, pwdHistoryLength);
- sambaNTPwdHistory_len = MIN(sambaNTPwdHistory_len, pwdHistoryLength);
+ sambaLMPwdHistory_len = MIN(sambaLMPwdHistory_len,
+ pwdHistoryLength);
+ sambaNTPwdHistory_len = MIN(sambaNTPwdHistory_len,
+ pwdHistoryLength);
for (i=0; lmNewHash && i<sambaLMPwdHistory_len;i++) {
- if (memcmp(lmNewHash->hash, sambaLMPwdHistory[i].hash, 16) == 0) {
+ if (memcmp(lmNewHash->hash, sambaLMPwdHistory[i].hash,
+ 16) == 0) {
if (reject_reason) {
- *reject_reason = SAMR_REJECT_IN_HISTORY;
+ *reject_reason = SAM_PWD_CHANGE_PWD_IN_HISTORY;
}
return NT_STATUS_PASSWORD_RESTRICTION;
}
}
for (i=0; ntNewHash && i<sambaNTPwdHistory_len;i++) {
- if (memcmp(ntNewHash->hash, sambaNTPwdHistory[i].hash, 16) == 0) {
+ if (memcmp(ntNewHash->hash, sambaNTPwdHistory[i].hash,
+ 16) == 0) {
if (reject_reason) {
- *reject_reason = SAMR_REJECT_IN_HISTORY;
+ *reject_reason = SAM_PWD_CHANGE_PWD_IN_HISTORY;
}
return NT_STATUS_PASSWORD_RESTRICTION;
}
@@ -1852,7 +1810,7 @@ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
#define CHECK_RET(x) do { if (x != 0) return NT_STATUS_NO_MEMORY; } while(0)
/* the password is acceptable. Start forming the new fields */
- if (new_password) {
+ if (new_password != NULL) {
/* if we know the cleartext UTF16 password, then set it.
* Modules in ldb will set all the appropriate
* hashes */
@@ -1875,6 +1833,9 @@ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
}
}
+ if (reject_reason) {
+ *reject_reason = SAM_PWD_CHANGE_NO_ERROR;
+ }
return NT_STATUS_OK;
}
@@ -1893,7 +1854,7 @@ NTSTATUS samdb_set_password_sid(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
struct samr_Password *lmNewHash,
struct samr_Password *ntNewHash,
bool user_change,
- enum samr_RejectReason *reject_reason,
+ enum samPwdChangeReason *reject_reason,
struct samr_DomInfo1 **_dominfo)
{
NTSTATUS nt_status;
@@ -2567,3 +2528,53 @@ int drsuapi_DsReplicaCursor2_compare(const struct drsuapi_DsReplicaCursor2 *c1,
{
return GUID_compare(&c1->source_dsa_invocation_id, &c2->source_dsa_invocation_id);
}
+
+/*
+ see if we are a RODC
+
+ TODO: This should take a sam_ctx, and lookup the right object (with
+ a cache)
+*/
+bool samdb_rodc(struct loadparm_context *lp_ctx)
+{
+ return lp_parm_bool(lp_ctx, NULL, "repl", "RODC", false);
+}
+
+
+/*
+ return NTDS options flags. See MS-ADTS 7.1.1.2.2.1.2.1.1
+
+ flags are DS_NTDS_OPTION_*
+*/
+int samdb_ntds_options(struct ldb_context *ldb, uint32_t *options)
+{
+ TALLOC_CTX *tmp_ctx;
+ const char *attrs[] = { "options", NULL };
+ int ret;
+ struct ldb_result *res;
+
+ tmp_ctx = talloc_new(ldb);
+ if (tmp_ctx == NULL) {
+ goto failed;
+ }
+
+ ret = ldb_search(ldb, tmp_ctx, &res, samdb_ntds_settings_dn(ldb), LDB_SCOPE_BASE, attrs, NULL);
+ if (ret) {
+ goto failed;
+ }
+
+ if (res->count != 1) {
+ goto failed;
+ }
+
+ *options = samdb_result_uint(res->msgs[0], "options", 0);
+
+ talloc_free(tmp_ctx);
+
+ return LDB_SUCCESS;
+
+failed:
+ DEBUG(1,("Failed to find our own NTDS Settings objectGUID in the ldb!\n"));
+ talloc_free(tmp_ctx);
+ return LDB_ERR_NO_SUCH_OBJECT;
+}
diff --git a/source4/dsdb/config.mk b/source4/dsdb/config.mk
index 4150ba0d54..59daa745e9 100644
--- a/source4/dsdb/config.mk
+++ b/source4/dsdb/config.mk
@@ -25,7 +25,6 @@ $(eval $(call proto_header_template,$(dsdbsrcdir)/samdb/samdb_proto.h,$(SAMDB_OB
PRIVATE_DEPENDENCIES = LIBLDB
SAMDB_COMMON_OBJ_FILES = $(addprefix $(dsdbsrcdir)/common/, \
- sidmap.o \
util.o) \
../libds/common/flag_mapping.o
$(eval $(call proto_header_template,$(dsdbsrcdir)/common/proto.h,$(SAMDB_COMMON_OBJ_FILES:.o=.c)))
@@ -40,7 +39,8 @@ SAMDB_SCHEMA_OBJ_FILES = $(addprefix $(dsdbsrcdir)/schema/, \
schema_syntax.o \
schema_description.o \
schema_convert_to_ol.o \
- schema_inferiors.o)
+ schema_inferiors.o \
+ schema_prefixmap.o)
$(eval $(call proto_header_template,$(dsdbsrcdir)/schema/proto.h,$(SAMDB_SCHEMA_OBJ_FILES:.o=.c)))
# PUBLIC_HEADERS += dsdb/schema/schema.h
diff --git a/source4/dsdb/kcc/kcc_periodic.c b/source4/dsdb/kcc/kcc_periodic.c
index 44e0c7ae8b..30d43033cb 100644
--- a/source4/dsdb/kcc/kcc_periodic.c
+++ b/source4/dsdb/kcc/kcc_periodic.c
@@ -152,7 +152,7 @@ static NTSTATUS kccsrv_simple_update(struct kccsrv_service *s, TALLOC_CTX *mem_c
r1->other_info = talloc_zero(reps, struct repsFromTo1OtherInfo);
r1->other_info->dns_name = talloc_asprintf(r1->other_info, "%s._msdcs.%s",
GUID_string(mem_ctx, &ntds_guid),
- lp_realm(s->task->lp_ctx));
+ lp_dnsdomain(s->task->lp_ctx));
r1->source_dsa_obj_guid = ntds_guid;
r1->source_dsa_invocation_id = invocation_id;
r1->replica_flags =
diff --git a/source4/dsdb/repl/drepl_out_helpers.c b/source4/dsdb/repl/drepl_out_helpers.c
index 5c63c111f3..c86956c42f 100644
--- a/source4/dsdb/repl/drepl_out_helpers.c
+++ b/source4/dsdb/repl/drepl_out_helpers.c
@@ -506,10 +506,9 @@ static void dreplsrv_update_refs_send(struct dreplsrv_op_pull_source_state *st)
ntds_guid_str = GUID_string(r, &service->ntds_guid);
if (composite_nomem(ntds_guid_str, c)) return;
- /* lp_realm() is not really right here */
ntds_dns_name = talloc_asprintf(r, "%s._msdcs.%s",
ntds_guid_str,
- lp_realm(service->task->lp_ctx));
+ lp_dnsdomain(service->task->lp_ctx));
if (composite_nomem(ntds_dns_name, c)) return;
r->in.bind_handle = &drsuapi->bind_handle;
@@ -520,7 +519,7 @@ static void dreplsrv_update_refs_send(struct dreplsrv_op_pull_source_state *st)
r->in.req.req1.options =
DRSUAPI_DS_REPLICA_UPDATE_ADD_REFERENCE |
DRSUAPI_DS_REPLICA_UPDATE_DELETE_REFERENCE;
- if (!lp_parm_bool(service->task->lp_ctx, NULL, "repl", "RODC", false)) {
+ if (!samdb_rodc(service->task->lp_ctx)) {
r->in.req.req1.options |= DRSUAPI_DS_REPLICA_UPDATE_WRITEABLE;
}
diff --git a/source4/dsdb/repl/replicated_objects.c b/source4/dsdb/repl/replicated_objects.c
index 5d7ae11a57..ec5dcd4720 100644
--- a/source4/dsdb/repl/replicated_objects.c
+++ b/source4/dsdb/repl/replicated_objects.c
@@ -424,35 +424,78 @@ WERROR dsdb_origin_objects_commit(struct ldb_context *ldb,
return WERR_OK;
}
+ ret = ldb_transaction_start(ldb);
+ if (ret != LDB_SUCCESS) {
+ return WERR_DS_INTERNAL_FAILURE;
+ }
+
objects = talloc_array(mem_ctx, struct ldb_message *,
num_objects);
- W_ERROR_HAVE_NO_MEMORY(objects);
+ if (objects == NULL) {
+ status = WERR_NOMEM;
+ goto cancel;
+ }
for (i=0, cur = first_object; cur; cur = cur->next_object, i++) {
status = dsdb_convert_object(ldb, schema,
cur, objects, &objects[i]);
- W_ERROR_NOT_OK_RETURN(status);
+ if (!W_ERROR_IS_OK(status)) {
+ goto cancel;
+ }
}
ids = talloc_array(mem_ctx,
struct drsuapi_DsReplicaObjectIdentifier2,
num_objects);
- W_ERROR_HAVE_NO_MEMORY(objects);
+ if (ids == NULL) {
+ status = WERR_NOMEM;
+ goto cancel;
+ }
for (i=0; i < num_objects; i++) {
struct dom_sid *sid = NULL;
+ struct ldb_request *add_req;
DEBUG(6,(__location__ ": adding %s\n",
ldb_dn_get_linearized(objects[i]->dn)));
+
+ ret = ldb_build_add_req(&add_req,
+ ldb,
+ objects,
+ objects[i],
+ NULL,
+ NULL,
+ ldb_op_default_callback,
+ NULL);
+ if (ret != LDB_SUCCESS) {
+ status = WERR_DS_INTERNAL_FAILURE;
+ goto cancel;
+ }
+
+ ret = ldb_request_add_control(add_req, LDB_CONTROL_RELAX_OID, true, NULL);
+ if (ret != LDB_SUCCESS) {
+ status = WERR_DS_INTERNAL_FAILURE;
+ goto cancel;
+ }
- ret = ldb_add(ldb, objects[i]);
- if (ret != 0) {
+ ret = ldb_request(ldb, add_req);
+ if (ret == LDB_SUCCESS) {
+ ret = ldb_wait(add_req->handle, LDB_WAIT_ALL);
+ }
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0,(__location__ ": Failed add of %s - %s\n",
+ ldb_dn_get_linearized(objects[i]->dn), ldb_errstring(ldb)));
+ status = WERR_DS_INTERNAL_FAILURE;
goto cancel;
}
+
+ talloc_free(add_req);
+
ret = ldb_search(ldb, objects, &res, objects[i]->dn,
LDB_SCOPE_BASE, attrs,
"(objectClass=*)");
- if (ret != 0) {
+ if (ret != LDB_SUCCESS) {
+ status = WERR_DS_INTERNAL_FAILURE;
goto cancel;
}
ids[i].guid = samdb_result_guid(res->msgs[0], "objectGUID");
@@ -464,13 +507,19 @@ WERROR dsdb_origin_objects_commit(struct ldb_context *ldb,
}
}
+ ret = ldb_transaction_commit(ldb);
+ if (ret != LDB_SUCCESS) {
+ return WERR_DS_INTERNAL_FAILURE;
+ }
+
talloc_free(objects);
*_num = num_objects;
*_ids = ids;
return WERR_OK;
+
cancel:
talloc_free(objects);
ldb_transaction_cancel(ldb);
- return WERR_FOOBAR;
+ return status;
}
diff --git a/source4/dsdb/samdb/cracknames.c b/source4/dsdb/samdb/cracknames.c
index 723f51356a..8f7f481e2d 100644
--- a/source4/dsdb/samdb/cracknames.c
+++ b/source4/dsdb/samdb/cracknames.c
@@ -1288,11 +1288,9 @@ NTSTATUS crack_name_to_nt4_name(TALLOC_CTX *mem_ctx,
}
p[0] = '\0';
- if (p[1]) {
- *nt4_account = talloc_strdup(mem_ctx, &p[1]);
- if (*nt4_account == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
+ *nt4_account = talloc_strdup(mem_ctx, &p[1]);
+ if (*nt4_account == NULL) {
+ return NT_STATUS_NO_MEMORY;
}
return NT_STATUS_OK;
diff --git a/source4/dsdb/samdb/ldb_modules/acl.c b/source4/dsdb/samdb/ldb_modules/acl.c
index 1b02abcb8e..2f123145db 100644
--- a/source4/dsdb/samdb/ldb_modules/acl.c
+++ b/source4/dsdb/samdb/ldb_modules/acl.c
@@ -802,6 +802,7 @@ static int acl_modify(struct ldb_module *module, struct ldb_request *req)
return LDB_ERR_OPERATIONS_ERROR;
}
+/* TODO Is this really right? */
/* if (what_is_user(module) == SECURITY_SYSTEM) */
return ldb_next_request(module, req);
@@ -813,7 +814,7 @@ static int acl_modify(struct ldb_module *module, struct ldb_request *req)
ac->user_type = what_is_user(module);
ac->sec_result = LDB_SUCCESS;
if (!is_root_base_dn(ldb, req->op.mod.message->dn) && parent && !is_root_base_dn(ldb, parent)){
- filter = talloc_asprintf(req,"(&(objectClass=*)(|(%s=%s)(%s=%s))))",
+ filter = talloc_asprintf(req,"(&(objectClass=*)(|(%s=%s)(%s=%s))))",
ldb_dn_get_component_name(parent,0),
ldb_dn_get_component_val(parent,0)->data,
ldb_dn_get_component_name(req->op.mod.message->dn,0),
diff --git a/source4/dsdb/samdb/ldb_modules/anr.c b/source4/dsdb/samdb/ldb_modules/anr.c
index deeccac072..a5220b3f91 100644
--- a/source4/dsdb/samdb/ldb_modules/anr.c
+++ b/source4/dsdb/samdb/ldb_modules/anr.c
@@ -67,8 +67,10 @@ static struct ldb_parse_tree *make_parse_list(struct ldb_module *module,
* Make an equality or prefix match tree, from the attribute, operation and matching value supplied
*/
static struct ldb_parse_tree *make_match_tree(struct ldb_module *module,
- TALLOC_CTX *mem_ctx, enum ldb_parse_op op,
- const char *attr, const DATA_BLOB *match)
+ TALLOC_CTX *mem_ctx,
+ enum ldb_parse_op op,
+ const char *attr,
+ struct ldb_val *match)
{
struct ldb_context *ldb;
struct ldb_parse_tree *match_tree;
@@ -123,7 +125,7 @@ struct anr_context {
*/
static int anr_replace_value(struct anr_context *ac,
TALLOC_CTX *mem_ctx,
- const struct ldb_val *match,
+ struct ldb_val *match,
struct ldb_parse_tree **ntree)
{
struct ldb_parse_tree *tree = NULL;
@@ -146,7 +148,7 @@ static int anr_replace_value(struct anr_context *ac,
ac->found_anr = true;
if (match->length > 1 && match->data[0] == '=') {
- DATA_BLOB *match2 = talloc(mem_ctx, DATA_BLOB);
+ struct ldb_val *match2 = talloc(mem_ctx, struct ldb_val);
*match2 = data_blob_const(match->data+1, match->length - 1);
if (match2 == NULL){
ldb_oom(ldb);
@@ -181,8 +183,8 @@ static int anr_replace_value(struct anr_context *ac,
if (p) {
struct ldb_parse_tree *first_split_filter, *second_split_filter, *split_filters, *match_tree_1, *match_tree_2;
- DATA_BLOB *first_match = talloc(tree, DATA_BLOB);
- DATA_BLOB *second_match = talloc(tree, DATA_BLOB);
+ struct ldb_val *first_match = talloc(tree, struct ldb_val);
+ struct ldb_val *second_match = talloc(tree, struct ldb_val);
if (!first_match || !second_match) {
ldb_oom(ldb);
return LDB_ERR_OPERATIONS_ERROR;
diff --git a/source4/dsdb/samdb/ldb_modules/config.mk b/source4/dsdb/samdb/ldb_modules/config.mk
index a49b238591..ea4e722822 100644
--- a/source4/dsdb/samdb/ldb_modules/config.mk
+++ b/source4/dsdb/samdb/ldb_modules/config.mk
@@ -1,4 +1,14 @@
################################################
+# Start SUBSYSTEM DSDB_MODULE_HELPERS
+[SUBSYSTEM::DSDB_MODULE_HELPERS]
+PRIVATE_DEPENDENCIES = LIBLDB
+
+DSDB_MODULE_HELPERS_OBJ_FILES = $(dsdbsrcdir)/samdb/ldb_modules/util.o
+
+$(eval $(call proto_header_template,$(dsdbsrcdir)/samdb/ldb_modules/util_proto.h,$(DSDB_MODULE_HELPERS_OBJ_FILES:.o=.c)))
+
+
+################################################
# Start MODULE ldb_objectguid
[MODULE::ldb_objectguid]
SUBSYSTEM = LIBLDB
@@ -15,7 +25,7 @@ ldb_objectguid_OBJ_FILES = $(dsdbsrcdir)/samdb/ldb_modules/objectguid.o
SUBSYSTEM = LIBLDB
PRIVATE_DEPENDENCIES = SAMDB LIBTALLOC LIBEVENTS \
LIBNDR NDR_DRSUAPI \
- NDR_DRSBLOBS LIBNDR
+ NDR_DRSBLOBS LIBNDR DSDB_MODULE_HELPERS
INIT_FUNCTION = LDB_MODULE(repl_meta_data)
# End MODULE ldb_repl_meta_data
################################################
@@ -39,7 +49,7 @@ ldb_dsdb_cache_OBJ_FILES = \
# Start MODULE ldb_schema_fsmo
[MODULE::ldb_schema_fsmo]
SUBSYSTEM = LIBLDB
-PRIVATE_DEPENDENCIES = SAMDB LIBTALLOC LIBEVENTS
+PRIVATE_DEPENDENCIES = SAMDB LIBTALLOC LIBEVENTS DSDB_MODULE_HELPERS
INIT_FUNCTION = LDB_MODULE(schema_fsmo)
# End MODULE ldb_schema_fsmo
################################################
@@ -51,7 +61,7 @@ ldb_schema_fsmo_OBJ_FILES = \
# Start MODULE ldb_naming_fsmo
[MODULE::ldb_naming_fsmo]
SUBSYSTEM = LIBLDB
-PRIVATE_DEPENDENCIES = SAMDB LIBTALLOC LIBEVENTS
+PRIVATE_DEPENDENCIES = SAMDB LIBTALLOC LIBEVENTS DSDB_MODULE_HELPERS
INIT_FUNCTION = LDB_MODULE(naming_fsmo)
# End MODULE ldb_naming_fsmo
################################################
@@ -63,7 +73,7 @@ ldb_naming_fsmo_OBJ_FILES = \
# Start MODULE ldb_pdc_fsmo
[MODULE::ldb_pdc_fsmo]
SUBSYSTEM = LIBLDB
-PRIVATE_DEPENDENCIES = SAMDB LIBTALLOC LIBEVENTS
+PRIVATE_DEPENDENCIES = SAMDB LIBTALLOC LIBEVENTS DSDB_MODULE_HELPERS
INIT_FUNCTION = LDB_MODULE(pdc_fsmo)
# End MODULE ldb_pdc_fsmo
################################################
@@ -220,7 +230,7 @@ ldb_show_deleted_OBJ_FILES = $(dsdbsrcdir)/samdb/ldb_modules/show_deleted.o
# Start MODULE ldb_partition
[MODULE::ldb_partition]
SUBSYSTEM = LIBLDB
-PRIVATE_DEPENDENCIES = LIBTALLOC LIBEVENTS SAMDB
+PRIVATE_DEPENDENCIES = LIBTALLOC LIBEVENTS SAMDB DSDB_MODULE_HELPERS
INIT_FUNCTION = LDB_MODULE(partition)
# End MODULE ldb_partition
################################################
@@ -369,3 +379,15 @@ INIT_FUNCTION = LDB_MODULE(acl)
################################################
ldb_acl_OBJ_FILES = $(dsdbsrcdir)/samdb/ldb_modules/acl.o
+
+################################################
+# Start MODULE ldb_lazy_commit
+[MODULE::ldb_lazy_commit]
+PRIVATE_DEPENDENCIES = SAMDB
+SUBSYSTEM = LIBLDB
+INIT_FUNCTION = LDB_MODULE(lazy_commit)
+
+# End MODULE ldb_lazy_commit
+################################################
+
+ldb_lazy_commit_OBJ_FILES = $(dsdbsrcdir)/samdb/ldb_modules/lazy_commit.o
diff --git a/source4/dsdb/samdb/ldb_modules/extended_dn_out.c b/source4/dsdb/samdb/ldb_modules/extended_dn_out.c
index f93090ace9..bb5e3795db 100644
--- a/source4/dsdb/samdb/ldb_modules/extended_dn_out.c
+++ b/source4/dsdb/samdb/ldb_modules/extended_dn_out.c
@@ -340,7 +340,8 @@ static int extended_callback(struct ldb_request *req, struct ldb_reply *ares)
}
/* Look to see if this attributeSyntax is a DN */
- if (strcmp(attribute->attributeSyntax_oid, "2.5.5.1") != 0) {
+ if (strcmp(attribute->attributeSyntax_oid, "2.5.5.1") != 0 &&
+ strcmp(attribute->attributeSyntax_oid, "2.5.5.7") != 0) {
continue;
}
@@ -617,7 +618,8 @@ static int extended_dn_out_dereference_init(struct ldb_module *module)
NULL
};
- if (strcmp(cur->syntax->attributeSyntax_oid, "2.5.5.1") != 0) {
+ if (strcmp(cur->syntax->attributeSyntax_oid, "2.5.5.1") != 0 &&
+ strcmp(cur->syntax->attributeSyntax_oid, "2.5.5.7") != 0) {
continue;
}
dereference_control->dereference
diff --git a/source4/dsdb/samdb/ldb_modules/extended_dn_store.c b/source4/dsdb/samdb/ldb_modules/extended_dn_store.c
index 3234f6f269..122a9bb2b7 100644
--- a/source4/dsdb/samdb/ldb_modules/extended_dn_store.c
+++ b/source4/dsdb/samdb/ldb_modules/extended_dn_store.c
@@ -303,7 +303,8 @@ static int extended_dn_add(struct ldb_module *module, struct ldb_request *req)
}
/* We only setup an extended DN GUID on these particular DN objects */
- if (strcmp(schema_attr->attributeSyntax_oid, "2.5.5.1") != 0) {
+ if (strcmp(schema_attr->attributeSyntax_oid, "2.5.5.1") != 0 &&
+ strcmp(schema_attr->attributeSyntax_oid, "2.5.5.7") != 0) {
continue;
}
@@ -376,7 +377,8 @@ static int extended_dn_modify(struct ldb_module *module, struct ldb_request *req
}
/* We only setup an extended DN GUID on these particular DN objects */
- if (strcmp(schema_attr->attributeSyntax_oid, "2.5.5.1") != 0) {
+ if (strcmp(schema_attr->attributeSyntax_oid, "2.5.5.1") != 0 &&
+ strcmp(schema_attr->attributeSyntax_oid, "2.5.5.7") != 0) {
continue;
}
diff --git a/source4/dsdb/samdb/ldb_modules/instancetype.c b/source4/dsdb/samdb/ldb_modules/instancetype.c
index de46c0a42a..201ed04412 100644
--- a/source4/dsdb/samdb/ldb_modules/instancetype.c
+++ b/source4/dsdb/samdb/ldb_modules/instancetype.c
@@ -77,8 +77,6 @@ static int instancetype_add(struct ldb_module *module, struct ldb_request *req)
struct it_context *ac;
uint32_t instance_type;
int ret;
- const struct ldb_control *partition_ctrl;
- const struct dsdb_control_current_partition *partition;
ldb = ldb_module_get_ctx(module);
@@ -90,31 +88,19 @@ static int instancetype_add(struct ldb_module *module, struct ldb_request *req)
}
if (ldb_msg_find_element(req->op.add.message, "instanceType")) {
+ unsigned int instanceType = ldb_msg_find_attr_as_uint(req->op.add.message, "instanceType", 0);
+
+ if (instanceType & INSTANCE_TYPE_IS_NC_HEAD) {
+ /* Do something in future */
+ }
+
/* TODO: we need to validate and possibly create a new
partition */
return ldb_next_request(module, req);
}
- partition_ctrl = ldb_request_get_control(req, DSDB_CONTROL_CURRENT_PARTITION_OID);
- if (!partition_ctrl) {
- ldb_debug_set(ldb, LDB_DEBUG_FATAL,
- "instancetype_add: no current partition control found");
- return LDB_ERR_CONSTRAINT_VIOLATION;
- }
-
- partition = talloc_get_type(partition_ctrl->data,
- struct dsdb_control_current_partition);
- SMB_ASSERT(partition && partition->version == DSDB_CONTROL_CURRENT_PARTITION_VERSION);
-
- ac = talloc(req, struct it_context);
- if (ac == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
- ac->module = module;
- ac->req = req;
-
/* we have to copy the message as the caller might have it as a const */
- msg = ldb_msg_copy_shallow(ac, req->op.add.message);
+ msg = ldb_msg_copy_shallow(req, req->op.add.message);
if (msg == NULL) {
ldb_oom(ldb);
return LDB_ERR_OPERATIONS_ERROR;
@@ -124,12 +110,6 @@ static int instancetype_add(struct ldb_module *module, struct ldb_request *req)
* TODO: calculate correct instance type
*/
instance_type = INSTANCE_TYPE_WRITE;
- if (ldb_dn_compare(partition->dn, msg->dn) == 0) {
- instance_type |= INSTANCE_TYPE_IS_NC_HEAD;
- if (ldb_dn_compare(msg->dn, samdb_base_dn(ldb)) != 0) {
- instance_type |= INSTANCE_TYPE_NC_ABOVE;
- }
- }
ret = ldb_msg_add_fmt(msg, "instanceType", "%u", instance_type);
if (ret != LDB_SUCCESS) {
@@ -137,10 +117,10 @@ static int instancetype_add(struct ldb_module *module, struct ldb_request *req)
return LDB_ERR_OPERATIONS_ERROR;
}
- ret = ldb_build_add_req(&down_req, ldb, ac,
+ ret = ldb_build_add_req(&down_req, ldb, req,
msg,
req->controls,
- ac, it_callback,
+ req->context, req->callback,
req);
if (ret != LDB_SUCCESS) {
return ret;
diff --git a/source4/dsdb/samdb/ldb_modules/kludge_acl.c b/source4/dsdb/samdb/ldb_modules/kludge_acl.c
index 34f848de8a..79309e82bf 100644
--- a/source4/dsdb/samdb/ldb_modules/kludge_acl.c
+++ b/source4/dsdb/samdb/ldb_modules/kludge_acl.c
@@ -379,7 +379,7 @@ static int kludge_acl_search(struct ldb_module *module, struct ldb_request *req)
ac, kludge_acl_callback,
req);
if (ret != LDB_SUCCESS) {
- return LDB_ERR_OPERATIONS_ERROR;
+ return ret;
}
/* check if there's an SD_FLAGS control */
diff --git a/source4/dsdb/samdb/ldb_modules/lazy_commit.c b/source4/dsdb/samdb/ldb_modules/lazy_commit.c
new file mode 100644
index 0000000000..69ac99e246
--- /dev/null
+++ b/source4/dsdb/samdb/ldb_modules/lazy_commit.c
@@ -0,0 +1,132 @@
+/*
+ ldb database library
+
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Name: ldb
+ *
+ * Component: ldb lazy_commit module
+ *
+ * Description: module to pretend to support the 'lazy commit' control
+ *
+ * Author: Andrew Bartlett
+ */
+
+#include "ldb_module.h"
+
+static int unlazy_op(struct ldb_module *module, struct ldb_request *req)
+{
+ int ret;
+ struct ldb_request *new_req;
+ struct ldb_control **saved_controls;
+ struct ldb_control *control = ldb_request_get_control(req, LDB_CONTROL_SERVER_LAZY_COMMIT);
+ if (!control) {
+ return ldb_next_request(module, req);
+ }
+
+ switch (req->operation) {
+ case LDB_SEARCH:
+ ret = ldb_build_search_req_ex(&new_req, ldb_module_get_ctx(module),
+ req,
+ req->op.search.base,
+ req->op.search.scope,
+ req->op.search.tree,
+ req->op.search.attrs,
+ req->controls,
+ req->context, req->callback,
+ req);
+ break;
+ case LDB_ADD:
+ ret = ldb_build_add_req(&new_req, ldb_module_get_ctx(module), req,
+ req->op.add.message,
+ req->controls,
+ req->context, req->callback,
+ req);
+ break;
+ case LDB_MODIFY:
+ ret = ldb_build_mod_req(&new_req, ldb_module_get_ctx(module), req,
+ req->op.mod.message,
+ req->controls,
+ req->context, req->callback,
+ req);
+ break;
+ case LDB_DELETE:
+ ret = ldb_build_del_req(&new_req, ldb_module_get_ctx(module), req,
+ req->op.del.dn,
+ req->controls,
+ req->context, req->callback,
+ req);
+ break;
+ case LDB_RENAME:
+ ret = ldb_build_rename_req(&new_req, ldb_module_get_ctx(module), req,
+ req->op.rename.olddn,
+ req->op.rename.newdn,
+ req->controls,
+ req->context, req->callback,
+ req);
+ break;
+ case LDB_EXTENDED:
+ ret = ldb_build_extended_req(&new_req, ldb_module_get_ctx(module),
+ req,
+ req->op.extended.oid,
+ req->op.extended.data,
+ req->controls,
+ req->context, req->callback,
+ req);
+ break;
+ default:
+ ldb_set_errstring(ldb_module_get_ctx(module),
+ "Unsupported request type!");
+ ret = LDB_ERR_UNWILLING_TO_PERFORM;
+ }
+
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ save_controls(control, req, &saved_controls);
+ return ldb_next_request(module, new_req);
+}
+
+static int unlazy_init(struct ldb_module *module)
+{
+ int ret;
+ struct ldb_context *ldb;
+ ldb = ldb_module_get_ctx(module);
+
+ ret = ldb_mod_register_control(module, LDB_CONTROL_SHOW_DELETED_OID);
+ if (ret != LDB_SUCCESS) {
+ ldb_debug(ldb, LDB_DEBUG_ERROR,
+ "lazy_commit: Unable to register control with rootdse!\n");
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ return ldb_next_init(module);
+}
+
+const struct ldb_module_ops ldb_lazy_commit_module_ops = {
+ .name = "lazy_commit",
+ .search = unlazy_op,
+ .add = unlazy_op,
+ .modify = unlazy_op,
+ .del = unlazy_op,
+ .rename = unlazy_op,
+ .request = unlazy_op,
+ .extended = unlazy_op,
+ .init_context = unlazy_init,
+};
diff --git a/source4/dsdb/samdb/ldb_modules/local_password.c b/source4/dsdb/samdb/ldb_modules/local_password.c
index 58c0f1f0d5..9c386b354d 100644
--- a/source4/dsdb/samdb/ldb_modules/local_password.c
+++ b/source4/dsdb/samdb/ldb_modules/local_password.c
@@ -633,8 +633,7 @@ static int lpdb_delete_callabck(struct ldb_request *req,
ret = ldb_next_request(ac->module, search_req);
if (ret != LDB_SUCCESS) {
- return ldb_module_done(ac->req, NULL, NULL,
- LDB_ERR_OPERATIONS_ERROR);
+ return ldb_module_done(ac->req, NULL, NULL, ret);
}
return LDB_SUCCESS;
}
@@ -1082,7 +1081,7 @@ static int local_password_search(struct ldb_module *module, struct ldb_request *
ac, lpdb_remote_search_callback,
req);
if (ret != LDB_SUCCESS) {
- return LDB_ERR_OPERATIONS_ERROR;
+ return ret;
}
/* perform the search */
diff --git a/source4/dsdb/samdb/ldb_modules/naming_fsmo.c b/source4/dsdb/samdb/ldb_modules/naming_fsmo.c
index 607bf054d2..15cad259ce 100644
--- a/source4/dsdb/samdb/ldb_modules/naming_fsmo.c
+++ b/source4/dsdb/samdb/ldb_modules/naming_fsmo.c
@@ -28,6 +28,7 @@
#include "librpc/gen_ndr/ndr_drsuapi.h"
#include "librpc/gen_ndr/ndr_drsblobs.h"
#include "../lib/util/dlinklist.h"
+#include "dsdb/samdb/ldb_modules/util.h"
static int naming_fsmo_init(struct ldb_module *module)
{
@@ -65,34 +66,15 @@ static int naming_fsmo_init(struct ldb_module *module)
}
ldb_module_set_private(module, naming_fsmo);
- ret = ldb_search(ldb, mem_ctx, &naming_res,
- naming_dn, LDB_SCOPE_BASE,
- naming_attrs, NULL);
+ ret = dsdb_module_search_dn(module, mem_ctx, &naming_res,
+ naming_dn,
+ naming_attrs);
if (ret == LDB_ERR_NO_SUCH_OBJECT) {
ldb_debug(ldb, LDB_DEBUG_WARNING,
"naming_fsmo_init: no partitions dn present: (skip loading of naming contexts details)\n");
talloc_free(mem_ctx);
return ldb_next_init(module);
}
- if (ret != LDB_SUCCESS) {
- ldb_debug_set(ldb, LDB_DEBUG_FATAL,
- "naming_fsmo_init: failed to search the cross-ref container: %s: %s",
- ldb_strerror(ret), ldb_errstring(ldb));
- talloc_free(mem_ctx);
- return ret;
- }
- if (naming_res->count == 0) {
- ldb_debug(ldb, LDB_DEBUG_WARNING,
- "naming_fsmo_init: no cross-ref container present: (skip loading of naming contexts details)\n");
- talloc_free(mem_ctx);
- return ldb_next_init(module);
- } else if (naming_res->count > 1) {
- ldb_debug_set(ldb, LDB_DEBUG_FATAL,
- "naming_fsmo_init: [%u] cross-ref containers found on a base search",
- naming_res->count);
- talloc_free(mem_ctx);
- return LDB_ERR_CONSTRAINT_VIOLATION;
- }
naming_fsmo->master_dn = ldb_msg_find_attr_as_dn(ldb, naming_fsmo, naming_res->msgs[0], "fSMORoleOwner");
if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), naming_fsmo->master_dn) == 0) {
diff --git a/source4/dsdb/samdb/ldb_modules/objectclass.c b/source4/dsdb/samdb/ldb_modules/objectclass.c
index 3cf252c71a..003d6731d4 100644
--- a/source4/dsdb/samdb/ldb_modules/objectclass.c
+++ b/source4/dsdb/samdb/ldb_modules/objectclass.c
@@ -2,7 +2,7 @@
ldb database library
Copyright (C) Simo Sorce 2006-2008
- Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2007
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2009
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -42,6 +42,7 @@
#include "libcli/security/security.h"
#include "auth/auth.h"
#include "param/param.h"
+#include "../libds/common/flags.h"
struct oc_context {
@@ -138,7 +139,13 @@ static int objectclass_sort(struct ldb_module *module,
if (!current->objectclass) {
ldb_asprintf_errstring(ldb, "objectclass %.*s is not a valid objectClass in schema",
(int)objectclass_element->values[i].length, (const char *)objectclass_element->values[i].data);
- return LDB_ERR_OBJECT_CLASS_VIOLATION;
+ /* This looks weird, but windows apparently returns this for invalid objectClass values */
+ return LDB_ERR_NO_SUCH_ATTRIBUTE;
+ } else if (current->objectclass->isDefunct) {
+ ldb_asprintf_errstring(ldb, "objectclass %.*s marked as isDefunct objectClass in schema - not valid for new objects",
+ (int)objectclass_element->values[i].length, (const char *)objectclass_element->values[i].data);
+ /* This looks weird, but windows apparently returns this for invalid objectClass values */
+ return LDB_ERR_NO_SUCH_ATTRIBUTE;
}
/* this is the root of the tree. We will start
@@ -323,6 +330,8 @@ static int fix_dn(TALLOC_CTX *mem_ctx,
struct ldb_dn **fixed_dn)
{
char *upper_rdn_attr;
+ const struct ldb_val *rdn_val;
+
/* Fix up the DN to be in the standard form, taking particular care to match the parent DN */
*fixed_dn = ldb_dn_copy(mem_ctx, parent_dn);
@@ -332,15 +341,21 @@ static int fix_dn(TALLOC_CTX *mem_ctx,
if (!upper_rdn_attr) {
return LDB_ERR_OPERATIONS_ERROR;
}
-
+
/* Create a new child */
if (ldb_dn_add_child_fmt(*fixed_dn, "X=X") == false) {
return LDB_ERR_OPERATIONS_ERROR;
}
+ /* AD doesn't allow the rDN to be longer than 64 characters */
+ rdn_val = ldb_dn_get_rdn_val(newdn);
+ if (!rdn_val || rdn_val->length > 64) {
+ DEBUG(2,(__location__ ": rDN longer than 64 limit for '%s'\n", ldb_dn_get_linearized(newdn)));
+ return LDB_ERR_CONSTRAINT_VIOLATION;
+ }
+
/* And replace it with CN=foo (we need the attribute in upper case */
- return ldb_dn_set_component(*fixed_dn, 0, upper_rdn_attr,
- *ldb_dn_get_rdn_val(newdn));
+ return ldb_dn_set_component(*fixed_dn, 0, upper_rdn_attr, *rdn_val);
}
/* Fix all attribute names to be in the correct case, and check they are all valid per the schema */
@@ -355,7 +370,8 @@ static int fix_attributes(struct ldb_context *ldb, const struct dsdb_schema *sch
if (!attribute) {
if (strcasecmp(msg->elements[i].name, "clearTextPassword") != 0) {
ldb_asprintf_errstring(ldb, "attribute %s is not a valid attribute in schema", msg->elements[i].name);
- return LDB_ERR_UNDEFINED_ATTRIBUTE_TYPE;
+ /* Apparently Windows sends exactly this behaviour */
+ return LDB_ERR_NO_SUCH_ATTRIBUTE;
}
} else {
msg->elements[i].name = attribute->lDAPDisplayName;
@@ -374,7 +390,7 @@ static int objectclass_add(struct ldb_module *module, struct ldb_request *req)
struct oc_context *ac;
struct ldb_dn *parent_dn;
int ret;
- static const char * const parent_attrs[] = { "objectGUID", NULL };
+ static const char * const parent_attrs[] = { "objectGUID", "objectClass", NULL };
ldb = ldb_module_get_ctx(module);
@@ -458,7 +474,7 @@ static int objectclass_do_add(struct oc_context *ac)
ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, parent does not exist!",
ldb_dn_get_linearized(msg->dn));
talloc_free(mem_ctx);
- return LDB_ERR_UNWILLING_TO_PERFORM;
+ return LDB_ERR_NO_SUCH_OBJECT;
}
} else {
const struct ldb_val *parent_guid;
@@ -484,9 +500,6 @@ static int objectclass_do_add(struct oc_context *ac)
return LDB_ERR_UNWILLING_TO_PERFORM;
}
- /* TODO: Check this is a valid child to this parent,
- * by reading the allowedChildClasses and
- * allowedChildClasssesEffective attributes */
ret = ldb_msg_add_steal_value(msg, "parentGUID", discard_const(parent_guid));
if (ret != LDB_SUCCESS) {
ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, failed to add parentGUID",
@@ -547,7 +560,59 @@ static int objectclass_do_add(struct oc_context *ac)
if (!current->next) {
struct ldb_message_element *el;
int32_t systemFlags = 0;
- DATA_BLOB *sd;
+ const char *rdn_name = ldb_dn_get_rdn_name(msg->dn);
+ if (current->objectclass->rDNAttID
+ && ldb_attr_cmp(rdn_name, current->objectclass->rDNAttID) != 0) {
+ ldb_asprintf_errstring(ldb,
+ "RDN %s is not correct for most specific structural objectclass %s, should be %s",
+ rdn_name, current->objectclass->lDAPDisplayName, current->objectclass->rDNAttID);
+ return LDB_ERR_NAMING_VIOLATION;
+ }
+
+ if (ac->search_res && ac->search_res->message) {
+ struct ldb_message_element *oc_el
+ = ldb_msg_find_element(ac->search_res->message, "objectClass");
+
+ bool allowed_class = false;
+ int i, j;
+ for (i=0; allowed_class == false && oc_el && i < oc_el->num_values; i++) {
+ const struct dsdb_class *sclass;
+
+ sclass = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &oc_el->values[i]);
+ if (!sclass) {
+ /* We don't know this class? what is going on? */
+ continue;
+ }
+ if (ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
+ for (j=0; sclass->systemPossibleInferiors && sclass->systemPossibleInferiors[j]; j++) {
+ if (ldb_attr_cmp(current->objectclass->lDAPDisplayName, sclass->systemPossibleInferiors[j]) == 0) {
+ allowed_class = true;
+ break;
+ }
+ }
+ } else {
+ for (j=0; sclass->systemPossibleInferiors && sclass->systemPossibleInferiors[j]; j++) {
+ if (ldb_attr_cmp(current->objectclass->lDAPDisplayName, sclass->systemPossibleInferiors[j]) == 0) {
+ allowed_class = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (!allowed_class) {
+ ldb_asprintf_errstring(ldb, "structural objectClass %s is not a valid child class for %s",
+ current->objectclass->lDAPDisplayName, ldb_dn_get_linearized(ac->search_res->message->dn));
+ return LDB_ERR_NAMING_VIOLATION;
+ }
+ }
+
+ if (current->objectclass->systemOnly && !ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
+ ldb_asprintf_errstring(ldb, "objectClass %s is systemOnly, rejecting creation of %s",
+ current->objectclass->lDAPDisplayName, ldb_dn_get_linearized(msg->dn));
+ return LDB_ERR_UNWILLING_TO_PERFORM;
+ }
+
if (!ldb_msg_find_element(msg, "objectCategory")) {
value = talloc_strdup(msg, current->objectclass->defaultObjectCategory);
if (value == NULL) {
@@ -649,7 +714,13 @@ static int objectclass_modify(struct ldb_module *module, struct ldb_request *req
if (!schema) {
return ldb_next_request(module, req);
}
- objectclass_element = ldb_msg_find_element(req->op.mod.message, "objectClass");
+
+ /* As with the "real" AD we don't accept empty messages */
+ if (req->op.mod.message->num_elements == 0) {
+ ldb_set_errstring(ldb, "objectclass: modify message must have "
+ "elements/attributes!");
+ return LDB_ERR_UNWILLING_TO_PERFORM;
+ }
ac = oc_init_context(module, req);
if (ac == NULL) {
@@ -658,6 +729,7 @@ static int objectclass_modify(struct ldb_module *module, struct ldb_request *req
/* If no part of this touches the objectClass, then we don't
* need to make any changes. */
+ objectclass_element = ldb_msg_find_element(req->op.mod.message, "objectClass");
/* If the only operation is the deletion of the objectClass
* then go on with just fixing the attribute case */
@@ -824,6 +896,8 @@ static int oc_modify_callback(struct ldb_request *req, struct ldb_reply *ares)
LDB_ERR_OPERATIONS_ERROR);
}
+ talloc_free(ares);
+
ret = ldb_build_search_req(&search_req, ldb, ac,
ac->req->op.mod.message->dn, LDB_SCOPE_BASE,
"(objectClass=*)",
@@ -1032,6 +1106,7 @@ static int objectclass_rename_callback(struct ldb_request *req, struct ldb_reply
ares->response, ares->error);
}
+ talloc_free(ares);
/* the ac->search_res should contain the new parents objectGUID */
parent_guid = ldb_msg_find_ldb_val(ac->search_res->message, "objectGUID");
diff --git a/source4/dsdb/samdb/ldb_modules/objectguid.c b/source4/dsdb/samdb/ldb_modules/objectguid.c
index 3d218edc76..12dd402617 100644
--- a/source4/dsdb/samdb/ldb_modules/objectguid.c
+++ b/source4/dsdb/samdb/ldb_modules/objectguid.c
@@ -209,7 +209,7 @@ static int objectguid_add(struct ldb_module *module, struct ldb_request *req)
ac, og_op_callback,
req);
if (ret != LDB_SUCCESS) {
- return LDB_ERR_OPERATIONS_ERROR;
+ return ret;
}
/* go on with the call chain */
@@ -267,7 +267,7 @@ static int objectguid_modify(struct ldb_module *module, struct ldb_request *req)
ac, og_op_callback,
req);
if (ret != LDB_SUCCESS) {
- return LDB_ERR_OPERATIONS_ERROR;
+ return ret;
}
/* go on with the call chain */
diff --git a/source4/dsdb/samdb/ldb_modules/partition.c b/source4/dsdb/samdb/ldb_modules/partition.c
index 6e86d4c484..c5bbdf8dce 100644
--- a/source4/dsdb/samdb/ldb_modules/partition.c
+++ b/source4/dsdb/samdb/ldb_modules/partition.c
@@ -829,14 +829,22 @@ static int partition_sequence_number(struct ldb_module *module, struct ldb_reque
res,
ldb_extended_default_callback,
NULL);
- ret = ldb_next_request(module, treq);
- if (ret == LDB_SUCCESS) {
- ret = ldb_wait(treq->handle, LDB_WAIT_ALL);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(res);
+ return ret;
}
+
+ ret = ldb_next_request(module, treq);
if (ret != LDB_SUCCESS) {
talloc_free(res);
return ret;
}
+ ret = ldb_wait(treq->handle, LDB_WAIT_ALL);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(res);
+ return ret;
+ }
+
seqr = talloc_get_type(res->extended->data,
struct ldb_seqnum_result);
if (seqr->flags & LDB_SEQ_TIMESTAMP_SEQUENCE) {
@@ -1083,7 +1091,7 @@ static int partition_extended_schema_update_now(struct ldb_module *module, struc
}
/* fire the first one */
- ret = partition_call_first(ac);
+ ret = partition_call_first(ac);
if (ret != LDB_SUCCESS){
return ret;
@@ -1385,14 +1393,14 @@ static int partition_init(struct ldb_module *module)
if (ret != LDB_SUCCESS) {
ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_ERROR,
"partition: Unable to register control with rootdse!\n");
- return LDB_ERR_OPERATIONS_ERROR;
+ return ret;
}
ret = ldb_mod_register_control(module, LDB_CONTROL_SEARCH_OPTIONS_OID);
if (ret != LDB_SUCCESS) {
ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_ERROR,
"partition: Unable to register control with rootdse!\n");
- return LDB_ERR_OPERATIONS_ERROR;
+ return ret;
}
talloc_free(mem_ctx);
diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c
index fdb044198b..a3c99f4222 100644
--- a/source4/dsdb/samdb/ldb_modules/password_hash.c
+++ b/source4/dsdb/samdb/ldb_modules/password_hash.c
@@ -87,9 +87,9 @@ struct domain_data {
bool store_cleartext;
uint_t pwdProperties;
uint_t pwdHistoryLength;
- char *netbios_domain;
- char *dns_domain;
- char *realm;
+ const char *netbios_domain;
+ const char *dns_domain;
+ const char *realm;
};
struct setup_password_fields_io {
@@ -1552,9 +1552,8 @@ static int get_domain_data_callback(struct ldb_request *req,
struct ldb_context *ldb;
struct domain_data *data;
struct ph_context *ac;
+ struct loadparm_context *lp_ctx;
int ret;
- char *tmp;
- char *p;
ac = talloc_get_type(req->context, struct ph_context);
ldb = ldb_module_get_ctx(ac->module);
@@ -1591,43 +1590,13 @@ static int get_domain_data_callback(struct ldb_request *req,
* but that doesn't really matter, as it's just used for salt
* and kerberos principals, which don't exist here */
- tmp = ldb_dn_canonical_string(data, ares->message->dn);
- if (!tmp) {
- return ldb_module_done(ac->req, NULL, NULL,
- LDB_ERR_OPERATIONS_ERROR);
- }
+ lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
+ struct loadparm_context);
- /* But it puts a trailing (or just before 'builtin') / on things, so kill that */
- p = strchr(tmp, '/');
- if (p) {
- p[0] = '\0';
- }
-
- data->dns_domain = strlower_talloc(data, tmp);
- if (data->dns_domain == NULL) {
- ldb_oom(ldb);
- return ldb_module_done(ac->req, NULL, NULL,
- LDB_ERR_OPERATIONS_ERROR);
- }
- data->realm = strupper_talloc(data, tmp);
- if (data->realm == NULL) {
- ldb_oom(ldb);
- return ldb_module_done(ac->req, NULL, NULL,
- LDB_ERR_OPERATIONS_ERROR);
- }
- /* FIXME: NetbIOS name is *always* the first domain component ?? -SSS */
- p = strchr(tmp, '.');
- if (p) {
- p[0] = '\0';
- }
- data->netbios_domain = strupper_talloc(data, tmp);
- if (data->netbios_domain == NULL) {
- ldb_oom(ldb);
- return ldb_module_done(ac->req, NULL, NULL,
- LDB_ERR_OPERATIONS_ERROR);
- }
+ data->dns_domain = lp_dnsdomain(lp_ctx);
+ data->realm = lp_realm(lp_ctx);
+ data->netbios_domain = lp_workgroup(lp_ctx);
- talloc_free(tmp);
ac->domain = data;
break;
@@ -1673,7 +1642,7 @@ static int build_domain_data_request(struct ph_context *ac)
ldb = ldb_module_get_ctx(ac->module);
filter = talloc_asprintf(ac,
- "(&(objectSid=%s)(|(|(objectClass=domain)(objectClass=builtinDomain))(objectClass=samba4LocalDomain)))",
+ "(objectSid=%s)",
ldap_encode_ndr_dom_sid(ac, ac->domain_sid));
if (filter == NULL) {
ldb_oom(ldb);
@@ -1682,7 +1651,7 @@ static int build_domain_data_request(struct ph_context *ac)
return ldb_build_search_req(&ac->dom_req, ldb, ac,
ldb_get_default_basedn(ldb),
- LDB_SCOPE_SUBTREE,
+ LDB_SCOPE_BASE,
filter, attrs,
NULL,
ac, get_domain_data_callback,
diff --git a/source4/dsdb/samdb/ldb_modules/pdc_fsmo.c b/source4/dsdb/samdb/ldb_modules/pdc_fsmo.c
index 950f87eb74..6d814f9334 100644
--- a/source4/dsdb/samdb/ldb_modules/pdc_fsmo.c
+++ b/source4/dsdb/samdb/ldb_modules/pdc_fsmo.c
@@ -27,6 +27,7 @@
#include "librpc/gen_ndr/ndr_drsuapi.h"
#include "librpc/gen_ndr/ndr_drsblobs.h"
#include "../lib/util/dlinklist.h"
+#include "dsdb/samdb/ldb_modules/util.h"
static int pdc_fsmo_init(struct ldb_module *module)
{
@@ -64,9 +65,9 @@ static int pdc_fsmo_init(struct ldb_module *module)
}
ldb_module_set_private(module, pdc_fsmo);
- ret = ldb_search(ldb, mem_ctx, &pdc_res,
- pdc_dn, LDB_SCOPE_BASE,
- pdc_attrs, NULL);
+ ret = dsdb_module_search_dn(module, mem_ctx, &pdc_res,
+ pdc_dn,
+ pdc_attrs);
if (ret == LDB_ERR_NO_SUCH_OBJECT) {
ldb_debug(ldb, LDB_DEBUG_WARNING,
"pdc_fsmo_init: no domain object present: (skip loading of domain details)\n");
@@ -79,19 +80,6 @@ static int pdc_fsmo_init(struct ldb_module *module)
talloc_free(mem_ctx);
return ret;
}
- if (pdc_res->count == 0) {
- ldb_debug(ldb, LDB_DEBUG_WARNING,
- "pdc_fsmo_init: no domain object present: (skip loading of domain details)\n");
- talloc_free(mem_ctx);
- return ldb_next_init(module);
- } else if (pdc_res->count > 1) {
- ldb_debug_set(ldb, LDB_DEBUG_FATAL,
- "pdc_fsmo_init: [%u] domain objects found on a base search",
- pdc_res->count);
- DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
- talloc_free(mem_ctx);
- return LDB_ERR_CONSTRAINT_VIOLATION;
- }
pdc_fsmo->master_dn = ldb_msg_find_attr_as_dn(ldb, mem_ctx, pdc_res->msgs[0], "fSMORoleOwner");
if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), pdc_fsmo->master_dn) == 0) {
diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
index 253596ddea..74dd7e5bbb 100644
--- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
+++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
@@ -457,11 +457,14 @@ static int replmd_op_callback(struct ldb_request *req, struct ldb_reply *ares)
static int replmd_add(struct ldb_module *module, struct ldb_request *req)
{
struct ldb_context *ldb;
+ struct ldb_control *control;
+ struct ldb_control **saved_controls;
struct replmd_replicated_request *ac;
const struct dsdb_schema *schema;
enum ndr_err_code ndr_err;
struct ldb_request *down_req;
struct ldb_message *msg;
+ const DATA_BLOB *guid_blob;
struct GUID guid;
struct ldb_val guid_value;
struct replPropertyMetaDataBlob nmd;
@@ -473,6 +476,14 @@ static int replmd_add(struct ldb_module *module, struct ldb_request *req)
char *time_str;
int ret;
uint32_t i, ni=0;
+ bool allow_add_guid = false;
+ bool remove_current_guid = false;
+
+ /* check if there's a show relax control (used by provision to say 'I know what I'm doing') */
+ control = ldb_request_get_control(req, LDB_CONTROL_RELAX_OID);
+ if (control) {
+ allow_add_guid = 1;
+ }
/* do not manipulate our control entries */
if (ldb_dn_is_special(req->op.add.message->dn)) {
@@ -498,26 +509,43 @@ static int replmd_add(struct ldb_module *module, struct ldb_request *req)
ac->schema = schema;
- if (ldb_msg_find_element(req->op.add.message, "objectGUID") != NULL) {
- ldb_debug_set(ldb, LDB_DEBUG_ERROR,
+ guid_blob = ldb_msg_find_ldb_val(req->op.add.message, "objectGUID");
+ if ( guid_blob != NULL ) {
+ if( !allow_add_guid ) {
+ ldb_debug_set(ldb, LDB_DEBUG_ERROR,
"replmd_add: it's not allowed to add an object with objectGUID\n");
- return LDB_ERR_UNWILLING_TO_PERFORM;
+ talloc_free(ac);
+ return LDB_ERR_UNWILLING_TO_PERFORM;
+ } else {
+ NTSTATUS status = GUID_from_data_blob(guid_blob,&guid);
+ if ( !NT_STATUS_IS_OK(status)) {
+ ldb_debug_set(ldb, LDB_DEBUG_ERROR,
+ "replmd_add: Unable to parse as a GUID the attribute objectGUID\n");
+ talloc_free(ac);
+ return LDB_ERR_UNWILLING_TO_PERFORM;
+ }
+ /* we remove this attribute as it can be a string and will not be treated
+ correctly and then we will readd it latter on in the good format*/
+ remove_current_guid = true;
+ }
+ } else {
+ /* a new GUID */
+ guid = GUID_random();
}
/* Get a sequence number from the backend */
ret = ldb_sequence_number(ldb, LDB_SEQ_NEXT, &seq_num);
if (ret != LDB_SUCCESS) {
+ talloc_free(ac);
return ret;
}
- /* a new GUID */
- guid = GUID_random();
-
/* get our invocationId */
our_invocation_id = samdb_ntds_invocation_id(ldb);
if (!our_invocation_id) {
ldb_debug_set(ldb, LDB_DEBUG_ERROR,
"replmd_add: unable to find invocationId\n");
+ talloc_free(ac);
return LDB_ERR_OPERATIONS_ERROR;
}
@@ -525,6 +553,7 @@ static int replmd_add(struct ldb_module *module, struct ldb_request *req)
msg = ldb_msg_copy_shallow(ac, req->op.add.message);
if (msg == NULL) {
ldb_oom(ldb);
+ talloc_free(ac);
return LDB_ERR_OPERATIONS_ERROR;
}
@@ -532,8 +561,13 @@ static int replmd_add(struct ldb_module *module, struct ldb_request *req)
unix_to_nt_time(&now, t);
time_str = ldb_timestring(msg, t);
if (!time_str) {
+ ldb_oom(ldb);
+ talloc_free(ac);
return LDB_ERR_OPERATIONS_ERROR;
}
+ if (remove_current_guid) {
+ ldb_msg_remove_attr(msg,"objectGUID");
+ }
/*
* remove autogenerated attributes
@@ -548,7 +582,8 @@ static int replmd_add(struct ldb_module *module, struct ldb_request *req)
ret = ldb_msg_add_fmt(msg, "instanceType", "%u", INSTANCE_TYPE_WRITE);
if (ret != LDB_SUCCESS) {
ldb_oom(ldb);
- return LDB_ERR_OPERATIONS_ERROR;
+ talloc_free(ac);
+ return ret;
}
}
@@ -558,7 +593,8 @@ static int replmd_add(struct ldb_module *module, struct ldb_request *req)
ret = ldb_msg_add_string(msg, "whenCreated", time_str);
if (ret != LDB_SUCCESS) {
ldb_oom(ldb);
- return LDB_ERR_OPERATIONS_ERROR;
+ talloc_free(ac);
+ return ret;
}
/* build the replication meta_data */
@@ -570,6 +606,7 @@ static int replmd_add(struct ldb_module *module, struct ldb_request *req)
nmd.ctr.ctr1.count);
if (!nmd.ctr.ctr1.array) {
ldb_oom(ldb);
+ talloc_free(ac);
return LDB_ERR_OPERATIONS_ERROR;
}
@@ -585,6 +622,7 @@ static int replmd_add(struct ldb_module *module, struct ldb_request *req)
ldb_debug_set(ldb, LDB_DEBUG_ERROR,
"replmd_add: attribute '%s' not defined in schema\n",
e->name);
+ talloc_free(ac);
return LDB_ERR_NO_SUCH_ATTRIBUTE;
}
@@ -612,6 +650,7 @@ static int replmd_add(struct ldb_module *module, struct ldb_request *req)
*/
ret = replmd_replPropertyMetaDataCtr1_sort(&nmd.ctr.ctr1, schema, msg->dn);
if (ret != LDB_SUCCESS) {
+ talloc_free(ac);
return ret;
}
@@ -622,6 +661,7 @@ static int replmd_add(struct ldb_module *module, struct ldb_request *req)
(ndr_push_flags_fn_t)ndr_push_GUID);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
ldb_oom(ldb);
+ talloc_free(ac);
return LDB_ERR_OPERATIONS_ERROR;
}
ndr_err = ndr_push_struct_blob(&nmd_value, msg,
@@ -630,6 +670,7 @@ static int replmd_add(struct ldb_module *module, struct ldb_request *req)
(ndr_push_flags_fn_t)ndr_push_replPropertyMetaDataBlob);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
ldb_oom(ldb);
+ talloc_free(ac);
return LDB_ERR_OPERATIONS_ERROR;
}
@@ -639,27 +680,32 @@ static int replmd_add(struct ldb_module *module, struct ldb_request *req)
ret = ldb_msg_add_value(msg, "objectGUID", &guid_value, NULL);
if (ret != LDB_SUCCESS) {
ldb_oom(ldb);
- return LDB_ERR_OPERATIONS_ERROR;
+ talloc_free(ac);
+ return ret;
}
ret = ldb_msg_add_string(msg, "whenChanged", time_str);
if (ret != LDB_SUCCESS) {
ldb_oom(ldb);
- return LDB_ERR_OPERATIONS_ERROR;
+ talloc_free(ac);
+ return ret;
}
ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNCreated", seq_num);
if (ret != LDB_SUCCESS) {
ldb_oom(ldb);
- return LDB_ERR_OPERATIONS_ERROR;
+ talloc_free(ac);
+ return ret;
}
ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNChanged", seq_num);
if (ret != LDB_SUCCESS) {
ldb_oom(ldb);
- return LDB_ERR_OPERATIONS_ERROR;
+ talloc_free(ac);
+ return ret;
}
ret = ldb_msg_add_value(msg, "replPropertyMetaData", &nmd_value, NULL);
if (ret != LDB_SUCCESS) {
ldb_oom(ldb);
- return LDB_ERR_OPERATIONS_ERROR;
+ talloc_free(ac);
+ return ret;
}
/*
@@ -673,14 +719,22 @@ static int replmd_add(struct ldb_module *module, struct ldb_request *req)
ac, replmd_op_callback,
req);
if (ret != LDB_SUCCESS) {
+ talloc_free(ac);
return ret;
}
ret = replmd_notify(module, msg->dn, seq_num);
if (ret != LDB_SUCCESS) {
+ talloc_free(ac);
return ret;
}
+ /* if a control is there remove if from the modified request */
+ if (control && !save_controls(control, down_req, &saved_controls)) {
+ talloc_free(ac);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
/* go on with the call chain */
return ldb_next_request(module, down_req);
}
@@ -785,7 +839,7 @@ static int replmd_update_rpmd(struct ldb_module *module,
/* search for the existing replPropertyMetaDataBlob */
ret = dsdb_search_dn_with_deleted(ldb, msg, &res, msg->dn, attrs);
- if (ret != LDB_SUCCESS || res->count < 1) {
+ if (ret != LDB_SUCCESS || res->count != 1) {
DEBUG(0,(__location__ ": Object %s failed to find replPropertyMetaData\n",
ldb_dn_get_linearized(msg->dn)));
return LDB_ERR_OPERATIONS_ERROR;
@@ -880,9 +934,10 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req)
const struct dsdb_schema *schema;
struct ldb_request *down_req;
struct ldb_message *msg;
- int ret;
+ struct ldb_result *res;
time_t t = time(NULL);
uint64_t seq_num = 0;
+ int ret;
/* do not manipulate our control entries */
if (ldb_dn_is_special(req->op.mod.message->dn)) {
@@ -911,13 +966,12 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req)
/* we have to copy the message as the caller might have it as a const */
msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
if (msg == NULL) {
+ ldb_oom(ldb);
talloc_free(ac);
return LDB_ERR_OPERATIONS_ERROR;
}
/* TODO:
- * - get the whole old object
- * - if the old object doesn't exist report an error
* - give an error when a readonly attribute should
* be modified
* - merge the changed into the old object
@@ -926,8 +980,15 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req)
* attribute was changed
*/
+ ret = dsdb_search_dn_with_deleted(ldb, msg, &res, msg->dn, NULL);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(ac);
+ return ret;
+ }
+
ret = replmd_update_rpmd(module, msg, &seq_num);
if (ret != LDB_SUCCESS) {
+ talloc_free(ac);
return ret;
}
@@ -941,6 +1002,7 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req)
ac, replmd_op_callback,
req);
if (ret != LDB_SUCCESS) {
+ talloc_free(ac);
return ret;
}
talloc_steal(down_req, msg);
@@ -950,12 +1012,12 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req)
if (seq_num != 0) {
if (add_time_element(msg, "whenChanged", t) != LDB_SUCCESS) {
talloc_free(ac);
- return LDB_ERR_OPERATIONS_ERROR;
+ return ret;
}
if (add_uint64_element(msg, "uSNChanged", seq_num) != LDB_SUCCESS) {
talloc_free(ac);
- return LDB_ERR_OPERATIONS_ERROR;
+ return ret;
}
}
diff --git a/source4/dsdb/samdb/ldb_modules/rootdse.c b/source4/dsdb/samdb/ldb_modules/rootdse.c
index a8e08ec3ad..83e4e3b50e 100644
--- a/source4/dsdb/samdb/ldb_modules/rootdse.c
+++ b/source4/dsdb/samdb/ldb_modules/rootdse.c
@@ -722,9 +722,9 @@ static int rootdse_modify(struct ldb_module *module, struct ldb_request *req)
}
_PUBLIC_ const struct ldb_module_ops ldb_rootdse_module_ops = {
- .name = "rootdse",
+ .name = "rootdse",
.init_context = rootdse_init,
.search = rootdse_search,
- .request = rootdse_request,
+ .request = rootdse_request,
.modify = rootdse_modify
};
diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c
index e59b5dd1ce..2a0bb2dfe6 100644
--- a/source4/dsdb/samdb/ldb_modules/samldb.c
+++ b/source4/dsdb/samdb/ldb_modules/samldb.c
@@ -284,8 +284,7 @@ static int samldb_get_parent_domain(struct samldb_ctx *ac)
ret = ldb_build_search_req(&req, ldb, ac,
dn, LDB_SCOPE_BASE,
"(|(objectClass=domain)"
- "(objectClass=builtinDomain)"
- "(objectClass=samba4LocalDomain))",
+ "(objectClass=builtinDomain))",
attrs,
NULL,
ac, samldb_get_parent_domain_callback,
@@ -559,10 +558,10 @@ static int samldb_get_sid_domain(struct samldb_ctx *ac)
/* get the domain component part of the provided SID */
ac->domain_sid->num_auths--;
- filter = talloc_asprintf(ac, "(&(objectSid=%s)"
- "(|(objectClass=domain)"
- "(objectClass=builtinDomain)"
- "(objectClass=samba4LocalDomain)))",
+ filter = talloc_asprintf(ac,
+ "(&(objectSid=%s)"
+ "(|(objectClass=domain)"
+ "(objectClass=builtinDomain)))",
ldap_encode_ndr_dom_sid(ac, ac->domain_sid));
if (filter == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
@@ -699,8 +698,14 @@ static int samldb_check_primaryGroupID_1(struct samldb_ctx *ac)
static int samldb_check_primaryGroupID_2(struct samldb_ctx *ac)
{
- if (ac->res_dn == NULL)
+ if (ac->res_dn == NULL) {
+ struct ldb_context *ldb;
+ ldb = ldb_module_get_ctx(ac->module);
+ ldb_asprintf_errstring(ldb,
+ "Failed to find group sid %s",
+ dom_sid_string(ac->sid, ac->sid));
return LDB_ERR_UNWILLING_TO_PERFORM;
+ }
return samldb_next_step(ac);
}
@@ -1866,7 +1871,7 @@ static int samldb_add(struct ldb_module *module, struct ldb_request *req)
int ret;
ldb = ldb_module_get_ctx(module);
- ldb_debug(ldb, LDB_DEBUG_TRACE, "samldb_add_record\n");
+ ldb_debug(ldb, LDB_DEBUG_TRACE, "samldb_add\n");
/* do not manipulate our control entries */
if (ldb_dn_is_special(req->op.add.message->dn)) {
diff --git a/source4/dsdb/samdb/ldb_modules/schema_fsmo.c b/source4/dsdb/samdb/ldb_modules/schema_fsmo.c
index c482ab57df..2b6606c147 100644
--- a/source4/dsdb/samdb/ldb_modules/schema_fsmo.c
+++ b/source4/dsdb/samdb/ldb_modules/schema_fsmo.c
@@ -5,6 +5,7 @@
checkings, it also loads the dsdb_schema.
Copyright (C) Stefan Metzmacher <metze@samba.org> 2007
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -28,6 +29,7 @@
#include "librpc/gen_ndr/ndr_drsuapi.h"
#include "librpc/gen_ndr/ndr_drsblobs.h"
#include "param/param.h"
+#include "dsdb/samdb/ldb_modules/util.h"
static int generate_objectClasses(struct ldb_context *ldb, struct ldb_message *msg,
const struct dsdb_schema *schema);
@@ -90,13 +92,107 @@ struct schema_fsmo_search_data {
const struct dsdb_schema *schema;
};
+/*
+ Given an LDB module (pointing at the schema DB), and the DN, set the populated schema
+*/
+
+static int dsdb_schema_from_schema_dn(TALLOC_CTX *mem_ctx, struct ldb_module *module,
+ struct smb_iconv_convenience *iconv_convenience,
+ struct ldb_dn *schema_dn,
+ struct dsdb_schema **schema)
+{
+ TALLOC_CTX *tmp_ctx;
+ char *error_string;
+ int ret;
+ struct ldb_context *ldb = ldb_module_get_ctx(module);
+ struct ldb_result *schema_res;
+ struct ldb_result *a_res;
+ struct ldb_result *c_res;
+ static const char *schema_attrs[] = {
+ "prefixMap",
+ "schemaInfo",
+ "fSMORoleOwner",
+ NULL
+ };
+ unsigned flags;
+
+ tmp_ctx = talloc_new(mem_ctx);
+ if (!tmp_ctx) {
+ ldb_oom(ldb);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ /* we don't want to trace the schema load */
+ flags = ldb_get_flags(ldb);
+ ldb_set_flags(ldb, flags & ~LDB_FLG_ENABLE_TRACING);
+
+ /*
+ * setup the prefix mappings and schema info
+ */
+ ret = dsdb_module_search_dn(module, tmp_ctx, &schema_res,
+ schema_dn, schema_attrs);
+ if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+ goto failed;
+ } else if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb,
+ "dsdb_schema: failed to search the schema head: %s",
+ ldb_errstring(ldb));
+ goto failed;
+ }
+
+ /*
+ * load the attribute definitions
+ */
+ ret = dsdb_module_search(module, tmp_ctx, &a_res,
+ schema_dn, LDB_SCOPE_ONELEVEL, NULL,
+ "(objectClass=attributeSchema)");
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb,
+ "dsdb_schema: failed to search attributeSchema objects: %s",
+ ldb_errstring(ldb));
+ goto failed;
+ }
+
+ /*
+ * load the objectClass definitions
+ */
+ ret = dsdb_module_search(module, tmp_ctx, &c_res,
+ schema_dn, LDB_SCOPE_ONELEVEL, NULL,
+ "(objectClass=classSchema)");
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb,
+ "dsdb_schema: failed to search attributeSchema objects: %s",
+ ldb_errstring(ldb));
+ goto failed;
+ }
+
+ ret = dsdb_schema_from_ldb_results(tmp_ctx, ldb,
+ lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
+ schema_res, a_res, c_res, schema, &error_string);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb,
+ "dsdb_schema load failed: %s",
+ error_string);
+ goto failed;
+ }
+ talloc_steal(mem_ctx, *schema);
+
+failed:
+ if (flags & LDB_FLG_ENABLE_TRACING) {
+ flags = ldb_get_flags(ldb);
+ ldb_set_flags(ldb, flags | LDB_FLG_ENABLE_TRACING);
+ }
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+
static int schema_fsmo_init(struct ldb_module *module)
{
struct ldb_context *ldb;
TALLOC_CTX *mem_ctx;
struct ldb_dn *schema_dn;
struct dsdb_schema *schema;
- char *error_string = NULL;
int ret;
struct schema_fsmo_private_data *data;
@@ -134,9 +230,9 @@ static int schema_fsmo_init(struct ldb_module *module)
return LDB_ERR_OPERATIONS_ERROR;
}
- ret = dsdb_schema_from_schema_dn(mem_ctx, ldb,
+ ret = dsdb_schema_from_schema_dn(mem_ctx, module,
lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
- schema_dn, &schema, &error_string);
+ schema_dn, &schema);
if (ret == LDB_ERR_NO_SUCH_OBJECT) {
ldb_reset_err_string(ldb);
@@ -147,9 +243,6 @@ static int schema_fsmo_init(struct ldb_module *module)
}
if (ret != LDB_SUCCESS) {
- ldb_asprintf_errstring(ldb,
- "schema_fsmo_init: dsdb_schema load failed: %s",
- error_string);
talloc_free(mem_ctx);
return ret;
}
@@ -246,7 +339,6 @@ static int schema_fsmo_extended(struct ldb_module *module, struct ldb_request *r
struct ldb_context *ldb;
struct ldb_dn *schema_dn;
struct dsdb_schema *schema;
- char *error_string = NULL;
int ret;
TALLOC_CTX *mem_ctx;
@@ -270,9 +362,9 @@ static int schema_fsmo_extended(struct ldb_module *module, struct ldb_request *r
return LDB_ERR_OPERATIONS_ERROR;
}
- ret = dsdb_schema_from_schema_dn(mem_ctx, ldb,
+ ret = dsdb_schema_from_schema_dn(mem_ctx, module,
lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
- schema_dn, &schema, &error_string);
+ schema_dn, &schema);
if (ret == LDB_ERR_NO_SUCH_OBJECT) {
ldb_reset_err_string(ldb);
@@ -283,9 +375,6 @@ static int schema_fsmo_extended(struct ldb_module *module, struct ldb_request *r
}
if (ret != LDB_SUCCESS) {
- ldb_asprintf_errstring(ldb,
- "schema_fsmo_extended: dsdb_schema load failed: %s",
- error_string);
talloc_free(mem_ctx);
return ldb_next_request(module, req);
}
diff --git a/source4/dsdb/samdb/ldb_modules/subtree_delete.c b/source4/dsdb/samdb/ldb_modules/subtree_delete.c
index 241cc5f7d6..e1ce9c1fa8 100644
--- a/source4/dsdb/samdb/ldb_modules/subtree_delete.c
+++ b/source4/dsdb/samdb/ldb_modules/subtree_delete.c
@@ -55,6 +55,8 @@ static struct subtree_delete_context *subdel_ctx_init(struct ldb_module *module,
ac->module = module;
ac->req = req;
+ ac->num_children = 0;
+
return ac;
}
diff --git a/source4/dsdb/samdb/ldb_modules/tests/samba3sam.py b/source4/dsdb/samdb/ldb_modules/tests/samba3sam.py
index fe96b88221..c61d3973a1 100644
--- a/source4/dsdb/samdb/ldb_modules/tests/samba3sam.py
+++ b/source4/dsdb/samdb/ldb_modules/tests/samba3sam.py
@@ -313,6 +313,14 @@ class MapTestCase(MapBaseTestCase):
# Add a set of split records
self.ldb.add_ldif("""
+dn: """+ self.samba4.dn("cn=Domain Users") + """
+objectClass: group
+cn: Domain Users
+objectSid: S-1-5-21-4231626423-2410014848-2360679739-513
+""")
+
+ # Add a set of split records
+ self.ldb.add_ldif("""
dn: """+ self.samba4.dn("cn=X") + """
objectClass: user
cn: X
@@ -459,7 +467,7 @@ objectSid: S-1-5-21-4231626423-2410014848-2360679739-552
# errors, letting the search fail with no results.
#res = self.ldb.search("(objectSid=S-1-5-21-4231626423-2410014848-2360679739-552)", scope=SCOPE_DEFAULT, attrs)
res = self.ldb.search(expression="(objectSid=*)", base=None, scope=SCOPE_DEFAULT, attrs=["dnsHostName", "lastLogon", "objectSid"])
- self.assertEquals(len(res), 3)
+ self.assertEquals(len(res), 4)
self.assertEquals(str(res[0].dn), self.samba4.dn("cn=X"))
self.assertEquals(str(res[0]["dnsHostName"]), "x")
self.assertEquals(str(res[0]["lastLogon"]), "x")
@@ -621,7 +629,7 @@ objectSid: S-1-5-21-4231626423-2410014848-2360679739-552
# Search by negated local attribute
res = self.ldb.search(expression="(!(revision=x))",
attrs=["dnsHostName", "lastLogon"])
- self.assertEquals(len(res), 5)
+ self.assertEquals(len(res), 6)
self.assertEquals(str(res[0].dn), self.samba4.dn("cn=B"))
self.assertTrue(not "dnsHostName" in res[0])
self.assertEquals(str(res[0]["lastLogon"]), "y")
@@ -638,7 +646,7 @@ objectSid: S-1-5-21-4231626423-2410014848-2360679739-552
# Search by negated remote attribute
res = self.ldb.search(expression="(!(description=x))",
attrs=["dnsHostName", "lastLogon"])
- self.assertEquals(len(res), 3)
+ self.assertEquals(len(res), 4)
self.assertEquals(str(res[0].dn), self.samba4.dn("cn=Z"))
self.assertEquals(str(res[0]["dnsHostName"]), "z")
self.assertEquals(str(res[0]["lastLogon"]), "z")
@@ -649,7 +657,7 @@ objectSid: S-1-5-21-4231626423-2410014848-2360679739-552
# Search by negated conjunction of local attributes
res = self.ldb.search(expression="(!(&(codePage=x)(revision=x)))",
attrs=["dnsHostName", "lastLogon"])
- self.assertEquals(len(res), 5)
+ self.assertEquals(len(res), 6)
self.assertEquals(str(res[0].dn), self.samba4.dn("cn=B"))
self.assertTrue(not "dnsHostName" in res[0])
self.assertEquals(str(res[0]["lastLogon"]), "y")
@@ -666,7 +674,7 @@ objectSid: S-1-5-21-4231626423-2410014848-2360679739-552
# Search by negated conjunction of remote attributes
res = self.ldb.search(expression="(!(&(lastLogon=x)(description=x)))",
attrs=["dnsHostName", "lastLogon"])
- self.assertEquals(len(res), 5)
+ self.assertEquals(len(res), 6)
self.assertEquals(str(res[0].dn), self.samba4.dn("cn=Y"))
self.assertEquals(str(res[0]["dnsHostName"]), "y")
self.assertEquals(str(res[0]["lastLogon"]), "y")
@@ -683,7 +691,7 @@ objectSid: S-1-5-21-4231626423-2410014848-2360679739-552
# Search by negated conjunction of local and remote attribute
res = self.ldb.search(expression="(!(&(codePage=x)(description=x)))",
attrs=["dnsHostName", "lastLogon"])
- self.assertEquals(len(res), 5)
+ self.assertEquals(len(res), 6)
self.assertEquals(str(res[0].dn), self.samba4.dn("cn=B"))
self.assertTrue(not "dnsHostName" in res[0])
self.assertEquals(str(res[0]["lastLogon"]), "y")
@@ -716,7 +724,7 @@ objectSid: S-1-5-21-4231626423-2410014848-2360679739-552
# Search by negated disjunction of remote attributes
res = self.ldb.search(expression="(!(|(badPwdCount=x)(lastLogon=x)))",
attrs=["dnsHostName", "lastLogon"])
- self.assertEquals(len(res), 4)
+ self.assertEquals(len(res), 5)
self.assertEquals(str(res[0].dn), self.samba4.dn("cn=Y"))
self.assertEquals(str(res[0]["dnsHostName"]), "y")
self.assertEquals(str(res[0]["lastLogon"]), "y")
@@ -730,7 +738,7 @@ objectSid: S-1-5-21-4231626423-2410014848-2360679739-552
# Search by negated disjunction of local and remote attribute
res = self.ldb.search(expression="(!(|(revision=x)(lastLogon=y)))",
attrs=["dnsHostName", "lastLogon"])
- self.assertEquals(len(res), 4)
+ self.assertEquals(len(res), 5)
self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A"))
self.assertTrue(not "dnsHostName" in res[0])
self.assertEquals(str(res[0]["lastLogon"]), "x")
@@ -743,7 +751,7 @@ objectSid: S-1-5-21-4231626423-2410014848-2360679739-552
# Search by complex parse tree
res = self.ldb.search(expression="(|(&(revision=x)(dnsHostName=x))(!(&(description=x)(nextRid=y)))(badPwdCount=y))", attrs=["dnsHostName", "lastLogon"])
- self.assertEquals(len(res), 6)
+ self.assertEquals(len(res), 7)
self.assertEquals(str(res[0].dn), self.samba4.dn("cn=B"))
self.assertTrue(not "dnsHostName" in res[0])
self.assertEquals(str(res[0]["lastLogon"]), "y")
diff --git a/source4/dsdb/samdb/ldb_modules/util.c b/source4/dsdb/samdb/ldb_modules/util.c
new file mode 100644
index 0000000000..476eb08ed0
--- /dev/null
+++ b/source4/dsdb/samdb/ldb_modules/util.c
@@ -0,0 +1,128 @@
+/*
+ Unix SMB/CIFS implementation.
+ Samba utility functions
+
+ Copyright (C) Andrew Tridgell 2009
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "ldb.h"
+#include "ldb_module.h"
+
+/*
+ search for attrs on one DN, in the modules below
+ */
+int dsdb_module_search_dn(struct ldb_module *module,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_result **_res,
+ struct ldb_dn *basedn,
+ const char * const *attrs)
+{
+ int ret;
+ struct ldb_request *req;
+ TALLOC_CTX *tmp_ctx;
+ struct ldb_result *res;
+
+ tmp_ctx = talloc_new(mem_ctx);
+
+ res = talloc_zero(tmp_ctx, struct ldb_result);
+ if (!res) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
+ basedn,
+ LDB_SCOPE_BASE,
+ NULL,
+ attrs,
+ NULL,
+ res,
+ ldb_search_default_callback,
+ NULL);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ ret = ldb_next_request(module, req);
+ if (ret == LDB_SUCCESS) {
+ ret = ldb_wait(req->handle, LDB_WAIT_ALL);
+ }
+
+ if (ret != LDB_SUCCESS) {
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ if (res->count != 1) {
+ /* we may be reading a DB that does not have the 'check base on search' option... */
+ ret = LDB_ERR_NO_SUCH_OBJECT;
+ } else {
+ *_res = talloc_steal(mem_ctx, res);
+ }
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+/*
+ search for attrs in the modules below
+ */
+int dsdb_module_search(struct ldb_module *module,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_result **_res,
+ struct ldb_dn *basedn, enum ldb_scope scope,
+ const char * const *attrs,
+ const char *expression)
+{
+ int ret;
+ struct ldb_request *req;
+ TALLOC_CTX *tmp_ctx;
+ struct ldb_result *res;
+
+ tmp_ctx = talloc_new(mem_ctx);
+
+ res = talloc_zero(tmp_ctx, struct ldb_result);
+ if (!res) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
+ basedn,
+ scope,
+ expression,
+ attrs,
+ NULL,
+ res,
+ ldb_search_default_callback,
+ NULL);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ ret = ldb_next_request(module, req);
+ if (ret == LDB_SUCCESS) {
+ ret = ldb_wait(req->handle, LDB_WAIT_ALL);
+ }
+
+ talloc_free(req);
+ if (ret == LDB_SUCCESS) {
+ *_res = talloc_steal(mem_ctx, res);
+ }
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
diff --git a/source4/dsdb/samdb/ldb_modules/util.h b/source4/dsdb/samdb/ldb_modules/util.h
new file mode 100644
index 0000000000..0a1ab83c6d
--- /dev/null
+++ b/source4/dsdb/samdb/ldb_modules/util.h
@@ -0,0 +1,22 @@
+/*
+ Unix SMB/CIFS implementation.
+ Samba utility functions
+
+ Copyright (C) Andrew Tridgell 2009
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "dsdb/samdb/ldb_modules/util_proto.h"
diff --git a/source4/dsdb/samdb/samdb_privilege.c b/source4/dsdb/samdb/samdb_privilege.c
index e9c6f4c527..e7742c681c 100644
--- a/source4/dsdb/samdb/samdb_privilege.c
+++ b/source4/dsdb/samdb/samdb_privilege.c
@@ -26,11 +26,30 @@
#include "libcli/security/security.h"
#include "../lib/util/util_ldb.h"
#include "param/param.h"
+#include "ldb_wrap.h"
+
+/* connect to the privilege database */
+struct ldb_context *privilege_connect(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev_ctx,
+ struct loadparm_context *lp_ctx)
+{
+ char *path;
+ struct ldb_context *pdb;
+
+ path = private_path(mem_ctx, lp_ctx, "privilege.ldb");
+ if (!path) return NULL;
+
+ pdb = ldb_wrap_connect(mem_ctx, ev_ctx, lp_ctx, path,
+ NULL, NULL, 0, NULL);
+ talloc_free(path);
+
+ return pdb;
+}
/*
add privilege bits for one sid to a security_token
*/
-static NTSTATUS samdb_privilege_setup_sid(void *samctx, TALLOC_CTX *mem_ctx,
+static NTSTATUS samdb_privilege_setup_sid(struct ldb_context *pdb, TALLOC_CTX *mem_ctx,
struct security_token *token,
const struct dom_sid *sid)
{
@@ -43,7 +62,7 @@ static NTSTATUS samdb_privilege_setup_sid(void *samctx, TALLOC_CTX *mem_ctx,
sidstr = ldap_encode_ndr_dom_sid(mem_ctx, sid);
NT_STATUS_HAVE_NO_MEMORY(sidstr);
- ret = gendb_search(samctx, mem_ctx, NULL, &res, attrs, "objectSid=%s", sidstr);
+ ret = gendb_search(pdb, mem_ctx, NULL, &res, attrs, "objectSid=%s", sidstr);
talloc_free(sidstr);
if (ret != 1) {
/* not an error to not match */
@@ -76,7 +95,7 @@ static NTSTATUS samdb_privilege_setup_sid(void *samctx, TALLOC_CTX *mem_ctx,
NTSTATUS samdb_privilege_setup(struct tevent_context *ev_ctx,
struct loadparm_context *lp_ctx, struct security_token *token)
{
- void *samctx;
+ struct ldb_context *pdb;
TALLOC_CTX *mem_ctx;
int i;
NTSTATUS status;
@@ -98,8 +117,8 @@ NTSTATUS samdb_privilege_setup(struct tevent_context *ev_ctx,
}
mem_ctx = talloc_new(token);
- samctx = samdb_connect(mem_ctx, ev_ctx, lp_ctx, system_session(mem_ctx, lp_ctx));
- if (samctx == NULL) {
+ pdb = privilege_connect(mem_ctx, ev_ctx, lp_ctx);
+ if (pdb == NULL) {
talloc_free(mem_ctx);
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
@@ -107,7 +126,7 @@ NTSTATUS samdb_privilege_setup(struct tevent_context *ev_ctx,
token->privilege_mask = 0;
for (i=0;i<token->num_sids;i++) {
- status = samdb_privilege_setup_sid(samctx, mem_ctx,
+ status = samdb_privilege_setup_sid(pdb, mem_ctx,
token, token->sids[i]);
if (!NT_STATUS_IS_OK(status)) {
talloc_free(mem_ctx);
diff --git a/source4/dsdb/schema/prefixmap.h b/source4/dsdb/schema/prefixmap.h
new file mode 100644
index 0000000000..7b28c88749
--- /dev/null
+++ b/source4/dsdb/schema/prefixmap.h
@@ -0,0 +1,45 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ DRS::prefixMap data structures
+
+ Copyright (C) Kamen Mazdrashki <kamen.mazdrashki@postpath.com> 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _DSDB_PREFIXMAP_H
+#define _DSDB_PREFIXMAP_H
+
+/**
+ * oid-prefix in prefixmap
+ */
+struct dsdb_schema_prefixmap_oid {
+ uint32_t id;
+ DATA_BLOB *bin_oid; /* partial binary-oid prefix */
+};
+
+/**
+ * DSDB prefixMap internal presentation
+ */
+struct dsdb_schema_prefixmap {
+ uint32_t length;
+ struct dsdb_schema_prefixmap_oid *prefixes;
+};
+
+
+#include "dsdb/schema/proto.h"
+
+
+#endif /* _DSDB_PREFIXMAP_H */
diff --git a/source4/dsdb/schema/schema.h b/source4/dsdb/schema/schema.h
index 4e7e503931..ddd9b375f6 100644
--- a/source4/dsdb/schema/schema.h
+++ b/source4/dsdb/schema/schema.h
@@ -119,6 +119,7 @@ struct dsdb_class {
const char **mustContain;
const char **mayContain;
const char **possibleInferiors;
+ const char **systemPossibleInferiors;
const char *defaultSecurityDescriptor;
diff --git a/source4/dsdb/schema/schema_inferiors.c b/source4/dsdb/schema/schema_inferiors.c
index b02d557c58..ecac74a954 100644
--- a/source4/dsdb/schema/schema_inferiors.c
+++ b/source4/dsdb/schema/schema_inferiors.c
@@ -149,19 +149,22 @@ void schema_subclasses_order_recurse(struct dsdb_schema *schema, struct dsdb_cla
return;
}
-static void schema_create_subclasses(struct dsdb_schema *schema)
+static int schema_create_subclasses(struct dsdb_schema *schema)
{
- struct dsdb_class *schema_class;
+ struct dsdb_class *schema_class, *top;
for (schema_class=schema->classes; schema_class; schema_class=schema_class->next) {
struct dsdb_class *schema_class2 = dsdb_class_by_lDAPDisplayName(schema, schema_class->subClassOf);
if (schema_class2 == NULL) {
DEBUG(0,("ERROR: no subClassOf for '%s'\n", schema_class->lDAPDisplayName));
- continue;
+ return LDB_ERR_OPERATIONS_ERROR;
}
if (schema_class2 && schema_class != schema_class2) {
if (schema_class2->subclasses_direct == NULL) {
schema_class2->subclasses_direct = str_list_make_empty(schema_class2);
+ if (!schema_class2->subclasses_direct) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
}
schema_class2->subclasses_direct = str_list_add_const(schema_class2->subclasses_direct,
schema_class->lDAPDisplayName);
@@ -175,7 +178,14 @@ static void schema_create_subclasses(struct dsdb_schema *schema)
schema_class->subClass_order = 0;
}
- schema_subclasses_order_recurse(schema, dsdb_class_by_lDAPDisplayName(schema, "top"), 1);
+ top = dsdb_class_by_lDAPDisplayName(schema, "top");
+ if (!top) {
+ DEBUG(0,("ERROR: no 'top' class in loaded schema\n"));
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ schema_subclasses_order_recurse(schema, top, 1);
+ return LDB_SUCCESS;
}
static void schema_fill_possible_inferiors(struct dsdb_schema *schema, struct dsdb_class *schema_class)
@@ -198,6 +208,25 @@ static void schema_fill_possible_inferiors(struct dsdb_schema *schema, struct ds
schema_class->possibleInferiors = str_list_unique(schema_class->possibleInferiors);
}
+static void schema_fill_system_possible_inferiors(struct dsdb_schema *schema, struct dsdb_class *schema_class)
+{
+ struct dsdb_class *c2;
+
+ for (c2=schema->classes; c2; c2=c2->next) {
+ char **superiors = schema_posssuperiors(schema, c2);
+ if (c2->objectClassCategory != 2
+ && c2->objectClassCategory != 3
+ && str_list_check(superiors, schema_class->lDAPDisplayName)) {
+ if (schema_class->systemPossibleInferiors == NULL) {
+ schema_class->systemPossibleInferiors = str_list_make_empty(schema_class);
+ }
+ schema_class->systemPossibleInferiors = str_list_add_const(schema_class->systemPossibleInferiors,
+ c2->lDAPDisplayName);
+ }
+ }
+ schema_class->systemPossibleInferiors = str_list_unique(schema_class->systemPossibleInferiors);
+}
+
/*
fill in a string class name from a governs_ID
*/
@@ -275,16 +304,21 @@ static void schema_fill_from_ids(struct dsdb_schema *schema)
}
}
-void schema_fill_constructed(struct dsdb_schema *schema)
+int schema_fill_constructed(struct dsdb_schema *schema)
{
+ int ret;
struct dsdb_class *schema_class;
schema_fill_from_ids(schema);
- schema_create_subclasses(schema);
+ ret = schema_create_subclasses(schema);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
for (schema_class=schema->classes; schema_class; schema_class=schema_class->next) {
schema_fill_possible_inferiors(schema, schema_class);
+ schema_fill_system_possible_inferiors(schema, schema_class);
}
/* free up our internal cache elements */
@@ -298,4 +332,5 @@ void schema_fill_constructed(struct dsdb_schema *schema)
schema_class->subclasses = NULL;
schema_class->posssuperiors = NULL;
}
+ return LDB_SUCCESS;
}
diff --git a/source4/dsdb/schema/schema_init.c b/source4/dsdb/schema/schema_init.c
index b876ab09fc..f8b7d5dd44 100644
--- a/source4/dsdb/schema/schema_init.c
+++ b/source4/dsdb/schema/schema_init.c
@@ -29,6 +29,9 @@
#include "librpc/gen_ndr/ndr_drsblobs.h"
#include "param/param.h"
#include "lib/ldb/include/ldb_module.h"
+#include "../lib/util/asn1.h"
+
+static WERROR dsdb_read_prefixes_from_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, uint32_t* num_prefixes, struct dsdb_schema_oid_prefix **prefixes);
struct dsdb_schema *dsdb_new_schema(TALLOC_CTX *mem_ctx, struct smb_iconv_convenience *iconv_convenience)
{
@@ -50,11 +53,11 @@ WERROR dsdb_load_oid_mappings_drsuapi(struct dsdb_schema *schema, const struct d
W_ERROR_HAVE_NO_MEMORY(schema->prefixes);
for (i=0, j=0; i < ctr->num_mappings; i++) {
- if (ctr->mappings[i].oid.oid == NULL) {
+ if (ctr->mappings[i].oid.binary_oid == NULL) {
return WERR_INVALID_PARAM;
}
- if (strncasecmp(ctr->mappings[i].oid.oid, "ff", 2) == 0) {
+ if (ctr->mappings[i].oid.binary_oid[0] == 0xFF) {
if (ctr->mappings[i].id_prefix != 0) {
return WERR_INVALID_PARAM;
}
@@ -64,21 +67,33 @@ WERROR dsdb_load_oid_mappings_drsuapi(struct dsdb_schema *schema, const struct d
return WERR_INVALID_PARAM;
}
- if (ctr->mappings[i].oid.__ndr_size != 21) {
+ if (ctr->mappings[i].oid.length != 21) {
return WERR_INVALID_PARAM;
}
- schema->schema_info = talloc_strdup(schema, ctr->mappings[i].oid.oid);
+ schema->schema_info = hex_encode_talloc(schema,
+ ctr->mappings[i].oid.binary_oid,
+ ctr->mappings[i].oid.length);
W_ERROR_HAVE_NO_MEMORY(schema->schema_info);
} else {
+ DATA_BLOB oid_blob;
+ const char *partial_oid = NULL;
+
/* the last array member should contain the magic value not a oid */
if (i == (ctr->num_mappings - 1)) {
return WERR_INVALID_PARAM;
}
+ oid_blob = data_blob_const(ctr->mappings[i].oid.binary_oid,
+ ctr->mappings[i].oid.length);
+ if (!ber_read_partial_OID_String(schema->prefixes, oid_blob, &partial_oid)) {
+ DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X",
+ ctr->mappings[i].id_prefix));
+ return WERR_INVALID_PARAM;
+ }
+
schema->prefixes[j].id = ctr->mappings[i].id_prefix<<16;
- schema->prefixes[j].oid = talloc_asprintf(schema->prefixes, "%s.",
- ctr->mappings[i].oid.oid);
+ schema->prefixes[j].oid = partial_oid;
W_ERROR_HAVE_NO_MEMORY(schema->prefixes[j].oid);
schema->prefixes[j].oid_len = strlen(schema->prefixes[j].oid);
j++;
@@ -96,7 +111,7 @@ WERROR dsdb_load_oid_mappings_ldb(struct dsdb_schema *schema,
WERROR status;
enum ndr_err_code ndr_err;
struct prefixMapBlob pfm;
- char *schema_info;
+ DATA_BLOB schema_info_blob;
TALLOC_CTX *mem_ctx = talloc_new(schema);
W_ERROR_HAVE_NO_MEMORY(mem_ctx);
@@ -125,12 +140,12 @@ WERROR dsdb_load_oid_mappings_ldb(struct dsdb_schema *schema,
pfm.ctr.dsdb.num_mappings);
W_ERROR_HAVE_NO_MEMORY(pfm.ctr.dsdb.mappings);
- schema_info = data_blob_hex_string(pfm.ctr.dsdb.mappings, schemaInfo);
- W_ERROR_HAVE_NO_MEMORY(schema_info);
+ schema_info_blob = data_blob_dup_talloc(pfm.ctr.dsdb.mappings, schemaInfo);
+ W_ERROR_HAVE_NO_MEMORY(schema_info_blob.data);
pfm.ctr.dsdb.mappings[pfm.ctr.dsdb.num_mappings - 1].id_prefix = 0;
- pfm.ctr.dsdb.mappings[pfm.ctr.dsdb.num_mappings - 1].oid.__ndr_size = schemaInfo->length;
- pfm.ctr.dsdb.mappings[pfm.ctr.dsdb.num_mappings - 1].oid.oid = schema_info;
+ pfm.ctr.dsdb.mappings[pfm.ctr.dsdb.num_mappings - 1].oid.length = schemaInfo->length;
+ pfm.ctr.dsdb.mappings[pfm.ctr.dsdb.num_mappings - 1].oid.binary_oid = schema_info_blob.data;
/* call the drsuapi version */
status = dsdb_load_oid_mappings_drsuapi(schema, &pfm.ctr.dsdb);
@@ -146,6 +161,7 @@ WERROR dsdb_get_oid_mappings_drsuapi(const struct dsdb_schema *schema,
TALLOC_CTX *mem_ctx,
struct drsuapi_DsReplicaOIDMapping_Ctr **_ctr)
{
+ DATA_BLOB oid_blob;
struct drsuapi_DsReplicaOIDMapping_Ctr *ctr;
uint32_t i;
@@ -158,18 +174,23 @@ WERROR dsdb_get_oid_mappings_drsuapi(const struct dsdb_schema *schema,
W_ERROR_HAVE_NO_MEMORY(ctr->mappings);
for (i=0; i < schema->num_prefixes; i++) {
+ if (!ber_write_partial_OID_String(ctr->mappings, &oid_blob, schema->prefixes[i].oid)) {
+ DEBUG(0, ("write_partial_OID failed for %s", schema->prefixes[i].oid));
+ return WERR_INTERNAL_ERROR;
+ }
+
ctr->mappings[i].id_prefix = schema->prefixes[i].id>>16;
- ctr->mappings[i].oid.oid = talloc_strndup(ctr->mappings,
- schema->prefixes[i].oid,
- schema->prefixes[i].oid_len - 1);
- W_ERROR_HAVE_NO_MEMORY(ctr->mappings[i].oid.oid);
+ ctr->mappings[i].oid.length = oid_blob.length;
+ ctr->mappings[i].oid.binary_oid = oid_blob.data;
}
if (include_schema_info) {
+ oid_blob = strhex_to_data_blob(ctr->mappings, schema->schema_info);
+ W_ERROR_HAVE_NO_MEMORY(oid_blob.data);
+
ctr->mappings[i].id_prefix = 0;
- ctr->mappings[i].oid.oid = talloc_strdup(ctr->mappings,
- schema->schema_info);
- W_ERROR_HAVE_NO_MEMORY(ctr->mappings[i].oid.oid);
+ ctr->mappings[i].oid.length = oid_blob.length;
+ ctr->mappings[i].oid.binary_oid = oid_blob.data;
}
*_ctr = ctr;
@@ -209,13 +230,14 @@ WERROR dsdb_get_oid_mappings_ldb(const struct dsdb_schema *schema,
WERROR dsdb_verify_oid_mappings_drsuapi(const struct dsdb_schema *schema, const struct drsuapi_DsReplicaOIDMapping_Ctr *ctr)
{
uint32_t i,j;
+ DATA_BLOB oid_blob;
for (i=0; i < ctr->num_mappings; i++) {
- if (ctr->mappings[i].oid.oid == NULL) {
+ if (ctr->mappings[i].oid.binary_oid == NULL) {
return WERR_INVALID_PARAM;
}
- if (strncasecmp(ctr->mappings[i].oid.oid, "ff", 2) == 0) {
+ if (ctr->mappings[i].oid.binary_oid[0] == 0xFF) {
if (ctr->mappings[i].id_prefix != 0) {
return WERR_INVALID_PARAM;
}
@@ -225,13 +247,19 @@ WERROR dsdb_verify_oid_mappings_drsuapi(const struct dsdb_schema *schema, const
return WERR_INVALID_PARAM;
}
- if (ctr->mappings[i].oid.__ndr_size != 21) {
+ if (ctr->mappings[i].oid.length != 21) {
return WERR_INVALID_PARAM;
}
- if (strcasecmp(schema->schema_info, ctr->mappings[i].oid.oid) != 0) {
+ oid_blob = strhex_to_data_blob(NULL, schema->schema_info);
+ W_ERROR_HAVE_NO_MEMORY(oid_blob.data);
+
+ if (memcmp(oid_blob.data, ctr->mappings[i].oid.binary_oid, 21) != 0) {
+ data_blob_free(&oid_blob);
return WERR_DS_DRA_SCHEMA_MISMATCH;
}
+
+ data_blob_free(&oid_blob);
} else {
/* the last array member should contain the magic value not a oid */
if (i == (ctr->num_mappings - 1)) {
@@ -239,21 +267,26 @@ WERROR dsdb_verify_oid_mappings_drsuapi(const struct dsdb_schema *schema, const
}
for (j=0; j < schema->num_prefixes; j++) {
- size_t oid_len;
if (schema->prefixes[j].id != (ctr->mappings[i].id_prefix<<16)) {
continue;
}
- oid_len = strlen(ctr->mappings[i].oid.oid);
+ if (!ber_write_partial_OID_String(NULL, &oid_blob, schema->prefixes[j].oid)) {
+ return WERR_INTERNAL_ERROR;
+ }
- if (oid_len != (schema->prefixes[j].oid_len - 1)) {
+ if (oid_blob.length != ctr->mappings[j].oid.length) {
+ data_blob_free(&oid_blob);
return WERR_DS_DRA_SCHEMA_MISMATCH;
}
- if (strncmp(ctr->mappings[i].oid.oid, schema->prefixes[j].oid, oid_len) != 0) {
- return WERR_DS_DRA_SCHEMA_MISMATCH;
+ if (memcmp(ctr->mappings[i].oid.binary_oid, oid_blob.data, oid_blob.length) != 0) {
+ data_blob_free(&oid_blob);
+ return WERR_DS_DRA_SCHEMA_MISMATCH;
}
+ data_blob_free(&oid_blob);
+
break;
}
@@ -282,7 +315,7 @@ WERROR dsdb_map_int2oid(const struct dsdb_schema *schema, uint32_t in, TALLOC_CT
continue;
}
- val = talloc_asprintf(mem_ctx, "%s%u",
+ val = talloc_asprintf(mem_ctx, "%s.%u",
schema->prefixes[i].oid,
in & 0xFFFF);
W_ERROR_HAVE_NO_MEMORY(val);
@@ -389,8 +422,6 @@ WERROR dsdb_prefix_map_update(TALLOC_CTX *mem_ctx, uint32_t *num_prefixes, struc
DEBUG(0,("dsdb_prefix_map_update: size of the remaining string invalid\n"));
return WERR_FOOBAR;
}
- /* Add one because we need to copy the dot */
- size += 1;
/* Create a spot in the prefixMap for one more prefix*/
(*prefixes) = talloc_realloc(mem_ctx, *prefixes, struct dsdb_schema_oid_prefix, new_num_prefixes);
@@ -410,37 +441,33 @@ WERROR dsdb_prefix_map_update(TALLOC_CTX *mem_ctx, uint32_t *num_prefixes, struc
WERROR dsdb_find_prefix_for_oid(uint32_t num_prefixes, const struct dsdb_schema_oid_prefix *prefixes, const char *in, uint32_t *out)
{
uint32_t i;
+ char *oid_prefix;
+ char *pstr;
+ char *end_str;
+ unsigned val;
- for (i=0; i < num_prefixes; i++) {
- const char *val_str;
- char *end_str;
- unsigned val;
+ /* make oid prefix, i.e. oid w/o last subidentifier */
+ pstr = strrchr(in, '.');
+ if (!pstr) return WERR_INVALID_PARAM;
+ if (pstr < in) return WERR_INVALID_PARAM;
+ if ((pstr - in) < 4) return WERR_INVALID_PARAM;
- if (strncmp(prefixes[i].oid, in, prefixes[i].oid_len) != 0) {
- continue;
- }
+ oid_prefix = talloc_strndup(0, in, pstr - in);
- val_str = in + prefixes[i].oid_len;
- end_str = NULL;
- errno = 0;
-
- if (val_str[0] == '\0') {
- return WERR_INVALID_PARAM;
+ for (i=0; i < num_prefixes; i++) {
+ if (strcmp(prefixes[i].oid, oid_prefix) == 0) {
+ break;
}
+ }
- /* two '.' chars are invalid */
- if (val_str[0] == '.') {
- return WERR_INVALID_PARAM;
- }
+ talloc_free(oid_prefix);
- val = strtoul(val_str, &end_str, 10);
- if (end_str[0] == '.' && end_str[1] != '\0') {
- /*
- * if it's a '.' and not the last char
- * then maybe an other mapping apply
- */
- continue;
- } else if (end_str[0] != '\0') {
+ if (i < num_prefixes) {
+ /* move next to '.' char */
+ pstr++;
+
+ val = strtoul(pstr, &end_str, 10);
+ if (end_str[0] != '\0') {
return WERR_INVALID_PARAM;
} else if (val > 0xFFFF) {
return WERR_INVALID_PARAM;
@@ -487,8 +514,16 @@ WERROR dsdb_write_prefixes_from_schema_to_ldb(TALLOC_CTX *mem_ctx, struct ldb_co
}
for (i=0; i < schema->num_prefixes; i++) {
- pm.ctr.dsdb.mappings[i].id_prefix = schema->prefixes[i].id>>16;
- pm.ctr.dsdb.mappings[i].oid.oid = talloc_strdup(pm.ctr.dsdb.mappings, schema->prefixes[i].oid);
+ DATA_BLOB oid_blob;
+
+ if (!ber_write_partial_OID_String(pm.ctr.dsdb.mappings, &oid_blob, schema->prefixes[i].oid)) {
+ DEBUG(0, ("write_partial_OID failed for %s", schema->prefixes[i].oid));
+ return WERR_INTERNAL_ERROR;
+ }
+
+ pm.ctr.dsdb.mappings[i].id_prefix = schema->prefixes[i].id>>16;
+ pm.ctr.dsdb.mappings[i].oid.length = oid_blob.length;
+ pm.ctr.dsdb.mappings[i].oid.binary_oid = oid_blob.data;
}
ndr_err = ndr_push_struct_blob(&ndr_blob, msg,
@@ -519,14 +554,14 @@ WERROR dsdb_write_prefixes_from_schema_to_ldb(TALLOC_CTX *mem_ctx, struct ldb_co
return WERR_OK;
}
-WERROR dsdb_read_prefixes_from_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, uint32_t* num_prefixes, struct dsdb_schema_oid_prefix **prefixes)
+static WERROR dsdb_read_prefixes_from_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, uint32_t* num_prefixes, struct dsdb_schema_oid_prefix **prefixes)
{
struct prefixMapBlob *blob;
enum ndr_err_code ndr_err;
uint32_t i;
const struct ldb_val *prefix_val;
struct ldb_dn *schema_dn;
- struct ldb_result *schema_res;
+ struct ldb_result *schema_res = NULL;
int ret;
static const char *schema_attrs[] = {
"prefixMap",
@@ -586,10 +621,21 @@ WERROR dsdb_read_prefixes_from_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
return WERR_NOMEM;
}
for (i=0; i < blob->ctr.dsdb.num_mappings; i++) {
- char *oid;
+ DATA_BLOB oid_blob;
+ const char *partial_oid;
+
+ oid_blob = data_blob_const(blob->ctr.dsdb.mappings[i].oid.binary_oid,
+ blob->ctr.dsdb.mappings[i].oid.length);
+
+ if (!ber_read_partial_OID_String(mem_ctx, oid_blob, &partial_oid)) {
+ DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X",
+ blob->ctr.dsdb.mappings[i].id_prefix));
+ talloc_free(blob);
+ return WERR_INVALID_PARAM;
+ }
+
(*prefixes)[i].id = blob->ctr.dsdb.mappings[i].id_prefix<<16;
- oid = talloc_strdup(mem_ctx, blob->ctr.dsdb.mappings[i].oid.oid);
- (*prefixes)[i].oid = talloc_asprintf_append(oid, ".");
+ (*prefixes)[i].oid = partial_oid;
(*prefixes)[i].oid_len = strlen((*prefixes)[i].oid);
}
@@ -906,7 +952,7 @@ WERROR dsdb_class_from_ldb(const struct dsdb_schema *schema,
/*
Create a DSDB schema from the ldb results provided. This is called
directly when the schema is provisioned from an on-disk LDIF file, or
- from dsdb_schema_from_schema_dn below
+ from dsdb_schema_from_schema_dn in schema_fsmo
*/
int dsdb_schema_from_ldb_results(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
@@ -1013,115 +1059,6 @@ int dsdb_schema_from_ldb_results(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
return LDB_SUCCESS;
}
-/*
- Given an LDB, and the DN, return a populated schema
-*/
-
-int dsdb_schema_from_schema_dn(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
- struct smb_iconv_convenience *iconv_convenience,
- struct ldb_dn *schema_dn,
- struct dsdb_schema **schema,
- char **error_string_out)
-{
- TALLOC_CTX *tmp_ctx;
- char *error_string;
- int ret;
-
- struct ldb_result *schema_res;
- struct ldb_result *a_res;
- struct ldb_result *c_res;
- static const char *schema_attrs[] = {
- "prefixMap",
- "schemaInfo",
- "fSMORoleOwner",
- NULL
- };
- unsigned flags;
-
- tmp_ctx = talloc_new(mem_ctx);
- if (!tmp_ctx) {
- dsdb_oom(error_string_out, mem_ctx);
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- /* we don't want to trace the schema load */
- flags = ldb_get_flags(ldb);
- ldb_set_flags(ldb, flags & ~LDB_FLG_ENABLE_TRACING);
-
- /*
- * setup the prefix mappings and schema info
- */
- ret = ldb_search(ldb, tmp_ctx, &schema_res,
- schema_dn, LDB_SCOPE_BASE, schema_attrs, NULL);
- if (ret == LDB_ERR_NO_SUCH_OBJECT) {
- goto failed;
- } else if (ret != LDB_SUCCESS) {
- *error_string_out = talloc_asprintf(mem_ctx,
- "dsdb_schema: failed to search the schema head: %s",
- ldb_errstring(ldb));
- goto failed;
- }
- if (schema_res->count != 1) {
- *error_string_out = talloc_asprintf(mem_ctx,
- "dsdb_schema: [%u] schema heads found on a base search",
- schema_res->count);
- goto failed;
- }
-
- /*
- * load the attribute definitions
- */
- ret = ldb_search(ldb, tmp_ctx, &a_res,
- schema_dn, LDB_SCOPE_ONELEVEL, NULL,
- "(objectClass=attributeSchema)");
- if (ret != LDB_SUCCESS) {
- *error_string_out = talloc_asprintf(mem_ctx,
- "dsdb_schema: failed to search attributeSchema objects: %s",
- ldb_errstring(ldb));
- goto failed;
- }
-
- /*
- * load the objectClass definitions
- */
- ret = ldb_search(ldb, tmp_ctx, &c_res,
- schema_dn, LDB_SCOPE_ONELEVEL, NULL,
- "(objectClass=classSchema)");
- if (ret != LDB_SUCCESS) {
- *error_string_out = talloc_asprintf(mem_ctx,
- "dsdb_schema: failed to search attributeSchema objects: %s",
- ldb_errstring(ldb));
- goto failed;
- }
-
- ret = dsdb_schema_from_ldb_results(tmp_ctx, ldb,
- lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
- schema_res, a_res, c_res, schema, &error_string);
- if (ret != LDB_SUCCESS) {
- *error_string_out = talloc_asprintf(mem_ctx,
- "dsdb_schema load failed: %s",
- error_string);
- goto failed;
- }
- talloc_steal(mem_ctx, *schema);
- talloc_free(tmp_ctx);
-
- if (flags & LDB_FLG_ENABLE_TRACING) {
- flags = ldb_get_flags(ldb);
- ldb_set_flags(ldb, flags | LDB_FLG_ENABLE_TRACING);
- }
-
- return LDB_SUCCESS;
-
-failed:
- if (flags & LDB_FLG_ENABLE_TRACING) {
- flags = ldb_get_flags(ldb);
- ldb_set_flags(ldb, flags | LDB_FLG_ENABLE_TRACING);
- }
- talloc_free(tmp_ctx);
- return ret;
-}
-
static const struct {
const char *name;
diff --git a/source4/dsdb/schema/schema_prefixmap.c b/source4/dsdb/schema/schema_prefixmap.c
new file mode 100644
index 0000000000..d24c5add00
--- /dev/null
+++ b/source4/dsdb/schema/schema_prefixmap.c
@@ -0,0 +1,22 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ DRS::prefixMap implementation
+
+ Copyright (C) Kamen Mazdrashki <kamen.mazdrashki@postpath.com> 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
diff --git a/source4/dsdb/schema/schema_set.c b/source4/dsdb/schema/schema_set.c
index 6f09f63596..9f22b32334 100644
--- a/source4/dsdb/schema/schema_set.c
+++ b/source4/dsdb/schema/schema_set.c
@@ -346,7 +346,10 @@ int dsdb_set_schema(struct ldb_context *ldb, struct dsdb_schema *schema)
return ret;
}
- schema_fill_constructed(schema);
+ ret = schema_fill_constructed(schema);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
ret = ldb_set_opaque(ldb, "dsdb_schema", schema);
if (ret != LDB_SUCCESS) {
diff --git a/source4/dsdb/schema/schema_syntax.c b/source4/dsdb/schema/schema_syntax.c
index c564471d4b..cbbd4a8636 100644
--- a/source4/dsdb/schema/schema_syntax.c
+++ b/source4/dsdb/schema/schema_syntax.c
@@ -1204,6 +1204,8 @@ static WERROR dsdb_syntax_DN_ldb_to_drsuapi(struct ldb_context *ldb,
return WERR_OK;
}
+
+
static WERROR dsdb_syntax_DN_BINARY_drsuapi_to_ldb(struct ldb_context *ldb,
const struct dsdb_schema *schema,
const struct dsdb_attribute *attr,
@@ -1212,6 +1214,7 @@ static WERROR dsdb_syntax_DN_BINARY_drsuapi_to_ldb(struct ldb_context *ldb,
struct ldb_message_element *out)
{
uint32_t i;
+ int ret;
out->flags = 0;
out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
@@ -1222,39 +1225,81 @@ static WERROR dsdb_syntax_DN_BINARY_drsuapi_to_ldb(struct ldb_context *ldb,
W_ERROR_HAVE_NO_MEMORY(out->values);
for (i=0; i < out->num_values; i++) {
- struct drsuapi_DsReplicaObjectIdentifier3Binary id3b;
- char *binary;
- char *str;
+ struct drsuapi_DsReplicaObjectIdentifier3Binary id3;
enum ndr_err_code ndr_err;
+ DATA_BLOB guid_blob;
+ struct ldb_dn *dn;
+ TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+ if (!tmp_ctx) {
+ W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
+ }
if (in->value_ctr.values[i].blob == NULL) {
+ talloc_free(tmp_ctx);
return WERR_FOOBAR;
}
if (in->value_ctr.values[i].blob->length == 0) {
+ talloc_free(tmp_ctx);
return WERR_FOOBAR;
}
- ndr_err = ndr_pull_struct_blob_all(in->value_ctr.values[i].blob,
- out->values, schema->iconv_convenience, &id3b,
- (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3Binary);
+
+ /* windows sometimes sends an extra two pad bytes here */
+ ndr_err = ndr_pull_struct_blob(in->value_ctr.values[i].blob,
+ tmp_ctx, schema->iconv_convenience, &id3,
+ (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3Binary);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
+ talloc_free(tmp_ctx);
return ntstatus_to_werror(status);
}
- /* TODO: handle id3.guid and id3.sid */
- binary = data_blob_hex_string(out->values, &id3b.binary);
- W_ERROR_HAVE_NO_MEMORY(binary);
+ dn = ldb_dn_new(tmp_ctx, ldb, id3.dn);
+ if (!dn) {
+ talloc_free(tmp_ctx);
+ /* If this fails, it must be out of memory, as it does not do much parsing */
+ W_ERROR_HAVE_NO_MEMORY(dn);
+ }
- str = talloc_asprintf(out->values, "B:%u:%s:%s",
- (unsigned int)(id3b.binary.length * 2), /* because of 2 hex chars per byte */
- binary,
- id3b.dn);
- W_ERROR_HAVE_NO_MEMORY(str);
+ ndr_err = ndr_push_struct_blob(&guid_blob, tmp_ctx, schema->iconv_convenience, &id3.guid,
+ (ndr_push_flags_fn_t)ndr_push_GUID);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
+ talloc_free(tmp_ctx);
+ return ntstatus_to_werror(status);
+ }
- /* TODO: handle id3.guid and id3.sid */
- out->values[i] = data_blob_string_const(str);
+ ret = ldb_dn_set_extended_component(dn, "GUID", &guid_blob);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(tmp_ctx);
+ return WERR_FOOBAR;
+ }
+
+ talloc_free(guid_blob.data);
+
+ if (id3.__ndr_size_sid) {
+ DATA_BLOB sid_blob;
+ ndr_err = ndr_push_struct_blob(&sid_blob, tmp_ctx, schema->iconv_convenience, &id3.sid,
+ (ndr_push_flags_fn_t)ndr_push_dom_sid);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
+ talloc_free(tmp_ctx);
+ return ntstatus_to_werror(status);
+ }
+
+ ret = ldb_dn_set_extended_component(dn, "SID", &sid_blob);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(tmp_ctx);
+ return WERR_FOOBAR;
+ }
+ }
+
+ /* set binary stuff */
+ ldb_dn_set_binary(dn, &id3.binary);
+
+ out->values[i] = data_blob_string_const(ldb_dn_get_extended_linearized(out->values, dn, 1));
+ talloc_free(tmp_ctx);
}
return WERR_OK;
@@ -1285,27 +1330,72 @@ static WERROR dsdb_syntax_DN_BINARY_ldb_to_drsuapi(struct ldb_context *ldb,
W_ERROR_HAVE_NO_MEMORY(blobs);
for (i=0; i < in->num_values; i++) {
- struct drsuapi_DsReplicaObjectIdentifier3Binary id3b;
+ struct drsuapi_DsReplicaObjectIdentifier3Binary id3;
enum ndr_err_code ndr_err;
+ const DATA_BLOB *guid_blob, *sid_blob;
+ struct ldb_dn *dn;
+ TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+ W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
out->value_ctr.values[i].blob = &blobs[i];
- /* TODO: handle id3b.guid and id3b.sid, id3.binary */
- ZERO_STRUCT(id3b);
- id3b.dn = (const char *)in->values[i].data;
- id3b.binary = data_blob(NULL, 0);
+ dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &in->values[i]);
+
+ W_ERROR_HAVE_NO_MEMORY(dn);
+
+ guid_blob = ldb_dn_get_extended_component(dn, "GUID");
- ndr_err = ndr_push_struct_blob(&blobs[i], blobs, schema->iconv_convenience, &id3b,
- (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3Binary);
+ ZERO_STRUCT(id3);
+
+ if (guid_blob) {
+ ndr_err = ndr_pull_struct_blob_all(guid_blob,
+ tmp_ctx, schema->iconv_convenience, &id3.guid,
+ (ndr_pull_flags_fn_t)ndr_pull_GUID);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
+ talloc_free(tmp_ctx);
+ return ntstatus_to_werror(status);
+ }
+ }
+
+ sid_blob = ldb_dn_get_extended_component(dn, "SID");
+ if (sid_blob) {
+
+ ndr_err = ndr_pull_struct_blob_all(sid_blob,
+ tmp_ctx, schema->iconv_convenience, &id3.sid,
+ (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
+ talloc_free(tmp_ctx);
+ return ntstatus_to_werror(status);
+ }
+ }
+
+ id3.dn = ldb_dn_get_linearized(dn);
+ if (strncmp(id3.dn, "B:", 2) == 0) {
+ id3.dn = strchr(id3.dn, ':');
+ id3.dn = strchr(id3.dn+1, ':');
+ id3.dn = strchr(id3.dn+1, ':');
+ id3.dn++;
+ }
+
+ /* get binary stuff */
+ ldb_dn_get_binary(dn, &id3.binary);
+
+ ndr_err = ndr_push_struct_blob(&blobs[i], blobs, schema->iconv_convenience, &id3, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3Binary);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
+ talloc_free(tmp_ctx);
return ntstatus_to_werror(status);
}
+ talloc_free(tmp_ctx);
}
return WERR_OK;
}
+
+
static WERROR dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb(struct ldb_context *ldb,
const struct dsdb_schema *schema,
const struct dsdb_attribute *attr,