summaryrefslogtreecommitdiff
path: root/source4/dsdb
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@samba.org>2007-12-17 04:22:44 +0100
committerStefan Metzmacher <metze@samba.org>2007-12-21 05:50:41 +0100
commit71e2cafe96f4755b67d01ced497bf5b63aad30f6 (patch)
tree6b0ba3ef5aaec87871d1642a554bb97c9754f316 /source4/dsdb
parent20a6fcf726d6e0ed656f0e26977eef6be8b8b862 (diff)
downloadsamba-71e2cafe96f4755b67d01ced497bf5b63aad30f6.tar.gz
samba-71e2cafe96f4755b67d01ced497bf5b63aad30f6.tar.bz2
samba-71e2cafe96f4755b67d01ced497bf5b63aad30f6.zip
r26483: Merge ldb module dependency fixes, fix auth python module.
(This used to be commit 85eeecf997a071ca7e7ad0247e8d34d49b7ffcbb)
Diffstat (limited to 'source4/dsdb')
-rw-r--r--source4/dsdb/common/util.c1895
-rw-r--r--source4/dsdb/config.mk19
-rw-r--r--source4/dsdb/samdb/ldb_modules/config.mk35
-rw-r--r--source4/dsdb/samdb/ldb_modules/partition.c22
-rw-r--r--source4/dsdb/samdb/ldb_modules/schema.c4
-rw-r--r--source4/dsdb/samdb/samdb.c1859
-rw-r--r--source4/dsdb/samdb/samdb.h1
-rw-r--r--source4/dsdb/schema/schema.h2
8 files changed, 1946 insertions, 1891 deletions
diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c
new file mode 100644
index 0000000000..efc1b20ae0
--- /dev/null
+++ b/source4/dsdb/common/util.c
@@ -0,0 +1,1895 @@
+/*
+ Unix SMB/CIFS implementation.
+ Samba utility functions
+
+ Copyright (C) Andrew Tridgell 2004
+ Copyright (C) Volker Lendecke 2004
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006
+ Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
+
+ 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 "ldb.h"
+#include "ldb_errors.h"
+#include "lib/util/util_ldb.h"
+#include "dsdb/samdb/samdb.h"
+#include "libcli/security/security.h"
+#include "librpc/gen_ndr/ndr_security.h"
+#include "dsdb/common/flags.h"
+#include "dsdb/common/proto.h"
+#include "libcli/ldap/ldap_ndr.h"
+#include "libcli/auth/libcli_auth.h"
+
+/*
+ search the sam for the specified attributes in a specific domain, filter on
+ objectSid being in domain_sid.
+*/
+int samdb_search_domain(struct ldb_context *sam_ldb,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_dn *basedn,
+ struct ldb_message ***res,
+ const char * const *attrs,
+ const struct dom_sid *domain_sid,
+ const char *format, ...) _PRINTF_ATTRIBUTE(7,8)
+{
+ va_list ap;
+ int i, count;
+
+ va_start(ap, format);
+ count = gendb_search_v(sam_ldb, mem_ctx, basedn,
+ res, attrs, format, ap);
+ va_end(ap);
+
+ i=0;
+
+ while (i<count) {
+ struct dom_sid *entry_sid;
+
+ entry_sid = samdb_result_dom_sid(mem_ctx, (*res)[i], "objectSid");
+
+ if ((entry_sid == NULL) ||
+ (!dom_sid_in_domain(domain_sid, entry_sid))) {
+ /* Delete that entry from the result set */
+ (*res)[i] = (*res)[count-1];
+ count -= 1;
+ talloc_free(entry_sid);
+ continue;
+ }
+ talloc_free(entry_sid);
+ i += 1;
+ }
+
+ return count;
+}
+
+/*
+ search the sam for a single string attribute in exactly 1 record
+*/
+const char *samdb_search_string_v(struct ldb_context *sam_ldb,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_dn *basedn,
+ const char *attr_name,
+ const char *format, va_list ap) _PRINTF_ATTRIBUTE(5,0)
+{
+ int count;
+ const char *attrs[2] = { NULL, NULL };
+ struct ldb_message **res = NULL;
+
+ attrs[0] = attr_name;
+
+ count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
+ if (count > 1) {
+ DEBUG(1,("samdb: search for %s %s not single valued (count=%d)\n",
+ attr_name, format, count));
+ }
+ if (count != 1) {
+ talloc_free(res);
+ return NULL;
+ }
+
+ return samdb_result_string(res[0], attr_name, NULL);
+}
+
+
+/*
+ search the sam for a single string attribute in exactly 1 record
+*/
+const char *samdb_search_string(struct ldb_context *sam_ldb,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_dn *basedn,
+ const char *attr_name,
+ const char *format, ...) _PRINTF_ATTRIBUTE(5,6)
+{
+ va_list ap;
+ const char *str;
+
+ va_start(ap, format);
+ str = samdb_search_string_v(sam_ldb, mem_ctx, basedn, attr_name, format, ap);
+ va_end(ap);
+
+ return str;
+}
+
+struct ldb_dn *samdb_search_dn(struct ldb_context *sam_ldb,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_dn *basedn,
+ const char *format, ...) _PRINTF_ATTRIBUTE(4,5)
+{
+ va_list ap;
+ struct ldb_dn *ret;
+ struct ldb_message **res = NULL;
+ int count;
+
+ va_start(ap, format);
+ count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, NULL, format, ap);
+ va_end(ap);
+
+ if (count != 1) return NULL;
+
+ ret = talloc_steal(mem_ctx, res[0]->dn);
+ talloc_free(res);
+
+ return ret;
+}
+
+/*
+ search the sam for a dom_sid attribute in exactly 1 record
+*/
+struct dom_sid *samdb_search_dom_sid(struct ldb_context *sam_ldb,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_dn *basedn,
+ const char *attr_name,
+ const char *format, ...) _PRINTF_ATTRIBUTE(5,6)
+{
+ va_list ap;
+ int count;
+ struct ldb_message **res;
+ const char *attrs[2] = { NULL, NULL };
+ struct dom_sid *sid;
+
+ attrs[0] = attr_name;
+
+ va_start(ap, format);
+ count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
+ va_end(ap);
+ if (count > 1) {
+ DEBUG(1,("samdb: search for %s %s not single valued (count=%d)\n",
+ attr_name, format, count));
+ }
+ if (count != 1) {
+ talloc_free(res);
+ return NULL;
+ }
+ sid = samdb_result_dom_sid(mem_ctx, res[0], attr_name);
+ talloc_free(res);
+ return sid;
+}
+
+/*
+ return the count of the number of records in the sam matching the query
+*/
+int samdb_search_count(struct ldb_context *sam_ldb,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_dn *basedn,
+ const char *format, ...) _PRINTF_ATTRIBUTE(4,5)
+{
+ va_list ap;
+ struct ldb_message **res;
+ const char * const attrs[] = { NULL };
+ int ret;
+
+ va_start(ap, format);
+ ret = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
+ va_end(ap);
+
+ return ret;
+}
+
+
+/*
+ search the sam for a single integer attribute in exactly 1 record
+*/
+uint_t samdb_search_uint(struct ldb_context *sam_ldb,
+ TALLOC_CTX *mem_ctx,
+ uint_t default_value,
+ struct ldb_dn *basedn,
+ const char *attr_name,
+ const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
+{
+ va_list ap;
+ int count;
+ struct ldb_message **res;
+ const char *attrs[2] = { NULL, NULL };
+
+ attrs[0] = attr_name;
+
+ va_start(ap, format);
+ count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
+ va_end(ap);
+
+ if (count != 1) {
+ return default_value;
+ }
+
+ return samdb_result_uint(res[0], attr_name, default_value);
+}
+
+/*
+ search the sam for a single signed 64 bit integer attribute in exactly 1 record
+*/
+int64_t samdb_search_int64(struct ldb_context *sam_ldb,
+ TALLOC_CTX *mem_ctx,
+ int64_t default_value,
+ struct ldb_dn *basedn,
+ const char *attr_name,
+ const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
+{
+ va_list ap;
+ int count;
+ struct ldb_message **res;
+ const char *attrs[2] = { NULL, NULL };
+
+ attrs[0] = attr_name;
+
+ va_start(ap, format);
+ count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
+ va_end(ap);
+
+ if (count != 1) {
+ return default_value;
+ }
+
+ return samdb_result_int64(res[0], attr_name, default_value);
+}
+
+/*
+ search the sam for multipe records each giving a single string attribute
+ return the number of matches, or -1 on error
+*/
+int samdb_search_string_multiple(struct ldb_context *sam_ldb,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_dn *basedn,
+ const char ***strs,
+ const char *attr_name,
+ const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
+{
+ va_list ap;
+ int count, i;
+ const char *attrs[2] = { NULL, NULL };
+ struct ldb_message **res = NULL;
+
+ attrs[0] = attr_name;
+
+ va_start(ap, format);
+ count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
+ va_end(ap);
+
+ if (count <= 0) {
+ return count;
+ }
+
+ /* make sure its single valued */
+ for (i=0;i<count;i++) {
+ if (res[i]->num_elements != 1) {
+ DEBUG(1,("samdb: search for %s %s not single valued\n",
+ attr_name, format));
+ talloc_free(res);
+ return -1;
+ }
+ }
+
+ *strs = talloc_array(mem_ctx, const char *, count+1);
+ if (! *strs) {
+ talloc_free(res);
+ return -1;
+ }
+
+ for (i=0;i<count;i++) {
+ (*strs)[i] = samdb_result_string(res[i], attr_name, NULL);
+ }
+ (*strs)[count] = NULL;
+
+ return count;
+}
+
+/*
+ pull a uint from a result set.
+*/
+uint_t samdb_result_uint(const struct ldb_message *msg, const char *attr, uint_t default_value)
+{
+ return ldb_msg_find_attr_as_uint(msg, attr, default_value);
+}
+
+/*
+ pull a (signed) int64 from a result set.
+*/
+int64_t samdb_result_int64(const struct ldb_message *msg, const char *attr, int64_t default_value)
+{
+ return ldb_msg_find_attr_as_int64(msg, attr, default_value);
+}
+
+/*
+ pull a string from a result set.
+*/
+const char *samdb_result_string(const struct ldb_message *msg, const char *attr,
+ const char *default_value)
+{
+ return ldb_msg_find_attr_as_string(msg, attr, default_value);
+}
+
+struct ldb_dn *samdb_result_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const struct ldb_message *msg,
+ const char *attr, struct ldb_dn *default_value)
+{
+ struct ldb_dn *ret_dn = ldb_msg_find_attr_as_dn(ldb, mem_ctx, msg, attr);
+ if (!ret_dn) {
+ return default_value;
+ }
+ return ret_dn;
+}
+
+/*
+ pull a rid from a objectSid in a result set.
+*/
+uint32_t samdb_result_rid_from_sid(TALLOC_CTX *mem_ctx, const struct ldb_message *msg,
+ const char *attr, uint32_t default_value)
+{
+ struct dom_sid *sid;
+ uint32_t rid;
+
+ sid = samdb_result_dom_sid(mem_ctx, msg, attr);
+ if (sid == NULL) {
+ return default_value;
+ }
+ rid = sid->sub_auths[sid->num_auths-1];
+ talloc_free(sid);
+ return rid;
+}
+
+/*
+ pull a dom_sid structure from a objectSid in a result set.
+*/
+struct dom_sid *samdb_result_dom_sid(TALLOC_CTX *mem_ctx, const struct ldb_message *msg,
+ const char *attr)
+{
+ const struct ldb_val *v;
+ struct dom_sid *sid;
+ enum ndr_err_code ndr_err;
+ v = ldb_msg_find_ldb_val(msg, attr);
+ if (v == NULL) {
+ return NULL;
+ }
+ sid = talloc(mem_ctx, struct dom_sid);
+ if (sid == NULL) {
+ return NULL;
+ }
+ ndr_err = ndr_pull_struct_blob(v, sid, sid,
+ (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ talloc_free(sid);
+ return NULL;
+ }
+ return sid;
+}
+
+/*
+ pull a guid structure from a objectGUID in a result set.
+*/
+struct GUID samdb_result_guid(const struct ldb_message *msg, const char *attr)
+{
+ const struct ldb_val *v;
+ enum ndr_err_code ndr_err;
+ struct GUID guid;
+ TALLOC_CTX *mem_ctx;
+
+ ZERO_STRUCT(guid);
+
+ v = ldb_msg_find_ldb_val(msg, attr);
+ if (!v) return guid;
+
+ mem_ctx = talloc_named_const(NULL, 0, "samdb_result_guid");
+ if (!mem_ctx) return guid;
+ ndr_err = ndr_pull_struct_blob(v, mem_ctx, &guid,
+ (ndr_pull_flags_fn_t)ndr_pull_GUID);
+ talloc_free(mem_ctx);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ return guid;
+ }
+
+ return guid;
+}
+
+/*
+ pull a sid prefix from a objectSid in a result set.
+ this is used to find the domain sid for a user
+*/
+struct dom_sid *samdb_result_sid_prefix(TALLOC_CTX *mem_ctx, const struct ldb_message *msg,
+ const char *attr)
+{
+ struct dom_sid *sid = samdb_result_dom_sid(mem_ctx, msg, attr);
+ if (!sid || sid->num_auths < 1) return NULL;
+ sid->num_auths--;
+ return sid;
+}
+
+/*
+ pull a NTTIME in a result set.
+*/
+NTTIME samdb_result_nttime(struct ldb_message *msg, const char *attr, NTTIME default_value)
+{
+ return ldb_msg_find_attr_as_uint64(msg, attr, default_value);
+}
+
+/*
+ pull a uint64_t from a result set.
+*/
+uint64_t samdb_result_uint64(struct ldb_message *msg, const char *attr, uint64_t default_value)
+{
+ return ldb_msg_find_attr_as_uint64(msg, attr, default_value);
+}
+
+
+/*
+ construct the allow_password_change field from the PwdLastSet attribute and the
+ domain password settings
+*/
+NTTIME samdb_result_allow_password_change(struct ldb_context *sam_ldb,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_dn *domain_dn,
+ struct ldb_message *msg,
+ const char *attr)
+{
+ uint64_t attr_time = samdb_result_uint64(msg, attr, 0);
+ int64_t minPwdAge;
+
+ if (attr_time == 0) {
+ return 0;
+ }
+
+ minPwdAge = samdb_search_int64(sam_ldb, mem_ctx, 0, domain_dn, "minPwdAge", NULL);
+
+ /* yes, this is a -= not a += as minPwdAge is stored as the negative
+ of the number of 100-nano-seconds */
+ attr_time -= minPwdAge;
+
+ return attr_time;
+}
+
+/*
+ construct the force_password_change field from the PwdLastSet attribute and the
+ domain password settings
+*/
+NTTIME samdb_result_force_password_change(struct ldb_context *sam_ldb,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_dn *domain_dn,
+ struct ldb_message *msg)
+{
+ uint64_t attr_time = samdb_result_uint64(msg, "pwdLastSet", 0);
+ uint32_t user_flags = samdb_result_uint64(msg, "userAccountControl", 0);
+ int64_t maxPwdAge;
+
+ if (user_flags & UF_DONT_EXPIRE_PASSWD) {
+ return 0x7FFFFFFFFFFFFFFFULL;
+ }
+
+ if (attr_time == 0) {
+ return 0;
+ }
+
+ maxPwdAge = samdb_search_int64(sam_ldb, mem_ctx, 0, domain_dn, "maxPwdAge", NULL);
+ if (maxPwdAge == 0) {
+ return 0;
+ } else {
+ attr_time -= maxPwdAge;
+ }
+
+ return attr_time;
+}
+
+/*
+ pull a samr_Password structutre from a result set.
+*/
+struct samr_Password *samdb_result_hash(TALLOC_CTX *mem_ctx, struct ldb_message *msg, const char *attr)
+{
+ struct samr_Password *hash = NULL;
+ const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
+ if (val && (val->length >= sizeof(hash->hash))) {
+ hash = talloc(mem_ctx, struct samr_Password);
+ memcpy(hash->hash, val->data, MIN(val->length, sizeof(hash->hash)));
+ }
+ return hash;
+}
+
+/*
+ pull an array of samr_Password structutres from a result set.
+*/
+uint_t samdb_result_hashes(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+ const char *attr, struct samr_Password **hashes)
+{
+ uint_t count = 0;
+ const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
+ int i;
+
+ *hashes = NULL;
+ if (!val) {
+ return 0;
+ }
+ count = val->length / 16;
+ if (count == 0) {
+ return 0;
+ }
+
+ *hashes = talloc_array(mem_ctx, struct samr_Password, count);
+ if (! *hashes) {
+ return 0;
+ }
+
+ for (i=0;i<count;i++) {
+ memcpy((*hashes)[i].hash, (i*16)+(char *)val->data, 16);
+ }
+
+ return count;
+}
+
+NTSTATUS samdb_result_passwords(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+ struct samr_Password **lm_pwd, struct samr_Password **nt_pwd)
+{
+ struct samr_Password *lmPwdHash, *ntPwdHash;
+ if (nt_pwd) {
+ int num_nt;
+ num_nt = samdb_result_hashes(mem_ctx, msg, "unicodePwd", &ntPwdHash);
+ if (num_nt == 0) {
+ *nt_pwd = NULL;
+ } else if (num_nt > 1) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ } else {
+ *nt_pwd = &ntPwdHash[0];
+ }
+ }
+ if (lm_pwd) {
+ int num_lm;
+ num_lm = samdb_result_hashes(mem_ctx, msg, "dBCSPwd", &lmPwdHash);
+ if (num_lm == 0) {
+ *lm_pwd = NULL;
+ } else if (num_lm > 1) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ } else {
+ *lm_pwd = &lmPwdHash[0];
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+/*
+ pull a samr_LogonHours structutre from a result set.
+*/
+struct samr_LogonHours samdb_result_logon_hours(TALLOC_CTX *mem_ctx, struct ldb_message *msg, const char *attr)
+{
+ struct samr_LogonHours hours;
+ const int units_per_week = 168;
+ const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
+ ZERO_STRUCT(hours);
+ hours.bits = talloc_array(mem_ctx, uint8_t, units_per_week);
+ if (!hours.bits) {
+ return hours;
+ }
+ hours.units_per_week = units_per_week;
+ memset(hours.bits, 0xFF, units_per_week);
+ if (val) {
+ memcpy(hours.bits, val->data, MIN(val->length, units_per_week));
+ }
+ return hours;
+}
+
+/*
+ pull a set of account_flags from a result set.
+*/
+uint16_t samdb_result_acct_flags(struct ldb_message *msg, const char *attr)
+{
+ uint_t userAccountControl = ldb_msg_find_attr_as_uint(msg, attr, 0);
+ return samdb_uf2acb(userAccountControl);
+}
+
+
+/* Find an attribute, with a particular value */
+
+/* The current callers of this function expect a very specific
+ * behaviour: In particular, objectClass subclass equivilance is not
+ * wanted. This means that we should not lookup the schema for the
+ * comparison function */
+struct ldb_message_element *samdb_find_attribute(struct ldb_context *ldb,
+ const struct ldb_message *msg,
+ const char *name, const char *value)
+{
+ int i;
+ struct ldb_message_element *el = ldb_msg_find_element(msg, name);
+
+ if (!el) {
+ return NULL;
+ }
+
+ for (i=0;i<el->num_values;i++) {
+ if (ldb_attr_cmp(value, (char *)el->values[i].data) == 0) {
+ return el;
+ }
+ }
+
+ return NULL;
+}
+
+int samdb_find_or_add_value(struct ldb_context *ldb, struct ldb_message *msg, const char *name, const char *set_value)
+{
+ if (samdb_find_attribute(ldb, msg, name, set_value) == NULL) {
+ return samdb_msg_add_string(ldb, msg, msg, name, set_value);
+ }
+ return LDB_SUCCESS;
+}
+
+int samdb_find_or_add_attribute(struct ldb_context *ldb, struct ldb_message *msg, const char *name, const char *set_value)
+{
+ struct ldb_message_element *el;
+
+ el = ldb_msg_find_element(msg, name);
+ if (el) {
+ return LDB_SUCCESS;
+ }
+
+ return samdb_msg_add_string(ldb, msg, msg, name, set_value);
+}
+
+
+
+/*
+ add a string element to a message
+*/
+int samdb_msg_add_string(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+ const char *attr_name, const char *str)
+{
+ char *s = talloc_strdup(mem_ctx, str);
+ char *a = talloc_strdup(mem_ctx, attr_name);
+ if (s == NULL || a == NULL) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ return ldb_msg_add_string(msg, a, s);
+}
+
+/*
+ add a dom_sid element to a message
+*/
+int samdb_msg_add_dom_sid(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+ const char *attr_name, struct dom_sid *sid)
+{
+ struct ldb_val v;
+ enum ndr_err_code ndr_err;
+
+ ndr_err = ndr_push_struct_blob(&v, mem_ctx, sid,
+ (ndr_push_flags_fn_t)ndr_push_dom_sid);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ return -1;
+ }
+ return ldb_msg_add_value(msg, attr_name, &v, NULL);
+}
+
+
+/*
+ add a delete element operation to a message
+*/
+int samdb_msg_add_delete(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+ const char *attr_name)
+{
+ /* we use an empty replace rather than a delete, as it allows for
+ samdb_replace() to be used everywhere */
+ return ldb_msg_add_empty(msg, attr_name, LDB_FLAG_MOD_REPLACE, NULL);
+}
+
+/*
+ add a add attribute value to a message
+*/
+int samdb_msg_add_addval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+ const char *attr_name, const char *value)
+{
+ struct ldb_message_element *el;
+ char *a, *v;
+ int ret;
+ a = talloc_strdup(mem_ctx, attr_name);
+ if (a == NULL)
+ return -1;
+ v = talloc_strdup(mem_ctx, value);
+ if (v == NULL)
+ return -1;
+ ret = ldb_msg_add_string(msg, a, v);
+ if (ret != 0)
+ return ret;
+ el = ldb_msg_find_element(msg, a);
+ if (el == NULL)
+ return -1;
+ el->flags = LDB_FLAG_MOD_ADD;
+ return 0;
+}
+
+/*
+ add a delete attribute value to a message
+*/
+int samdb_msg_add_delval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+ const char *attr_name, const char *value)
+{
+ struct ldb_message_element *el;
+ char *a, *v;
+ int ret;
+ a = talloc_strdup(mem_ctx, attr_name);
+ if (a == NULL)
+ return -1;
+ v = talloc_strdup(mem_ctx, value);
+ if (v == NULL)
+ return -1;
+ ret = ldb_msg_add_string(msg, a, v);
+ if (ret != 0)
+ return ret;
+ el = ldb_msg_find_element(msg, a);
+ if (el == NULL)
+ return -1;
+ el->flags = LDB_FLAG_MOD_DELETE;
+ return 0;
+}
+
+/*
+ add a int element to a message
+*/
+int samdb_msg_add_int(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+ const char *attr_name, int v)
+{
+ const char *s = talloc_asprintf(mem_ctx, "%d", v);
+ return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, s);
+}
+
+/*
+ add a uint_t element to a message
+*/
+int samdb_msg_add_uint(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+ const char *attr_name, uint_t v)
+{
+ const char *s = talloc_asprintf(mem_ctx, "%u", v);
+ return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, s);
+}
+
+/*
+ add a (signed) int64_t element to a message
+*/
+int samdb_msg_add_int64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+ const char *attr_name, int64_t v)
+{
+ const char *s = talloc_asprintf(mem_ctx, "%lld", (long long)v);
+ return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, s);
+}
+
+/*
+ add a uint64_t element to a message
+*/
+int samdb_msg_add_uint64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+ const char *attr_name, uint64_t v)
+{
+ const char *s = talloc_asprintf(mem_ctx, "%llu", (unsigned long long)v);
+ return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, s);
+}
+
+/*
+ add a samr_Password element to a message
+*/
+int samdb_msg_add_hash(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+ const char *attr_name, struct samr_Password *hash)
+{
+ struct ldb_val val;
+ val.data = talloc_memdup(mem_ctx, hash->hash, 16);
+ if (!val.data) {
+ return -1;
+ }
+ val.length = 16;
+ return ldb_msg_add_value(msg, attr_name, &val, NULL);
+}
+
+/*
+ add a samr_Password array to a message
+*/
+int samdb_msg_add_hashes(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+ const char *attr_name, struct samr_Password *hashes, uint_t count)
+{
+ struct ldb_val val;
+ int i;
+ val.data = talloc_array_size(mem_ctx, 16, count);
+ val.length = count*16;
+ if (!val.data) {
+ return -1;
+ }
+ for (i=0;i<count;i++) {
+ memcpy(i*16 + (char *)val.data, hashes[i].hash, 16);
+ }
+ return ldb_msg_add_value(msg, attr_name, &val, NULL);
+}
+
+/*
+ add a acct_flags element to a message
+*/
+int samdb_msg_add_acct_flags(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+ const char *attr_name, uint32_t v)
+{
+ return samdb_msg_add_uint(sam_ldb, mem_ctx, msg, attr_name, samdb_acb2uf(v));
+}
+
+/*
+ add a logon_hours element to a message
+*/
+int samdb_msg_add_logon_hours(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+ const char *attr_name, struct samr_LogonHours *hours)
+{
+ struct ldb_val val;
+ val.length = hours->units_per_week / 8;
+ val.data = hours->bits;
+ return ldb_msg_add_value(msg, attr_name, &val, NULL);
+}
+
+/*
+ add a general value element to a message
+*/
+int samdb_msg_add_value(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+ const char *attr_name, const struct ldb_val *val)
+{
+ return ldb_msg_add_value(msg, attr_name, val, NULL);
+}
+
+/*
+ sets a general value element to a message
+*/
+int samdb_msg_set_value(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+ const char *attr_name, const struct ldb_val *val)
+{
+ struct ldb_message_element *el;
+
+ el = ldb_msg_find_element(msg, attr_name);
+ if (el) {
+ el->num_values = 0;
+ }
+ return ldb_msg_add_value(msg, attr_name, val, NULL);
+}
+
+/*
+ set a string element in a message
+*/
+int samdb_msg_set_string(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+ const char *attr_name, const char *str)
+{
+ struct ldb_message_element *el;
+
+ el = ldb_msg_find_element(msg, attr_name);
+ if (el) {
+ el->num_values = 0;
+ }
+ return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, str);
+}
+
+/*
+ replace elements in a record
+*/
+int samdb_replace(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg)
+{
+ int i;
+
+ /* mark all the message elements as LDB_FLAG_MOD_REPLACE */
+ for (i=0;i<msg->num_elements;i++) {
+ msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
+ }
+
+ /* modify the samdb record */
+ return ldb_modify(sam_ldb, msg);
+}
+
+/*
+ return a default security descriptor
+*/
+struct security_descriptor *samdb_default_security_descriptor(TALLOC_CTX *mem_ctx)
+{
+ struct security_descriptor *sd;
+
+ sd = security_descriptor_initialise(mem_ctx);
+
+ return sd;
+}
+
+struct ldb_dn *samdb_base_dn(struct ldb_context *sam_ctx)
+{
+ return ldb_get_default_basedn(sam_ctx);
+}
+
+struct ldb_dn *samdb_config_dn(struct ldb_context *sam_ctx)
+{
+ return ldb_get_config_basedn(sam_ctx);
+}
+
+struct ldb_dn *samdb_schema_dn(struct ldb_context *sam_ctx)
+{
+ return ldb_get_schema_basedn(sam_ctx);
+}
+
+struct ldb_dn *samdb_root_dn(struct ldb_context *sam_ctx)
+{
+ return ldb_get_root_basedn(sam_ctx);
+}
+
+struct ldb_dn *samdb_partitions_dn(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx)
+{
+ struct ldb_dn *new_dn;
+
+ new_dn = ldb_dn_copy(mem_ctx, samdb_config_dn(sam_ctx));
+ if ( ! ldb_dn_add_child_fmt(new_dn, "CN=Partitions")) {
+ talloc_free(new_dn);
+ return NULL;
+ }
+ return new_dn;
+}
+
+struct ldb_dn *samdb_sites_dn(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx)
+{
+ struct ldb_dn *new_dn;
+
+ new_dn = ldb_dn_copy(mem_ctx, samdb_config_dn(sam_ctx));
+ if ( ! ldb_dn_add_child_fmt(new_dn, "CN=Sites")) {
+ talloc_free(new_dn);
+ return NULL;
+ }
+ return new_dn;
+}
+
+/*
+ work out the domain sid for the current open ldb
+*/
+const struct dom_sid *samdb_domain_sid(struct ldb_context *ldb)
+{
+ TALLOC_CTX *tmp_ctx;
+ struct dom_sid *domain_sid;
+
+ /* see if we have a cached copy */
+ domain_sid = (struct dom_sid *)ldb_get_opaque(ldb, "cache.domain_sid");
+ if (domain_sid) {
+ return domain_sid;
+ }
+
+ tmp_ctx = talloc_new(ldb);
+ if (tmp_ctx == NULL) {
+ goto failed;
+ }
+
+ /* find the domain_sid */
+ domain_sid = samdb_search_dom_sid(ldb, tmp_ctx, ldb_get_default_basedn(ldb),
+ "objectSid", "objectClass=domainDNS");
+ if (domain_sid == NULL) {
+ goto failed;
+ }
+
+ /* cache the domain_sid in the ldb */
+ if (ldb_set_opaque(ldb, "cache.domain_sid", domain_sid) != LDB_SUCCESS) {
+ goto failed;
+ }
+
+ talloc_steal(ldb, domain_sid);
+ talloc_free(tmp_ctx);
+
+ return domain_sid;
+
+failed:
+ DEBUG(1,("Failed to find domain_sid for open ldb\n"));
+ talloc_free(tmp_ctx);
+ return NULL;
+}
+
+bool samdb_set_domain_sid(struct ldb_context *ldb, const struct dom_sid *dom_sid_in)
+{
+ TALLOC_CTX *tmp_ctx;
+ struct dom_sid *dom_sid_new;
+ struct dom_sid *dom_sid_old;
+
+ /* see if we have a cached copy */
+ dom_sid_old = talloc_get_type(ldb_get_opaque(ldb,
+ "cache.domain_sid"), struct dom_sid);
+
+ tmp_ctx = talloc_new(ldb);
+ if (tmp_ctx == NULL) {
+ goto failed;
+ }
+
+ dom_sid_new = dom_sid_dup(tmp_ctx, dom_sid_in);
+ if (!dom_sid_new) {
+ goto failed;
+ }
+
+ /* cache the domain_sid in the ldb */
+ if (ldb_set_opaque(ldb, "cache.domain_sid", dom_sid_new) != LDB_SUCCESS) {
+ goto failed;
+ }
+
+ talloc_steal(ldb, dom_sid_new);
+ talloc_free(tmp_ctx);
+ talloc_free(dom_sid_old);
+
+ return true;
+
+failed:
+ DEBUG(1,("Failed to set our own cached domain SID in the ldb!\n"));
+ talloc_free(tmp_ctx);
+ return false;
+}
+
+/* Obtain the short name of the flexible single master operator
+ * (FSMO), such as the PDC Emulator */
+const char *samdb_result_fsmo_name(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const struct ldb_message *msg,
+ const char *attr)
+{
+ /* Format is cn=NTDS Settings,cn=<NETBIOS name of FSMO>,.... */
+ struct ldb_dn *fsmo_dn = ldb_msg_find_attr_as_dn(ldb, mem_ctx, msg, attr);
+ const struct ldb_val *val = ldb_dn_get_component_val(fsmo_dn, 1);
+ const char *name = ldb_dn_get_component_name(fsmo_dn, 1);
+
+ if (!name || (ldb_attr_cmp(name, "cn") != 0)) {
+ /* Ensure this matches the format. This gives us a
+ * bit more confidence that a 'cn' value will be a
+ * ascii string */
+ return NULL;
+ }
+ if (val) {
+ return (char *)val->data;
+ }
+ return NULL;
+}
+
+/*
+ work out the ntds settings dn for the current open ldb
+*/
+struct ldb_dn *samdb_ntds_settings_dn(struct ldb_context *ldb)
+{
+ TALLOC_CTX *tmp_ctx;
+ const char *root_attrs[] = { "dsServiceName", NULL };
+ int ret;
+ struct ldb_result *root_res;
+ struct ldb_dn *settings_dn;
+
+ /* see if we have a cached copy */
+ settings_dn = (struct ldb_dn *)ldb_get_opaque(ldb, "cache.settings_dn");
+ if (settings_dn) {
+ return settings_dn;
+ }
+
+ tmp_ctx = talloc_new(ldb);
+ if (tmp_ctx == NULL) {
+ goto failed;
+ }
+
+
+ ret = ldb_search(ldb, ldb_dn_new(tmp_ctx, ldb, ""), LDB_SCOPE_BASE, NULL, root_attrs, &root_res);
+ if (ret) {
+ DEBUG(1,("Searching for dsServiceName in rootDSE failed: %s\n",
+ ldb_errstring(ldb)));
+ goto failed;
+ }
+ talloc_steal(tmp_ctx, root_res);
+
+ if (root_res->count != 1) {
+ goto failed;
+ }
+
+ settings_dn = ldb_msg_find_attr_as_dn(ldb, tmp_ctx, root_res->msgs[0], "dsServiceName");
+
+ /* cache the domain_sid in the ldb */
+ if (ldb_set_opaque(ldb, "cache.settings_dn", settings_dn) != LDB_SUCCESS) {
+ goto failed;
+ }
+
+ talloc_steal(ldb, settings_dn);
+ talloc_free(tmp_ctx);
+
+ return settings_dn;
+
+failed:
+ DEBUG(1,("Failed to find our own NTDS Settings DN in the ldb!\n"));
+ talloc_free(tmp_ctx);
+ return NULL;
+}
+
+/*
+ work out the ntds settings invocationId for the current open ldb
+*/
+const struct GUID *samdb_ntds_invocation_id(struct ldb_context *ldb)
+{
+ TALLOC_CTX *tmp_ctx;
+ const char *attrs[] = { "invocationId", NULL };
+ int ret;
+ struct ldb_result *res;
+ struct GUID *invocation_id;
+
+ /* see if we have a cached copy */
+ invocation_id = (struct GUID *)ldb_get_opaque(ldb, "cache.invocation_id");
+ if (invocation_id) {
+ return invocation_id;
+ }
+
+ tmp_ctx = talloc_new(ldb);
+ if (tmp_ctx == NULL) {
+ goto failed;
+ }
+
+ ret = ldb_search(ldb, samdb_ntds_settings_dn(ldb), LDB_SCOPE_BASE, NULL, attrs, &res);
+ if (ret) {
+ goto failed;
+ }
+ talloc_steal(tmp_ctx, res);
+
+ if (res->count != 1) {
+ goto failed;
+ }
+
+ invocation_id = talloc(tmp_ctx, struct GUID);
+ if (!invocation_id) {
+ goto failed;
+ }
+
+ *invocation_id = samdb_result_guid(res->msgs[0], "invocationId");
+
+ /* cache the domain_sid in the ldb */
+ if (ldb_set_opaque(ldb, "cache.invocation_id", invocation_id) != LDB_SUCCESS) {
+ goto failed;
+ }
+
+ talloc_steal(ldb, invocation_id);
+ talloc_free(tmp_ctx);
+
+ return invocation_id;
+
+failed:
+ DEBUG(1,("Failed to find our own NTDS Settings invocationId in the ldb!\n"));
+ talloc_free(tmp_ctx);
+ return NULL;
+}
+
+bool samdb_set_ntds_invocation_id(struct ldb_context *ldb, const struct GUID *invocation_id_in)
+{
+ TALLOC_CTX *tmp_ctx;
+ struct GUID *invocation_id_new;
+ struct GUID *invocation_id_old;
+
+ /* see if we have a cached copy */
+ invocation_id_old = (struct GUID *)ldb_get_opaque(ldb,
+ "cache.invocation_id");
+
+ tmp_ctx = talloc_new(ldb);
+ if (tmp_ctx == NULL) {
+ goto failed;
+ }
+
+ invocation_id_new = talloc(tmp_ctx, struct GUID);
+ if (!invocation_id_new) {
+ goto failed;
+ }
+
+ *invocation_id_new = *invocation_id_in;
+
+ /* cache the domain_sid in the ldb */
+ if (ldb_set_opaque(ldb, "cache.invocation_id", invocation_id_new) != LDB_SUCCESS) {
+ goto failed;
+ }
+
+ talloc_steal(ldb, invocation_id_new);
+ talloc_free(tmp_ctx);
+ talloc_free(invocation_id_old);
+
+ return true;
+
+failed:
+ DEBUG(1,("Failed to set our own cached invocationId in the ldb!\n"));
+ talloc_free(tmp_ctx);
+ return false;
+}
+
+/*
+ work out the ntds settings objectGUID for the current open ldb
+*/
+const struct GUID *samdb_ntds_objectGUID(struct ldb_context *ldb)
+{
+ TALLOC_CTX *tmp_ctx;
+ const char *attrs[] = { "objectGUID", NULL };
+ int ret;
+ struct ldb_result *res;
+ struct GUID *ntds_guid;
+
+ /* see if we have a cached copy */
+ ntds_guid = (struct GUID *)ldb_get_opaque(ldb, "cache.ntds_guid");
+ if (ntds_guid) {
+ return ntds_guid;
+ }
+
+ tmp_ctx = talloc_new(ldb);
+ if (tmp_ctx == NULL) {
+ goto failed;
+ }
+
+ ret = ldb_search(ldb, samdb_ntds_settings_dn(ldb), LDB_SCOPE_BASE, NULL, attrs, &res);
+ if (ret) {
+ goto failed;
+ }
+ talloc_steal(tmp_ctx, res);
+
+ if (res->count != 1) {
+ goto failed;
+ }
+
+ ntds_guid = talloc(tmp_ctx, struct GUID);
+ if (!ntds_guid) {
+ goto failed;
+ }
+
+ *ntds_guid = samdb_result_guid(res->msgs[0], "objectGUID");
+
+ /* cache the domain_sid in the ldb */
+ if (ldb_set_opaque(ldb, "cache.ntds_guid", ntds_guid) != LDB_SUCCESS) {
+ goto failed;
+ }
+
+ talloc_steal(ldb, ntds_guid);
+ talloc_free(tmp_ctx);
+
+ return ntds_guid;
+
+failed:
+ DEBUG(1,("Failed to find our own NTDS Settings objectGUID in the ldb!\n"));
+ talloc_free(tmp_ctx);
+ return NULL;
+}
+
+bool samdb_set_ntds_objectGUID(struct ldb_context *ldb, const struct GUID *ntds_guid_in)
+{
+ TALLOC_CTX *tmp_ctx;
+ struct GUID *ntds_guid_new;
+ struct GUID *ntds_guid_old;
+
+ /* see if we have a cached copy */
+ ntds_guid_old = (struct GUID *)ldb_get_opaque(ldb, "cache.ntds_guid");
+
+ tmp_ctx = talloc_new(ldb);
+ if (tmp_ctx == NULL) {
+ goto failed;
+ }
+
+ ntds_guid_new = talloc(tmp_ctx, struct GUID);
+ if (!ntds_guid_new) {
+ goto failed;
+ }
+
+ *ntds_guid_new = *ntds_guid_in;
+
+ /* cache the domain_sid in the ldb */
+ if (ldb_set_opaque(ldb, "cache.ntds_guid", ntds_guid_new) != LDB_SUCCESS) {
+ goto failed;
+ }
+
+ talloc_steal(ldb, ntds_guid_new);
+ talloc_free(tmp_ctx);
+ talloc_free(ntds_guid_old);
+
+ return true;
+
+failed:
+ DEBUG(1,("Failed to set our own cached invocationId in the ldb!\n"));
+ talloc_free(tmp_ctx);
+ return false;
+}
+
+/*
+ work out the server dn for the current open ldb
+*/
+struct ldb_dn *samdb_server_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)
+{
+ return ldb_dn_get_parent(mem_ctx, samdb_ntds_settings_dn(ldb));
+}
+
+/*
+ work out the server dn for the current open ldb
+*/
+struct ldb_dn *samdb_server_site_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)
+{
+ struct ldb_dn *server_dn;
+ struct ldb_dn *server_site_dn;
+
+ server_dn = samdb_server_dn(ldb, mem_ctx);
+ if (!server_dn) return NULL;
+
+ server_site_dn = ldb_dn_get_parent(mem_ctx, server_dn);
+
+ talloc_free(server_dn);
+ return server_site_dn;
+}
+
+/*
+ work out if we are the PDC for the domain of the current open ldb
+*/
+bool samdb_is_pdc(struct ldb_context *ldb)
+{
+ const char *dom_attrs[] = { "fSMORoleOwner", NULL };
+ int ret;
+ struct ldb_result *dom_res;
+ TALLOC_CTX *tmp_ctx;
+ bool is_pdc;
+ struct ldb_dn *pdc;
+
+ tmp_ctx = talloc_new(ldb);
+ if (tmp_ctx == NULL) {
+ DEBUG(1, ("talloc_new failed in samdb_is_pdc"));
+ return false;
+ }
+
+ ret = ldb_search(ldb, ldb_get_default_basedn(ldb), LDB_SCOPE_BASE, NULL, dom_attrs, &dom_res);
+ if (ret) {
+ DEBUG(1,("Searching for fSMORoleOwner in %s failed: %s\n",
+ ldb_dn_get_linearized(ldb_get_default_basedn(ldb)),
+ ldb_errstring(ldb)));
+ goto failed;
+ }
+ talloc_steal(tmp_ctx, dom_res);
+ if (dom_res->count != 1) {
+ goto failed;
+ }
+
+ pdc = ldb_msg_find_attr_as_dn(ldb, tmp_ctx, dom_res->msgs[0], "fSMORoleOwner");
+
+ if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), pdc) == 0) {
+ is_pdc = true;
+ } else {
+ is_pdc = false;
+ }
+
+ talloc_free(tmp_ctx);
+
+ return is_pdc;
+
+failed:
+ DEBUG(1,("Failed to find if we are the PDC for this ldb\n"));
+ talloc_free(tmp_ctx);
+ return false;
+}
+
+
+/* Find a domain object in the parents of a particular DN. */
+int samdb_search_for_parent_domain(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_dn *dn,
+ struct ldb_dn **parent_dn, const char **errstring)
+{
+ TALLOC_CTX *local_ctx;
+ struct ldb_dn *sdn = dn;
+ struct ldb_result *res = NULL;
+ int ret = 0;
+ const char *attrs[] = { NULL };
+
+ local_ctx = talloc_new(mem_ctx);
+ if (local_ctx == NULL) return LDB_ERR_OPERATIONS_ERROR;
+
+ while ((sdn = ldb_dn_get_parent(local_ctx, sdn))) {
+ ret = ldb_search(ldb, sdn, LDB_SCOPE_BASE,
+ "(|(objectClass=domain)(objectClass=builtinDomain))", attrs, &res);
+ if (ret == LDB_SUCCESS) {
+ talloc_steal(local_ctx, res);
+ if (res->count == 1) {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+
+ if (ret != LDB_SUCCESS) {
+ *errstring = talloc_asprintf(mem_ctx, "Error searching for parent domain of %s, failed searching for %s: %s",
+ ldb_dn_get_linearized(dn),
+ ldb_dn_get_linearized(sdn),
+ ldb_errstring(ldb));
+ talloc_free(local_ctx);
+ return ret;
+ }
+ if (res->count != 1) {
+ *errstring = talloc_asprintf(mem_ctx, "Invalid dn (%s), not child of a domain object",
+ ldb_dn_get_linearized(dn));
+ talloc_free(local_ctx);
+ return LDB_ERR_CONSTRAINT_VIOLATION;
+ }
+
+ *parent_dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
+ talloc_free(local_ctx);
+ return ret;
+}
+
+/*
+ check that a password is sufficiently complex
+*/
+static bool samdb_password_complexity_ok(const char *pass)
+{
+ return check_password_quality(pass);
+}
+
+
+
+/*
+ set the user password using plaintext, obeying any user or domain
+ password restrictions
+
+ note that this function doesn't actually store the result in the
+ database, it just fills in the "mod" structure with ldb modify
+ elements to setup the correct change when samdb_replace() is
+ called. This allows the caller to combine the change with other
+ changes (as is needed by some of the set user info levels)
+
+ The caller should probably have a transaction wrapping this
+*/
+_PUBLIC_ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
+ struct ldb_dn *user_dn,
+ struct ldb_dn *domain_dn,
+ struct ldb_message *mod,
+ const char *new_pass,
+ struct samr_Password *lmNewHash,
+ struct samr_Password *ntNewHash,
+ bool user_change,
+ enum samr_RejectReason *reject_reason,
+ struct samr_DomInfo1 **_dominfo)
+{
+ const char * const user_attrs[] = { "userAccountControl", "lmPwdHistory",
+ "ntPwdHistory",
+ "dBCSPwd", "unicodePwd",
+ "objectSid",
+ "pwdLastSet", NULL };
+ const char * const domain_attrs[] = { "pwdProperties", "pwdHistoryLength",
+ "maxPwdAge", "minPwdAge",
+ "minPwdLength", NULL };
+ NTTIME pwdLastSet;
+ int64_t minPwdAge;
+ uint_t minPwdLength, pwdProperties, pwdHistoryLength;
+ uint_t userAccountControl;
+ struct samr_Password *sambaLMPwdHistory, *sambaNTPwdHistory, *lmPwdHash, *ntPwdHash;
+ struct samr_Password local_lmNewHash, local_ntNewHash;
+ int sambaLMPwdHistory_len, sambaNTPwdHistory_len;
+ struct dom_sid *domain_sid;
+ struct ldb_message **res;
+ bool restrictions;
+ int count;
+ time_t now = time(NULL);
+ NTTIME now_nt;
+ int i;
+
+ /* we need to know the time to compute password age */
+ unix_to_nt_time(&now_nt, now);
+
+ /* pull all the user parameters */
+ count = gendb_search_dn(ctx, mem_ctx, user_dn, &res, user_attrs);
+ 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);
+
+ /* Only non-trust accounts have restrictions (possibly this
+ * test is the wrong way around, but I like to be restrictive
+ * if possible */
+ restrictions = !(userAccountControl & (UF_INTERDOMAIN_TRUST_ACCOUNT
+ |UF_WORKSTATION_TRUST_ACCOUNT
+ |UF_SERVER_TRUST_ACCOUNT));
+
+ if (domain_dn) {
+ /* pull the domain parameters */
+ 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),
+ ldb_dn_get_linearized(user_dn)));
+ return NT_STATUS_NO_SUCH_DOMAIN;
+ }
+ } else {
+ /* work out the domain sid, and pull the domain from there */
+ 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));
+ 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),
+ ldb_dn_get_linearized(user_dn)));
+ return NT_STATUS_NO_SUCH_DOMAIN;
+ }
+ }
+
+ 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);
+
+ if (_dominfo) {
+ struct samr_DomInfo1 *dominfo;
+ /* on failure we need to fill in the reject reasons */
+ dominfo = talloc(mem_ctx, struct samr_DomInfo1);
+ if (dominfo == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ dominfo->min_password_length = minPwdLength;
+ dominfo->password_properties = pwdProperties;
+ dominfo->password_history_length = pwdHistoryLength;
+ dominfo->max_password_age = minPwdAge;
+ dominfo->min_password_age = minPwdAge;
+ *_dominfo = dominfo;
+ }
+
+ if (restrictions && new_pass) {
+
+ /* check the various password restrictions */
+ if (restrictions && minPwdLength > strlen_m(new_pass)) {
+ if (reject_reason) {
+ *reject_reason = SAMR_REJECT_TOO_SHORT;
+ }
+ return NT_STATUS_PASSWORD_RESTRICTION;
+ }
+
+ /* possibly check password complexity */
+ if (restrictions && pwdProperties & DOMAIN_PASSWORD_COMPLEX &&
+ !samdb_password_complexity_ok(new_pass)) {
+ if (reject_reason) {
+ *reject_reason = SAMR_REJECT_COMPLEXITY;
+ }
+ return NT_STATUS_PASSWORD_RESTRICTION;
+ }
+
+ /* compute the new nt and lm hashes */
+ if (E_deshash(new_pass, local_lmNewHash.hash)) {
+ lmNewHash = &local_lmNewHash;
+ }
+ if (!E_md4hash(new_pass, local_ntNewHash.hash)) {
+ /* If we can't convert this password to UCS2, then we should not accept it */
+ if (reject_reason) {
+ *reject_reason = SAMR_REJECT_OTHER;
+ }
+ return NT_STATUS_PASSWORD_RESTRICTION;
+ }
+ ntNewHash = &local_ntNewHash;
+ }
+
+ if (user_change) {
+ /* are all password changes disallowed? */
+ if (pwdProperties & DOMAIN_REFUSE_PASSWORD_CHANGE) {
+ if (reject_reason) {
+ *reject_reason = SAMR_REJECT_OTHER;
+ }
+ return NT_STATUS_PASSWORD_RESTRICTION;
+ }
+
+ /* can this user change password? */
+ if (userAccountControl & UF_PASSWD_CANT_CHANGE) {
+ if (reject_reason) {
+ *reject_reason = SAMR_REJECT_OTHER;
+ }
+ return NT_STATUS_PASSWORD_RESTRICTION;
+ }
+
+ /* 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;
+ }
+ return NT_STATUS_PASSWORD_RESTRICTION;
+ }
+
+ /* check the immediately past password */
+ if (pwdHistoryLength > 0) {
+ if (lmNewHash && lmPwdHash && memcmp(lmNewHash->hash, lmPwdHash->hash, 16) == 0) {
+ if (reject_reason) {
+ *reject_reason = SAMR_REJECT_IN_HISTORY;
+ }
+ return NT_STATUS_PASSWORD_RESTRICTION;
+ }
+ if (ntNewHash && ntPwdHash && memcmp(ntNewHash->hash, ntPwdHash->hash, 16) == 0) {
+ if (reject_reason) {
+ *reject_reason = SAMR_REJECT_IN_HISTORY;
+ }
+ return NT_STATUS_PASSWORD_RESTRICTION;
+ }
+ }
+
+ /* check the password history */
+ 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 (reject_reason) {
+ *reject_reason = SAMR_REJECT_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 (reject_reason) {
+ *reject_reason = SAMR_REJECT_IN_HISTORY;
+ }
+ return NT_STATUS_PASSWORD_RESTRICTION;
+ }
+ }
+ }
+
+#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_pass) {
+ /* if we know the cleartext, then only set it.
+ * Modules in ldb will set all the appropriate
+ * hashes */
+ CHECK_RET(samdb_msg_add_string(ctx, mem_ctx, mod,
+ "sambaPassword", new_pass));
+ } else {
+ /* We don't have the cleartext, so delete the old one
+ * and set what we have of the hashes */
+ CHECK_RET(samdb_msg_add_delete(ctx, mem_ctx, mod, "sambaPassword"));
+
+ if (lmNewHash) {
+ CHECK_RET(samdb_msg_add_hash(ctx, mem_ctx, mod, "dBCSPwd", lmNewHash));
+ } else {
+ CHECK_RET(samdb_msg_add_delete(ctx, mem_ctx, mod, "dBCSPwd"));
+ }
+
+ if (ntNewHash) {
+ CHECK_RET(samdb_msg_add_hash(ctx, mem_ctx, mod, "unicodePwd", ntNewHash));
+ } else {
+ CHECK_RET(samdb_msg_add_delete(ctx, mem_ctx, mod, "unicodePwd"));
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/*
+ set the user password using plaintext, obeying any user or domain
+ password restrictions
+
+ This wrapper function takes a SID as input, rather than a user DN,
+ and actually performs the password change
+
+*/
+_PUBLIC_ NTSTATUS samdb_set_password_sid(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
+ const struct dom_sid *user_sid,
+ const char *new_pass,
+ struct samr_Password *lmNewHash,
+ struct samr_Password *ntNewHash,
+ bool user_change,
+ enum samr_RejectReason *reject_reason,
+ struct samr_DomInfo1 **_dominfo)
+{
+ NTSTATUS nt_status;
+ struct ldb_dn *user_dn;
+ struct ldb_message *msg;
+ int ret;
+
+ ret = ldb_transaction_start(ctx);
+ if (ret) {
+ DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(ctx)));
+ return NT_STATUS_TRANSACTION_ABORTED;
+ }
+
+ user_dn = samdb_search_dn(ctx, mem_ctx, NULL,
+ "(&(objectSid=%s)(objectClass=user))",
+ ldap_encode_ndr_dom_sid(mem_ctx, user_sid));
+ if (!user_dn) {
+ ldb_transaction_cancel(ctx);
+ DEBUG(3, ("samdb_set_password_sid: SID %s not found in samdb, returning NO_SUCH_USER\n",
+ dom_sid_string(mem_ctx, user_sid)));
+ return NT_STATUS_NO_SUCH_USER;
+ }
+
+ msg = ldb_msg_new(mem_ctx);
+ if (msg == NULL) {
+ ldb_transaction_cancel(ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ msg->dn = ldb_dn_copy(msg, user_dn);
+ if (!msg->dn) {
+ ldb_transaction_cancel(ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ nt_status = samdb_set_password(ctx, mem_ctx,
+ user_dn, NULL,
+ msg, new_pass,
+ lmNewHash, ntNewHash,
+ user_change, /* This is a password set, not change */
+ reject_reason, _dominfo);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ ldb_transaction_cancel(ctx);
+ return nt_status;
+ }
+
+ /* modify the samdb record */
+ ret = samdb_replace(ctx, mem_ctx, msg);
+ if (ret != 0) {
+ ldb_transaction_cancel(ctx);
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ ret = ldb_transaction_commit(ctx);
+ if (ret != 0) {
+ DEBUG(0,("Failed to commit transaction to change password on %s: %s\n",
+ ldb_dn_get_linearized(msg->dn),
+ ldb_errstring(ctx)));
+ return NT_STATUS_TRANSACTION_ABORTED;
+ }
+ return NT_STATUS_OK;
+}
+
+
+
+NTSTATUS samdb_create_foreign_security_principal(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
+ struct dom_sid *sid, struct ldb_dn **ret_dn)
+{
+ struct ldb_message *msg;
+ struct ldb_dn *basedn;
+ const char *sidstr;
+ int ret;
+
+ sidstr = dom_sid_string(mem_ctx, sid);
+ NT_STATUS_HAVE_NO_MEMORY(sidstr);
+
+ /* We might have to create a ForeignSecurityPrincipal, even if this user
+ * is in our own domain */
+
+ msg = ldb_msg_new(mem_ctx);
+ if (msg == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* TODO: Hmmm. This feels wrong. How do I find the base dn to
+ * put the ForeignSecurityPrincipals? d_state->domain_dn does
+ * not work, this is wrong for the Builtin domain, there's no
+ * cn=For...,cn=Builtin,dc={BASEDN}. -- vl
+ */
+
+ basedn = samdb_search_dn(sam_ctx, mem_ctx, NULL,
+ "(&(objectClass=container)(cn=ForeignSecurityPrincipals))");
+
+ if (basedn == NULL) {
+ DEBUG(0, ("Failed to find DN for "
+ "ForeignSecurityPrincipal container\n"));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ /* add core elements to the ldb_message for the alias */
+ msg->dn = ldb_dn_copy(mem_ctx, basedn);
+ if ( ! ldb_dn_add_child_fmt(msg->dn, "CN=%s", sidstr))
+ return NT_STATUS_NO_MEMORY;
+
+ samdb_msg_add_string(sam_ctx, mem_ctx, msg,
+ "objectClass",
+ "foreignSecurityPrincipal");
+
+ /* create the alias */
+ ret = ldb_add(sam_ctx, msg);
+ if (ret != 0) {
+ DEBUG(0,("Failed to create foreignSecurityPrincipal "
+ "record %s: %s\n",
+ ldb_dn_get_linearized(msg->dn),
+ ldb_errstring(sam_ctx)));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ *ret_dn = msg->dn;
+ return NT_STATUS_OK;
+}
+
+
+/*
+ Find the DN of a domain, assuming it to be a dotted.dns name
+*/
+
+struct ldb_dn *samdb_dns_domain_to_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *dns_domain)
+{
+ int i;
+ TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+ const char *binary_encoded;
+ const char **split_realm;
+ struct ldb_dn *dn;
+
+ if (!tmp_ctx) {
+ return NULL;
+ }
+
+ split_realm = str_list_make(tmp_ctx, dns_domain, ".");
+ if (!split_realm) {
+ talloc_free(tmp_ctx);
+ return NULL;
+ }
+ dn = ldb_dn_new(mem_ctx, ldb, NULL);
+ for (i=0; split_realm[i]; i++) {
+ binary_encoded = ldb_binary_encode_string(tmp_ctx, split_realm[i]);
+ if (!ldb_dn_add_base_fmt(dn, "dc=%s", binary_encoded)) {
+ DEBUG(2, ("Failed to add dc=%s element to DN %s\n",
+ binary_encoded, ldb_dn_get_linearized(dn)));
+ talloc_free(tmp_ctx);
+ return NULL;
+ }
+ }
+ if (!ldb_dn_validate(dn)) {
+ DEBUG(2, ("Failed to validated DN %s\n",
+ ldb_dn_get_linearized(dn)));
+ return NULL;
+ }
+ return dn;
+}
+/*
+ Find the DN of a domain, be it the netbios or DNS name
+*/
+
+struct ldb_dn *samdb_domain_to_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
+ const char *domain_name)
+{
+ const char * const domain_ref_attrs[] = {
+ "ncName", NULL
+ };
+ const char * const domain_ref2_attrs[] = {
+ NULL
+ };
+ struct ldb_result *res_domain_ref;
+ char *escaped_domain = ldb_binary_encode_string(mem_ctx, domain_name);
+ /* find the domain's DN */
+ int ret_domain = ldb_search_exp_fmt(ldb, mem_ctx,
+ &res_domain_ref,
+ samdb_partitions_dn(ldb, mem_ctx),
+ LDB_SCOPE_ONELEVEL,
+ domain_ref_attrs,
+ "(&(nETBIOSName=%s)(objectclass=crossRef))",
+ escaped_domain);
+ if (ret_domain != 0) {
+ return NULL;
+ }
+
+ if (res_domain_ref->count == 0) {
+ ret_domain = ldb_search_exp_fmt(ldb, mem_ctx,
+ &res_domain_ref,
+ samdb_dns_domain_to_dn(ldb, mem_ctx, domain_name),
+ LDB_SCOPE_BASE,
+ domain_ref2_attrs,
+ "(objectclass=domain)");
+ if (ret_domain != 0) {
+ return NULL;
+ }
+
+ if (res_domain_ref->count == 1) {
+ return res_domain_ref->msgs[0]->dn;
+ }
+ return NULL;
+ }
+
+ if (res_domain_ref->count > 1) {
+ DEBUG(0,("Found %d records matching domain [%s]\n",
+ ret_domain, domain_name));
+ return NULL;
+ }
+
+ return samdb_result_dn(ldb, mem_ctx, res_domain_ref->msgs[0], "nCName", NULL);
+
+}
diff --git a/source4/dsdb/config.mk b/source4/dsdb/config.mk
index ad9721458f..83d1ee3bea 100644
--- a/source4/dsdb/config.mk
+++ b/source4/dsdb/config.mk
@@ -9,20 +9,29 @@ PUBLIC_PROTO_HEADER = samdb/samdb_proto.h
PUBLIC_HEADERS = samdb/samdb.h
PUBLIC_DEPENDENCIES = HEIMDAL_KRB5
PRIVATE_DEPENDENCIES = LIBNDR NDR_MISC NDR_DRSUAPI NDR_DRSBLOBS NSS_WRAPPER \
- auth_system_session LDAP_ENCODE
+ auth_system_session LDAP_ENCODE LIBCLI_AUTH LIBNDR \
+ SAMDB_SCHEMA LDB_WRAP SAMDB_COMMON
OBJ_FILES = \
samdb/samdb.o \
samdb/samdb_privilege.o \
samdb/cracknames.o \
+ repl/replicated_objects.o
+
+[SUBSYSTEM::SAMDB_COMMON]
+PUBLIC_PROTO_HEADER = common/proto.h
+OBJ_FILES = \
common/sidmap.o \
common/flag_mapping.o \
+ common/util.o
+
+[SUBSYSTEM::SAMDB_SCHEMA]
+PUBLIC_PROTO_HEADER = schema/proto.h
+PUBLIC_HEADERS = schema/schema.h
+PRIVATE_DEPENDENCIES = SAMDB_COMMON
+OBJ_FILES = \
schema/schema_init.o \
schema/schema_syntax.o \
schema/schema_constructed.o \
- repl/replicated_objects.o
-#
-# End SUBSYSTEM SAMDB
-################################################
#######################
# Start SUBSYSTEM DREPL_SRV
diff --git a/source4/dsdb/samdb/ldb_modules/config.mk b/source4/dsdb/samdb/ldb_modules/config.mk
index 8350b77b29..95bb7de06c 100644
--- a/source4/dsdb/samdb/ldb_modules/config.mk
+++ b/source4/dsdb/samdb/ldb_modules/config.mk
@@ -11,11 +11,12 @@ OBJ_FILES = \
################################################
################################################
-# Start MODULE ldb_repl_mata_data
+# Start MODULE ldb_repl_meta_data
[MODULE::ldb_repl_meta_data]
SUBSYSTEM = LIBLDB
OUTPUT_TYPE = SHARED_LIBRARY
-PRIVATE_DEPENDENCIES = SAMDB LIBTALLOC LIBNDR NDR_MISC NDR_DRSUAPI NDR_DRSBLOBS
+PRIVATE_DEPENDENCIES = SAMDB LIBTALLOC LIBNDR NDR_MISC NDR_DRSUAPI \
+ NDR_DRSBLOBS LIBNDR
INIT_FUNCTION = repl_meta_data_module_init
OBJ_FILES = \
repl_meta_data.o
@@ -75,7 +76,7 @@ OBJ_FILES = \
[MODULE::ldb_samldb]
SUBSYSTEM = LIBLDB
OUTPUT_TYPE = SHARED_LIBRARY
-PRIVATE_DEPENDENCIES = LIBTALLOC LDAP_ENCODE
+PRIVATE_DEPENDENCIES = LIBTALLOC LDAP_ENCODE NDR_MISC SAMDB
INIT_FUNCTION = samldb_module_init
OBJ_FILES = \
samldb.o
@@ -89,7 +90,8 @@ OBJ_FILES = \
SUBSYSTEM = LIBLDB
OUTPUT_TYPE = SHARED_LIBRARY
INIT_FUNCTION = ldb_samba3sam_module_init
-PRIVATE_DEPENDENCIES = LIBTALLOC ldb_map SMBPASSWD NSS_WRAPPER
+PRIVATE_DEPENDENCIES = LIBTALLOC ldb_map SMBPASSWD NSS_WRAPPER LIBSECURITY \
+ NDR_SECURITY
OBJ_FILES = \
samba3sam.o
#
@@ -102,7 +104,7 @@ OBJ_FILES = \
SUBSYSTEM = LIBLDB
OUTPUT_TYPE = SHARED_LIBRARY
INIT_FUNCTION = ldb_simple_ldap_map_module_init
-PRIVATE_DEPENDENCIES = LIBTALLOC ldb_map
+PRIVATE_DEPENDENCIES = LIBTALLOC ldb_map LIBNDR NDR_MISC
ENABLE = YES
ALIASES = entryuuid nsuniqueid
OBJ_FILES = \
@@ -127,7 +129,7 @@ OBJ_FILES = \
# Start MODULE ldb_rootdse
[MODULE::ldb_rootdse]
SUBSYSTEM = LIBLDB
-PRIVATE_DEPENDENCIES = LIBTALLOC
+PRIVATE_DEPENDENCIES = LIBTALLOC SAMDB
OUTPUT_TYPE = SHARED_LIBRARY
INIT_FUNCTION = rootdse_module_init
OBJ_FILES = \
@@ -143,7 +145,8 @@ SUBSYSTEM = LIBLDB
OUTPUT_TYPE = SHARED_LIBRARY
INIT_FUNCTION = password_hash_module_init
OBJ_FILES = password_hash.o
-PRIVATE_DEPENDENCIES = HEIMDAL_HDB_KEYS LIBTALLOC HEIMDAL_KRB5 LDAP_ENCODE
+PRIVATE_DEPENDENCIES = HEIMDAL_HDB_KEYS LIBTALLOC HEIMDAL_KRB5 LDAP_ENCODE \
+ LIBCLI_AUTH NDR_DRSBLOBS KERBEROS SAMDB
#
# End MODULE ldb_password_hash
################################################
@@ -151,7 +154,7 @@ PRIVATE_DEPENDENCIES = HEIMDAL_HDB_KEYS LIBTALLOC HEIMDAL_KRB5 LDAP_ENCODE
################################################
# Start MODULE ldb_local_password
[MODULE::ldb_local_password]
-PRIVATE_DEPENDENCIES = LIBTALLOC
+PRIVATE_DEPENDENCIES = LIBTALLOC LIBNDR SAMDB
OUTPUT_TYPE = SHARED_LIBRARY
SUBSYSTEM = LIBLDB
INIT_FUNCTION = local_password_module_init
@@ -163,7 +166,7 @@ OBJ_FILES = local_password.o
################################################
# Start MODULE ldb_kludge_acl
[MODULE::ldb_kludge_acl]
-PRIVATE_DEPENDENCIES = LIBTALLOC LIBSECURITY
+PRIVATE_DEPENDENCIES = LIBTALLOC LIBSECURITY SAMDB
OUTPUT_TYPE = SHARED_LIBRARY
SUBSYSTEM = LIBLDB
INIT_FUNCTION = ldb_kludge_acl_init
@@ -178,7 +181,7 @@ OBJ_FILES = \
[MODULE::ldb_extended_dn]
SUBSYSTEM = LIBLDB
OUTPUT_TYPE = SHARED_LIBRARY
-PRIVATE_DEPENDENCIES = LIBTALLOC
+PRIVATE_DEPENDENCIES = LIBTALLOC LIBNDR LIBSECURITY SAMDB
INIT_FUNCTION = ldb_extended_dn_init
OBJ_FILES = \
extended_dn.o
@@ -204,7 +207,7 @@ OBJ_FILES = \
[MODULE::ldb_partition]
SUBSYSTEM = LIBLDB
OUTPUT_TYPE = SHARED_LIBRARY
-PRIVATE_DEPENDENCIES = LIBTALLOC
+PRIVATE_DEPENDENCIES = LIBTALLOC SAMDB
INIT_FUNCTION = ldb_partition_init
OBJ_FILES = \
partition.o
@@ -217,7 +220,7 @@ OBJ_FILES = \
[MODULE::ldb_schema]
SUBSYSTEM = LIBLDB
OUTPUT_TYPE = SHARED_LIBRARY
-PRIVATE_DEPENDENCIES = LIBTALLOC
+PRIVATE_DEPENDENCIES = LIBTALLOC LIBLDB
INIT_FUNCTION = ldb_schema_init
OBJ_FILES = \
schema.o schema_syntax.o
@@ -230,7 +233,7 @@ OBJ_FILES = \
[MODULE::ldb_update_keytab]
SUBSYSTEM = LIBLDB
OUTPUT_TYPE = SHARED_LIBRARY
-PRIVATE_DEPENDENCIES = LIBTALLOC CREDENTIALS_KRB5
+PRIVATE_DEPENDENCIES = LIBTALLOC CREDENTIALS
#Also depends on credentials, but that would loop
INIT_FUNCTION = ldb_update_kt_init
OBJ_FILES = \
@@ -245,7 +248,7 @@ OBJ_FILES = \
INIT_FUNCTION = ldb_objectclass_init
OUTPUT_TYPE = SHARED_LIBRARY
CFLAGS = -Ilib/ldb/include
-PRIVATE_DEPENDENCIES = LIBTALLOC
+PRIVATE_DEPENDENCIES = LIBTALLOC LIBSECURITY NDR_SECURITY SAMDB
SUBSYSTEM = LIBLDB
OBJ_FILES = \
objectclass.o
@@ -284,7 +287,7 @@ OBJ_FILES = \
INIT_FUNCTION = ldb_linked_attributes_init
CFLAGS = -Ilib/ldb/include
OUTPUT_TYPE = SHARED_LIBRARY
-PRIVATE_DEPENDENCIES = LIBTALLOC SAMDB
+PRIVATE_DEPENDENCIES = LIBTALLOC SAMDB
SUBSYSTEM = LIBLDB
OBJ_FILES = \
linked_attributes.o
@@ -310,7 +313,7 @@ OBJ_FILES = \
INIT_FUNCTION = ldb_anr_init
CFLAGS = -Ilib/ldb/include
OUTPUT_TYPE = SHARED_LIBRARY
-PRIVATE_DEPENDENCIES = LIBTALLOC
+PRIVATE_DEPENDENCIES = LIBTALLOC LIBSAMBA-UTIL SAMDB
SUBSYSTEM = LIBLDB
OBJ_FILES = \
anr.o
diff --git a/source4/dsdb/samdb/ldb_modules/partition.c b/source4/dsdb/samdb/ldb_modules/partition.c
index bf4421ab0d..4586810d96 100644
--- a/source4/dsdb/samdb/ldb_modules/partition.c
+++ b/source4/dsdb/samdb/ldb_modules/partition.c
@@ -117,9 +117,9 @@ static struct dsdb_control_current_partition *find_partition(struct partition_pr
return NULL;
};
-/*
- fire the caller's callback for every entry, but only send 'done' once.
-*/
+/**
+ * fire the caller's callback for every entry, but only send 'done' once.
+ */
static int partition_search_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
{
struct partition_context *ac;
@@ -139,9 +139,9 @@ static int partition_search_callback(struct ldb_context *ldb, void *context, str
}
}
-/*
- only fire the 'last' callback, and only for START-TLS for now
-*/
+/**
+ * only fire the 'last' callback, and only for START-TLS for now
+ */
static int partition_other_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
{
struct partition_context *ac;
@@ -248,7 +248,9 @@ static int partition_send_request(struct partition_context *ac, struct ldb_contr
return LDB_SUCCESS;
}
-/* Send a request down to all the partitions */
+/**
+ * Send a request down to all the partitions
+ */
static int partition_send_all(struct ldb_module *module,
struct partition_context *ac,
struct ldb_control *remove_control,
@@ -270,8 +272,10 @@ static int partition_send_all(struct ldb_module *module,
return LDB_SUCCESS;
}
-/* Figure out which backend a request needs to be aimed at. Some
- * requests must be replicated to all backends */
+/**
+ * Figure out which backend a request needs to be aimed at. Some
+ * requests must be replicated to all backends
+ */
static int partition_replicate(struct ldb_module *module, struct ldb_request *req, struct ldb_dn *dn)
{
unsigned i;
diff --git a/source4/dsdb/samdb/ldb_modules/schema.c b/source4/dsdb/samdb/ldb_modules/schema.c
index cf923d673b..525193ac8c 100644
--- a/source4/dsdb/samdb/ldb_modules/schema.c
+++ b/source4/dsdb/samdb/ldb_modules/schema.c
@@ -329,7 +329,7 @@ done:
static int schema_init_classes(struct ldb_module *module, struct schema_private_data *data)
{
- static const char *schema_attrs[] = { "governsID",
+ const char *schema_attrs[] = { "governsID",
"lDAPDisplayName",
"objectClassCategory",
"defaultObjectCategory",
@@ -542,7 +542,7 @@ static int schema_add_check_parent(struct ldb_context *ldb, void *context, struc
static int schema_add_build_parent_req(struct schema_context *sctx)
{
- static const char * const parent_attrs[] = { "objectClass", NULL };
+ const char * const parent_attrs[] = { "objectClass", NULL };
int ret;
sctx->parent_req = talloc_zero(sctx, struct ldb_request);
diff --git a/source4/dsdb/samdb/samdb.c b/source4/dsdb/samdb/samdb.c
index 4366b7d0b9..b042d1d3b7 100644
--- a/source4/dsdb/samdb/samdb.c
+++ b/source4/dsdb/samdb/samdb.c
@@ -86,623 +86,6 @@ struct ldb_context *samdb_connect(TALLOC_CTX *mem_ctx,
}
/*
- search the sam for the specified attributes in a specific domain, filter on
- objectSid being in domain_sid.
-*/
-int samdb_search_domain(struct ldb_context *sam_ldb,
- TALLOC_CTX *mem_ctx,
- struct ldb_dn *basedn,
- struct ldb_message ***res,
- const char * const *attrs,
- const struct dom_sid *domain_sid,
- const char *format, ...) _PRINTF_ATTRIBUTE(7,8)
-{
- va_list ap;
- int i, count;
-
- va_start(ap, format);
- count = gendb_search_v(sam_ldb, mem_ctx, basedn,
- res, attrs, format, ap);
- va_end(ap);
-
- i=0;
-
- while (i<count) {
- struct dom_sid *entry_sid;
-
- entry_sid = samdb_result_dom_sid(mem_ctx, (*res)[i], "objectSid");
-
- if ((entry_sid == NULL) ||
- (!dom_sid_in_domain(domain_sid, entry_sid))) {
- /* Delete that entry from the result set */
- (*res)[i] = (*res)[count-1];
- count -= 1;
- talloc_free(entry_sid);
- continue;
- }
- talloc_free(entry_sid);
- i += 1;
- }
-
- return count;
-}
-
-/*
- search the sam for a single string attribute in exactly 1 record
-*/
-const char *samdb_search_string_v(struct ldb_context *sam_ldb,
- TALLOC_CTX *mem_ctx,
- struct ldb_dn *basedn,
- const char *attr_name,
- const char *format, va_list ap) _PRINTF_ATTRIBUTE(5,0)
-{
- int count;
- const char *attrs[2] = { NULL, NULL };
- struct ldb_message **res = NULL;
-
- attrs[0] = attr_name;
-
- count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
- if (count > 1) {
- DEBUG(1,("samdb: search for %s %s not single valued (count=%d)\n",
- attr_name, format, count));
- }
- if (count != 1) {
- talloc_free(res);
- return NULL;
- }
-
- return samdb_result_string(res[0], attr_name, NULL);
-}
-
-
-/*
- search the sam for a single string attribute in exactly 1 record
-*/
-const char *samdb_search_string(struct ldb_context *sam_ldb,
- TALLOC_CTX *mem_ctx,
- struct ldb_dn *basedn,
- const char *attr_name,
- const char *format, ...) _PRINTF_ATTRIBUTE(5,6)
-{
- va_list ap;
- const char *str;
-
- va_start(ap, format);
- str = samdb_search_string_v(sam_ldb, mem_ctx, basedn, attr_name, format, ap);
- va_end(ap);
-
- return str;
-}
-
-struct ldb_dn *samdb_search_dn(struct ldb_context *sam_ldb,
- TALLOC_CTX *mem_ctx,
- struct ldb_dn *basedn,
- const char *format, ...) _PRINTF_ATTRIBUTE(4,5)
-{
- va_list ap;
- struct ldb_dn *ret;
- struct ldb_message **res = NULL;
- int count;
-
- va_start(ap, format);
- count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, NULL, format, ap);
- va_end(ap);
-
- if (count != 1) return NULL;
-
- ret = talloc_steal(mem_ctx, res[0]->dn);
- talloc_free(res);
-
- return ret;
-}
-
-/*
- search the sam for a dom_sid attribute in exactly 1 record
-*/
-struct dom_sid *samdb_search_dom_sid(struct ldb_context *sam_ldb,
- TALLOC_CTX *mem_ctx,
- struct ldb_dn *basedn,
- const char *attr_name,
- const char *format, ...) _PRINTF_ATTRIBUTE(5,6)
-{
- va_list ap;
- int count;
- struct ldb_message **res;
- const char *attrs[2] = { NULL, NULL };
- struct dom_sid *sid;
-
- attrs[0] = attr_name;
-
- va_start(ap, format);
- count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
- va_end(ap);
- if (count > 1) {
- DEBUG(1,("samdb: search for %s %s not single valued (count=%d)\n",
- attr_name, format, count));
- }
- if (count != 1) {
- talloc_free(res);
- return NULL;
- }
- sid = samdb_result_dom_sid(mem_ctx, res[0], attr_name);
- talloc_free(res);
- return sid;
-}
-
-/*
- return the count of the number of records in the sam matching the query
-*/
-int samdb_search_count(struct ldb_context *sam_ldb,
- TALLOC_CTX *mem_ctx,
- struct ldb_dn *basedn,
- const char *format, ...) _PRINTF_ATTRIBUTE(4,5)
-{
- va_list ap;
- struct ldb_message **res;
- const char * const attrs[] = { NULL };
- int ret;
-
- va_start(ap, format);
- ret = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
- va_end(ap);
-
- return ret;
-}
-
-
-/*
- search the sam for a single integer attribute in exactly 1 record
-*/
-uint_t samdb_search_uint(struct ldb_context *sam_ldb,
- TALLOC_CTX *mem_ctx,
- uint_t default_value,
- struct ldb_dn *basedn,
- const char *attr_name,
- const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
-{
- va_list ap;
- int count;
- struct ldb_message **res;
- const char *attrs[2] = { NULL, NULL };
-
- attrs[0] = attr_name;
-
- va_start(ap, format);
- count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
- va_end(ap);
-
- if (count != 1) {
- return default_value;
- }
-
- return samdb_result_uint(res[0], attr_name, default_value);
-}
-
-/*
- search the sam for a single signed 64 bit integer attribute in exactly 1 record
-*/
-int64_t samdb_search_int64(struct ldb_context *sam_ldb,
- TALLOC_CTX *mem_ctx,
- int64_t default_value,
- struct ldb_dn *basedn,
- const char *attr_name,
- const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
-{
- va_list ap;
- int count;
- struct ldb_message **res;
- const char *attrs[2] = { NULL, NULL };
-
- attrs[0] = attr_name;
-
- va_start(ap, format);
- count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
- va_end(ap);
-
- if (count != 1) {
- return default_value;
- }
-
- return samdb_result_int64(res[0], attr_name, default_value);
-}
-
-/*
- search the sam for multipe records each giving a single string attribute
- return the number of matches, or -1 on error
-*/
-int samdb_search_string_multiple(struct ldb_context *sam_ldb,
- TALLOC_CTX *mem_ctx,
- struct ldb_dn *basedn,
- const char ***strs,
- const char *attr_name,
- const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
-{
- va_list ap;
- int count, i;
- const char *attrs[2] = { NULL, NULL };
- struct ldb_message **res = NULL;
-
- attrs[0] = attr_name;
-
- va_start(ap, format);
- count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
- va_end(ap);
-
- if (count <= 0) {
- return count;
- }
-
- /* make sure its single valued */
- for (i=0;i<count;i++) {
- if (res[i]->num_elements != 1) {
- DEBUG(1,("samdb: search for %s %s not single valued\n",
- attr_name, format));
- talloc_free(res);
- return -1;
- }
- }
-
- *strs = talloc_array(mem_ctx, const char *, count+1);
- if (! *strs) {
- talloc_free(res);
- return -1;
- }
-
- for (i=0;i<count;i++) {
- (*strs)[i] = samdb_result_string(res[i], attr_name, NULL);
- }
- (*strs)[count] = NULL;
-
- return count;
-}
-
-/*
- pull a uint from a result set.
-*/
-uint_t samdb_result_uint(const struct ldb_message *msg, const char *attr, uint_t default_value)
-{
- return ldb_msg_find_attr_as_uint(msg, attr, default_value);
-}
-
-/*
- pull a (signed) int64 from a result set.
-*/
-int64_t samdb_result_int64(const struct ldb_message *msg, const char *attr, int64_t default_value)
-{
- return ldb_msg_find_attr_as_int64(msg, attr, default_value);
-}
-
-/*
- pull a string from a result set.
-*/
-const char *samdb_result_string(const struct ldb_message *msg, const char *attr,
- const char *default_value)
-{
- return ldb_msg_find_attr_as_string(msg, attr, default_value);
-}
-
-struct ldb_dn *samdb_result_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const struct ldb_message *msg,
- const char *attr, struct ldb_dn *default_value)
-{
- struct ldb_dn *ret_dn = ldb_msg_find_attr_as_dn(ldb, mem_ctx, msg, attr);
- if (!ret_dn) {
- return default_value;
- }
- return ret_dn;
-}
-
-/*
- pull a rid from a objectSid in a result set.
-*/
-uint32_t samdb_result_rid_from_sid(TALLOC_CTX *mem_ctx, const struct ldb_message *msg,
- const char *attr, uint32_t default_value)
-{
- struct dom_sid *sid;
- uint32_t rid;
-
- sid = samdb_result_dom_sid(mem_ctx, msg, attr);
- if (sid == NULL) {
- return default_value;
- }
- rid = sid->sub_auths[sid->num_auths-1];
- talloc_free(sid);
- return rid;
-}
-
-/*
- pull a dom_sid structure from a objectSid in a result set.
-*/
-struct dom_sid *samdb_result_dom_sid(TALLOC_CTX *mem_ctx, const struct ldb_message *msg,
- const char *attr)
-{
- const struct ldb_val *v;
- struct dom_sid *sid;
- enum ndr_err_code ndr_err;
- v = ldb_msg_find_ldb_val(msg, attr);
- if (v == NULL) {
- return NULL;
- }
- sid = talloc(mem_ctx, struct dom_sid);
- if (sid == NULL) {
- return NULL;
- }
- ndr_err = ndr_pull_struct_blob(v, sid, sid,
- (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- talloc_free(sid);
- return NULL;
- }
- return sid;
-}
-
-/*
- pull a guid structure from a objectGUID in a result set.
-*/
-struct GUID samdb_result_guid(const struct ldb_message *msg, const char *attr)
-{
- const struct ldb_val *v;
- enum ndr_err_code ndr_err;
- struct GUID guid;
- TALLOC_CTX *mem_ctx;
-
- ZERO_STRUCT(guid);
-
- v = ldb_msg_find_ldb_val(msg, attr);
- if (!v) return guid;
-
- mem_ctx = talloc_named_const(NULL, 0, "samdb_result_guid");
- if (!mem_ctx) return guid;
- ndr_err = ndr_pull_struct_blob(v, mem_ctx, &guid,
- (ndr_pull_flags_fn_t)ndr_pull_GUID);
- talloc_free(mem_ctx);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- return guid;
- }
-
- return guid;
-}
-
-/*
- pull a sid prefix from a objectSid in a result set.
- this is used to find the domain sid for a user
-*/
-struct dom_sid *samdb_result_sid_prefix(TALLOC_CTX *mem_ctx, const struct ldb_message *msg,
- const char *attr)
-{
- struct dom_sid *sid = samdb_result_dom_sid(mem_ctx, msg, attr);
- if (!sid || sid->num_auths < 1) return NULL;
- sid->num_auths--;
- return sid;
-}
-
-/*
- pull a NTTIME in a result set.
-*/
-NTTIME samdb_result_nttime(struct ldb_message *msg, const char *attr, NTTIME default_value)
-{
- return ldb_msg_find_attr_as_uint64(msg, attr, default_value);
-}
-
-/*
- pull a uint64_t from a result set.
-*/
-uint64_t samdb_result_uint64(struct ldb_message *msg, const char *attr, uint64_t default_value)
-{
- return ldb_msg_find_attr_as_uint64(msg, attr, default_value);
-}
-
-
-/*
- construct the allow_password_change field from the PwdLastSet attribute and the
- domain password settings
-*/
-NTTIME samdb_result_allow_password_change(struct ldb_context *sam_ldb,
- TALLOC_CTX *mem_ctx,
- struct ldb_dn *domain_dn,
- struct ldb_message *msg,
- const char *attr)
-{
- uint64_t attr_time = samdb_result_uint64(msg, attr, 0);
- int64_t minPwdAge;
-
- if (attr_time == 0) {
- return 0;
- }
-
- minPwdAge = samdb_search_int64(sam_ldb, mem_ctx, 0, domain_dn, "minPwdAge", NULL);
-
- /* yes, this is a -= not a += as minPwdAge is stored as the negative
- of the number of 100-nano-seconds */
- attr_time -= minPwdAge;
-
- return attr_time;
-}
-
-/*
- construct the force_password_change field from the PwdLastSet attribute and the
- domain password settings
-*/
-NTTIME samdb_result_force_password_change(struct ldb_context *sam_ldb,
- TALLOC_CTX *mem_ctx,
- struct ldb_dn *domain_dn,
- struct ldb_message *msg)
-{
- uint64_t attr_time = samdb_result_uint64(msg, "pwdLastSet", 0);
- uint32_t user_flags = samdb_result_uint64(msg, "userAccountControl", 0);
- int64_t maxPwdAge;
-
- if (user_flags & UF_DONT_EXPIRE_PASSWD) {
- return 0x7FFFFFFFFFFFFFFFULL;
- }
-
- if (attr_time == 0) {
- return 0;
- }
-
- maxPwdAge = samdb_search_int64(sam_ldb, mem_ctx, 0, domain_dn, "maxPwdAge", NULL);
- if (maxPwdAge == 0) {
- return 0;
- } else {
- attr_time -= maxPwdAge;
- }
-
- return attr_time;
-}
-
-/*
- pull a samr_Password structutre from a result set.
-*/
-struct samr_Password *samdb_result_hash(TALLOC_CTX *mem_ctx, struct ldb_message *msg, const char *attr)
-{
- struct samr_Password *hash = NULL;
- const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
- if (val && (val->length >= sizeof(hash->hash))) {
- hash = talloc(mem_ctx, struct samr_Password);
- memcpy(hash->hash, val->data, MIN(val->length, sizeof(hash->hash)));
- }
- return hash;
-}
-
-/*
- pull an array of samr_Password structutres from a result set.
-*/
-uint_t samdb_result_hashes(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
- const char *attr, struct samr_Password **hashes)
-{
- uint_t count = 0;
- const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
- int i;
-
- *hashes = NULL;
- if (!val) {
- return 0;
- }
- count = val->length / 16;
- if (count == 0) {
- return 0;
- }
-
- *hashes = talloc_array(mem_ctx, struct samr_Password, count);
- if (! *hashes) {
- return 0;
- }
-
- for (i=0;i<count;i++) {
- memcpy((*hashes)[i].hash, (i*16)+(char *)val->data, 16);
- }
-
- return count;
-}
-
-NTSTATUS samdb_result_passwords(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
- struct samr_Password **lm_pwd, struct samr_Password **nt_pwd)
-{
- struct samr_Password *lmPwdHash, *ntPwdHash;
- if (nt_pwd) {
- int num_nt;
- num_nt = samdb_result_hashes(mem_ctx, msg, "unicodePwd", &ntPwdHash);
- if (num_nt == 0) {
- *nt_pwd = NULL;
- } else if (num_nt > 1) {
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- } else {
- *nt_pwd = &ntPwdHash[0];
- }
- }
- if (lm_pwd) {
- int num_lm;
- num_lm = samdb_result_hashes(mem_ctx, msg, "dBCSPwd", &lmPwdHash);
- if (num_lm == 0) {
- *lm_pwd = NULL;
- } else if (num_lm > 1) {
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- } else {
- *lm_pwd = &lmPwdHash[0];
- }
- }
- return NT_STATUS_OK;
-}
-
-/*
- pull a samr_LogonHours structutre from a result set.
-*/
-struct samr_LogonHours samdb_result_logon_hours(TALLOC_CTX *mem_ctx, struct ldb_message *msg, const char *attr)
-{
- struct samr_LogonHours hours;
- const int units_per_week = 168;
- const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
- ZERO_STRUCT(hours);
- hours.bits = talloc_array(mem_ctx, uint8_t, units_per_week);
- if (!hours.bits) {
- return hours;
- }
- hours.units_per_week = units_per_week;
- memset(hours.bits, 0xFF, units_per_week);
- if (val) {
- memcpy(hours.bits, val->data, MIN(val->length, units_per_week));
- }
- return hours;
-}
-
-/*
- pull a set of account_flags from a result set.
-*/
-uint16_t samdb_result_acct_flags(struct ldb_message *msg, const char *attr)
-{
- uint_t userAccountControl = ldb_msg_find_attr_as_uint(msg, attr, 0);
- return samdb_uf2acb(userAccountControl);
-}
-
-
-/* Find an attribute, with a particular value */
-
-/* The current callers of this function expect a very specific
- * behaviour: In particular, objectClass subclass equivilance is not
- * wanted. This means that we should not lookup the schema for the
- * comparison function */
-struct ldb_message_element *samdb_find_attribute(struct ldb_context *ldb,
- const struct ldb_message *msg,
- const char *name, const char *value)
-{
- int i;
- struct ldb_message_element *el = ldb_msg_find_element(msg, name);
-
- if (!el) {
- return NULL;
- }
-
- for (i=0;i<el->num_values;i++) {
- if (ldb_attr_cmp(value, (char *)el->values[i].data) == 0) {
- return el;
- }
- }
-
- return NULL;
-}
-
-int samdb_find_or_add_value(struct ldb_context *ldb, struct ldb_message *msg, const char *name, const char *set_value)
-{
- if (samdb_find_attribute(ldb, msg, name, set_value) == NULL) {
- return samdb_msg_add_string(ldb, msg, msg, name, set_value);
- }
- return LDB_SUCCESS;
-}
-
-int samdb_find_or_add_attribute(struct ldb_context *ldb, struct ldb_message *msg, const char *name, const char *set_value)
-{
- struct ldb_message_element *el;
-
- el = ldb_msg_find_element(msg, name);
- if (el) {
- return LDB_SUCCESS;
- }
-
- return samdb_msg_add_string(ldb, msg, msg, name, set_value);
-}
-
-
-/*
copy from a template record to a message
*/
int samdb_copy_template(struct ldb_context *ldb,
@@ -795,1098 +178,6 @@ int samdb_copy_template(struct ldb_context *ldb,
}
-/*
- add a string element to a message
-*/
-int samdb_msg_add_string(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
- const char *attr_name, const char *str)
-{
- char *s = talloc_strdup(mem_ctx, str);
- char *a = talloc_strdup(mem_ctx, attr_name);
- if (s == NULL || a == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
- return ldb_msg_add_string(msg, a, s);
-}
-
-/*
- add a dom_sid element to a message
-*/
-int samdb_msg_add_dom_sid(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
- const char *attr_name, struct dom_sid *sid)
-{
- struct ldb_val v;
- enum ndr_err_code ndr_err;
-
- ndr_err = ndr_push_struct_blob(&v, mem_ctx, sid,
- (ndr_push_flags_fn_t)ndr_push_dom_sid);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- return -1;
- }
- return ldb_msg_add_value(msg, attr_name, &v, NULL);
-}
-
-
-/*
- add a delete element operation to a message
-*/
-int samdb_msg_add_delete(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
- const char *attr_name)
-{
- /* we use an empty replace rather than a delete, as it allows for
- samdb_replace() to be used everywhere */
- return ldb_msg_add_empty(msg, attr_name, LDB_FLAG_MOD_REPLACE, NULL);
-}
-
-/*
- add a add attribute value to a message
-*/
-int samdb_msg_add_addval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
- const char *attr_name, const char *value)
-{
- struct ldb_message_element *el;
- char *a, *v;
- int ret;
- a = talloc_strdup(mem_ctx, attr_name);
- if (a == NULL)
- return -1;
- v = talloc_strdup(mem_ctx, value);
- if (v == NULL)
- return -1;
- ret = ldb_msg_add_string(msg, a, v);
- if (ret != 0)
- return ret;
- el = ldb_msg_find_element(msg, a);
- if (el == NULL)
- return -1;
- el->flags = LDB_FLAG_MOD_ADD;
- return 0;
-}
-
-/*
- add a delete attribute value to a message
-*/
-int samdb_msg_add_delval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
- const char *attr_name, const char *value)
-{
- struct ldb_message_element *el;
- char *a, *v;
- int ret;
- a = talloc_strdup(mem_ctx, attr_name);
- if (a == NULL)
- return -1;
- v = talloc_strdup(mem_ctx, value);
- if (v == NULL)
- return -1;
- ret = ldb_msg_add_string(msg, a, v);
- if (ret != 0)
- return ret;
- el = ldb_msg_find_element(msg, a);
- if (el == NULL)
- return -1;
- el->flags = LDB_FLAG_MOD_DELETE;
- return 0;
-}
-
-/*
- add a int element to a message
-*/
-int samdb_msg_add_int(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
- const char *attr_name, int v)
-{
- const char *s = talloc_asprintf(mem_ctx, "%d", v);
- return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, s);
-}
-
-/*
- add a uint_t element to a message
-*/
-int samdb_msg_add_uint(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
- const char *attr_name, uint_t v)
-{
- const char *s = talloc_asprintf(mem_ctx, "%u", v);
- return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, s);
-}
-
-/*
- add a (signed) int64_t element to a message
-*/
-int samdb_msg_add_int64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
- const char *attr_name, int64_t v)
-{
- const char *s = talloc_asprintf(mem_ctx, "%lld", (long long)v);
- return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, s);
-}
-
-/*
- add a uint64_t element to a message
-*/
-int samdb_msg_add_uint64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
- const char *attr_name, uint64_t v)
-{
- const char *s = talloc_asprintf(mem_ctx, "%llu", (unsigned long long)v);
- return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, s);
-}
-
-/*
- add a samr_Password element to a message
-*/
-int samdb_msg_add_hash(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
- const char *attr_name, struct samr_Password *hash)
-{
- struct ldb_val val;
- val.data = talloc_memdup(mem_ctx, hash->hash, 16);
- if (!val.data) {
- return -1;
- }
- val.length = 16;
- return ldb_msg_add_value(msg, attr_name, &val, NULL);
-}
-
-/*
- add a samr_Password array to a message
-*/
-int samdb_msg_add_hashes(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
- const char *attr_name, struct samr_Password *hashes, uint_t count)
-{
- struct ldb_val val;
- int i;
- val.data = talloc_array_size(mem_ctx, 16, count);
- val.length = count*16;
- if (!val.data) {
- return -1;
- }
- for (i=0;i<count;i++) {
- memcpy(i*16 + (char *)val.data, hashes[i].hash, 16);
- }
- return ldb_msg_add_value(msg, attr_name, &val, NULL);
-}
-
-/*
- add a acct_flags element to a message
-*/
-int samdb_msg_add_acct_flags(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
- const char *attr_name, uint32_t v)
-{
- return samdb_msg_add_uint(sam_ldb, mem_ctx, msg, attr_name, samdb_acb2uf(v));
-}
-
-/*
- add a logon_hours element to a message
-*/
-int samdb_msg_add_logon_hours(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
- const char *attr_name, struct samr_LogonHours *hours)
-{
- struct ldb_val val;
- val.length = hours->units_per_week / 8;
- val.data = hours->bits;
- return ldb_msg_add_value(msg, attr_name, &val, NULL);
-}
-
-/*
- add a general value element to a message
-*/
-int samdb_msg_add_value(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
- const char *attr_name, const struct ldb_val *val)
-{
- return ldb_msg_add_value(msg, attr_name, val, NULL);
-}
-
-/*
- sets a general value element to a message
-*/
-int samdb_msg_set_value(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
- const char *attr_name, const struct ldb_val *val)
-{
- struct ldb_message_element *el;
-
- el = ldb_msg_find_element(msg, attr_name);
- if (el) {
- el->num_values = 0;
- }
- return ldb_msg_add_value(msg, attr_name, val, NULL);
-}
-
-/*
- set a string element in a message
-*/
-int samdb_msg_set_string(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
- const char *attr_name, const char *str)
-{
- struct ldb_message_element *el;
-
- el = ldb_msg_find_element(msg, attr_name);
- if (el) {
- el->num_values = 0;
- }
- return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, str);
-}
-
-/*
- replace elements in a record
-*/
-int samdb_replace(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg)
-{
- int i;
-
- /* mark all the message elements as LDB_FLAG_MOD_REPLACE */
- for (i=0;i<msg->num_elements;i++) {
- msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
- }
-
- /* modify the samdb record */
- return ldb_modify(sam_ldb, msg);
-}
-
-/*
- return a default security descriptor
-*/
-struct security_descriptor *samdb_default_security_descriptor(TALLOC_CTX *mem_ctx)
-{
- struct security_descriptor *sd;
-
- sd = security_descriptor_initialise(mem_ctx);
-
- return sd;
-}
-
-struct ldb_dn *samdb_base_dn(struct ldb_context *sam_ctx)
-{
- return ldb_get_default_basedn(sam_ctx);
-}
-
-struct ldb_dn *samdb_config_dn(struct ldb_context *sam_ctx)
-{
- return ldb_get_config_basedn(sam_ctx);
-}
-
-struct ldb_dn *samdb_schema_dn(struct ldb_context *sam_ctx)
-{
- return ldb_get_schema_basedn(sam_ctx);
-}
-
-struct ldb_dn *samdb_root_dn(struct ldb_context *sam_ctx)
-{
- return ldb_get_root_basedn(sam_ctx);
-}
-
-struct ldb_dn *samdb_partitions_dn(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx)
-{
- struct ldb_dn *new_dn;
-
- new_dn = ldb_dn_copy(mem_ctx, samdb_config_dn(sam_ctx));
- if ( ! ldb_dn_add_child_fmt(new_dn, "CN=Partitions")) {
- talloc_free(new_dn);
- return NULL;
- }
- return new_dn;
-}
-
-struct ldb_dn *samdb_sites_dn(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx)
-{
- struct ldb_dn *new_dn;
-
- new_dn = ldb_dn_copy(mem_ctx, samdb_config_dn(sam_ctx));
- if ( ! ldb_dn_add_child_fmt(new_dn, "CN=Sites")) {
- talloc_free(new_dn);
- return NULL;
- }
- return new_dn;
-}
-
-/*
- work out the domain sid for the current open ldb
-*/
-const struct dom_sid *samdb_domain_sid(struct ldb_context *ldb)
-{
- TALLOC_CTX *tmp_ctx;
- struct dom_sid *domain_sid;
-
- /* see if we have a cached copy */
- domain_sid = (struct dom_sid *)ldb_get_opaque(ldb, "cache.domain_sid");
- if (domain_sid) {
- return domain_sid;
- }
-
- tmp_ctx = talloc_new(ldb);
- if (tmp_ctx == NULL) {
- goto failed;
- }
-
- /* find the domain_sid */
- domain_sid = samdb_search_dom_sid(ldb, tmp_ctx, ldb_get_default_basedn(ldb),
- "objectSid", "objectClass=domainDNS");
- if (domain_sid == NULL) {
- goto failed;
- }
-
- /* cache the domain_sid in the ldb */
- if (ldb_set_opaque(ldb, "cache.domain_sid", domain_sid) != LDB_SUCCESS) {
- goto failed;
- }
-
- talloc_steal(ldb, domain_sid);
- talloc_free(tmp_ctx);
-
- return domain_sid;
-
-failed:
- DEBUG(1,("Failed to find domain_sid for open ldb\n"));
- talloc_free(tmp_ctx);
- return NULL;
-}
-
-bool samdb_set_domain_sid(struct ldb_context *ldb, const struct dom_sid *dom_sid_in)
-{
- TALLOC_CTX *tmp_ctx;
- struct dom_sid *dom_sid_new;
- struct dom_sid *dom_sid_old;
-
- /* see if we have a cached copy */
- dom_sid_old = talloc_get_type(ldb_get_opaque(ldb,
- "cache.domain_sid"), struct dom_sid);
-
- tmp_ctx = talloc_new(ldb);
- if (tmp_ctx == NULL) {
- goto failed;
- }
-
- dom_sid_new = dom_sid_dup(tmp_ctx, dom_sid_in);
- if (!dom_sid_new) {
- goto failed;
- }
-
- /* cache the domain_sid in the ldb */
- if (ldb_set_opaque(ldb, "cache.domain_sid", dom_sid_new) != LDB_SUCCESS) {
- goto failed;
- }
-
- talloc_steal(ldb, dom_sid_new);
- talloc_free(tmp_ctx);
- talloc_free(dom_sid_old);
-
- return true;
-
-failed:
- DEBUG(1,("Failed to set our own cached domain SID in the ldb!\n"));
- talloc_free(tmp_ctx);
- return false;
-}
-
-/* Obtain the short name of the flexible single master operator
- * (FSMO), such as the PDC Emulator */
-const char *samdb_result_fsmo_name(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const struct ldb_message *msg,
- const char *attr)
-{
- /* Format is cn=NTDS Settings,cn=<NETBIOS name of FSMO>,.... */
- struct ldb_dn *fsmo_dn = ldb_msg_find_attr_as_dn(ldb, mem_ctx, msg, attr);
- const struct ldb_val *val = ldb_dn_get_component_val(fsmo_dn, 1);
- const char *name = ldb_dn_get_component_name(fsmo_dn, 1);
-
- if (!name || (ldb_attr_cmp(name, "cn") != 0)) {
- /* Ensure this matches the format. This gives us a
- * bit more confidence that a 'cn' value will be a
- * ascii string */
- return NULL;
- }
- if (val) {
- return (char *)val->data;
- }
- return NULL;
-}
-
-/*
- work out the ntds settings dn for the current open ldb
-*/
-struct ldb_dn *samdb_ntds_settings_dn(struct ldb_context *ldb)
-{
- TALLOC_CTX *tmp_ctx;
- const char *root_attrs[] = { "dsServiceName", NULL };
- int ret;
- struct ldb_result *root_res;
- struct ldb_dn *settings_dn;
-
- /* see if we have a cached copy */
- settings_dn = (struct ldb_dn *)ldb_get_opaque(ldb, "cache.settings_dn");
- if (settings_dn) {
- return settings_dn;
- }
-
- tmp_ctx = talloc_new(ldb);
- if (tmp_ctx == NULL) {
- goto failed;
- }
-
-
- ret = ldb_search(ldb, ldb_dn_new(tmp_ctx, ldb, ""), LDB_SCOPE_BASE, NULL, root_attrs, &root_res);
- if (ret) {
- DEBUG(1,("Searching for dsServiceName in rootDSE failed: %s\n",
- ldb_errstring(ldb)));
- goto failed;
- }
- talloc_steal(tmp_ctx, root_res);
-
- if (root_res->count != 1) {
- goto failed;
- }
-
- settings_dn = ldb_msg_find_attr_as_dn(ldb, tmp_ctx, root_res->msgs[0], "dsServiceName");
-
- /* cache the domain_sid in the ldb */
- if (ldb_set_opaque(ldb, "cache.settings_dn", settings_dn) != LDB_SUCCESS) {
- goto failed;
- }
-
- talloc_steal(ldb, settings_dn);
- talloc_free(tmp_ctx);
-
- return settings_dn;
-
-failed:
- DEBUG(1,("Failed to find our own NTDS Settings DN in the ldb!\n"));
- talloc_free(tmp_ctx);
- return NULL;
-}
-
-/*
- work out the ntds settings invocationId for the current open ldb
-*/
-const struct GUID *samdb_ntds_invocation_id(struct ldb_context *ldb)
-{
- TALLOC_CTX *tmp_ctx;
- const char *attrs[] = { "invocationId", NULL };
- int ret;
- struct ldb_result *res;
- struct GUID *invocation_id;
-
- /* see if we have a cached copy */
- invocation_id = (struct GUID *)ldb_get_opaque(ldb, "cache.invocation_id");
- if (invocation_id) {
- return invocation_id;
- }
-
- tmp_ctx = talloc_new(ldb);
- if (tmp_ctx == NULL) {
- goto failed;
- }
-
- ret = ldb_search(ldb, samdb_ntds_settings_dn(ldb), LDB_SCOPE_BASE, NULL, attrs, &res);
- if (ret) {
- goto failed;
- }
- talloc_steal(tmp_ctx, res);
-
- if (res->count != 1) {
- goto failed;
- }
-
- invocation_id = talloc(tmp_ctx, struct GUID);
- if (!invocation_id) {
- goto failed;
- }
-
- *invocation_id = samdb_result_guid(res->msgs[0], "invocationId");
-
- /* cache the domain_sid in the ldb */
- if (ldb_set_opaque(ldb, "cache.invocation_id", invocation_id) != LDB_SUCCESS) {
- goto failed;
- }
-
- talloc_steal(ldb, invocation_id);
- talloc_free(tmp_ctx);
-
- return invocation_id;
-
-failed:
- DEBUG(1,("Failed to find our own NTDS Settings invocationId in the ldb!\n"));
- talloc_free(tmp_ctx);
- return NULL;
-}
-
-bool samdb_set_ntds_invocation_id(struct ldb_context *ldb, const struct GUID *invocation_id_in)
-{
- TALLOC_CTX *tmp_ctx;
- struct GUID *invocation_id_new;
- struct GUID *invocation_id_old;
-
- /* see if we have a cached copy */
- invocation_id_old = (struct GUID *)ldb_get_opaque(ldb,
- "cache.invocation_id");
-
- tmp_ctx = talloc_new(ldb);
- if (tmp_ctx == NULL) {
- goto failed;
- }
-
- invocation_id_new = talloc(tmp_ctx, struct GUID);
- if (!invocation_id_new) {
- goto failed;
- }
-
- *invocation_id_new = *invocation_id_in;
-
- /* cache the domain_sid in the ldb */
- if (ldb_set_opaque(ldb, "cache.invocation_id", invocation_id_new) != LDB_SUCCESS) {
- goto failed;
- }
-
- talloc_steal(ldb, invocation_id_new);
- talloc_free(tmp_ctx);
- talloc_free(invocation_id_old);
-
- return true;
-
-failed:
- DEBUG(1,("Failed to set our own cached invocationId in the ldb!\n"));
- talloc_free(tmp_ctx);
- return false;
-}
-
-/*
- work out the ntds settings objectGUID for the current open ldb
-*/
-const struct GUID *samdb_ntds_objectGUID(struct ldb_context *ldb)
-{
- TALLOC_CTX *tmp_ctx;
- const char *attrs[] = { "objectGUID", NULL };
- int ret;
- struct ldb_result *res;
- struct GUID *ntds_guid;
-
- /* see if we have a cached copy */
- ntds_guid = (struct GUID *)ldb_get_opaque(ldb, "cache.ntds_guid");
- if (ntds_guid) {
- return ntds_guid;
- }
-
- tmp_ctx = talloc_new(ldb);
- if (tmp_ctx == NULL) {
- goto failed;
- }
-
- ret = ldb_search(ldb, samdb_ntds_settings_dn(ldb), LDB_SCOPE_BASE, NULL, attrs, &res);
- if (ret) {
- goto failed;
- }
- talloc_steal(tmp_ctx, res);
-
- if (res->count != 1) {
- goto failed;
- }
-
- ntds_guid = talloc(tmp_ctx, struct GUID);
- if (!ntds_guid) {
- goto failed;
- }
-
- *ntds_guid = samdb_result_guid(res->msgs[0], "objectGUID");
-
- /* cache the domain_sid in the ldb */
- if (ldb_set_opaque(ldb, "cache.ntds_guid", ntds_guid) != LDB_SUCCESS) {
- goto failed;
- }
-
- talloc_steal(ldb, ntds_guid);
- talloc_free(tmp_ctx);
-
- return ntds_guid;
-
-failed:
- DEBUG(1,("Failed to find our own NTDS Settings objectGUID in the ldb!\n"));
- talloc_free(tmp_ctx);
- return NULL;
-}
-
-bool samdb_set_ntds_objectGUID(struct ldb_context *ldb, const struct GUID *ntds_guid_in)
-{
- TALLOC_CTX *tmp_ctx;
- struct GUID *ntds_guid_new;
- struct GUID *ntds_guid_old;
-
- /* see if we have a cached copy */
- ntds_guid_old = (struct GUID *)ldb_get_opaque(ldb, "cache.ntds_guid");
-
- tmp_ctx = talloc_new(ldb);
- if (tmp_ctx == NULL) {
- goto failed;
- }
-
- ntds_guid_new = talloc(tmp_ctx, struct GUID);
- if (!ntds_guid_new) {
- goto failed;
- }
-
- *ntds_guid_new = *ntds_guid_in;
-
- /* cache the domain_sid in the ldb */
- if (ldb_set_opaque(ldb, "cache.ntds_guid", ntds_guid_new) != LDB_SUCCESS) {
- goto failed;
- }
-
- talloc_steal(ldb, ntds_guid_new);
- talloc_free(tmp_ctx);
- talloc_free(ntds_guid_old);
-
- return true;
-
-failed:
- DEBUG(1,("Failed to set our own cached invocationId in the ldb!\n"));
- talloc_free(tmp_ctx);
- return false;
-}
-
-/*
- work out the server dn for the current open ldb
-*/
-struct ldb_dn *samdb_server_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)
-{
- return ldb_dn_get_parent(mem_ctx, samdb_ntds_settings_dn(ldb));
-}
-
-/*
- work out the server dn for the current open ldb
-*/
-struct ldb_dn *samdb_server_site_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)
-{
- struct ldb_dn *server_dn;
- struct ldb_dn *server_site_dn;
-
- server_dn = samdb_server_dn(ldb, mem_ctx);
- if (!server_dn) return NULL;
-
- server_site_dn = ldb_dn_get_parent(mem_ctx, server_dn);
-
- talloc_free(server_dn);
- return server_site_dn;
-}
-
-/*
- work out if we are the PDC for the domain of the current open ldb
-*/
-bool samdb_is_pdc(struct ldb_context *ldb)
-{
- const char *dom_attrs[] = { "fSMORoleOwner", NULL };
- int ret;
- struct ldb_result *dom_res;
- TALLOC_CTX *tmp_ctx;
- bool is_pdc;
- struct ldb_dn *pdc;
-
- tmp_ctx = talloc_new(ldb);
- if (tmp_ctx == NULL) {
- DEBUG(1, ("talloc_new failed in samdb_is_pdc"));
- return false;
- }
-
- ret = ldb_search(ldb, ldb_get_default_basedn(ldb), LDB_SCOPE_BASE, NULL, dom_attrs, &dom_res);
- if (ret) {
- DEBUG(1,("Searching for fSMORoleOwner in %s failed: %s\n",
- ldb_dn_get_linearized(ldb_get_default_basedn(ldb)),
- ldb_errstring(ldb)));
- goto failed;
- }
- talloc_steal(tmp_ctx, dom_res);
- if (dom_res->count != 1) {
- goto failed;
- }
-
- pdc = ldb_msg_find_attr_as_dn(ldb, tmp_ctx, dom_res->msgs[0], "fSMORoleOwner");
-
- if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), pdc) == 0) {
- is_pdc = true;
- } else {
- is_pdc = false;
- }
-
- talloc_free(tmp_ctx);
-
- return is_pdc;
-
-failed:
- DEBUG(1,("Failed to find if we are the PDC for this ldb\n"));
- talloc_free(tmp_ctx);
- return false;
-}
-
-
-/* Find a domain object in the parents of a particular DN. */
-int samdb_search_for_parent_domain(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_dn *dn,
- struct ldb_dn **parent_dn, const char **errstring)
-{
- TALLOC_CTX *local_ctx;
- struct ldb_dn *sdn = dn;
- struct ldb_result *res = NULL;
- int ret = 0;
- const char *attrs[] = { NULL };
-
- local_ctx = talloc_new(mem_ctx);
- if (local_ctx == NULL) return LDB_ERR_OPERATIONS_ERROR;
-
- while ((sdn = ldb_dn_get_parent(local_ctx, sdn))) {
- ret = ldb_search(ldb, sdn, LDB_SCOPE_BASE,
- "(|(objectClass=domain)(objectClass=builtinDomain))", attrs, &res);
- if (ret == LDB_SUCCESS) {
- talloc_steal(local_ctx, res);
- if (res->count == 1) {
- break;
- }
- } else {
- break;
- }
- }
-
- if (ret != LDB_SUCCESS) {
- *errstring = talloc_asprintf(mem_ctx, "Error searching for parent domain of %s, failed searching for %s: %s",
- ldb_dn_get_linearized(dn),
- ldb_dn_get_linearized(sdn),
- ldb_errstring(ldb));
- talloc_free(local_ctx);
- return ret;
- }
- if (res->count != 1) {
- *errstring = talloc_asprintf(mem_ctx, "Invalid dn (%s), not child of a domain object",
- ldb_dn_get_linearized(dn));
- talloc_free(local_ctx);
- return LDB_ERR_CONSTRAINT_VIOLATION;
- }
-
- *parent_dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
- talloc_free(local_ctx);
- return ret;
-}
-
-/*
- check that a password is sufficiently complex
-*/
-static bool samdb_password_complexity_ok(const char *pass)
-{
- return check_password_quality(pass);
-}
-
-
-
-/*
- set the user password using plaintext, obeying any user or domain
- password restrictions
-
- note that this function doesn't actually store the result in the
- database, it just fills in the "mod" structure with ldb modify
- elements to setup the correct change when samdb_replace() is
- called. This allows the caller to combine the change with other
- changes (as is needed by some of the set user info levels)
-
- The caller should probably have a transaction wrapping this
-*/
-_PUBLIC_ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
- struct ldb_dn *user_dn,
- struct ldb_dn *domain_dn,
- struct ldb_message *mod,
- const char *new_pass,
- struct samr_Password *lmNewHash,
- struct samr_Password *ntNewHash,
- bool user_change,
- enum samr_RejectReason *reject_reason,
- struct samr_DomInfo1 **_dominfo)
-{
- const char * const user_attrs[] = { "userAccountControl", "lmPwdHistory",
- "ntPwdHistory",
- "dBCSPwd", "unicodePwd",
- "objectSid",
- "pwdLastSet", NULL };
- const char * const domain_attrs[] = { "pwdProperties", "pwdHistoryLength",
- "maxPwdAge", "minPwdAge",
- "minPwdLength", NULL };
- NTTIME pwdLastSet;
- int64_t minPwdAge;
- uint_t minPwdLength, pwdProperties, pwdHistoryLength;
- uint_t userAccountControl;
- struct samr_Password *sambaLMPwdHistory, *sambaNTPwdHistory, *lmPwdHash, *ntPwdHash;
- struct samr_Password local_lmNewHash, local_ntNewHash;
- int sambaLMPwdHistory_len, sambaNTPwdHistory_len;
- struct dom_sid *domain_sid;
- struct ldb_message **res;
- bool restrictions;
- int count;
- time_t now = time(NULL);
- NTTIME now_nt;
- int i;
-
- /* we need to know the time to compute password age */
- unix_to_nt_time(&now_nt, now);
-
- /* pull all the user parameters */
- count = gendb_search_dn(ctx, mem_ctx, user_dn, &res, user_attrs);
- 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);
-
- /* Only non-trust accounts have restrictions (possibly this
- * test is the wrong way around, but I like to be restrictive
- * if possible */
- restrictions = !(userAccountControl & (UF_INTERDOMAIN_TRUST_ACCOUNT
- |UF_WORKSTATION_TRUST_ACCOUNT
- |UF_SERVER_TRUST_ACCOUNT));
-
- if (domain_dn) {
- /* pull the domain parameters */
- 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),
- ldb_dn_get_linearized(user_dn)));
- return NT_STATUS_NO_SUCH_DOMAIN;
- }
- } else {
- /* work out the domain sid, and pull the domain from there */
- 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));
- 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),
- ldb_dn_get_linearized(user_dn)));
- return NT_STATUS_NO_SUCH_DOMAIN;
- }
- }
-
- 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);
-
- if (_dominfo) {
- struct samr_DomInfo1 *dominfo;
- /* on failure we need to fill in the reject reasons */
- dominfo = talloc(mem_ctx, struct samr_DomInfo1);
- if (dominfo == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
- dominfo->min_password_length = minPwdLength;
- dominfo->password_properties = pwdProperties;
- dominfo->password_history_length = pwdHistoryLength;
- dominfo->max_password_age = minPwdAge;
- dominfo->min_password_age = minPwdAge;
- *_dominfo = dominfo;
- }
-
- if (restrictions && new_pass) {
-
- /* check the various password restrictions */
- if (restrictions && minPwdLength > strlen_m(new_pass)) {
- if (reject_reason) {
- *reject_reason = SAMR_REJECT_TOO_SHORT;
- }
- return NT_STATUS_PASSWORD_RESTRICTION;
- }
-
- /* possibly check password complexity */
- if (restrictions && pwdProperties & DOMAIN_PASSWORD_COMPLEX &&
- !samdb_password_complexity_ok(new_pass)) {
- if (reject_reason) {
- *reject_reason = SAMR_REJECT_COMPLEXITY;
- }
- return NT_STATUS_PASSWORD_RESTRICTION;
- }
-
- /* compute the new nt and lm hashes */
- if (E_deshash(new_pass, local_lmNewHash.hash)) {
- lmNewHash = &local_lmNewHash;
- }
- if (!E_md4hash(new_pass, local_ntNewHash.hash)) {
- /* If we can't convert this password to UCS2, then we should not accept it */
- if (reject_reason) {
- *reject_reason = SAMR_REJECT_OTHER;
- }
- return NT_STATUS_PASSWORD_RESTRICTION;
- }
- ntNewHash = &local_ntNewHash;
- }
-
- if (user_change) {
- /* are all password changes disallowed? */
- if (pwdProperties & DOMAIN_REFUSE_PASSWORD_CHANGE) {
- if (reject_reason) {
- *reject_reason = SAMR_REJECT_OTHER;
- }
- return NT_STATUS_PASSWORD_RESTRICTION;
- }
-
- /* can this user change password? */
- if (userAccountControl & UF_PASSWD_CANT_CHANGE) {
- if (reject_reason) {
- *reject_reason = SAMR_REJECT_OTHER;
- }
- return NT_STATUS_PASSWORD_RESTRICTION;
- }
-
- /* 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;
- }
- return NT_STATUS_PASSWORD_RESTRICTION;
- }
-
- /* check the immediately past password */
- if (pwdHistoryLength > 0) {
- if (lmNewHash && lmPwdHash && memcmp(lmNewHash->hash, lmPwdHash->hash, 16) == 0) {
- if (reject_reason) {
- *reject_reason = SAMR_REJECT_IN_HISTORY;
- }
- return NT_STATUS_PASSWORD_RESTRICTION;
- }
- if (ntNewHash && ntPwdHash && memcmp(ntNewHash->hash, ntPwdHash->hash, 16) == 0) {
- if (reject_reason) {
- *reject_reason = SAMR_REJECT_IN_HISTORY;
- }
- return NT_STATUS_PASSWORD_RESTRICTION;
- }
- }
-
- /* check the password history */
- 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 (reject_reason) {
- *reject_reason = SAMR_REJECT_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 (reject_reason) {
- *reject_reason = SAMR_REJECT_IN_HISTORY;
- }
- return NT_STATUS_PASSWORD_RESTRICTION;
- }
- }
- }
-
-#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_pass) {
- /* if we know the cleartext, then only set it.
- * Modules in ldb will set all the appropriate
- * hashes */
- CHECK_RET(samdb_msg_add_string(ctx, mem_ctx, mod,
- "sambaPassword", new_pass));
- } else {
- /* We don't have the cleartext, so delete the old one
- * and set what we have of the hashes */
- CHECK_RET(samdb_msg_add_delete(ctx, mem_ctx, mod, "sambaPassword"));
-
- if (lmNewHash) {
- CHECK_RET(samdb_msg_add_hash(ctx, mem_ctx, mod, "dBCSPwd", lmNewHash));
- } else {
- CHECK_RET(samdb_msg_add_delete(ctx, mem_ctx, mod, "dBCSPwd"));
- }
-
- if (ntNewHash) {
- CHECK_RET(samdb_msg_add_hash(ctx, mem_ctx, mod, "unicodePwd", ntNewHash));
- } else {
- CHECK_RET(samdb_msg_add_delete(ctx, mem_ctx, mod, "unicodePwd"));
- }
- }
-
- return NT_STATUS_OK;
-}
-
-
-/*
- set the user password using plaintext, obeying any user or domain
- password restrictions
-
- This wrapper function takes a SID as input, rather than a user DN,
- and actually performs the password change
-
-*/
-_PUBLIC_ NTSTATUS samdb_set_password_sid(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
- const struct dom_sid *user_sid,
- const char *new_pass,
- struct samr_Password *lmNewHash,
- struct samr_Password *ntNewHash,
- bool user_change,
- enum samr_RejectReason *reject_reason,
- struct samr_DomInfo1 **_dominfo)
-{
- NTSTATUS nt_status;
- struct ldb_dn *user_dn;
- struct ldb_message *msg;
- int ret;
-
- ret = ldb_transaction_start(ctx);
- if (ret) {
- DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(ctx)));
- return NT_STATUS_TRANSACTION_ABORTED;
- }
-
- user_dn = samdb_search_dn(ctx, mem_ctx, NULL,
- "(&(objectSid=%s)(objectClass=user))",
- ldap_encode_ndr_dom_sid(mem_ctx, user_sid));
- if (!user_dn) {
- ldb_transaction_cancel(ctx);
- DEBUG(3, ("samdb_set_password_sid: SID %s not found in samdb, returning NO_SUCH_USER\n",
- dom_sid_string(mem_ctx, user_sid)));
- return NT_STATUS_NO_SUCH_USER;
- }
-
- msg = ldb_msg_new(mem_ctx);
- if (msg == NULL) {
- ldb_transaction_cancel(ctx);
- return NT_STATUS_NO_MEMORY;
- }
-
- msg->dn = ldb_dn_copy(msg, user_dn);
- if (!msg->dn) {
- ldb_transaction_cancel(ctx);
- return NT_STATUS_NO_MEMORY;
- }
-
- nt_status = samdb_set_password(ctx, mem_ctx,
- user_dn, NULL,
- msg, new_pass,
- lmNewHash, ntNewHash,
- user_change, /* This is a password set, not change */
- reject_reason, _dominfo);
- if (!NT_STATUS_IS_OK(nt_status)) {
- ldb_transaction_cancel(ctx);
- return nt_status;
- }
-
- /* modify the samdb record */
- ret = samdb_replace(ctx, mem_ctx, msg);
- if (ret != 0) {
- ldb_transaction_cancel(ctx);
- return NT_STATUS_ACCESS_DENIED;
- }
-
- ret = ldb_transaction_commit(ctx);
- if (ret != 0) {
- DEBUG(0,("Failed to commit transaction to change password on %s: %s\n",
- ldb_dn_get_linearized(msg->dn),
- ldb_errstring(ctx)));
- return NT_STATUS_TRANSACTION_ABORTED;
- }
- return NT_STATUS_OK;
-}
-
/****************************************************************************
Create the SID list for this user.
****************************************************************************/
@@ -1961,153 +252,3 @@ NTSTATUS security_token_create(TALLOC_CTX *mem_ctx,
return NT_STATUS_OK;
}
-
-
-NTSTATUS samdb_create_foreign_security_principal(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
- struct dom_sid *sid, struct ldb_dn **ret_dn)
-{
- struct ldb_message *msg;
- struct ldb_dn *basedn;
- const char *sidstr;
- int ret;
-
- sidstr = dom_sid_string(mem_ctx, sid);
- NT_STATUS_HAVE_NO_MEMORY(sidstr);
-
- /* We might have to create a ForeignSecurityPrincipal, even if this user
- * is in our own domain */
-
- msg = ldb_msg_new(mem_ctx);
- if (msg == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- /* TODO: Hmmm. This feels wrong. How do I find the base dn to
- * put the ForeignSecurityPrincipals? d_state->domain_dn does
- * not work, this is wrong for the Builtin domain, there's no
- * cn=For...,cn=Builtin,dc={BASEDN}. -- vl
- */
-
- basedn = samdb_search_dn(sam_ctx, mem_ctx, NULL,
- "(&(objectClass=container)(cn=ForeignSecurityPrincipals))");
-
- if (basedn == NULL) {
- DEBUG(0, ("Failed to find DN for "
- "ForeignSecurityPrincipal container\n"));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
-
- /* add core elements to the ldb_message for the alias */
- msg->dn = ldb_dn_copy(mem_ctx, basedn);
- if ( ! ldb_dn_add_child_fmt(msg->dn, "CN=%s", sidstr))
- return NT_STATUS_NO_MEMORY;
-
- samdb_msg_add_string(sam_ctx, mem_ctx, msg,
- "objectClass",
- "foreignSecurityPrincipal");
-
- /* create the alias */
- ret = ldb_add(sam_ctx, msg);
- if (ret != 0) {
- DEBUG(0,("Failed to create foreignSecurityPrincipal "
- "record %s: %s\n",
- ldb_dn_get_linearized(msg->dn),
- ldb_errstring(sam_ctx)));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
- *ret_dn = msg->dn;
- return NT_STATUS_OK;
-}
-
-
-/*
- Find the DN of a domain, assuming it to be a dotted.dns name
-*/
-
-struct ldb_dn *samdb_dns_domain_to_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *dns_domain)
-{
- int i;
- TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
- const char *binary_encoded;
- const char **split_realm;
- struct ldb_dn *dn;
-
- if (!tmp_ctx) {
- return NULL;
- }
-
- split_realm = str_list_make(tmp_ctx, dns_domain, ".");
- if (!split_realm) {
- talloc_free(tmp_ctx);
- return NULL;
- }
- dn = ldb_dn_new(mem_ctx, ldb, NULL);
- for (i=0; split_realm[i]; i++) {
- binary_encoded = ldb_binary_encode_string(tmp_ctx, split_realm[i]);
- if (!ldb_dn_add_base_fmt(dn, "dc=%s", binary_encoded)) {
- DEBUG(2, ("Failed to add dc=%s element to DN %s\n",
- binary_encoded, ldb_dn_get_linearized(dn)));
- talloc_free(tmp_ctx);
- return NULL;
- }
- }
- if (!ldb_dn_validate(dn)) {
- DEBUG(2, ("Failed to validated DN %s\n",
- ldb_dn_get_linearized(dn)));
- return NULL;
- }
- return dn;
-}
-/*
- Find the DN of a domain, be it the netbios or DNS name
-*/
-
-struct ldb_dn *samdb_domain_to_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
- const char *domain_name)
-{
- const char * const domain_ref_attrs[] = {
- "ncName", NULL
- };
- const char * const domain_ref2_attrs[] = {
- NULL
- };
- struct ldb_result *res_domain_ref;
- char *escaped_domain = ldb_binary_encode_string(mem_ctx, domain_name);
- /* find the domain's DN */
- int ret_domain = ldb_search_exp_fmt(ldb, mem_ctx,
- &res_domain_ref,
- samdb_partitions_dn(ldb, mem_ctx),
- LDB_SCOPE_ONELEVEL,
- domain_ref_attrs,
- "(&(nETBIOSName=%s)(objectclass=crossRef))",
- escaped_domain);
- if (ret_domain != 0) {
- return NULL;
- }
-
- if (res_domain_ref->count == 0) {
- ret_domain = ldb_search_exp_fmt(ldb, mem_ctx,
- &res_domain_ref,
- samdb_dns_domain_to_dn(ldb, mem_ctx, domain_name),
- LDB_SCOPE_BASE,
- domain_ref2_attrs,
- "(objectclass=domain)");
- if (ret_domain != 0) {
- return NULL;
- }
-
- if (res_domain_ref->count == 1) {
- return res_domain_ref->msgs[0]->dn;
- }
- return NULL;
- }
-
- if (res_domain_ref->count > 1) {
- DEBUG(0,("Found %d records matching domain [%s]\n",
- ret_domain, domain_name));
- return NULL;
- }
-
- return samdb_result_dn(ldb, mem_ctx, res_domain_ref->msgs[0], "nCName", NULL);
-
-}
diff --git a/source4/dsdb/samdb/samdb.h b/source4/dsdb/samdb/samdb.h
index 54d1ce2e75..5d8694d2d4 100644
--- a/source4/dsdb/samdb/samdb.h
+++ b/source4/dsdb/samdb/samdb.h
@@ -35,6 +35,7 @@ struct loadparm_context;
#include "librpc/gen_ndr/drsblobs.h"
#include "dsdb/schema/schema.h"
#include "dsdb/samdb/samdb_proto.h"
+#include "dsdb/common/proto.h"
#define DSDB_CONTROL_CURRENT_PARTITION_OID "1.3.6.1.4.1.7165.4.3.2"
struct dsdb_control_current_partition {
diff --git a/source4/dsdb/schema/schema.h b/source4/dsdb/schema/schema.h
index 1125f775ff..1379ddee9f 100644
--- a/source4/dsdb/schema/schema.h
+++ b/source4/dsdb/schema/schema.h
@@ -151,4 +151,6 @@ struct dsdb_schema {
struct dsdb_class *classes;
};
+#include "dsdb/schema/proto.h"
+
#endif /* _DSDB_SCHEMA_H */