diff options
Diffstat (limited to 'source4/dsdb/samdb')
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/anr.c | 310 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/config.mk | 46 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/naming_fsmo.c | 8 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/partition.c | 22 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/pdc_fsmo.c | 8 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/schema.c | 4 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/schema_fsmo.c | 8 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/update_keytab.c | 2 | ||||
-rw-r--r-- | source4/dsdb/samdb/samdb.c | 1859 | ||||
-rw-r--r-- | source4/dsdb/samdb/samdb.h | 1 |
10 files changed, 370 insertions, 1898 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/anr.c b/source4/dsdb/samdb/ldb_modules/anr.c new file mode 100644 index 0000000000..901215e972 --- /dev/null +++ b/source4/dsdb/samdb/ldb_modules/anr.c @@ -0,0 +1,310 @@ +/* + ldb database library + + Copyright (C) Amdrew Bartlett <abartlet@samba.org> 2007 + Copyright (C) Andrew Tridgell 2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* + * Name: ldb + * + * Component: ldb anr module + * + * Description: module to implement 'ambiguous name resolution' + * + * Author: Andrew Bartlett + */ + +#include "includes.h" +#include "ldb_includes.h" +#include "dsdb/samdb/samdb.h" + +/** + * Make a and 'and' or 'or' tree from the two supplied elements + */ +struct ldb_parse_tree *make_parse_list(struct ldb_module *module, + TALLOC_CTX *mem_ctx, enum ldb_parse_op op, + struct ldb_parse_tree *first_arm, struct ldb_parse_tree *second_arm) +{ + struct ldb_parse_tree *list; + + list = talloc(mem_ctx, struct ldb_parse_tree); + if (list == NULL){ + ldb_oom(module->ldb); + return NULL; + } + list->operation = op; + + list->u.list.num_elements = 2; + list->u.list.elements = talloc_array(list, struct ldb_parse_tree *, 2); + if (!list->u.list.elements) { + ldb_oom(module->ldb); + return NULL; + } + list->u.list.elements[0] = talloc_steal(list, first_arm); + list->u.list.elements[1] = talloc_steal(list, second_arm); + return list; +} + +/** + * Make an equality or prefix match tree, from the attribute, operation and matching value supplied + */ +struct ldb_parse_tree *make_match_tree(struct ldb_module *module, + TALLOC_CTX *mem_ctx, enum ldb_parse_op op, + const char *attr, const DATA_BLOB *match) +{ + struct ldb_parse_tree *match_tree; + + match_tree = talloc(mem_ctx, struct ldb_parse_tree); + + /* Depending on what type of match was selected, fill in the right part of the union */ + + match_tree->operation = op; + switch (op) { + case LDB_OP_SUBSTRING: + match_tree->u.substring.attr = attr; + + match_tree->u.substring.start_with_wildcard = 0; + match_tree->u.substring.end_with_wildcard = 1; + match_tree->u.substring.chunks = talloc_array(match_tree, struct ldb_val *, 2); + + if (match_tree->u.substring.chunks == NULL){ + ldb_oom(module->ldb); + return NULL; + } + match_tree->u.substring.chunks[0] = match; + match_tree->u.substring.chunks[1] = NULL; + break; + case LDB_OP_EQUALITY: + match_tree->u.equality.attr = attr; + match_tree->u.equality.value = *match; + break; + } + return match_tree; +} + +struct anr_context { + bool found_anr; + struct ldb_module *module; +}; + +/** + * Given the match for an 'ambigious name resolution' query, create a + * parse tree with an 'or' of all the anr attributes in the schema. + */ + +typedef struct ldb_parse_tree *(*anr_parse_tree_callback_t)(TALLOC_CTX *mem_ctx, + const struct ldb_val *match, + void *context); + + +/** + * Callback function to do the heavy lifting for the for the parse tree walker + */ +struct ldb_parse_tree *anr_replace_callback(TALLOC_CTX *mem_ctx, + const struct ldb_val *match, + void *context) +{ + struct ldb_parse_tree *tree = NULL; + struct anr_context *anr_context = talloc_get_type(context, struct anr_context); + struct ldb_module *module = anr_context->module; + struct ldb_parse_tree *match_tree; + uint8_t *p; + enum ldb_parse_op op; + struct dsdb_attribute *cur; + const struct dsdb_schema *schema = dsdb_get_schema(module->ldb); + if (!schema) { + ldb_asprintf_errstring(module->ldb, "no schema with which to construct anr filter"); + return NULL; + } + + anr_context->found_anr = true; + + if (match->length > 1 && match->data[0] == '=') { + DATA_BLOB *match2 = talloc(tree, DATA_BLOB); + *match2 = data_blob_const(match->data+1, match->length - 1); + if (match2 == NULL){ + ldb_oom(module->ldb); + return NULL; + } + match = match2; + op = LDB_OP_EQUALITY; + } else { + op = LDB_OP_SUBSTRING; + } + for (cur = schema->attributes; cur; cur = cur->next) { + if (!(cur->searchFlags & 0x4)) continue; + match_tree = make_match_tree(module, mem_ctx, op, cur->lDAPDisplayName, match); + + if (tree) { + /* Inject an 'or' with the current tree */ + tree = make_parse_list(module, mem_ctx, LDB_OP_OR, tree, match_tree); + if (tree == NULL) { + ldb_oom(module->ldb); + return NULL; + } + } else { + tree = match_tree; + } + } + + + /* If the search term has a space in it, + split it up at the first space. */ + + p = memchr(match->data, ' ', match->length); + + if (p) { + struct ldb_parse_tree *first_split_filter, *second_split_filter, *split_filters, *match_tree_1, *match_tree_2; + DATA_BLOB *first_match = talloc(tree, DATA_BLOB); + DATA_BLOB *second_match = talloc(tree, DATA_BLOB); + if (!first_match || !second_match) { + ldb_oom(module->ldb); + return NULL; + } + *first_match = data_blob_const(match->data, p-match->data); + *second_match = data_blob_const(p+1, match->length - (p-match->data) - 1); + + /* Add (|(&(givenname=first)(sn=second))(&(givenname=second)(sn=first))) */ + + match_tree_1 = make_match_tree(module, mem_ctx, op, "givenName", first_match); + match_tree_2 = make_match_tree(module, mem_ctx, op, "sn", second_match); + + first_split_filter = make_parse_list(module, context, LDB_OP_AND, match_tree_1, match_tree_2); + if (first_split_filter == NULL){ + ldb_oom(module->ldb); + return NULL; + } + + match_tree_1 = make_match_tree(module, mem_ctx, op, "sn", first_match); + match_tree_2 = make_match_tree(module, mem_ctx, op, "givenName", second_match); + + second_split_filter = make_parse_list(module, context, LDB_OP_AND, match_tree_1, match_tree_2); + if (second_split_filter == NULL){ + ldb_oom(module->ldb); + return NULL; + } + + split_filters = make_parse_list(module, mem_ctx, LDB_OP_OR, + first_split_filter, second_split_filter); + if (split_filters == NULL) { + ldb_oom(module->ldb); + return NULL; + } + + if (tree) { + /* Inject an 'or' with the current tree */ + tree = make_parse_list(module, mem_ctx, LDB_OP_OR, tree, split_filters); + } else { + tree = split_filters; + } + } + return tree; +} + +/* + replace any occurances of an attribute with a new, generated attribute tree +*/ +struct ldb_parse_tree *anr_replace_subtrees(struct ldb_parse_tree *tree, + const char *attr, + anr_parse_tree_callback_t callback, + void *context) +{ + int i; + switch (tree->operation) { + case LDB_OP_AND: + case LDB_OP_OR: + for (i=0;i<tree->u.list.num_elements;i++) { + tree->u.list.elements[i] = anr_replace_subtrees(tree->u.list.elements[i], + attr, callback, context); + if (!tree->u.list.elements[i]) { + return NULL; + } + } + break; + case LDB_OP_NOT: + tree->u.isnot.child = anr_replace_subtrees(tree->u.isnot.child, attr, callback, context); + if (!tree->u.isnot.child) { + return NULL; + } + break; + case LDB_OP_EQUALITY: + if (ldb_attr_cmp(tree->u.equality.attr, attr) == 0) { + tree = callback(tree, &tree->u.equality.value, + context); + if (!tree) { + return NULL; + } + } + break; + case LDB_OP_SUBSTRING: + if (ldb_attr_cmp(tree->u.substring.attr, attr) == 0) { + if (tree->u.substring.start_with_wildcard == 0 && + tree->u.substring.end_with_wildcard == 1 && + tree->u.substring.chunks[0] != NULL && + tree->u.substring.chunks[1] == NULL) { + tree = callback(tree, tree->u.substring.chunks[0], context); + if (!tree) { + return NULL; + } + } + } + break; + } + return tree; +} + +/* search */ +static int anr_search(struct ldb_module *module, struct ldb_request *req) +{ + struct ldb_parse_tree *anr_tree; + struct anr_context *context = talloc(req, struct anr_context); + if (!context) { + ldb_oom(module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + context->module = module; + context->found_anr = false; + + /* Yes, this is a problem with req->op.search.tree being const... */ + anr_tree = anr_replace_subtrees(req->op.search.tree, "anr", anr_replace_callback, context); + if (!anr_tree) { + return LDB_ERR_OPERATIONS_ERROR; + } + + if (context->found_anr) { + /* The above function modifies the tree if it finds "anr", so no + * point just setting this on the down_req */ + req->op.search.tree = talloc_steal(req, anr_tree); + + } + + /* TODO: Add a callback, and ensure we retry the search with surname and given name if we fail to match */ + + return ldb_next_request(module, req); +} + +static const struct ldb_module_ops anr_ops = { + .name = "anr", + .search = anr_search +}; + +int ldb_anr_init(void) +{ + return ldb_register_module(&anr_ops); +} + diff --git a/source4/dsdb/samdb/ldb_modules/config.mk b/source4/dsdb/samdb/ldb_modules/config.mk index b585d0da7f..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 @@ -304,3 +307,16 @@ OBJ_FILES = \ # End MODULE ldb_ranged_results ################################################ +################################################ +# Start MODULE ldb_anr +[MODULE::ldb_anr] +INIT_FUNCTION = ldb_anr_init +CFLAGS = -Ilib/ldb/include +OUTPUT_TYPE = SHARED_LIBRARY +PRIVATE_DEPENDENCIES = LIBTALLOC LIBSAMBA-UTIL SAMDB +SUBSYSTEM = LIBLDB +OBJ_FILES = \ + anr.o +# End MODULE ldb_anr +################################################ + diff --git a/source4/dsdb/samdb/ldb_modules/naming_fsmo.c b/source4/dsdb/samdb/ldb_modules/naming_fsmo.c index ddd357a4c6..d6b6a24287 100644 --- a/source4/dsdb/samdb/ldb_modules/naming_fsmo.c +++ b/source4/dsdb/samdb/ldb_modules/naming_fsmo.c @@ -52,7 +52,7 @@ static int naming_fsmo_init(struct ldb_module *module) naming_dn = samdb_partitions_dn(module->ldb, mem_ctx); if (!naming_dn) { ldb_debug(module->ldb, LDB_DEBUG_WARNING, - "naming_fsmo_init: no partitions dn present: (skip loading of naming contexts details)"); + "naming_fsmo_init: no partitions dn present: (skip loading of naming contexts details)\n"); talloc_free(mem_ctx); return ldb_next_init(module); } @@ -70,7 +70,7 @@ static int naming_fsmo_init(struct ldb_module *module) &naming_res); if (ret == LDB_ERR_NO_SUCH_OBJECT) { ldb_debug(module->ldb, LDB_DEBUG_WARNING, - "naming_fsmo_init: no partitions dn present: (skip loading of naming contexts details)"); + "naming_fsmo_init: no partitions dn present: (skip loading of naming contexts details)\n"); talloc_free(mem_ctx); return ldb_next_init(module); } @@ -84,7 +84,7 @@ static int naming_fsmo_init(struct ldb_module *module) talloc_steal(mem_ctx, naming_res); if (naming_res->count == 0) { ldb_debug(module->ldb, LDB_DEBUG_WARNING, - "naming_fsmo_init: no cross-ref container present: (skip loading of naming contexts details)"); + "naming_fsmo_init: no cross-ref container present: (skip loading of naming contexts details)\n"); talloc_free(mem_ctx); return ldb_next_init(module); } else if (naming_res->count > 1) { @@ -110,7 +110,7 @@ static int naming_fsmo_init(struct ldb_module *module) talloc_steal(module, naming_fsmo); ldb_debug(module->ldb, LDB_DEBUG_TRACE, - "naming_fsmo_init: we are master: %s", + "naming_fsmo_init: we are master: %s\n", (naming_fsmo->we_are_master?"yes":"no")); talloc_free(mem_ctx); 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/pdc_fsmo.c b/source4/dsdb/samdb/ldb_modules/pdc_fsmo.c index ed9b554bb1..0f3293ed1d 100644 --- a/source4/dsdb/samdb/ldb_modules/pdc_fsmo.c +++ b/source4/dsdb/samdb/ldb_modules/pdc_fsmo.c @@ -51,7 +51,7 @@ static int pdc_fsmo_init(struct ldb_module *module) pdc_dn = samdb_base_dn(module->ldb); if (!pdc_dn) { ldb_debug(module->ldb, LDB_DEBUG_WARNING, - "pdc_fsmo_init: no domain dn present: (skip loading of domain details)"); + "pdc_fsmo_init: no domain dn present: (skip loading of domain details)\n"); talloc_free(mem_ctx); return ldb_next_init(module); } @@ -69,7 +69,7 @@ static int pdc_fsmo_init(struct ldb_module *module) &pdc_res); if (ret == LDB_ERR_NO_SUCH_OBJECT) { ldb_debug(module->ldb, LDB_DEBUG_WARNING, - "pdc_fsmo_init: no domain object present: (skip loading of domain details)"); + "pdc_fsmo_init: no domain object present: (skip loading of domain details)\n"); talloc_free(mem_ctx); return ldb_next_init(module); } else if (ret != LDB_SUCCESS) { @@ -82,7 +82,7 @@ static int pdc_fsmo_init(struct ldb_module *module) talloc_steal(mem_ctx, pdc_res); if (pdc_res->count == 0) { ldb_debug(module->ldb, LDB_DEBUG_WARNING, - "pdc_fsmo_init: no domain object present: (skip loading of domain details)"); + "pdc_fsmo_init: no domain object present: (skip loading of domain details)\n"); talloc_free(mem_ctx); return ldb_next_init(module); } else if (pdc_res->count > 1) { @@ -108,7 +108,7 @@ static int pdc_fsmo_init(struct ldb_module *module) talloc_steal(module, pdc_fsmo); ldb_debug(module->ldb, LDB_DEBUG_TRACE, - "pdc_fsmo_init: we are master: %s", + "pdc_fsmo_init: we are master: %s\n", (pdc_fsmo->we_are_master?"yes":"no")); talloc_free(mem_ctx); 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/ldb_modules/schema_fsmo.c b/source4/dsdb/samdb/ldb_modules/schema_fsmo.c index 28853f3e34..559c91bd2d 100644 --- a/source4/dsdb/samdb/ldb_modules/schema_fsmo.c +++ b/source4/dsdb/samdb/ldb_modules/schema_fsmo.c @@ -60,7 +60,7 @@ static int schema_fsmo_init(struct ldb_module *module) schema_dn = samdb_schema_dn(module->ldb); if (!schema_dn) { ldb_debug(module->ldb, LDB_DEBUG_WARNING, - "schema_fsmo_init: no schema dn present: (skip schema loading)"); + "schema_fsmo_init: no schema dn present: (skip schema loading)\n"); return ldb_next_init(module); } @@ -92,7 +92,7 @@ static int schema_fsmo_init(struct ldb_module *module) &schema_res); if (ret == LDB_ERR_NO_SUCH_OBJECT) { ldb_debug(module->ldb, LDB_DEBUG_WARNING, - "schema_fsmo_init: no schema head present: (skip schema loading)"); + "schema_fsmo_init: no schema head present: (skip schema loading)\n"); talloc_free(mem_ctx); return ldb_next_init(module); } else if (ret != LDB_SUCCESS) { @@ -105,7 +105,7 @@ static int schema_fsmo_init(struct ldb_module *module) talloc_steal(mem_ctx, schema_res); if (schema_res->count == 0) { ldb_debug(module->ldb, LDB_DEBUG_WARNING, - "schema_fsmo_init: no schema head present: (skip schema loading)"); + "schema_fsmo_init: no schema head present: (skip schema loading)\n"); talloc_free(mem_ctx); return ldb_next_init(module); } else if (schema_res->count > 1) { @@ -246,7 +246,7 @@ static int schema_fsmo_init(struct ldb_module *module) talloc_steal(module, schema_fsmo); ldb_debug(module->ldb, LDB_DEBUG_TRACE, - "schema_fsmo_init: we are master: %s", + "schema_fsmo_init: we are master: %s\n", (schema_fsmo->we_are_master?"yes":"no")); talloc_free(mem_ctx); diff --git a/source4/dsdb/samdb/ldb_modules/update_keytab.c b/source4/dsdb/samdb/ldb_modules/update_keytab.c index 87efa6a6f8..a18efd757a 100644 --- a/source4/dsdb/samdb/ldb_modules/update_keytab.c +++ b/source4/dsdb/samdb/ldb_modules/update_keytab.c @@ -158,7 +158,7 @@ static int update_kt_end_trans(struct ldb_module *module) struct dn_list *p; for (p=data->changed_dns; p; p = p->next) { int kret; - kret = cli_credentials_update_keytab(p->creds); + kret = cli_credentials_update_keytab(p->creds, ldb_get_opaque(module->ldb, "loadparm")); if (kret != 0) { talloc_free(data->changed_dns); data->changed_dns = NULL; 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 { |