#include "libcli/ldap/ldap.h"
#include "dsdb/samdb/samdb.h"
#include "auth/auth.h"
+#include "librpc/gen_ndr/ndr_misc.h"
+#include "db_wrap.h"
+#include "libcli/security/security.h"
+#include "librpc/rpc/dcerpc.h"
struct samsync_ldb_secret {
struct samsync_ldb_secret *prev, *next;
};
struct samsync_ldb_state {
+ /* Values from the LSA lookup */
+ const struct libnet_SamSync_state *samsync_state;
+
struct dom_sid *dom_sid[3];
- struct ldb_context *sam_ldb;
+ struct ldb_context *sam_ldb, *remote_ldb;
struct ldb_dn *base_dn[3];
struct samsync_ldb_secret *secrets;
struct samsync_ldb_trusted_domain *trusted_domains;
static NTSTATUS samsync_ldb_add_foreignSecurityPrincipal(TALLOC_CTX *mem_ctx,
struct samsync_ldb_state *state,
struct dom_sid *sid,
- struct ldb_dn **fsp_dn)
+ struct ldb_dn **fsp_dn,
+ char **error_string)
{
const char *sidstr = dom_sid_string(mem_ctx, sid);
/* We assume that ForeignSecurityPrincipals are under the BASEDN of the main domain */
}
if (basedn == NULL) {
- DEBUG(0, ("Failed to find DN for "
- "ForeignSecurityPrincipal container\n"));
+ *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]));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
/* create the alias */
ret = samdb_add(state->sam_ldb, mem_ctx, msg);
if (ret != 0) {
- DEBUG(0,("Failed to create foreignSecurityPrincipal "
- "record %s: %s\n",
- ldb_dn_linearize(mem_ctx, msg->dn),
- ldb_errstring(state->sam_ldb)));
+ *error_string = talloc_asprintf(mem_ctx, "Failed to create foreignSecurityPrincipal "
+ "record %s: %s",
+ ldb_dn_linearize(mem_ctx, msg->dn),
+ ldb_errstring(state->sam_ldb));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
return NT_STATUS_OK;
static NTSTATUS samsync_ldb_handle_domain(TALLOC_CTX *mem_ctx,
struct samsync_ldb_state *state,
- struct creds_CredentialState *creds,
enum netr_SamDatabaseID database,
- struct netr_DELTA_ENUM *delta)
+ struct netr_DELTA_ENUM *delta,
+ char **error_string)
{
struct netr_DELTA_DOMAIN *domain = delta->delta_union.domain;
const char *domain_name = domain->domain_name.string;
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) {
const char *domain_attrs[] = {"nETBIOSName", "nCName", NULL};
struct ldb_message **msgs_domain;
"(&(&(nETBIOSName=%s)(objectclass=crossRef))(ncName=*))",
domain_name);
if (ret_domain == -1) {
+ *error_string = talloc_asprintf(mem_ctx, "gendb_search for domain failed: %s", ldb_errstring(state->sam_ldb));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
if (ret_domain != 1) {
+ *error_string = talloc_asprintf(mem_ctx, "Failed to find existing domain record for %s: %d results", domain_name,
+ ret_domain);
return NT_STATUS_NO_SUCH_DOMAIN;
}
state->base_dn[database] = samdb_result_dn(state, msgs_domain[0], "nCName", NULL);
- state->dom_sid[database] = samdb_search_dom_sid(state->sam_ldb, state,
- state->base_dn[database],
- "objectSid", NULL);
+ if (state->dom_sid[database]) {
+ /* Update the domain sid with the incoming
+ * domain (found on LSA pipe, database sid may
+ * be random) */
+ samdb_msg_add_dom_sid(state->sam_ldb, mem_ctx,
+ msg, "objectSid", state->dom_sid[database]);
+ } 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->samsync_state->domain_guid) {
+ NTSTATUS nt_status;
+ struct ldb_val v;
+ nt_status = ndr_push_struct_blob(&v, msg, state->samsync_state->domain_guid,
+ (ndr_push_flags_fn_t)ndr_push_GUID);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ *error_string = talloc_asprintf(mem_ctx, "ndr_push of domain GUID failed!");
+ return nt_status;
+ }
+
+ ldb_msg_add_value(msg, "objectGUID", &v);
+ }
} 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);
} 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;
msg, "oEMInformation", domain->comment.string);
samdb_msg_add_int64(state->sam_ldb, mem_ctx,
- msg, "forceLogoff", domain->force_logoff_time);
+ msg, "forceLogoff", domain->force_logoff_time);
samdb_msg_add_uint(state->sam_ldb, mem_ctx,
- msg, "minPwdLen", domain->min_password_length);
+ msg, "minPwdLen", domain->min_password_length);
samdb_msg_add_int64(state->sam_ldb, mem_ctx,
- msg, "maxPwdAge", domain->max_password_age);
+ msg, "maxPwdAge", domain->max_password_age);
samdb_msg_add_int64(state->sam_ldb, mem_ctx,
- msg, "minPwdAge", domain->min_password_age);
+ msg, "minPwdAge", domain->min_password_age);
samdb_msg_add_uint(state->sam_ldb, mem_ctx,
- msg, "pwdHistoryLength", domain->password_history_length);
+ msg, "pwdHistoryLength", domain->password_history_length);
samdb_msg_add_uint64(state->sam_ldb, mem_ctx,
msg, "modifiedCount",
static NTSTATUS samsync_ldb_handle_user(TALLOC_CTX *mem_ctx,
struct samsync_ldb_state *state,
- struct creds_CredentialState *creds,
enum netr_SamDatabaseID database,
- struct netr_DELTA_ENUM *delta)
+ struct netr_DELTA_ENUM *delta,
+ char **error_string)
{
uint32_t rid = delta->delta_id_union.rid;
struct netr_DELTA_USER *user = delta->delta_union.user;
const char *container, *obj_class;
char *cn_name;
int cn_name_len;
-
+ const struct dom_sid *user_sid;
struct ldb_message *msg;
struct ldb_message **msgs;
- int ret;
+ struct ldb_message **remote_msgs = NULL;
+ int ret, i;
uint32_t acb;
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", "objectGUID", NULL};
+
+ user_sid = dom_sid_add_rid(mem_ctx, state->dom_sid[database], rid);
+ if (!user_sid) {
+ return NT_STATUS_NO_MEMORY;
+ }
msg = ldb_msg_new(mem_ctx);
if (msg == NULL) {
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))",
- ldap_encode_ndr_dom_sid(mem_ctx, dom_sid_add_rid(mem_ctx, state->dom_sid[database], rid)));
+ ldap_encode_ndr_dom_sid(mem_ctx, user_sid));
if (ret == -1) {
+ *error_string = talloc_asprintf(mem_ctx, "LDB for user %s failed: %s",
+ dom_sid_string(mem_ctx, user_sid),
+ ldb_errstring(state->sam_ldb));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
} else if (ret == 0) {
add = True;
} else if (ret > 1) {
- DEBUG(0, ("More than one user with SID: %s\n",
- dom_sid_string(mem_ctx,
- dom_sid_add_rid(mem_ctx,
- state->dom_sid[database],
- rid))));
+ *error_string = talloc_asprintf(mem_ctx, "More than one user with SID: %s in local LDB",
+ dom_sid_string(mem_ctx, user_sid));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
} else {
- msg->dn = talloc_steal(msg, msgs[0]->dn);
+ msg->dn = msgs[0]->dn;
+ talloc_steal(msg, msgs[0]->dn);
}
+ /* and do the same on the remote database */
+ 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_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);
+ }
+ }
cn_name = talloc_strdup(mem_ctx, user->account_name.string);
NT_STATUS_HAVE_NO_MEMORY(cn_name);
cn_name_len = strlen(cn_name);
-#define ADD_OR_DEL(type, attrib, field) do {\
- if (user->field) { \
- samdb_msg_add_ ## type(state->sam_ldb, mem_ctx, msg, \
- attrib, user->field); \
- } else if (!add) { \
- samdb_msg_add_delete(state->sam_ldb, mem_ctx, msg, \
- attrib); \
- } \
+#define ADD_OR_DEL(type, attrib, field) do { \
+ if (user->field) { \
+ samdb_msg_add_ ## type(state->sam_ldb, mem_ctx, msg, \
+ attrib, user->field); \
+ } else if (!add) { \
+ samdb_msg_add_delete(state->sam_ldb, mem_ctx, msg, \
+ attrib); \
+ } \
} while (0);
ADD_OR_DEL(string, "samAccountName", account_name.string);
/* 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");
+ "sambaPassword");
if (user->lm_password_present) {
samdb_msg_add_hash(state->sam_ldb, mem_ctx, msg,
"lmPwdHash", &user->lmpassword);
#undef ADD_OR_DEL
+ for (i=0; remote_attrs[i]; i++) {
+ struct ldb_message_element *el = ldb_msg_find_element(remote_msgs[0], remote_attrs[i]);
+ if (!el) {
+ samdb_msg_add_delete(state->sam_ldb, mem_ctx, msg,
+ remote_attrs[i]);
+ } else {
+ ldb_msg_add(msg, el, LDB_FLAG_MOD_REPLACE);
+ }
+ }
+
acb = user->acct_flags;
if (acb & (ACB_WSTRUST)) {
cn_name[cn_name_len - 1] = '\0';
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);
if (!msg->dn) {
- return NT_STATUS_NO_MEMORY;
+ msg->dn = ldb_dn_string_compose(mem_ctx, state->base_dn[database],
+ "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) {
- DEBUG(0,("Failed to create user record %s\n",
- ldb_dn_linearize(mem_ctx, msg->dn)));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ 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),
+ ldb_errstring(state->sam_ldb));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
}
} else {
ret = samdb_replace(state->sam_ldb, mem_ctx, msg);
if (ret != 0) {
- DEBUG(0,("Failed to modify user record %s\n",
- ldb_dn_linearize(mem_ctx, msg->dn)));
+ *error_string = talloc_asprintf(mem_ctx, "Failed to modify user record %s: %s",
+ ldb_dn_linearize(mem_ctx, msg->dn),
+ ldb_errstring(state->sam_ldb));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
}
static NTSTATUS samsync_ldb_delete_user(TALLOC_CTX *mem_ctx,
struct samsync_ldb_state *state,
- struct creds_CredentialState *creds,
enum netr_SamDatabaseID database,
- struct netr_DELTA_ENUM *delta)
+ struct netr_DELTA_ENUM *delta,
+ char **error_string)
{
uint32_t rid = delta->delta_id_union.rid;
struct ldb_message **msgs;
ldap_encode_ndr_dom_sid(mem_ctx, dom_sid_add_rid(mem_ctx, state->dom_sid[database], rid)));
if (ret == -1) {
- DEBUG(0, ("gendb_search failed: %s\n", ldb_errstring(state->sam_ldb)));
+ *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) {
return NT_STATUS_NO_SUCH_USER;
} else if (ret > 1) {
- DEBUG(0, ("More than one user with SID: %s\n",
- dom_sid_string(mem_ctx,
- dom_sid_add_rid(mem_ctx,
- state->dom_sid[database],
- rid))));
+ *error_string = talloc_asprintf(mem_ctx, "More than one user with SID: %s",
+ dom_sid_string(mem_ctx,
+ dom_sid_add_rid(mem_ctx,
+ state->dom_sid[database],
+ rid)));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
ret = samdb_delete(state->sam_ldb, mem_ctx, msgs[0]->dn);
if (ret != 0) {
- DEBUG(0,("Failed to delete user record %s: %s\n",
- ldb_dn_linearize(mem_ctx, msgs[0]->dn),
- ldb_errstring(state->sam_ldb)));
+ *error_string = talloc_asprintf(mem_ctx, "Failed to delete user record %s: %s",
+ ldb_dn_linearize(mem_ctx, msgs[0]->dn),
+ ldb_errstring(state->sam_ldb));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
static NTSTATUS samsync_ldb_handle_group(TALLOC_CTX *mem_ctx,
struct samsync_ldb_state *state,
- struct creds_CredentialState *creds,
enum netr_SamDatabaseID database,
- struct netr_DELTA_ENUM *delta)
+ struct netr_DELTA_ENUM *delta,
+ char **error_string)
{
uint32_t rid = delta->delta_id_union.rid;
struct netr_DELTA_GROUP *group = delta->delta_union.group;
ldap_encode_ndr_dom_sid(mem_ctx, dom_sid_add_rid(mem_ctx, state->dom_sid[database], rid)));
if (ret == -1) {
- DEBUG(0, ("gendb_search failed: %s\n", ldb_errstring(state->sam_ldb)));
+ *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;
} else if (ret > 1) {
- DEBUG(0, ("More than one group/alias with SID: %s\n",
- dom_sid_string(mem_ctx,
- dom_sid_add_rid(mem_ctx,
- state->dom_sid[database],
- rid))));
+ *error_string = talloc_asprintf(mem_ctx, "More than one group/alias with SID: %s",
+ dom_sid_string(mem_ctx,
+ dom_sid_add_rid(mem_ctx,
+ state->dom_sid[database],
+ rid)));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
} else {
msg->dn = talloc_steal(msg, msgs[0]->dn);
cn_name = group->group_name.string;
-#define ADD_OR_DEL(type, attrib, field) do {\
- if (group->field) { \
- samdb_msg_add_ ## type(state->sam_ldb, mem_ctx, msg, \
- attrib, group->field); \
- } else if (!add) { \
- samdb_msg_add_delete(state->sam_ldb, mem_ctx, msg, \
- attrib); \
- } \
+#define ADD_OR_DEL(type, attrib, field) do { \
+ if (group->field) { \
+ samdb_msg_add_ ## type(state->sam_ldb, mem_ctx, msg, \
+ attrib, group->field); \
+ } else if (!add) { \
+ samdb_msg_add_delete(state->sam_ldb, mem_ctx, msg, \
+ attrib); \
+ } \
} while (0);
ADD_OR_DEL(string, "samAccountName", group_name.string);
ret = samdb_add(state->sam_ldb, mem_ctx, msg);
if (ret != 0) {
- DEBUG(0,("Failed to create group record %s: %s\n",
- ldb_dn_linearize(mem_ctx, msg->dn),
- ldb_errstring(state->sam_ldb)));
+ *error_string = talloc_asprintf(mem_ctx, "Failed to create group record %s: %s",
+ ldb_dn_linearize(mem_ctx, 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) {
- DEBUG(0,("Failed to modify group record %s: %s\n",
- ldb_dn_linearize(mem_ctx, msg->dn),
- ldb_errstring(state->sam_ldb)));
+ *error_string = talloc_asprintf(mem_ctx, "Failed to modify group record %s: %s",
+ ldb_dn_linearize(mem_ctx, msg->dn),
+ ldb_errstring(state->sam_ldb));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
}
}
static NTSTATUS samsync_ldb_delete_group(TALLOC_CTX *mem_ctx,
- struct samsync_ldb_state *state,
- struct creds_CredentialState *creds,
- enum netr_SamDatabaseID database,
- struct netr_DELTA_ENUM *delta)
+ struct samsync_ldb_state *state,
+ enum netr_SamDatabaseID database,
+ struct netr_DELTA_ENUM *delta,
+ char **error_string)
{
uint32_t rid = delta->delta_id_union.rid;
struct ldb_message **msgs;
ldap_encode_ndr_dom_sid(mem_ctx, dom_sid_add_rid(mem_ctx, state->dom_sid[database], rid)));
if (ret == -1) {
- DEBUG(0, ("gendb_search failed: %s\n", ldb_errstring(state->sam_ldb)));
+ *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) {
return NT_STATUS_NO_SUCH_GROUP;
} else if (ret > 1) {
- DEBUG(0, ("More than one group/alias with SID: %s\n",
- dom_sid_string(mem_ctx,
- dom_sid_add_rid(mem_ctx,
- state->dom_sid[database],
- rid))));
+ *error_string = talloc_asprintf(mem_ctx, "More than one group/alias with SID: %s",
+ dom_sid_string(mem_ctx,
+ dom_sid_add_rid(mem_ctx,
+ state->dom_sid[database],
+ rid)));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
ret = samdb_delete(state->sam_ldb, mem_ctx, msgs[0]->dn);
if (ret != 0) {
- DEBUG(0,("Failed to delete group record %s: %s\n",
- ldb_dn_linearize(mem_ctx, msgs[0]->dn),
- ldb_errstring(state->sam_ldb)));
+ *error_string = talloc_asprintf(mem_ctx, "Failed to delete group record %s: %s",
+ ldb_dn_linearize(mem_ctx, msgs[0]->dn),
+ ldb_errstring(state->sam_ldb));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
static NTSTATUS samsync_ldb_handle_group_member(TALLOC_CTX *mem_ctx,
struct samsync_ldb_state *state,
- struct creds_CredentialState *creds,
enum netr_SamDatabaseID database,
- struct netr_DELTA_ENUM *delta)
+ struct netr_DELTA_ENUM *delta,
+ char **error_string)
{
uint32_t rid = delta->delta_id_union.rid;
struct netr_DELTA_GROUP_MEMBER *group_member = delta->delta_union.group_member;
ldap_encode_ndr_dom_sid(mem_ctx, dom_sid_add_rid(mem_ctx, state->dom_sid[database], rid)));
if (ret == -1) {
- DEBUG(0, ("gendb_search failed: %s\n", ldb_errstring(state->sam_ldb)));
+ *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) {
return NT_STATUS_NO_SUCH_GROUP;
} else if (ret > 1) {
- DEBUG(0, ("More than one group/alias with SID: %s\n",
- dom_sid_string(mem_ctx,
- dom_sid_add_rid(mem_ctx,
- state->dom_sid[database],
- rid))));
+ *error_string = talloc_asprintf(mem_ctx, "More than one group/alias with SID: %s",
+ dom_sid_string(mem_ctx,
+ dom_sid_add_rid(mem_ctx,
+ state->dom_sid[database],
+ rid)));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
} else {
msg->dn = talloc_steal(msg, msgs[0]->dn);
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])));
-
+
if (ret == -1) {
- DEBUG(0, ("gendb_search failed: %s\n", ldb_errstring(state->sam_ldb)));
+ *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) {
return NT_STATUS_NO_SUCH_USER;
} else {
samdb_msg_add_string(state->sam_ldb, mem_ctx, msg, "member", ldb_dn_linearize(mem_ctx, msgs[0]->dn));
}
-
+
talloc_free(msgs);
}
-
+
ret = samdb_replace(state->sam_ldb, mem_ctx, msg);
if (ret != 0) {
- DEBUG(0,("Failed to modify group record %s: %s\n",
- ldb_dn_linearize(mem_ctx, msg->dn),
- ldb_errstring(state->sam_ldb)));
+ *error_string = talloc_asprintf(mem_ctx, "Failed to modify group record %s: %s",
+ ldb_dn_linearize(mem_ctx, msg->dn),
+ ldb_errstring(state->sam_ldb));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
static NTSTATUS samsync_ldb_handle_alias(TALLOC_CTX *mem_ctx,
struct samsync_ldb_state *state,
- struct creds_CredentialState *creds,
enum netr_SamDatabaseID database,
- struct netr_DELTA_ENUM *delta)
+ struct netr_DELTA_ENUM *delta,
+ char **error_string)
{
uint32_t rid = delta->delta_id_union.rid;
struct netr_DELTA_ALIAS *alias = delta->delta_union.alias;
ldap_encode_ndr_dom_sid(mem_ctx, dom_sid_add_rid(mem_ctx, state->dom_sid[database], rid)));
if (ret == -1) {
- DEBUG(0, ("gendb_search failed: %s\n", ldb_errstring(state->sam_ldb)));
+ *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;
} else if (ret > 1) {
- DEBUG(0, ("More than one group/alias with SID: %s\n",
- dom_sid_string(mem_ctx,
- dom_sid_add_rid(mem_ctx,
- state->dom_sid[database],
- rid))));
+ *error_string = talloc_asprintf(mem_ctx, "More than one group/alias with SID: %s",
+ dom_sid_string(mem_ctx,
+ dom_sid_add_rid(mem_ctx,
+ state->dom_sid[database],
+ rid)));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
} else {
msg->dn = talloc_steal(mem_ctx, msgs[0]->dn);
cn_name = alias->alias_name.string;
-#define ADD_OR_DEL(type, attrib, field) do {\
- if (alias->field) { \
- samdb_msg_add_ ## type(state->sam_ldb, mem_ctx, msg, \
- attrib, alias->field); \
- } else if (!add) { \
- samdb_msg_add_delete(state->sam_ldb, mem_ctx, msg, \
- attrib); \
- } \
- } while (0);
+#define ADD_OR_DEL(type, attrib, field) do { \
+ if (alias->field) { \
+ samdb_msg_add_ ## type(state->sam_ldb, mem_ctx, msg, \
+ attrib, alias->field); \
+ } else if (!add) { \
+ samdb_msg_add_delete(state->sam_ldb, mem_ctx, msg, \
+ attrib); \
+ } \
+ } while (0);
- ADD_OR_DEL(string, "samAccountName", alias_name.string);
+ ADD_OR_DEL(string, "samAccountName", alias_name.string);
if (samdb_msg_add_dom_sid(state->sam_ldb, mem_ctx, msg,
"objectSid", dom_sid_add_rid(mem_ctx, state->dom_sid[database], rid))) {
ret = samdb_add(state->sam_ldb, mem_ctx, msg);
if (ret != 0) {
- DEBUG(0,("Failed to create alias record %s: %s\n",
- ldb_dn_linearize(mem_ctx, msg->dn),
- ldb_errstring(state->sam_ldb)));
+ *error_string = talloc_asprintf(mem_ctx, "Failed to create alias record %s: %s",
+ ldb_dn_linearize(mem_ctx, 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) {
- DEBUG(0,("Failed to modify alias record %s: %s\n",
- ldb_dn_linearize(mem_ctx, msg->dn),
- ldb_errstring(state->sam_ldb)));
+ *error_string = talloc_asprintf(mem_ctx, "Failed to modify alias record %s: %s",
+ ldb_dn_linearize(mem_ctx, msg->dn),
+ ldb_errstring(state->sam_ldb));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
}
}
static NTSTATUS samsync_ldb_delete_alias(TALLOC_CTX *mem_ctx,
- struct samsync_ldb_state *state,
- struct creds_CredentialState *creds,
- enum netr_SamDatabaseID database,
- struct netr_DELTA_ENUM *delta)
+ struct samsync_ldb_state *state,
+ enum netr_SamDatabaseID database,
+ struct netr_DELTA_ENUM *delta,
+ char **error_string)
{
uint32_t rid = delta->delta_id_union.rid;
struct ldb_message **msgs;
ldap_encode_ndr_dom_sid(mem_ctx, dom_sid_add_rid(mem_ctx, state->dom_sid[database], rid)));
if (ret == -1) {
- DEBUG(0, ("gendb_search failed: %s\n", ldb_errstring(state->sam_ldb)));
+ *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) {
return NT_STATUS_NO_SUCH_ALIAS;
ret = samdb_delete(state->sam_ldb, mem_ctx, msgs[0]->dn);
if (ret != 0) {
- DEBUG(0,("Failed to delete alias record %s: %s\n",
- ldb_dn_linearize(mem_ctx, msgs[0]->dn),
- ldb_errstring(state->sam_ldb)));
+ *error_string = talloc_asprintf(mem_ctx, "Failed to delete alias record %s: %s",
+ ldb_dn_linearize(mem_ctx, msgs[0]->dn),
+ ldb_errstring(state->sam_ldb));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
static NTSTATUS samsync_ldb_handle_alias_member(TALLOC_CTX *mem_ctx,
struct samsync_ldb_state *state,
- struct creds_CredentialState *creds,
enum netr_SamDatabaseID database,
- struct netr_DELTA_ENUM *delta)
+ struct netr_DELTA_ENUM *delta,
+ char **error_string)
{
uint32_t rid = delta->delta_id_union.rid;
struct netr_DELTA_ALIAS_MEMBER *alias_member = delta->delta_union.alias_member;
ret = gendb_search(state->sam_ldb, mem_ctx, state->base_dn[database], &msgs, attrs,
"(&(objectClass=group)(objectSid=%s))",
ldap_encode_ndr_dom_sid(mem_ctx, dom_sid_add_rid(mem_ctx, state->dom_sid[database], rid)));
-
+
if (ret == -1) {
- DEBUG(0, ("gendb_search failed: %s\n", ldb_errstring(state->sam_ldb)));
+ *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) {
return NT_STATUS_NO_SUCH_GROUP;
} else if (ret > 1) {
- DEBUG(0, ("More than one group/alias with SID: %s\n",
- dom_sid_string(mem_ctx,
- dom_sid_add_rid(mem_ctx,
- state->dom_sid[database],
- rid))));
+ *error_string = talloc_asprintf(mem_ctx, "More than one group/alias with SID: %s",
+ dom_sid_string(mem_ctx,
+ dom_sid_add_rid(mem_ctx,
+ state->dom_sid[database],
+ rid)));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
} else {
msg->dn = talloc_steal(msg, msgs[0]->dn);
ldap_encode_ndr_dom_sid(mem_ctx, alias_member->sids.sids[i].sid));
if (ret == -1) {
- DEBUG(0, ("gendb_search failed: %s\n", ldb_errstring(state->sam_ldb)));
+ *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,
alias_member->sids.sids[i].sid,
- &alias_member_dn);
+ &alias_member_dn,
+ error_string);
if (!NT_STATUS_IS_OK(nt_status)) {
return nt_status;
}
- } else if (ret > 1) {
+ } else if (ret > 1) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
} else {
alias_member_dn = msgs[0]->dn;
ret = samdb_replace(state->sam_ldb, mem_ctx, msg);
if (ret != 0) {
- DEBUG(0,("Failed to modify group record %s: %s\n",
- ldb_dn_linearize(mem_ctx, msg->dn),
- ldb_errstring(state->sam_ldb)));
+ *error_string = talloc_asprintf(mem_ctx, "Failed to modify group record %s: %s",
+ ldb_dn_linearize(mem_ctx, msg->dn),
+ ldb_errstring(state->sam_ldb));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
}
static NTSTATUS samsync_ldb_handle_account(TALLOC_CTX *mem_ctx,
- struct samsync_ldb_state *state,
- struct creds_CredentialState *creds,
- enum netr_SamDatabaseID database,
- struct netr_DELTA_ENUM *delta)
+ struct samsync_ldb_state *state,
+ enum netr_SamDatabaseID database,
+ struct netr_DELTA_ENUM *delta,
+ char **error_string)
{
struct dom_sid *sid = delta->delta_id_union.sid;
struct netr_DELTA_ACCOUNT *account = delta->delta_union.account;
"(objectSid=%s)", ldap_encode_ndr_dom_sid(mem_ctx, sid));
if (ret == -1) {
- DEBUG(0, ("gendb_search failed: %s\n", ldb_errstring(state->sam_ldb)));
+ *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);
+ &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) {
- DEBUG(0, ("More than one account with SID: %s\n",
- dom_sid_string(mem_ctx, sid)));
+ *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);
ret = samdb_replace(state->sam_ldb, mem_ctx, msg);
if (ret != 0) {
- DEBUG(0,("Failed to modify privilege record %s\n",
- ldb_dn_linearize(mem_ctx, msg->dn)));
+ *error_string = talloc_asprintf(mem_ctx, "Failed to modify privilege record %s",
+ ldb_dn_linearize(mem_ctx, msg->dn));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
}
static NTSTATUS samsync_ldb_delete_account(TALLOC_CTX *mem_ctx,
- struct samsync_ldb_state *state,
- struct creds_CredentialState *creds,
- enum netr_SamDatabaseID database,
- struct netr_DELTA_ENUM *delta)
+ struct samsync_ldb_state *state,
+ enum netr_SamDatabaseID database,
+ struct netr_DELTA_ENUM *delta,
+ char **error_string)
{
struct dom_sid *sid = delta->delta_id_union.sid;
ldap_encode_ndr_dom_sid(mem_ctx, sid));
if (ret == -1) {
- DEBUG(0, ("gendb_search failed: %s\n", ldb_errstring(state->sam_ldb)));
+ *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) {
return NT_STATUS_NO_SUCH_USER;
} else if (ret > 1) {
- DEBUG(0, ("More than one account with SID: %s\n",
- dom_sid_string(mem_ctx, sid)));
+ *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 {
msg->dn = talloc_steal(msg, msgs[0]->dn);
ret = samdb_replace(state->sam_ldb, mem_ctx, msg);
if (ret != 0) {
- DEBUG(0,("Failed to modify privilege record %s\n",
- ldb_dn_linearize(mem_ctx, msg->dn)));
+ *error_string = talloc_asprintf(mem_ctx, "Failed to modify privilege record %s",
+ ldb_dn_linearize(mem_ctx, msg->dn));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
}
static NTSTATUS libnet_samsync_ldb_fn(TALLOC_CTX *mem_ctx,
- void *private,
- struct creds_CredentialState *creds,
- enum netr_SamDatabaseID database,
- struct netr_DELTA_ENUM *delta,
- char **error_string)
+ void *private,
+ enum netr_SamDatabaseID database,
+ struct netr_DELTA_ENUM *delta,
+ char **error_string)
{
NTSTATUS nt_status = NT_STATUS_OK;
- struct samsync_ldb_state *state = private;
+ struct samsync_ldb_state *state = talloc_get_type(private, struct samsync_ldb_state);
*error_string = NULL;
switch (delta->delta_type) {
{
nt_status = samsync_ldb_handle_domain(mem_ctx,
state,
- creds,
database,
- delta);
+ delta,
+ error_string);
break;
}
case NETR_DELTA_USER:
{
nt_status = samsync_ldb_handle_user(mem_ctx,
state,
- creds,
database,
- delta);
+ delta,
+ error_string);
break;
}
case NETR_DELTA_DELETE_USER:
{
nt_status = samsync_ldb_delete_user(mem_ctx,
state,
- creds,
database,
- delta);
+ delta,
+ error_string);
break;
}
case NETR_DELTA_GROUP:
{
nt_status = samsync_ldb_handle_group(mem_ctx,
state,
- creds,
database,
- delta);
+ delta,
+ error_string);
break;
}
case NETR_DELTA_DELETE_GROUP:
{
nt_status = samsync_ldb_delete_group(mem_ctx,
- state,
- creds,
- database,
- delta);
+ state,
+ database,
+ delta,
+ error_string);
break;
}
case NETR_DELTA_GROUP_MEMBER:
{
nt_status = samsync_ldb_handle_group_member(mem_ctx,
state,
- creds,
database,
- delta);
+ delta,
+ error_string);
break;
}
case NETR_DELTA_ALIAS:
{
nt_status = samsync_ldb_handle_alias(mem_ctx,
state,
- creds,
database,
- delta);
+ delta,
+ error_string);
break;
}
case NETR_DELTA_DELETE_ALIAS:
{
nt_status = samsync_ldb_delete_alias(mem_ctx,
- state,
- creds,
- database,
- delta);
+ state,
+ database,
+ delta,
+ error_string);
break;
}
case NETR_DELTA_ALIAS_MEMBER:
{
nt_status = samsync_ldb_handle_alias_member(mem_ctx,
state,
- creds,
database,
- delta);
+ delta,
+ error_string);
break;
}
case NETR_DELTA_ACCOUNT:
{
nt_status = samsync_ldb_handle_account(mem_ctx,
- state,
- creds,
- database,
- delta);
+ state,
+ database,
+ delta,
+ error_string);
break;
}
case NETR_DELTA_DELETE_ACCOUNT:
{
nt_status = samsync_ldb_delete_account(mem_ctx,
- state,
- creds,
- database,
- delta);
+ state,
+ database,
+ delta,
+ error_string);
break;
}
default:
/* Can't dump them all right now */
break;
}
+ if (!NT_STATUS_IS_OK(nt_status) && !*error_string) {
+ *error_string = talloc_asprintf(mem_ctx, "Failed to handle samsync delta: %s", nt_errstr(nt_status));
+ }
return nt_status;
}
+static NTSTATUS libnet_samsync_ldb_init(TALLOC_CTX *mem_ctx,
+ void *private,
+ 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(samsync_state->netlogon_pipe);
+ char *ldap_url;
+
+ 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 (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", server);
+
+ state->remote_ldb = ldb_wrap_connect(mem_ctx, ldap_url,
+ NULL, state->samsync_state->machine_net_ctx->cred,
+ 0, NULL);
+ 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;
+}
+
NTSTATUS libnet_samsync_ldb(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_samsync_ldb *r)
{
NTSTATUS nt_status;
state->secrets = NULL;
state->trusted_domains = NULL;
- state->sam_ldb = samdb_connect(state, system_session(state));
+ state->sam_ldb = ldb_wrap_connect(mem_ctx, lp_sam_url(), r->in.session_info,
+ ctx->cred, 0, NULL);
r2.out.error_string = NULL;
r2.in.binding_string = r->in.binding_string;
+ r2.in.init_fn = libnet_samsync_ldb_init;
r2.in.delta_fn = libnet_samsync_ldb_fn;
r2.in.fn_ctx = state;
r2.in.machine_account = NULL; /* TODO: Create a machine account, fill this in, and the delete it */
nt_status = libnet_SamSync_netlogon(ctx, state, &r2);
r->out.error_string = r2.out.error_string;
+ talloc_steal(mem_ctx, r->out.error_string);
if (!NT_STATUS_IS_OK(nt_status)) {
talloc_free(state);