summaryrefslogtreecommitdiff
path: root/source4/libnet/libnet_samsync_ldb.c
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2006-01-13 12:52:56 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:51:00 -0500
commitb15582ed816f3d477f978976f43b82cfa90bf6dc (patch)
tree01a6d0f6eaa039fe1262945c7dc2320f942e379a /source4/libnet/libnet_samsync_ldb.c
parent867ae22a9bf4cfe829e405fcbbb9de994505fc30 (diff)
downloadsamba-b15582ed816f3d477f978976f43b82cfa90bf6dc.tar.gz
samba-b15582ed816f3d477f978976f43b82cfa90bf6dc.tar.bz2
samba-b15582ed816f3d477f978976f43b82cfa90bf6dc.zip
r12903: Factor out a new routine libnet_RpcConnectDCInfo, to both connect to
the remote sever, and to query it for domain information. Provide and use this information in the SamSync/Vampire callbacks, to allow a parallel connection to LDAP, if we are talking to AD. This allows us to get at some important attributes not exposed in the old protocol. With this, we are able to do a all-GUI vampire of a AD domain from SWAT, including getting all the SIDs, servicePrincipalNames and the like correct. Andrew Bartlett (This used to be commit 918358cee0b4a1b2c9bc9e68d9d53428a634281e)
Diffstat (limited to 'source4/libnet/libnet_samsync_ldb.c')
-rw-r--r--source4/libnet/libnet_samsync_ldb.c164
1 files changed, 118 insertions, 46 deletions
diff --git a/source4/libnet/libnet_samsync_ldb.c b/source4/libnet/libnet_samsync_ldb.c
index 5587f208ef..da4e777a15 100644
--- a/source4/libnet/libnet_samsync_ldb.c
+++ b/source4/libnet/libnet_samsync_ldb.c
@@ -43,8 +43,13 @@ 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;
+
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;
@@ -106,7 +111,6 @@ static NTSTATUS samsync_ldb_add_foreignSecurityPrincipal(TALLOC_CTX *mem_ctx,
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,
char **error_string)
@@ -137,9 +141,13 @@ static NTSTATUS samsync_ldb_handle_domain(TALLOC_CTX *mem_ctx,
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->domain_sid) {
+ state->dom_sid[database] = dom_sid_dup(state, state->domain_sid);
+ } else {
+ state->dom_sid[database] = samdb_search_dom_sid(state->sam_ldb, state,
+ state->base_dn[database],
+ "objectSid", NULL);
+ }
} else if (database == SAM_DATABASE_BUILTIN) {
/* work out the builtin_dn - useful for so many calls its worth
fetching here */
@@ -187,6 +195,10 @@ 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);
@@ -199,7 +211,6 @@ static NTSTATUS samsync_ldb_handle_domain(TALLOC_CTX *mem_ctx,
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,
char **error_string)
@@ -209,13 +220,22 @@ static NTSTATUS samsync_ldb_handle_user(TALLOC_CTX *mem_ctx,
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;
+ 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", 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) {
@@ -225,29 +245,49 @@ static NTSTATUS samsync_ldb_handle_user(TALLOC_CTX *mem_ctx,
/* 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, "gendb_search for user %s failed: %s",
- dom_sid_string(mem_ctx,
- dom_sid_add_rid(mem_ctx,
- state->dom_sid[database],
- rid)),
+ *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) {
- *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)));
+ *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 */
+ 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);
@@ -324,6 +364,16 @@ static NTSTATUS samsync_ldb_handle_user(TALLOC_CTX *mem_ctx,
#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';
@@ -352,10 +402,17 @@ static NTSTATUS samsync_ldb_handle_user(TALLOC_CTX *mem_ctx,
ret = samdb_add(state->sam_ldb, mem_ctx, msg);
if (ret != 0) {
- *error_string = talloc_asprintf(mem_ctx, "Failed to create user record %s: %s",
- ldb_dn_linearize(mem_ctx, msg->dn),
- ldb_errstring(state->sam_ldb));
- 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);
@@ -372,7 +429,6 @@ static NTSTATUS samsync_ldb_handle_user(TALLOC_CTX *mem_ctx,
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,
char **error_string)
@@ -414,7 +470,6 @@ static NTSTATUS samsync_ldb_delete_user(TALLOC_CTX *mem_ctx,
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,
char **error_string)
@@ -513,7 +568,6 @@ static NTSTATUS samsync_ldb_handle_group(TALLOC_CTX *mem_ctx,
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,
char **error_string)
@@ -555,7 +609,6 @@ static NTSTATUS samsync_ldb_delete_group(TALLOC_CTX *mem_ctx,
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,
char **error_string)
@@ -629,7 +682,6 @@ static NTSTATUS samsync_ldb_handle_group_member(TALLOC_CTX *mem_ctx,
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,
char **error_string)
@@ -730,7 +782,6 @@ static NTSTATUS samsync_ldb_handle_alias(TALLOC_CTX *mem_ctx,
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,
char **error_string)
@@ -767,7 +818,6 @@ static NTSTATUS samsync_ldb_delete_alias(TALLOC_CTX *mem_ctx,
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,
char **error_string)
@@ -850,7 +900,6 @@ static NTSTATUS samsync_ldb_handle_alias_member(TALLOC_CTX *mem_ctx,
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,
char **error_string)
@@ -914,7 +963,6 @@ static NTSTATUS samsync_ldb_handle_account(TALLOC_CTX *mem_ctx,
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,
char **error_string)
@@ -964,13 +1012,12 @@ static NTSTATUS samsync_ldb_delete_account(TALLOC_CTX *mem_ctx,
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)
{
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) {
@@ -978,7 +1025,6 @@ static NTSTATUS libnet_samsync_ldb_fn(TALLOC_CTX *mem_ctx,
{
nt_status = samsync_ldb_handle_domain(mem_ctx,
state,
- creds,
database,
delta,
error_string);
@@ -988,7 +1034,6 @@ static NTSTATUS libnet_samsync_ldb_fn(TALLOC_CTX *mem_ctx,
{
nt_status = samsync_ldb_handle_user(mem_ctx,
state,
- creds,
database,
delta,
error_string);
@@ -998,7 +1043,6 @@ static NTSTATUS libnet_samsync_ldb_fn(TALLOC_CTX *mem_ctx,
{
nt_status = samsync_ldb_delete_user(mem_ctx,
state,
- creds,
database,
delta,
error_string);
@@ -1008,7 +1052,6 @@ static NTSTATUS libnet_samsync_ldb_fn(TALLOC_CTX *mem_ctx,
{
nt_status = samsync_ldb_handle_group(mem_ctx,
state,
- creds,
database,
delta,
error_string);
@@ -1018,7 +1061,6 @@ static NTSTATUS libnet_samsync_ldb_fn(TALLOC_CTX *mem_ctx,
{
nt_status = samsync_ldb_delete_group(mem_ctx,
state,
- creds,
database,
delta,
error_string);
@@ -1028,7 +1070,6 @@ static NTSTATUS libnet_samsync_ldb_fn(TALLOC_CTX *mem_ctx,
{
nt_status = samsync_ldb_handle_group_member(mem_ctx,
state,
- creds,
database,
delta,
error_string);
@@ -1038,7 +1079,6 @@ static NTSTATUS libnet_samsync_ldb_fn(TALLOC_CTX *mem_ctx,
{
nt_status = samsync_ldb_handle_alias(mem_ctx,
state,
- creds,
database,
delta,
error_string);
@@ -1048,7 +1088,6 @@ static NTSTATUS libnet_samsync_ldb_fn(TALLOC_CTX *mem_ctx,
{
nt_status = samsync_ldb_delete_alias(mem_ctx,
state,
- creds,
database,
delta,
error_string);
@@ -1058,7 +1097,6 @@ static NTSTATUS libnet_samsync_ldb_fn(TALLOC_CTX *mem_ctx,
{
nt_status = samsync_ldb_handle_alias_member(mem_ctx,
state,
- creds,
database,
delta,
error_string);
@@ -1068,7 +1106,6 @@ static NTSTATUS libnet_samsync_ldb_fn(TALLOC_CTX *mem_ctx,
{
nt_status = samsync_ldb_handle_account(mem_ctx,
state,
- creds,
database,
delta,
error_string);
@@ -1078,7 +1115,6 @@ static NTSTATUS libnet_samsync_ldb_fn(TALLOC_CTX *mem_ctx,
{
nt_status = samsync_ldb_delete_account(mem_ctx,
state,
- creds,
database,
delta,
error_string);
@@ -1094,6 +1130,40 @@ static NTSTATUS libnet_samsync_ldb_fn(TALLOC_CTX *mem_ctx,
return nt_status;
}
+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,
+ char **error_string)
+{
+ struct samsync_ldb_state *state = talloc_get_type(private, struct samsync_ldb_state);
+ const char *server = dcerpc_server_name(p);
+ char *ldap_url;
+
+ state->domain_name = domain_name;
+ state->domain_sid = domain_sid;
+ state->realm = realm;
+
+ if (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));
+
+ 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 */
+ }
+ return NT_STATUS_OK;
+}
+
NTSTATUS libnet_samsync_ldb(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_samsync_ldb *r)
{
NTSTATUS nt_status;
@@ -1111,11 +1181,13 @@ NTSTATUS libnet_samsync_ldb(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, str
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);