The branch, master has been updated via 8ddfe78 s3-dssync-passdb: implement accounts, aliases and groups via 6e0498d s3-dssync-passdb: fill in passdb_process_objects via 41ba1d3 s3-dssync-passdb: fill in passdb_finish. via 1f884cf s3-dssync-passdb: fill in passdb_startup. via 91e6dad s3-dssync-passdb: add basic routines and net function. via 1c1aeba s3:net: make some net_rpc_samsync.c functions static via 0313969 s3:net: "net rpc vampire" is an alias for "net rpc vampire passdb" via bf7a27c s3:libnet: add 'process_links' to dssync_ops via cecf54b s3:groupdb: allow machine accounts as members. via 255f2e0 s3:winbindd: catch lookup_names/sids schannel errors over ncacn_ip_tcp (bug #7944) from 50be0b2 s3: Remove superfluous ;
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 8ddfe78a5fdbae99856fd935a3103fad9df812f2 Author: Stefan Metzmacher <me...@samba.org> Date: Wed Jan 5 16:56:14 2011 +0100 s3-dssync-passdb: implement accounts, aliases and groups metze Autobuild-User: Stefan Metzmacher <me...@samba.org> Autobuild-Date: Wed Feb 2 16:30:26 CET 2011 on sn-devel-104 commit 6e0498d0e289ed596a86a1b084475bdeec9b7105 Author: Günther Deschner <g...@samba.org> Date: Sat Nov 22 00:35:20 2008 +0100 s3-dssync-passdb: fill in passdb_process_objects Guenther Signed-off-by: Stefan Metzmacher <me...@samba.org> commit 41ba1d3a1cdb1ecf3f3e607cea73c35dc19a3deb Author: Günther Deschner <g...@samba.org> Date: Fri Nov 21 23:59:55 2008 +0100 s3-dssync-passdb: fill in passdb_finish. Guenther Signed-off-by: Stefan Metzmacher <me...@samba.org> commit 1f884cfbcb126c8f8bfeeabd349e082ae8fae3b6 Author: Günther Deschner <g...@samba.org> Date: Fri Nov 21 23:58:42 2008 +0100 s3-dssync-passdb: fill in passdb_startup. Guenther Signed-off-by: Stefan Metzmacher <me...@samba.org> commit 91e6dad7494421c764c2fd701931f7053f15bda1 Author: Günther Deschner <g...@samba.org> Date: Fri Nov 21 23:48:45 2008 +0100 s3-dssync-passdb: add basic routines and net function. Guenther commit 1c1aebae827d68feb5a94247787e97c9f4ba43a3 Author: Stefan Metzmacher <me...@samba.org> Date: Tue Jan 4 13:02:35 2011 +0100 s3:net: make some net_rpc_samsync.c functions static metze commit 0313969aed6b6a5c7d75a3ec92b1797362a99046 Author: Stefan Metzmacher <me...@samba.org> Date: Tue Jan 4 08:50:20 2011 +0100 s3:net: "net rpc vampire" is an alias for "net rpc vampire passdb" The should use exactly the same code path for both. metze commit bf7a27c3975c3822e0de8ff15730e6d6d1f46457 Author: Stefan Metzmacher <me...@samba.org> Date: Thu Jan 13 17:18:24 2011 +0100 s3:libnet: add 'process_links' to dssync_ops This allows the backend to handle linked attributes. metze commit cecf54b32bf15b0e05af899ab12f06f110dd45ec Author: Stefan Metzmacher <me...@samba.org> Date: Fri Jan 21 11:55:10 2011 +0100 s3:groupdb: allow machine accounts as members. metze commit 255f2e06991aa543cd2c6f4d0123664b2a76c99d Author: Stefan Metzmacher <me...@samba.org> Date: Tue Feb 1 18:46:57 2011 +0100 s3:winbindd: catch lookup_names/sids schannel errors over ncacn_ip_tcp (bug #7944) If winbindd connects to a domain controller it doesn't establish the lsa connection over ncacn_ip_tcp direct. This happens only on demand. If someone does a 'net rpc testjoin' and then a wbinfo -n DOMAIN\\administrator, we'll get DCERPC faults with ACCESS_DENIED/SEC_PKG_ERROR, because winbindd's in memory copy of the schannel session key is invalidated. This problem can also happen on other calls, but the lookup_names/sids calls on thet lsa ncacn_ip_tcp connection are the most important ones. The long term fix is to store the schannel client state in a tdb, but for now it's enough to catch the error and invalidate the all connections to the dc and reestablish the schannel session key. The fix for bug 7568 (commit be396411a4e1f3a174f8a44b6c062d834135e70a) made this worse, as it assumes winbindd's in memory session key is always the current one. metze ----------------------------------------------------------------------- Summary of changes: source3/Makefile.in | 1 + source3/groupdb/mapping.c | 8 +- source3/libnet/libnet_dssync.c | 22 + source3/libnet/libnet_dssync.h | 6 + source3/libnet/libnet_dssync_passdb.c | 1880 +++++++++++++++++++++++++++++++++ source3/utils/net_proto.h | 24 - source3/utils/net_rpc.c | 5 +- source3/utils/net_rpc_samsync.c | 146 +++- source3/winbindd/winbindd_msrpc.c | 28 + 9 files changed, 2062 insertions(+), 58 deletions(-) create mode 100644 source3/libnet/libnet_dssync_passdb.c Changeset truncated at 500 lines: diff --git a/source3/Makefile.in b/source3/Makefile.in index 7e07435..b891dcd 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -1123,6 +1123,7 @@ LIBNET_OBJ = libnet/libnet_join.o \ librpc/gen_ndr/ndr_libnet_join.o LIBNET_DSSYNC_OBJ = libnet/libnet_dssync.o \ + libnet/libnet_dssync_passdb.o \ libnet/libnet_dssync_keytab.o \ ../libcli/drsuapi/repl_decrypt.o diff --git a/source3/groupdb/mapping.c b/source3/groupdb/mapping.c index 0c6da8c..837f84a 100644 --- a/source3/groupdb/mapping.c +++ b/source3/groupdb/mapping.c @@ -324,8 +324,8 @@ int smb_add_user_group(const char *unix_group, const char *unix_user) if (!add_script) { return -1; } - add_script = talloc_string_sub(ctx, - add_script, "%u", unix_user); + add_script = talloc_string_sub2(ctx, + add_script, "%u", unix_user, true, false, true); if (!add_script) { return -1; } @@ -364,8 +364,8 @@ int smb_delete_user_group(const char *unix_group, const char *unix_user) if (!del_script) { return -1; } - del_script = talloc_string_sub(ctx, - del_script, "%u", unix_user); + del_script = talloc_string_sub2(ctx, + del_script, "%u", unix_user, true, false, true); if (!del_script) { return -1; } diff --git a/source3/libnet/libnet_dssync.c b/source3/libnet/libnet_dssync.c index 3aed8b6..64a4df0 100644 --- a/source3/libnet/libnet_dssync.c +++ b/source3/libnet/libnet_dssync.c @@ -451,6 +451,8 @@ static NTSTATUS libnet_dssync_getncchanges(TALLOC_CTX *mem_ctx, for (y=0, last_query = false; !last_query; y++) { struct drsuapi_DsReplicaObjectListItemEx *first_object = NULL; struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr = NULL; + uint32_t linked_attributes_count = 0; + struct drsuapi_DsReplicaLinkedAttribute *linked_attributes = NULL; if (level == 8) { DEBUG(1,("start[%d] tmp_higest_usn: %llu , highest_usn: %llu\n",y, @@ -537,6 +539,9 @@ static NTSTATUS libnet_dssync_getncchanges(TALLOC_CTX *mem_ctx, first_object = ctr6->first_object; mapping_ctr = &ctr6->mapping_ctr; + linked_attributes = ctr6->linked_attributes; + linked_attributes_count = ctr6->linked_attributes_count; + if (ctr6->more_data) { req->req8.highwatermark = ctr6->new_highwatermark; } else { @@ -576,6 +581,23 @@ static NTSTATUS libnet_dssync_getncchanges(TALLOC_CTX *mem_ctx, goto out; } } + + if (linked_attributes_count == 0) { + continue; + } + + if (ctx->ops->process_links) { + status = ctx->ops->process_links(ctx, mem_ctx, + linked_attributes_count, + linked_attributes, + mapping_ctr); + if (!NT_STATUS_IS_OK(status)) { + ctx->error_message = talloc_asprintf(ctx, + "Failed to call processing function: %s", + nt_errstr(status)); + goto out; + } + } } *pnew_utdv = new_utdv; diff --git a/source3/libnet/libnet_dssync.h b/source3/libnet/libnet_dssync.h index 91f48f5..d426d8b 100644 --- a/source3/libnet/libnet_dssync.h +++ b/source3/libnet/libnet_dssync.h @@ -30,6 +30,11 @@ struct dssync_ops { TALLOC_CTX *mem_ctx, struct drsuapi_DsReplicaObjectListItemEx *objects, struct drsuapi_DsReplicaOIDMapping_Ctr *mappings); + NTSTATUS (*process_links)(struct dssync_context *ctx, + TALLOC_CTX *mem_ctx, + uint32_t count, + struct drsuapi_DsReplicaLinkedAttribute *links, + struct drsuapi_DsReplicaOIDMapping_Ctr *mappings); NTSTATUS (*finish)(struct dssync_context *ctx, TALLOC_CTX *mem_ctx, struct replUpToDateVectorBlob *new_utdv); }; @@ -58,6 +63,7 @@ struct dssync_context { }; extern const struct dssync_ops libnet_dssync_keytab_ops; +extern const struct dssync_ops libnet_dssync_passdb_ops; /* The following definitions come from libnet/libnet_dssync.c */ diff --git a/source3/libnet/libnet_dssync_passdb.c b/source3/libnet/libnet_dssync_passdb.c new file mode 100644 index 0000000..585428a --- /dev/null +++ b/source3/libnet/libnet_dssync_passdb.c @@ -0,0 +1,1880 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Guenther Deschner <g...@samba.org> 2008 + + 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 "libnet/libnet_dssync.h" +#include "libnet/libnet_samsync.h" +#include "../libcli/security/security.h" +#include "../libds/common/flags.h" +#include "../librpc/gen_ndr/ndr_drsuapi.h" +#include "dbwrap.h" + +/**************************************************************** +****************************************************************/ + +struct dssync_passdb { + struct pdb_methods *methods; + struct db_context *all; + struct db_context *aliases; + struct db_context *groups; +}; + +struct dssync_passdb_obj { + struct dssync_passdb_obj *self; + uint32_t type; + struct drsuapi_DsReplicaObjectListItemEx *cur; + TDB_DATA key; + TDB_DATA data; + struct db_context *members; +}; + +struct dssync_passdb_mem { + struct dssync_passdb_mem *self; + bool active; + struct drsuapi_DsReplicaObjectIdentifier3 *cur; + struct dssync_passdb_obj *obj; + TDB_DATA key; + TDB_DATA data; +}; + +static NTSTATUS dssync_insert_obj(struct dssync_passdb *pctx, + struct db_context *db, + struct dssync_passdb_obj *obj) +{ + NTSTATUS status; + struct db_record *rec; + + rec = db->fetch_locked(db, talloc_tos(), obj->key); + if (rec == NULL) { + return NT_STATUS_NO_MEMORY; + } + if (rec->value.dsize != 0) { + abort(); + } + + status = rec->store(rec, obj->data, TDB_INSERT); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(rec); + return status; + } + TALLOC_FREE(rec); + return NT_STATUS_OK; +} + +static struct dssync_passdb_obj *dssync_parse_obj(const TDB_DATA data) +{ + struct dssync_passdb_obj *obj; + + if (data.dsize != sizeof(obj)) { + return NULL; + } + + /* + * we need to copy the pointer to avoid alignment problems + * on some systems. + */ + memcpy(&obj, data.dptr, sizeof(obj)); + + return talloc_get_type_abort(obj, struct dssync_passdb_obj); +} + +static struct dssync_passdb_obj *dssync_search_obj_by_guid(struct dssync_passdb *pctx, + struct db_context *db, + const struct GUID *guid) +{ + struct dssync_passdb_obj *obj; + int ret; + TDB_DATA key; + TDB_DATA data; + + key = make_tdb_data((const uint8_t *)(void *)guid, + sizeof(*guid)); + + ret = db->fetch(db, talloc_tos(), key, &data); + if (ret != 0) { + return NULL; + } + + obj = dssync_parse_obj(data); + return obj; +} + +static NTSTATUS dssync_create_obj(struct dssync_passdb *pctx, + struct db_context *db, + uint32_t type, + struct drsuapi_DsReplicaObjectListItemEx *cur, + struct dssync_passdb_obj **_obj) +{ + NTSTATUS status; + struct dssync_passdb_obj *obj; + + obj = talloc_zero(pctx, struct dssync_passdb_obj); + if (obj == NULL) { + return NT_STATUS_NO_MEMORY; + } + obj->self = obj; + obj->cur = cur; + obj->type = type; + obj->key = make_tdb_data((const uint8_t *)(void *)&cur->object.identifier->guid, + sizeof(cur->object.identifier->guid)); + obj->data = make_tdb_data((const uint8_t *)(void *)&obj->self, + sizeof(obj->self)); + + obj->members = db_open_rbt(obj); + if (obj->members == NULL) { + return NT_STATUS_NO_MEMORY; + } + + status = dssync_insert_obj(pctx, db, obj); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(obj); + return status; + } + *_obj = obj; + return NT_STATUS_OK; +} + +static NTSTATUS dssync_insert_mem(struct dssync_passdb *pctx, + struct dssync_passdb_obj *obj, + struct dssync_passdb_mem *mem) +{ + NTSTATUS status; + struct db_record *rec; + + rec = obj->members->fetch_locked(obj->members, talloc_tos(), mem->key); + if (rec == NULL) { + return NT_STATUS_NO_MEMORY; + } + if (rec->value.dsize != 0) { + abort(); + } + + status = rec->store(rec, mem->data, TDB_INSERT); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(rec); + return status; + } + TALLOC_FREE(rec); + return NT_STATUS_OK; +} + +static NTSTATUS dssync_create_mem(struct dssync_passdb *pctx, + struct dssync_passdb_obj *obj, + bool active, + struct drsuapi_DsReplicaObjectIdentifier3 *cur, + struct dssync_passdb_mem **_mem) +{ + NTSTATUS status; + struct dssync_passdb_mem *mem; + + mem = talloc_zero(pctx, struct dssync_passdb_mem); + if (mem == NULL) { + return NT_STATUS_NO_MEMORY; + } + mem->self = mem; + mem->cur = cur; + mem->active = active; + mem->obj = NULL; + mem->key = make_tdb_data((const uint8_t *)(void *)&cur->guid, + sizeof(cur->guid)); + mem->data = make_tdb_data((const uint8_t *)(void *)&mem->self, + sizeof(mem->self)); + + status = dssync_insert_mem(pctx, obj, mem); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(obj); + return status; + } + *_mem = mem; + return NT_STATUS_OK; +} + +static struct dssync_passdb_mem *dssync_parse_mem(const TDB_DATA data) +{ + struct dssync_passdb_mem *mem; + + if (data.dsize != sizeof(mem)) { + return NULL; + } + + /* + * we need to copy the pointer to avoid alignment problems + * on some systems. + */ + memcpy(&mem, data.dptr, sizeof(mem)); + + return talloc_get_type_abort(mem, struct dssync_passdb_mem); +} + +static NTSTATUS passdb_startup(struct dssync_context *ctx, TALLOC_CTX *mem_ctx, + struct replUpToDateVectorBlob **pold_utdv) +{ + NTSTATUS status; + struct dssync_passdb *pctx; + + pctx = talloc_zero(mem_ctx, struct dssync_passdb); + if (pctx == NULL) { + return NT_STATUS_NO_MEMORY; + } + + if (ctx->output_filename) { + status = make_pdb_method_name(&pctx->methods, ctx->output_filename); + } else { + status = make_pdb_method_name(&pctx->methods, lp_passdb_backend()); + } + + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + pctx->all = db_open_rbt(pctx); + if (pctx->all == NULL) { + return NT_STATUS_NO_MEMORY; + } + pctx->aliases = db_open_rbt(pctx); + if (pctx->aliases == NULL) { + return NT_STATUS_NO_MEMORY; + } + pctx->groups = db_open_rbt(pctx); + if (pctx->groups == NULL) { + return NT_STATUS_NO_MEMORY; + } + + ctx->private_data = pctx; + + return status; +} + +/**************************************************************** +****************************************************************/ + +struct dssync_passdb_traverse_amembers { + struct dssync_context *ctx; + struct dssync_passdb_obj *obj; + const char *name; + uint32_t idx; +}; + +struct dssync_passdb_traverse_aliases { + struct dssync_context *ctx; + const char *name; + uint32_t idx; +}; + +static int dssync_passdb_traverse_amembers(struct db_record *rec, + void *private_data) +{ + struct dssync_passdb_traverse_amembers *state = + (struct dssync_passdb_traverse_amembers *)private_data; + struct dssync_passdb *pctx = + talloc_get_type_abort(state->ctx->private_data, + struct dssync_passdb); + struct dssync_passdb_mem *mem; + NTSTATUS status; + struct dom_sid alias_sid; + struct dom_sid member_sid; + const char *member_dn; + size_t num_members; + size_t i; + struct dom_sid *members; + bool is_member = false; + const char *action; + + state->idx++; + + alias_sid = state->obj->cur->object.identifier->sid; + + mem = dssync_parse_mem(rec->value); + if (mem == NULL) { + return -1; + } + + member_sid = mem->cur->sid; + member_dn = mem->cur->dn; + + mem->obj = dssync_search_obj_by_guid(pctx, pctx->all, &mem->cur->guid); + if (mem->obj == NULL) { + DEBUG(0,("alias[%s] member[%s] can't resolve member - ignoring\n", + sid_string_dbg(&alias_sid), + is_null_sid(&member_sid)? + sid_string_dbg(&member_sid): + member_dn)); + return 0; + } + + switch (mem->obj->type) { + case ATYPE_DISTRIBUTION_LOCAL_GROUP: + case ATYPE_DISTRIBUTION_GLOBAL_GROUP: + DEBUG(0, ("alias[%s] ignore distribution group [%s]\n", + sid_string_dbg(&alias_sid), + member_dn)); + return 0; + default: + break; + } + + DEBUG(0,("alias[%s] member[%s]\n", + sid_string_dbg(&alias_sid), + sid_string_dbg(&member_sid))); + + status = pdb_enum_aliasmem(&alias_sid, talloc_tos(), + &members, &num_members); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("Could not find current alias members %s - %s\n", + sid_string_dbg(&alias_sid), + nt_errstr(status))); + return -1; + } + + for (i=0; i < num_members; i++) { + bool match; + + match = dom_sid_equal(&members[i], &member_sid); + if (match) { + is_member = true; + break; + } + } + + status = NT_STATUS_OK; + action = "none"; + if (!is_member && mem->active) { + action = "add"; + pdb_add_aliasmem(&alias_sid, &member_sid); + } else if (is_member && !mem->active) { + action = "delete"; + pdb_del_aliasmem(&alias_sid, &member_sid); + } + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("Could not %s %s as alias members of %s - %s\n", + action, + sid_string_dbg(&member_sid), + sid_string_dbg(&alias_sid), + nt_errstr(status))); + return -1; + } + + return 0; +} + +static int dssync_passdb_traverse_aliases(struct db_record *rec, + void *private_data) +{ + struct dssync_passdb_traverse_aliases *state = + (struct dssync_passdb_traverse_aliases *)private_data; + struct dssync_passdb *pctx = + talloc_get_type_abort(state->ctx->private_data, + struct dssync_passdb); + struct dssync_passdb_traverse_amembers mstate; + struct dssync_passdb_obj *obj; -- Samba Shared Repository