X-Git-Url: http://git.samba.org/?a=blobdiff_plain;f=source4%2Flibnet%2Flibnet_samsync_ldb.c;h=10e5a34da462591816decb0066678542173a8218;hb=bfce9690bf6e6592d32dd41642a33cbe3c027b81;hp=da4e777a153fa29538941cc616119462a621956b;hpb=b15582ed816f3d477f978976f43b82cfa90bf6dc;p=obnox%2Fsamba%2Fsamba-obnox.git diff --git a/source4/libnet/libnet_samsync_ldb.c b/source4/libnet/libnet_samsync_ldb.c index da4e777a153..10e5a34da46 100644 --- a/source4/libnet/libnet_samsync_ldb.c +++ b/source4/libnet/libnet_samsync_ldb.c @@ -9,7 +9,7 @@ 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 2 of the License, or + 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, @@ -18,16 +18,20 @@ 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + along with this program. If not, see . */ #include "includes.h" #include "libnet/libnet.h" -#include "libcli/ldap/ldap.h" +#include "libcli/ldap/ldap_ndr.h" #include "dsdb/samdb/samdb.h" #include "auth/auth.h" +#include "../lib/util/util_ldb.h" +#include "librpc/gen_ndr/ndr_misc.h" +#include "ldb_wrap.h" +#include "libcli/security/security.h" +#include "param/param.h" struct samsync_ldb_secret { struct samsync_ldb_secret *prev, *next; @@ -44,17 +48,23 @@ struct samsync_ldb_trusted_domain { struct samsync_ldb_state { /* Values from the LSA lookup */ - const char *domain_name; - const struct dom_sid *domain_sid; - const char *realm; + const struct libnet_SamSync_state *samsync_state; struct dom_sid *dom_sid[3]; - struct ldb_context *sam_ldb, *remote_ldb; + struct ldb_context *sam_ldb, *remote_ldb, *pdb; struct ldb_dn *base_dn[3]; struct samsync_ldb_secret *secrets; struct samsync_ldb_trusted_domain *trusted_domains; }; +/* This wrapper is needed for the "ADD_OR_DEL" macros */ +static 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) +{ + return ldb_msg_add_string(msg, attr_name, str); +} + static NTSTATUS samsync_ldb_add_foreignSecurityPrincipal(TALLOC_CTX *mem_ctx, struct samsync_ldb_state *state, struct dom_sid *sid, @@ -77,7 +87,7 @@ static NTSTATUS samsync_ldb_add_foreignSecurityPrincipal(TALLOC_CTX *mem_ctx, *error_string = talloc_asprintf(mem_ctx, "Failed to find DN for " "ForeignSecurityPrincipal container under %s", - ldb_dn_linearize(mem_ctx, state->base_dn[SAM_DATABASE_DOMAIN])); + ldb_dn_get_linearized(state->base_dn[SAM_DATABASE_DOMAIN])); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -87,22 +97,20 @@ static NTSTATUS samsync_ldb_add_foreignSecurityPrincipal(TALLOC_CTX *mem_ctx, } /* add core elements to the ldb_message for the alias */ - msg->dn = ldb_dn_build_child(mem_ctx, "CN", sidstr, basedn); - if (msg->dn == NULL) - return NT_STATUS_NO_MEMORY; + msg->dn = basedn; + if ( ! ldb_dn_add_child_fmt(msg->dn, "CN=%s", sidstr)) + return NT_STATUS_UNSUCCESSFUL; - samdb_msg_add_string(state->sam_ldb, mem_ctx, msg, - "objectClass", - "foreignSecurityPrincipal"); + ldb_msg_add_string(msg, "objectClass", "foreignSecurityPrincipal"); *fsp_dn = msg->dn; /* create the alias */ - ret = samdb_add(state->sam_ldb, mem_ctx, msg); - if (ret != 0) { + ret = ldb_add(state->sam_ldb, msg); + if (ret != LDB_SUCCESS) { *error_string = talloc_asprintf(mem_ctx, "Failed to create foreignSecurityPrincipal " "record %s: %s", - ldb_dn_linearize(mem_ctx, msg->dn), + ldb_dn_get_linearized(msg->dn), ldb_errstring(state->sam_ldb)); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -120,12 +128,20 @@ static NTSTATUS samsync_ldb_handle_domain(TALLOC_CTX *mem_ctx, struct ldb_message *msg; int ret; + msg = ldb_msg_new(mem_ctx); + if (msg == NULL) { + return NT_STATUS_NO_MEMORY; + } + if (database == SAM_DATABASE_DOMAIN) { + struct ldb_dn *partitions_basedn; const char *domain_attrs[] = {"nETBIOSName", "nCName", NULL}; struct ldb_message **msgs_domain; int ret_domain; - ret_domain = gendb_search(state->sam_ldb, mem_ctx, NULL, &msgs_domain, domain_attrs, + partitions_basedn = samdb_partitions_dn(state->sam_ldb, mem_ctx); + + ret_domain = gendb_search(state->sam_ldb, mem_ctx, partitions_basedn, &msgs_domain, domain_attrs, "(&(&(nETBIOSName=%s)(objectclass=crossRef))(ncName=*))", domain_name); if (ret_domain == -1) { @@ -139,39 +155,65 @@ static NTSTATUS samsync_ldb_handle_domain(TALLOC_CTX *mem_ctx, return NT_STATUS_NO_SUCH_DOMAIN; } - state->base_dn[database] = samdb_result_dn(state, msgs_domain[0], "nCName", NULL); - - if (state->domain_sid) { - state->dom_sid[database] = dom_sid_dup(state, state->domain_sid); + state->base_dn[database] = samdb_result_dn(state->sam_ldb, state, msgs_domain[0], "nCName", NULL); + + if (state->dom_sid[database]) { + /* Update the domain sid with the incoming + * domain (found on LSA pipe, database sid may + * be random) */ + ret = samdb_msg_add_dom_sid(state->sam_ldb, + mem_ctx, + msg, + "objectSid", + state->dom_sid[database]); + if (ret != LDB_SUCCESS) { + return NT_STATUS_INTERNAL_ERROR; + } } else { + /* Well, we will have to use the one from the database */ state->dom_sid[database] = samdb_search_dom_sid(state->sam_ldb, state, state->base_dn[database], "objectSid", NULL); + if (state->dom_sid[database] == NULL) { + return NT_STATUS_INTERNAL_ERROR; + } + } + + if (state->samsync_state->domain_guid) { + struct ldb_val v; + NTSTATUS status; + status = GUID_to_ndr_blob(state->samsync_state->domain_guid, msg, &v); + if (!NT_STATUS_IS_OK(status)) { + *error_string = talloc_asprintf(mem_ctx, "ndr_push of domain GUID failed!"); + return status; + } + + ret = ldb_msg_add_value(msg, "objectGUID", &v, NULL); + if (ret != LDB_SUCCESS) { + return NT_STATUS_INTERNAL_ERROR; + } } } else if (database == SAM_DATABASE_BUILTIN) { /* work out the builtin_dn - useful for so many calls its worth fetching here */ const char *dnstring = samdb_search_string(state->sam_ldb, mem_ctx, NULL, "distinguishedName", "objectClass=builtinDomain"); - state->base_dn[database] = ldb_dn_explode(state, dnstring); - state->dom_sid[database] = dom_sid_parse_talloc(state, SID_BUILTIN); + state->base_dn[database] = ldb_dn_new(state, state->sam_ldb, dnstring); + if ( ! ldb_dn_validate(state->base_dn[database])) { + return NT_STATUS_INTERNAL_ERROR; + } } else { /* PRIVs DB */ return NT_STATUS_INVALID_PARAMETER; } - msg = ldb_msg_new(mem_ctx); - if (msg == NULL) { - return NT_STATUS_NO_MEMORY; - } - msg->dn = talloc_reference(mem_ctx, state->base_dn[database]); if (!msg->dn) { return NT_STATUS_NO_MEMORY; } - samdb_msg_add_string(state->sam_ldb, mem_ctx, - msg, "oEMInformation", domain->comment.string); + ldb_msg_add_string(msg, "oEMInformation", + domain->oem_information.string); samdb_msg_add_int64(state->sam_ldb, mem_ctx, msg, "forceLogoff", domain->force_logoff_time); @@ -195,16 +237,15 @@ static NTSTATUS samsync_ldb_handle_domain(TALLOC_CTX *mem_ctx, samdb_msg_add_uint64(state->sam_ldb, mem_ctx, msg, "creationTime", domain->domain_create_time); - /* Update the domain sid with the incoming domain */ - samdb_msg_add_dom_sid(state->sam_ldb, mem_ctx, - msg, "objectSid", state->dom_sid[database]); - /* TODO: Account lockout, password properties */ - ret = samdb_replace(state->sam_ldb, mem_ctx, msg); - - if (ret) { - return NT_STATUS_INTERNAL_ERROR; + ret = dsdb_replace(state->sam_ldb, msg, 0); + if (ret != LDB_SUCCESS) { + *error_string = talloc_asprintf(mem_ctx, + "Failed to modify domain record %s: %s", + ldb_dn_get_linearized(msg->dn), + ldb_errstring(state->sam_ldb)); + return NT_STATUS_INTERNAL_DB_CORRUPTION; } return NT_STATUS_OK; } @@ -223,14 +264,15 @@ static NTSTATUS samsync_ldb_handle_user(TALLOC_CTX *mem_ctx, const struct dom_sid *user_sid; struct ldb_message *msg; struct ldb_message **msgs; - struct ldb_message **remote_msgs; - int ret, i; + struct ldb_message **remote_msgs = NULL; + unsigned int i; + int ret; uint32_t acb; - BOOL add = False; + bool add = false; const char *attrs[] = { NULL }; /* we may change this to a global search, then fill in only the things not in ldap later */ const char *remote_attrs[] = { "userPrincipalName", "servicePrincipalName", - "msDS-KeyVersionNumber", NULL}; + "msDS-KeyVersionNumber", "objectGUID", NULL}; user_sid = dom_sid_add_rid(mem_ctx, state->dom_sid[database], rid); if (!user_sid) { @@ -242,6 +284,7 @@ static NTSTATUS samsync_ldb_handle_user(TALLOC_CTX *mem_ctx, return NT_STATUS_NO_MEMORY; } + msg->dn = NULL; /* search for the user, by rid */ ret = gendb_search(state->sam_ldb, mem_ctx, state->base_dn[database], &msgs, attrs, "(&(objectClass=user)(objectSid=%s))", @@ -253,7 +296,7 @@ static NTSTATUS samsync_ldb_handle_user(TALLOC_CTX *mem_ctx, ldb_errstring(state->sam_ldb)); return NT_STATUS_INTERNAL_DB_CORRUPTION; } else if (ret == 0) { - add = True; + add = true; } else if (ret > 1) { *error_string = talloc_asprintf(mem_ctx, "More than one user with SID: %s in local LDB", dom_sid_string(mem_ctx, user_sid)); @@ -264,29 +307,30 @@ static NTSTATUS samsync_ldb_handle_user(TALLOC_CTX *mem_ctx, } /* and do the same on the remote database */ - ret = gendb_search(state->remote_ldb, mem_ctx, state->base_dn[database], - &remote_msgs, remote_attrs, "(&(objectClass=user)(objectSid=%s))", - ldap_encode_ndr_dom_sid(mem_ctx, user_sid)); - - if (ret == -1) { - *error_string = talloc_asprintf(mem_ctx, "remote LDAP for user %s failed: %s", - dom_sid_string(mem_ctx, user_sid), - ldb_errstring(state->remote_ldb)); - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } else if (ret == 0) { - *error_string = talloc_asprintf(mem_ctx, "User exists in samsync but not in remote LDAP domain! (base: %s, SID: %s)", - ldb_dn_linearize(mem_ctx, state->base_dn[database]), - dom_sid_string(mem_ctx, user_sid)); - return NT_STATUS_NO_SUCH_USER; - } else if (ret > 1) { - *error_string = talloc_asprintf(mem_ctx, "More than one user in remote LDAP domain with SID: %s", - dom_sid_string(mem_ctx, user_sid)); - return NT_STATUS_INTERNAL_DB_CORRUPTION; - - /* Try to put things in the same location as the remote server */ - } else if (add) { - msg->dn = remote_msgs[0]->dn; - talloc_steal(msg, remote_msgs[0]->dn); + if (state->remote_ldb) { + ret = gendb_search(state->remote_ldb, mem_ctx, state->base_dn[database], + &remote_msgs, remote_attrs, "(&(objectClass=user)(objectSid=%s))", + ldap_encode_ndr_dom_sid(mem_ctx, user_sid)); + + if (ret == -1) { + *error_string = talloc_asprintf(mem_ctx, "remote LDAP for user %s failed: %s", + dom_sid_string(mem_ctx, user_sid), + ldb_errstring(state->remote_ldb)); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } else if (ret == 0) { + *error_string = talloc_asprintf(mem_ctx, "User exists in samsync but not in remote LDAP domain! (base: %s, SID: %s)", + ldb_dn_get_linearized(state->base_dn[database]), + dom_sid_string(mem_ctx, user_sid)); + return NT_STATUS_NO_SUCH_USER; + } else if (ret > 1) { + *error_string = talloc_asprintf(mem_ctx, "More than one user in remote LDAP domain with SID: %s", + dom_sid_string(mem_ctx, user_sid)); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + + /* Try to put things in the same location as the remote server */ + } else if (add) { + msg->dn = talloc_steal(msg, remote_msgs[0]->dn); + } } cn_name = talloc_strdup(mem_ctx, user->account_name.string); @@ -336,27 +380,27 @@ static NTSTATUS samsync_ldb_handle_user(TALLOC_CTX *mem_ctx, return NT_STATUS_NO_MEMORY; } - /* Passwords. Ensure there is no plaintext stored against - * this entry, as we only have hashes */ - samdb_msg_add_delete(state->sam_ldb, mem_ctx, msg, - "sambaPassword"); if (user->lm_password_present) { samdb_msg_add_hash(state->sam_ldb, mem_ctx, msg, - "lmPwdHash", &user->lmpassword); - } else { + "dBCSPwd", &user->lmpassword); + } else if (!add) { samdb_msg_add_delete(state->sam_ldb, mem_ctx, msg, - "lmPwdHash"); + "dBCSPwd"); } if (user->nt_password_present) { samdb_msg_add_hash(state->sam_ldb, mem_ctx, msg, - "ntPwdHash", &user->ntpassword); - } else { + "unicodePwd", &user->ntpassword); + } else if (!add) { samdb_msg_add_delete(state->sam_ldb, mem_ctx, msg, - "ntPwdHash"); + "unicodePwd"); } ADD_OR_DEL(string, "comment", comment.string); - ADD_OR_DEL(string, "userParameters", parameters.string); + + if (samdb_msg_add_parameters(state->sam_ldb, mem_ctx, msg, "userParameters", &user->parameters) != 0) { + return NT_STATUS_NO_MEMORY; + } + ADD_OR_DEL(uint, "countryCode", country_code); ADD_OR_DEL(uint, "codePage", code_page); @@ -392,33 +436,41 @@ static NTSTATUS samsync_ldb_handle_user(TALLOC_CTX *mem_ctx, obj_class = "user"; } if (add) { - samdb_msg_add_string(state->sam_ldb, mem_ctx, msg, - "objectClass", obj_class); - msg->dn = ldb_dn_string_compose(mem_ctx, state->base_dn[database], - "CN=%s, CN=%s", cn_name, container); + ldb_msg_add_string(msg, "objectClass", obj_class); if (!msg->dn) { - return NT_STATUS_NO_MEMORY; + msg->dn = ldb_dn_copy(mem_ctx, state->base_dn[database]); + ldb_dn_add_child_fmt(msg->dn, "CN=%s,CN=%s", cn_name, container); + if (!msg->dn) { + return NT_STATUS_NO_MEMORY; + } } - ret = samdb_add(state->sam_ldb, mem_ctx, msg); - if (ret != 0) { + ret = ldb_add(state->sam_ldb, msg); + if (ret != LDB_SUCCESS) { struct ldb_dn *first_try_dn = msg->dn; /* Try again with the default DN */ - msg->dn = talloc_steal(msg, msgs[0]->dn); - ret = samdb_add(state->sam_ldb, mem_ctx, msg); - if (ret != 0) { - *error_string = talloc_asprintf(mem_ctx, "Failed to create user record. Tried both %s and %s: %s", - ldb_dn_linearize(mem_ctx, first_try_dn), - ldb_dn_linearize(mem_ctx, msg->dn), + if (!remote_msgs) { + *error_string = talloc_asprintf(mem_ctx, "Failed to create user record. Tried %s: %s", + ldb_dn_get_linearized(first_try_dn), ldb_errstring(state->sam_ldb)); return NT_STATUS_INTERNAL_DB_CORRUPTION; + } else { + msg->dn = talloc_steal(msg, remote_msgs[0]->dn); + ret = ldb_add(state->sam_ldb, msg); + if (ret != LDB_SUCCESS) { + *error_string = talloc_asprintf(mem_ctx, "Failed to create user record. Tried both %s and %s: %s", + ldb_dn_get_linearized(first_try_dn), + ldb_dn_get_linearized(msg->dn), + ldb_errstring(state->sam_ldb)); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } } } } else { - ret = samdb_replace(state->sam_ldb, mem_ctx, msg); - if (ret != 0) { + ret = dsdb_replace(state->sam_ldb, msg, 0); + if (ret != LDB_SUCCESS) { *error_string = talloc_asprintf(mem_ctx, "Failed to modify user record %s: %s", - ldb_dn_linearize(mem_ctx, msg->dn), + ldb_dn_get_linearized(msg->dn), ldb_errstring(state->sam_ldb)); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -457,10 +509,10 @@ static NTSTATUS samsync_ldb_delete_user(TALLOC_CTX *mem_ctx, return NT_STATUS_INTERNAL_DB_CORRUPTION; } - ret = samdb_delete(state->sam_ldb, mem_ctx, msgs[0]->dn); - if (ret != 0) { + ret = ldb_delete(state->sam_ldb, msgs[0]->dn); + if (ret != LDB_SUCCESS) { *error_string = talloc_asprintf(mem_ctx, "Failed to delete user record %s: %s", - ldb_dn_linearize(mem_ctx, msgs[0]->dn), + ldb_dn_get_linearized(msgs[0]->dn), ldb_errstring(state->sam_ldb)); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -482,7 +534,7 @@ static NTSTATUS samsync_ldb_handle_group(TALLOC_CTX *mem_ctx, struct ldb_message *msg; struct ldb_message **msgs; int ret; - BOOL add = False; + bool add = false; const char *attrs[] = { NULL }; msg = ldb_msg_new(mem_ctx); @@ -499,7 +551,7 @@ static NTSTATUS samsync_ldb_handle_group(TALLOC_CTX *mem_ctx, *error_string = talloc_asprintf(mem_ctx, "gendb_search failed: %s", ldb_errstring(state->sam_ldb)); return NT_STATUS_INTERNAL_DB_CORRUPTION; } else if (ret == 0) { - add = True; + add = true; } else if (ret > 1) { *error_string = talloc_asprintf(mem_ctx, "More than one group/alias with SID: %s", dom_sid_string(mem_ctx, @@ -538,26 +590,25 @@ static NTSTATUS samsync_ldb_handle_group(TALLOC_CTX *mem_ctx, obj_class = "group"; if (add) { - samdb_msg_add_string(state->sam_ldb, mem_ctx, msg, - "objectClass", obj_class); - msg->dn = ldb_dn_string_compose(mem_ctx, state->base_dn[database], - "CN=%s, CN=%s", cn_name, container); + ldb_msg_add_string(msg, "objectClass", obj_class); + msg->dn = ldb_dn_copy(mem_ctx, state->base_dn[database]); + ldb_dn_add_child_fmt(msg->dn, "CN=%s,CN=%s", cn_name, container); if (!msg->dn) { return NT_STATUS_NO_MEMORY; } - ret = samdb_add(state->sam_ldb, mem_ctx, msg); - if (ret != 0) { + ret = ldb_add(state->sam_ldb, msg); + if (ret != LDB_SUCCESS) { *error_string = talloc_asprintf(mem_ctx, "Failed to create group record %s: %s", - ldb_dn_linearize(mem_ctx, msg->dn), + ldb_dn_get_linearized(msg->dn), ldb_errstring(state->sam_ldb)); return NT_STATUS_INTERNAL_DB_CORRUPTION; } } else { - ret = samdb_replace(state->sam_ldb, mem_ctx, msg); - if (ret != 0) { + ret = dsdb_replace(state->sam_ldb, msg, 0); + if (ret != LDB_SUCCESS) { *error_string = talloc_asprintf(mem_ctx, "Failed to modify group record %s: %s", - ldb_dn_linearize(mem_ctx, msg->dn), + ldb_dn_get_linearized(msg->dn), ldb_errstring(state->sam_ldb)); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -596,10 +647,10 @@ static NTSTATUS samsync_ldb_delete_group(TALLOC_CTX *mem_ctx, return NT_STATUS_INTERNAL_DB_CORRUPTION; } - ret = samdb_delete(state->sam_ldb, mem_ctx, msgs[0]->dn); - if (ret != 0) { + ret = ldb_delete(state->sam_ldb, msgs[0]->dn); + if (ret != LDB_SUCCESS) { *error_string = talloc_asprintf(mem_ctx, "Failed to delete group record %s: %s", - ldb_dn_linearize(mem_ctx, msgs[0]->dn), + ldb_dn_get_linearized(msgs[0]->dn), ldb_errstring(state->sam_ldb)); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -614,12 +665,13 @@ static NTSTATUS samsync_ldb_handle_group_member(TALLOC_CTX *mem_ctx, char **error_string) { uint32_t rid = delta->delta_id_union.rid; - struct netr_DELTA_GROUP_MEMBER *group_member = delta->delta_union.group_member; + struct netr_DELTA_GROUP_MEMBER *delta_group_member = delta->delta_union.group_member; struct ldb_message *msg; struct ldb_message **msgs; int ret; const char *attrs[] = { NULL }; - int i; + const char *str_dn; + uint32_t i; msg = ldb_msg_new(mem_ctx); if (msg == NULL) { @@ -649,11 +701,11 @@ static NTSTATUS samsync_ldb_handle_group_member(TALLOC_CTX *mem_ctx, talloc_free(msgs); - for (i=0; inum_rids; i++) { + for (i=0; inum_rids; i++) { /* search for the group, by rid */ ret = gendb_search(state->sam_ldb, mem_ctx, state->base_dn[database], &msgs, attrs, "(&(objectClass=user)(objectSid=%s))", - ldap_encode_ndr_dom_sid(mem_ctx, dom_sid_add_rid(mem_ctx, state->dom_sid[database], group_member->rids[i]))); + ldap_encode_ndr_dom_sid(mem_ctx, dom_sid_add_rid(mem_ctx, state->dom_sid[database], delta_group_member->rids[i]))); if (ret == -1) { *error_string = talloc_asprintf(mem_ctx, "gendb_search failed: %s", ldb_errstring(state->sam_ldb)); @@ -663,16 +715,19 @@ static NTSTATUS samsync_ldb_handle_group_member(TALLOC_CTX *mem_ctx, } else if (ret > 1) { return NT_STATUS_INTERNAL_DB_CORRUPTION; } else { - samdb_msg_add_string(state->sam_ldb, mem_ctx, msg, "member", ldb_dn_linearize(mem_ctx, msgs[0]->dn)); + str_dn = ldb_dn_alloc_linearized(msg, msgs[0]->dn); + NT_STATUS_HAVE_NO_MEMORY(str_dn); + ret = ldb_msg_add_string(msg, "member", str_dn); + if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY; } talloc_free(msgs); } - ret = samdb_replace(state->sam_ldb, mem_ctx, msg); - if (ret != 0) { + ret = dsdb_replace(state->sam_ldb, msg, 0); + if (ret != LDB_SUCCESS) { *error_string = talloc_asprintf(mem_ctx, "Failed to modify group record %s: %s", - ldb_dn_linearize(mem_ctx, msg->dn), + ldb_dn_get_linearized(msg->dn), ldb_errstring(state->sam_ldb)); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -694,7 +749,7 @@ static NTSTATUS samsync_ldb_handle_alias(TALLOC_CTX *mem_ctx, struct ldb_message *msg; struct ldb_message **msgs; int ret; - BOOL add = False; + bool add = false; const char *attrs[] = { NULL }; msg = ldb_msg_new(mem_ctx); @@ -711,7 +766,7 @@ static NTSTATUS samsync_ldb_handle_alias(TALLOC_CTX *mem_ctx, *error_string = talloc_asprintf(mem_ctx, "gendb_search failed: %s", ldb_errstring(state->sam_ldb)); return NT_STATUS_INTERNAL_DB_CORRUPTION; } else if (ret == 0) { - add = True; + add = true; } else if (ret > 1) { *error_string = talloc_asprintf(mem_ctx, "More than one group/alias with SID: %s", dom_sid_string(mem_ctx, @@ -752,26 +807,25 @@ static NTSTATUS samsync_ldb_handle_alias(TALLOC_CTX *mem_ctx, obj_class = "group"; if (add) { - samdb_msg_add_string(state->sam_ldb, mem_ctx, msg, - "objectClass", obj_class); - msg->dn = ldb_dn_string_compose(mem_ctx, state->base_dn[database], - "CN=%s, CN=%s", cn_name, container); + ldb_msg_add_string(msg, "objectClass", obj_class); + msg->dn = ldb_dn_copy(mem_ctx, state->base_dn[database]); + ldb_dn_add_child_fmt(msg->dn, "CN=%s,CN=%s", cn_name, container); if (!msg->dn) { return NT_STATUS_NO_MEMORY; } - ret = samdb_add(state->sam_ldb, mem_ctx, msg); - if (ret != 0) { + ret = ldb_add(state->sam_ldb, msg); + if (ret != LDB_SUCCESS) { *error_string = talloc_asprintf(mem_ctx, "Failed to create alias record %s: %s", - ldb_dn_linearize(mem_ctx, msg->dn), + ldb_dn_get_linearized(msg->dn), ldb_errstring(state->sam_ldb)); return NT_STATUS_INTERNAL_DB_CORRUPTION; } } else { - ret = samdb_replace(state->sam_ldb, mem_ctx, msg); - if (ret != 0) { + ret = dsdb_replace(state->sam_ldb, msg, 0); + if (ret != LDB_SUCCESS) { *error_string = talloc_asprintf(mem_ctx, "Failed to modify alias record %s: %s", - ldb_dn_linearize(mem_ctx, msg->dn), + ldb_dn_get_linearized(msg->dn), ldb_errstring(state->sam_ldb)); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -805,10 +859,10 @@ static NTSTATUS samsync_ldb_delete_alias(TALLOC_CTX *mem_ctx, return NT_STATUS_INTERNAL_DB_CORRUPTION; } - ret = samdb_delete(state->sam_ldb, mem_ctx, msgs[0]->dn); - if (ret != 0) { + ret = ldb_delete(state->sam_ldb, msgs[0]->dn); + if (ret != LDB_SUCCESS) { *error_string = talloc_asprintf(mem_ctx, "Failed to delete alias record %s: %s", - ldb_dn_linearize(mem_ctx, msgs[0]->dn), + ldb_dn_get_linearized(msgs[0]->dn), ldb_errstring(state->sam_ldb)); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -828,7 +882,7 @@ static NTSTATUS samsync_ldb_handle_alias_member(TALLOC_CTX *mem_ctx, struct ldb_message **msgs; int ret; const char *attrs[] = { NULL }; - int i; + uint32_t i; msg = ldb_msg_new(mem_ctx); if (msg == NULL) { @@ -860,6 +914,7 @@ static NTSTATUS samsync_ldb_handle_alias_member(TALLOC_CTX *mem_ctx, for (i=0; isids.num_sids; i++) { struct ldb_dn *alias_member_dn; + const char *str_dn; /* search for members, in the top basedn (normal users are builtin aliases) */ ret = gendb_search(state->sam_ldb, mem_ctx, state->base_dn[SAM_DATABASE_DOMAIN], &msgs, attrs, "(objectSid=%s)", @@ -882,15 +937,18 @@ static NTSTATUS samsync_ldb_handle_alias_member(TALLOC_CTX *mem_ctx, } else { alias_member_dn = msgs[0]->dn; } - samdb_msg_add_string(state->sam_ldb, mem_ctx, msg, "member", ldb_dn_linearize(mem_ctx, alias_member_dn)); + str_dn = ldb_dn_alloc_linearized(msg, alias_member_dn); + NT_STATUS_HAVE_NO_MEMORY(str_dn); + ret = ldb_msg_add_string(msg, "member", str_dn); + if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY; talloc_free(msgs); } - ret = samdb_replace(state->sam_ldb, mem_ctx, msg); - if (ret != 0) { + ret = dsdb_replace(state->sam_ldb, msg, 0); + if (ret != LDB_SUCCESS) { *error_string = talloc_asprintf(mem_ctx, "Failed to modify group record %s: %s", - ldb_dn_linearize(mem_ctx, msg->dn), + ldb_dn_get_linearized(msg->dn), ldb_errstring(state->sam_ldb)); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -908,53 +966,41 @@ static NTSTATUS samsync_ldb_handle_account(TALLOC_CTX *mem_ctx, struct netr_DELTA_ACCOUNT *account = delta->delta_union.account; struct ldb_message *msg; - struct ldb_message **msgs; - struct ldb_dn *privilege_dn; int ret; - const char *attrs[] = { NULL }; - int i; + uint32_t i; + char *dnstr, *sidstr; msg = ldb_msg_new(mem_ctx); if (msg == NULL) { return NT_STATUS_NO_MEMORY; } - /* search for the account, by sid, in the top basedn */ - ret = gendb_search(state->sam_ldb, mem_ctx, state->base_dn[SAM_DATABASE_DOMAIN], &msgs, attrs, - "(objectSid=%s)", ldap_encode_ndr_dom_sid(mem_ctx, sid)); + sidstr = dom_sid_string(msg, sid); + NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, msg); - if (ret == -1) { - *error_string = talloc_asprintf(mem_ctx, "gendb_search failed: %s", ldb_errstring(state->sam_ldb)); - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } else if (ret == 0) { - NTSTATUS nt_status; - nt_status = samsync_ldb_add_foreignSecurityPrincipal(mem_ctx, state, - sid, - &privilege_dn, - error_string); - privilege_dn = talloc_steal(msg, privilege_dn); - if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; - } - } else if (ret > 1) { - *error_string = talloc_asprintf(mem_ctx, "More than one account with SID: %s", - dom_sid_string(mem_ctx, sid)); - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } else { - privilege_dn = talloc_steal(msg, msgs[0]->dn); - } + dnstr = talloc_asprintf(msg, "sid=%s", sidstr); + NT_STATUS_HAVE_NO_MEMORY_AND_FREE(dnstr, msg); - msg->dn = privilege_dn; + msg->dn = ldb_dn_new(msg, state->pdb, dnstr); + NT_STATUS_HAVE_NO_MEMORY_AND_FREE(msg->dn, msg); for (i=0; i< account->privilege_entries; i++) { - samdb_msg_add_string(state->sam_ldb, mem_ctx, msg, "privilege", - account->privilege_name[i].string); + ldb_msg_add_string(msg, "privilege", account->privilege_name[i].string); + } + + ret = dsdb_replace(state->pdb, msg, 0); + if (ret == LDB_ERR_NO_SUCH_OBJECT) { + if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) { + talloc_free(msg); + return NT_STATUS_NO_MEMORY; + } + ldb_msg_add_string(msg, "comment", "added via samsync"); + ret = ldb_add(state->pdb, msg); } - ret = samdb_replace(state->sam_ldb, mem_ctx, msg); - if (ret != 0) { + if (ret != LDB_SUCCESS) { *error_string = talloc_asprintf(mem_ctx, "Failed to modify privilege record %s", - ldb_dn_linearize(mem_ctx, msg->dn)); + ldb_dn_get_linearized(msg->dn)); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -998,12 +1044,12 @@ static NTSTATUS samsync_ldb_delete_account(TALLOC_CTX *mem_ctx, } samdb_msg_add_delete(state->sam_ldb, mem_ctx, msg, - "privilage"); + "privilege"); - ret = samdb_replace(state->sam_ldb, mem_ctx, msg); - if (ret != 0) { + ret = dsdb_replace(state->sam_ldb, msg, 0); + if (ret != LDB_SUCCESS) { *error_string = talloc_asprintf(mem_ctx, "Failed to modify privilege record %s", - ldb_dn_linearize(mem_ctx, msg->dn)); + ldb_dn_get_linearized(msg->dn)); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -1011,13 +1057,13 @@ static NTSTATUS samsync_ldb_delete_account(TALLOC_CTX *mem_ctx, } static NTSTATUS libnet_samsync_ldb_fn(TALLOC_CTX *mem_ctx, - void *private, + void *private_data, enum netr_SamDatabaseID database, struct netr_DELTA_ENUM *delta, char **error_string) { NTSTATUS nt_status = NT_STATUS_OK; - struct samsync_ldb_state *state = talloc_get_type(private, struct samsync_ldb_state); + struct samsync_ldb_state *state = talloc_get_type(private_data, struct samsync_ldb_state); *error_string = NULL; switch (delta->delta_type) { @@ -1131,35 +1177,43 @@ static NTSTATUS libnet_samsync_ldb_fn(TALLOC_CTX *mem_ctx, } static NTSTATUS libnet_samsync_ldb_init(TALLOC_CTX *mem_ctx, - void *private, - struct libnet_context *machine_net_ctx, - struct dcerpc_pipe *p, - const char *domain_name, - const struct dom_sid *domain_sid, - const char *realm, + void *private_data, + struct libnet_SamSync_state *samsync_state, char **error_string) { - struct samsync_ldb_state *state = talloc_get_type(private, struct samsync_ldb_state); - const char *server = dcerpc_server_name(p); + struct samsync_ldb_state *state = talloc_get_type(private_data, struct samsync_ldb_state); + const char *server = dcerpc_server_name(samsync_state->netlogon_pipe); char *ldap_url; - state->domain_name = domain_name; - state->domain_sid = domain_sid; - state->realm = realm; + state->samsync_state = samsync_state; + + ZERO_STRUCT(state->dom_sid); + if (state->samsync_state->domain_sid) { + state->dom_sid[SAM_DATABASE_DOMAIN] = dom_sid_dup(state, state->samsync_state->domain_sid); + } + + state->dom_sid[SAM_DATABASE_BUILTIN] = dom_sid_parse_talloc(state, SID_BUILTIN); - if (realm) { + if (state->samsync_state->realm) { if (!server || !*server) { /* huh? how do we not have a server name? */ *error_string = talloc_strdup(mem_ctx, "No DCE/RPC server name available. How did we connect?"); return NT_STATUS_INVALID_PARAMETER; } - ldap_url = talloc_asprintf(state, "ldap://%s", dcerpc_server_name(p)); + ldap_url = talloc_asprintf(state, "ldap://%s", server); - state->remote_ldb = ldb_wrap_connect(mem_ctx, ldap_url, - NULL, machine_net_ctx->cred, - 0, NULL); - /* TODO: Make inquires to see if this is AD, then decide that - * the ldap connection is critical */ + state->remote_ldb = ldb_wrap_connect(mem_ctx, + NULL, + state->samsync_state->machine_net_ctx->lp_ctx, + ldap_url, + NULL, state->samsync_state->machine_net_ctx->cred, + 0); + if (!state->remote_ldb) { + *error_string = talloc_asprintf(mem_ctx, "Failed to connect to remote LDAP server at %s (used to extract additional data in SamSync replication)", ldap_url); + return NT_STATUS_NO_LOGON_SERVERS; + } + } else { + state->remote_ldb = NULL; } return NT_STATUS_OK; } @@ -1177,7 +1231,20 @@ NTSTATUS libnet_samsync_ldb(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, str state->secrets = NULL; state->trusted_domains = NULL; - state->sam_ldb = samdb_connect(state, system_session(state)); + state->sam_ldb = samdb_connect(mem_ctx, + ctx->event_ctx, + ctx->lp_ctx, + r->in.session_info, + 0); + if (!state->sam_ldb) { + return NT_STATUS_INTERNAL_DB_ERROR; + } + + state->pdb = privilege_connect(mem_ctx, + ctx->lp_ctx); + if (!state->pdb) { + return NT_STATUS_INTERNAL_DB_ERROR; + } r2.out.error_string = NULL; r2.in.binding_string = r->in.binding_string;