From 51f4de8fc85c314f23ca09ec88001f4dd2253b7f Mon Sep 17 00:00:00 2001 From: Matthias Dieter Wallnöfer Date: Sun, 31 Oct 2010 21:04:26 +0100 Subject: s4:samldb LDB module - validate "sAMAccountName" modifications Also the "sAMAccountName" attribute is protected against corruption (e.g. two accounts with the same name). --- source4/dsdb/samdb/ldb_modules/samldb.c | 74 +++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) (limited to 'source4/dsdb/samdb') diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index 79b557d5c8..b91ca3e83b 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -186,6 +186,9 @@ static int samldb_check_sAMAccountName(struct samldb_ctx *ac) return ldb_operr(ldb); } if (ret == 1) { + ldb_asprintf_errstring(ldb, + "samldb: Account name (sAMAccountName) '%s' already in use!", + name); return LDB_ERR_ENTRY_ALREADY_EXISTS; } @@ -1354,6 +1357,69 @@ static int samldb_group_type_change(struct samldb_ctx *ac) return LDB_SUCCESS; } +static int samldb_sam_accountname_check(struct samldb_ctx *ac) +{ + struct ldb_context *ldb = ldb_module_get_ctx(ac->module); + const char *no_attrs[] = { NULL }; + struct ldb_result *res; + const char *sam_accountname, *enc_str; + struct ldb_message_element *el; + struct ldb_message *tmp_msg; + int ret; + + ret = samldb_get_single_valued_attr(ac, "sAMAccountName", &el); + if (ret != LDB_SUCCESS) { + return ret; + } + if (el == NULL) { + /* we are not affected */ + return LDB_SUCCESS; + } + + /* Create a temporary message for fetching the "sAMAccountName" */ + tmp_msg = ldb_msg_new(ac->msg); + if (tmp_msg == NULL) { + return ldb_module_oom(ac->module); + } + ret = ldb_msg_add(tmp_msg, el, 0); + if (ret != LDB_SUCCESS) { + return ret; + } + sam_accountname = ldb_msg_find_attr_as_string(tmp_msg, "sAMAccountName", + NULL); + talloc_free(tmp_msg); + + if (sam_accountname == NULL) { + return ldb_operr(ldb); + } + + enc_str = ldb_binary_encode_string(ac, sam_accountname); + if (enc_str == NULL) { + return ldb_module_oom(ac->module); + } + + /* Make sure that a "sAMAccountName" is only used once */ + + ret = ldb_search(ldb, ac, &res, NULL, LDB_SCOPE_SUBTREE, no_attrs, + "(sAMAccountName=%s)", enc_str); + if (ret != LDB_SUCCESS) { + return ret; + } + if (res->count > 1) { + return ldb_operr(ldb); + } else if (res->count == 1) { + if (ldb_dn_compare(res->msgs[0]->dn, ac->msg->dn) != 0) { + ldb_asprintf_errstring(ldb, + "samldb: Account name (sAMAccountName) '%s' already in use!", + sam_accountname); + return LDB_ERR_ENTRY_ALREADY_EXISTS; + } + } + talloc_free(res); + + return LDB_SUCCESS; +} + static int samldb_member_check(struct samldb_ctx *ac) { struct ldb_context *ldb = ldb_module_get_ctx(ac->module); @@ -1768,6 +1834,14 @@ static int samldb_modify(struct ldb_module *module, struct ldb_request *req) } } + el = ldb_msg_find_element(ac->msg, "sAMAccountName"); + if (el != NULL) { + ret = samldb_sam_accountname_check(ac); + if (ret != LDB_SUCCESS) { + return ret; + } + } + el = ldb_msg_find_element(ac->msg, "member"); if (el != NULL) { ret = samldb_member_check(ac); -- cgit