summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/libnet/libnet_join.c250
-rw-r--r--source4/libnet/libnet_join.h1
-rw-r--r--source4/libnet/libnet_rpc.c191
-rw-r--r--source4/libnet/libnet_rpc.h19
-rw-r--r--source4/libnet/libnet_samdump.c9
-rw-r--r--source4/libnet/libnet_samdump_keytab.c5
-rw-r--r--source4/libnet/libnet_samsync_ldb.c164
-rw-r--r--source4/libnet/libnet_vampire.c43
-rw-r--r--source4/libnet/libnet_vampire.h9
9 files changed, 440 insertions, 251 deletions
diff --git a/source4/libnet/libnet_join.c b/source4/libnet/libnet_join.c
index c961ff0cfea..0147679bcdc 100644
--- a/source4/libnet/libnet_join.c
+++ b/source4/libnet/libnet_join.c
@@ -544,21 +544,23 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J
/*
* do a domain join using DCERPC/SAMR calls
- * 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation)
- * is it correct to contact the the pdc of the domain of the user who's password should be set?
- * 2. do a samr_Connect to get a policy handle
- * 3. do a samr_LookupDomain to get the domain sid
- * 4. do a samr_OpenDomain to get a domain handle
- * 5. do a samr_CreateAccount to try and get a new account
+ * - connect to the LSA pipe, to try and find out information about the domain
+ * - create a secondary connection to SAMR pipe
+ * - do a samr_Connect to get a policy handle
+ * - do a samr_LookupDomain to get the domain sid
+ * - do a samr_OpenDomain to get a domain handle
+ * - do a samr_CreateAccount to try and get a new account
*
* If that fails, do:
- * 5.1. do a samr_LookupNames to get the users rid
- * 5.2. do a samr_OpenUser to get a user handle
+ * - do a samr_LookupNames to get the users rid
+ * - do a samr_OpenUser to get a user handle
+ * - potentially delete and recreate the user
+ * - assert the account is of the right type with samrQueryUserInfo
*
- * 6. call libnet_SetPassword_samr_handle to set the password
+ * - call libnet_SetPassword_samr_handle to set the password
*
- * 7. do a samrSetUserInfo to set the account flags
- * 8. do some ADS specific things when we join as Domain Controller,
+ * - do a samrSetUserInfo to set the account flags
+ * - do some ADS specific things when we join as Domain Controller,
* look at libnet_joinADSDomain() for the details
*/
NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_JoinDomain *r)
@@ -566,17 +568,10 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
TALLOC_CTX *tmp_ctx;
NTSTATUS status, cu_status;
- struct libnet_RpcConnect *c;
- struct lsa_ObjectAttribute attr;
- struct lsa_QosInfo qos;
- struct lsa_OpenPolicy2 lsa_open_policy;
- struct policy_handle lsa_p_handle;
- struct lsa_QueryInfoPolicy2 lsa_query_info2;
- struct lsa_QueryInfoPolicy lsa_query_info;
-
- struct dcerpc_binding *samr_binding;
+
+ struct libnet_RpcConnectDCInfo *connect_with_info;
struct dcerpc_pipe *samr_pipe;
- struct dcerpc_pipe *lsa_pipe;
+
struct samr_Connect sc;
struct policy_handle p_handle;
struct samr_OpenDomain od;
@@ -596,9 +591,7 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
uint32_t rid, access_granted;
int policy_min_pw_len = 0;
- struct dom_sid *domain_sid = NULL;
struct dom_sid *account_sid = NULL;
- const char *domain_name = NULL;
const char *password_str = NULL;
const char *realm = NULL; /* Also flag for remote being AD */
@@ -619,162 +612,47 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
return NT_STATUS_NO_MEMORY;
}
- samr_pipe = talloc(tmp_ctx, struct dcerpc_pipe);
- if (!samr_pipe) {
- r->out.error_string = NULL;
- talloc_free(tmp_ctx);
- return NT_STATUS_NO_MEMORY;
- }
-
- c = talloc(tmp_ctx, struct libnet_RpcConnect);
- if (!c) {
+ connect_with_info = talloc(tmp_ctx, struct libnet_RpcConnectDCInfo);
+ if (!connect_with_info) {
r->out.error_string = NULL;
talloc_free(tmp_ctx);
return NT_STATUS_NO_MEMORY;
}
-
+
/* prepare connect to the LSA pipe of PDC */
if (r->in.level == LIBNET_JOINDOMAIN_AUTOMATIC) {
- c->level = LIBNET_RPC_CONNECT_PDC;
- c->in.name = r->in.domain_name;
+ connect_with_info->level = LIBNET_RPC_CONNECT_PDC;
+ connect_with_info->in.name = r->in.domain_name;
} else {
- c->level = LIBNET_RPC_CONNECT_BINDING;
- c->in.binding = r->in.binding;
+ connect_with_info->level = LIBNET_RPC_CONNECT_BINDING;
+ connect_with_info->in.binding = r->in.binding;
}
- c->in.dcerpc_iface = &dcerpc_table_lsarpc;
-
- /* connect to the LSA pipe of the PDC */
- status = libnet_RpcConnect(ctx, c, c);
+ connect_with_info->in.dcerpc_iface = &dcerpc_table_samr;
+ /*
+ establish a SAMR connection, on the same CIFS transport
+ */
+
+ status = libnet_RpcConnectDCInfo(ctx, connect_with_info);
if (!NT_STATUS_IS_OK(status)) {
- if (r->in.level == LIBNET_JOINDOMAIN_AUTOMATIC) {
+ if (r->in.binding) {
r->out.error_string = talloc_asprintf(mem_ctx,
- "Connection to LSA pipe of PDC of domain '%s' failed: %s",
- r->in.domain_name, nt_errstr(status));
+ "Connection to SAMR pipe of DC %s failed: %s",
+ r->in.binding, connect_with_info->out.error_string);
} else {
r->out.error_string = talloc_asprintf(mem_ctx,
- "Connection to LSA pipe with binding '%s' failed: %s",
- r->in.binding, nt_errstr(status));
- }
- talloc_free(tmp_ctx);
- return status;
- }
- lsa_pipe = c->out.dcerpc_pipe;
-
- /* Get an LSA policy handle */
-
- ZERO_STRUCT(lsa_p_handle);
- qos.len = 0;
- qos.impersonation_level = 2;
- qos.context_mode = 1;
- qos.effective_only = 0;
-
- attr.len = 0;
- attr.root_dir = NULL;
- attr.object_name = NULL;
- attr.attributes = 0;
- attr.sec_desc = NULL;
- attr.sec_qos = &qos;
-
- lsa_open_policy.in.attr = &attr;
-
- lsa_open_policy.in.system_name = talloc_asprintf(tmp_ctx, "\\");
- if (!lsa_open_policy.in.system_name) {
- r->out.error_string = NULL;
- talloc_free(tmp_ctx);
- return NT_STATUS_NO_MEMORY;
- }
-
- lsa_open_policy.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
- lsa_open_policy.out.handle = &lsa_p_handle;
-
- status = dcerpc_lsa_OpenPolicy2(lsa_pipe, tmp_ctx, &lsa_open_policy);
-
- /* This now fails on ncacn_ip_tcp against Win2k3 SP1 */
- if (NT_STATUS_IS_OK(status)) {
- /* Look to see if this is ADS (a fault indicates NT4 or Samba 3.0) */
-
- lsa_query_info2.in.handle = &lsa_p_handle;
- lsa_query_info2.in.level = LSA_POLICY_INFO_DNS;
-
- status = dcerpc_lsa_QueryInfoPolicy2(lsa_pipe, tmp_ctx,
- &lsa_query_info2);
-
- if (!NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
- if (!NT_STATUS_IS_OK(status)) {
- r->out.error_string = talloc_asprintf(mem_ctx,
- "lsa_QueryInfoPolicy2 failed: %s",
- nt_errstr(status));
- talloc_free(tmp_ctx);
- return status;
- }
- realm = lsa_query_info2.out.info->dns.dns_domain.string;
- }
-
- /* Grab the domain SID (regardless of the result of the previous call */
-
- lsa_query_info.in.handle = &lsa_p_handle;
- lsa_query_info.in.level = LSA_POLICY_INFO_DOMAIN;
-
- status = dcerpc_lsa_QueryInfoPolicy(lsa_pipe, tmp_ctx,
- &lsa_query_info);
-
- if (!NT_STATUS_IS_OK(status)) {
- r->out.error_string = talloc_asprintf(mem_ctx,
- "lsa_QueryInfoPolicy2 failed: %s",
- nt_errstr(status));
- talloc_free(tmp_ctx);
- return status;
- }
-
- domain_sid = lsa_query_info.out.info->domain.sid;
- domain_name = lsa_query_info.out.info->domain.name.string;
- } else {
- /* Cause the code further down to try this with just SAMR */
- domain_sid = NULL;
- if (r->in.level == LIBNET_JOINDOMAIN_AUTOMATIC) {
- domain_name = talloc_strdup(tmp_ctx, r->in.domain_name);
- } else {
- /* Bugger, we just lost our way to automaticly find the domain name */
- domain_name = talloc_strdup(tmp_ctx, lp_workgroup());
+ "Connection to SAMR pipe of PDC for %s failed: %s",
+ r->in.domain_name, connect_with_info->out.error_string);
}
- }
-
- /*
- establish a SAMR connection, on the same CIFS transport
- */
-
- /* Find the original binding string */
- samr_binding = talloc(tmp_ctx, struct dcerpc_binding);
- if (!samr_binding) {
- return NT_STATUS_NO_MEMORY;
- }
- *samr_binding = *lsa_pipe->binding;
-
- /* Make binding string for samr, not the other pipe */
- status = dcerpc_epm_map_binding(tmp_ctx, samr_binding,
- &dcerpc_table_samr,
- lsa_pipe->conn->event_ctx);
- if (!NT_STATUS_IS_OK(status)) {
- r->out.error_string = talloc_asprintf(mem_ctx,
- "Failed to map DCERPC/TCP NCACN_NP pipe for '%s' - %s",
- DCERPC_NETLOGON_UUID,
- nt_errstr(status));
talloc_free(tmp_ctx);
return status;
}
- /* Setup a SAMR connection */
- status = dcerpc_secondary_connection(lsa_pipe, &samr_pipe, samr_binding);
- if (!NT_STATUS_IS_OK(status)) {
- r->out.error_string = talloc_asprintf(mem_ctx,
- "SAMR secondary connection failed: %s",
- nt_errstr(status));
- talloc_free(tmp_ctx);
- return status;
- }
+ samr_pipe = connect_with_info->out.dcerpc_pipe,
- status = dcerpc_pipe_auth(samr_pipe, samr_binding, &dcerpc_table_samr, ctx->cred);
+ status = dcerpc_pipe_auth(samr_pipe,
+ connect_with_info->out.dcerpc_pipe->binding,
+ &dcerpc_table_samr, ctx->cred);
if (!NT_STATUS_IS_OK(status)) {
r->out.error_string = talloc_asprintf(mem_ctx,
"SAMR bind failed: %s",
@@ -799,11 +677,21 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
return status;
}
+ /* If this is a connection on ncacn_ip_tcp to Win2k3 SP1, we don't get back this useful info */
+ if (!connect_with_info->out.domain_name) {
+ if (r->in.level == LIBNET_JOINDOMAIN_AUTOMATIC) {
+ connect_with_info->out.domain_name = talloc_strdup(tmp_ctx, r->in.domain_name);
+ } else {
+ /* Bugger, we just lost our way to automaticly find the domain name */
+ connect_with_info->out.domain_name = talloc_strdup(tmp_ctx, lp_workgroup());
+ }
+ }
+
/* Perhaps we didn't get a SID above, because we are against ncacn_ip_tcp */
- if (!domain_sid) {
+ if (!connect_with_info->out.domain_sid) {
struct lsa_String name;
struct samr_LookupDomain l;
- name.string = domain_name;
+ name.string = connect_with_info->out.domain_name;
l.in.connect_handle = &p_handle;
l.in.domain_name = &name;
@@ -815,23 +703,23 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
talloc_free(tmp_ctx);
return status;
}
- domain_sid = l.out.sid;
+ connect_with_info->out.domain_sid = l.out.sid;
}
/* prepare samr_OpenDomain */
ZERO_STRUCT(d_handle);
od.in.connect_handle = &p_handle;
od.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
- od.in.sid = domain_sid;
+ od.in.sid = connect_with_info->out.domain_sid;
od.out.domain_handle = &d_handle;
/* do a samr_OpenDomain to get a domain handle */
status = dcerpc_samr_OpenDomain(samr_pipe, tmp_ctx, &od);
if (!NT_STATUS_IS_OK(status)) {
r->out.error_string = talloc_asprintf(mem_ctx,
- "samr_OpenDomain for [%s] failed: %s",
- r->in.domain_name,
- nt_errstr(status));
+ "samr_OpenDomain for [%s] failed: %s",
+ dom_sid_string(tmp_ctx, connect_with_info->out.domain_sid),
+ nt_errstr(status));
talloc_free(tmp_ctx);
return status;
}
@@ -1010,7 +898,7 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
"The machine account (%s) already exists in the domain %s, "
"but is a %s. You asked to join as a %s. Please delete "
"the account and try again.\n",
- r->in.account_name, domain_name, old_account_type, new_account_type);
+ r->in.account_name, connect_with_info->out.domain_name, old_account_type, new_account_type);
talloc_free(tmp_ctx);
return NT_STATUS_USER_EXISTS;
}
@@ -1065,7 +953,7 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
}
}
- account_sid = dom_sid_add_rid(mem_ctx, domain_sid, rid);
+ account_sid = dom_sid_add_rid(mem_ctx, connect_with_info->out.domain_sid, rid);
if (!account_sid) {
r->out.error_string = NULL;
talloc_free(tmp_ctx);
@@ -1074,24 +962,22 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
/* Finish out by pushing various bits of status data out for the caller to use */
r->out.join_password = password_str;
- talloc_steal(mem_ctx, password_str);
+ talloc_steal(mem_ctx, r->out.join_password);
- r->out.domain_sid = domain_sid;
- talloc_steal(mem_ctx, domain_sid);
+ r->out.domain_sid = connect_with_info->out.domain_sid;
+ talloc_steal(mem_ctx, r->out.domain_sid);
r->out.account_sid = account_sid;
- talloc_steal(mem_ctx, account_sid);
-
- r->out.domain_name = domain_name;
- talloc_steal(mem_ctx, domain_name);
- r->out.realm = realm;
- talloc_steal(mem_ctx, realm);
- r->out.lsa_pipe = lsa_pipe;
- talloc_steal(mem_ctx, lsa_pipe);
+ talloc_steal(mem_ctx, r->out.account_sid);
+
+ r->out.domain_name = connect_with_info->out.domain_name;
+ talloc_steal(mem_ctx, r->out.domain_name);
+ r->out.realm = connect_with_info->out.realm;
+ talloc_steal(mem_ctx, r->out.realm);
r->out.samr_pipe = samr_pipe;
talloc_steal(mem_ctx, samr_pipe);
- r->out.samr_binding = samr_binding;
- talloc_steal(mem_ctx, samr_binding);
+ r->out.samr_binding = samr_pipe->binding;
+ talloc_steal(mem_ctx, r->out.samr_binding);
r->out.user_handle = u_handle;
talloc_steal(mem_ctx, u_handle);
r->out.error_string = r2.samr_handle.out.error_string;
diff --git a/source4/libnet/libnet_join.h b/source4/libnet/libnet_join.h
index 04f23c1d995..35460b7a0ae 100644
--- a/source4/libnet/libnet_join.h
+++ b/source4/libnet/libnet_join.h
@@ -53,7 +53,6 @@ struct libnet_JoinDomain {
const char *account_dn_str;
const char *server_dn_str;
uint32_t kvno; /* msDS-KeyVersionNumber */
- struct dcerpc_pipe *lsa_pipe;
struct dcerpc_pipe *samr_pipe;
struct dcerpc_binding *samr_binding;
struct policy_handle *user_handle;
diff --git a/source4/libnet/libnet_rpc.c b/source4/libnet/libnet_rpc.c
index 1f98e575d1b..aba393d7fb9 100644
--- a/source4/libnet/libnet_rpc.c
+++ b/source4/libnet/libnet_rpc.c
@@ -78,7 +78,7 @@ static NTSTATUS libnet_RpcConnectSrv(struct libnet_context *ctx, TALLOC_CTX *mem
* @return nt status of the call
**/
-static NTSTATUS libnet_RpcConnectPdc(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_RpcConnect *r)
+static NTSTATUS libnet_RpcConnectDC(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_RpcConnect *r)
{
NTSTATUS status;
struct libnet_RpcConnect r2;
@@ -153,8 +153,195 @@ NTSTATUS libnet_RpcConnect(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
case LIBNET_RPC_CONNECT_PDC:
case LIBNET_RPC_CONNECT_DC:
- return libnet_RpcConnectPdc(ctx, mem_ctx, r);
+ return libnet_RpcConnectDC(ctx, mem_ctx, r);
}
return NT_STATUS_INVALID_LEVEL;
}
+
+/**
+ * Connects to rpc pipe on remote server or pdc, and returns info on the domain name, domain sid and realm
+ *
+ * @param ctx initialised libnet context
+ * @param r data structure containing necessary parameters and return values. Must be a talloc context
+ * @return nt status of the call
+ **/
+
+NTSTATUS libnet_RpcConnectDCInfo(struct libnet_context *ctx,
+ struct libnet_RpcConnectDCInfo *r)
+{
+ TALLOC_CTX *tmp_ctx;
+ NTSTATUS status;
+
+ struct libnet_RpcConnect *c;
+ struct lsa_ObjectAttribute attr;
+ struct lsa_QosInfo qos;
+ struct lsa_OpenPolicy2 lsa_open_policy;
+ struct policy_handle lsa_p_handle;
+ struct lsa_QueryInfoPolicy2 lsa_query_info2;
+ struct lsa_QueryInfoPolicy lsa_query_info;
+
+ struct dcerpc_pipe *lsa_pipe;
+
+ struct dcerpc_binding *final_binding;
+ struct dcerpc_pipe *final_pipe;
+
+ tmp_ctx = talloc_new(r);
+ if (!tmp_ctx) {
+ r->out.error_string = NULL;
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ c = talloc(tmp_ctx, struct libnet_RpcConnect);
+ if (!c) {
+ r->out.error_string = NULL;
+ talloc_free(tmp_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+ c->level = r->level;
+
+ if (r->level != LIBNET_RPC_CONNECT_BINDING) {
+ c->in.name = r->in.name;
+ } else {
+ c->in.binding = r->in.binding;
+ }
+
+ c->in.dcerpc_iface = &dcerpc_table_lsarpc;
+
+ /* connect to the LSA pipe of the PDC */
+
+ status = libnet_RpcConnect(ctx, c, c);
+ if (!NT_STATUS_IS_OK(status)) {
+ if (r->level != LIBNET_RPC_CONNECT_BINDING) {
+ r->out.error_string = talloc_asprintf(r,
+ "Connection to LSA pipe of DC failed: %s",
+ c->out.error_string);
+ } else {
+ r->out.error_string = talloc_asprintf(r,
+ "Connection to LSA pipe with binding '%s' failed: %s",
+ r->in.binding, c->out.error_string);
+ }
+ talloc_free(tmp_ctx);
+ return status;
+ }
+ lsa_pipe = c->out.dcerpc_pipe;
+
+ /* Get an LSA policy handle */
+
+ ZERO_STRUCT(lsa_p_handle);
+ qos.len = 0;
+ qos.impersonation_level = 2;
+ qos.context_mode = 1;
+ qos.effective_only = 0;
+
+ attr.len = 0;
+ attr.root_dir = NULL;
+ attr.object_name = NULL;
+ attr.attributes = 0;
+ attr.sec_desc = NULL;
+ attr.sec_qos = &qos;
+
+ lsa_open_policy.in.attr = &attr;
+
+ lsa_open_policy.in.system_name = talloc_asprintf(tmp_ctx, "\\");
+ if (!lsa_open_policy.in.system_name) {
+ r->out.error_string = NULL;
+ talloc_free(tmp_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ lsa_open_policy.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+ lsa_open_policy.out.handle = &lsa_p_handle;
+
+ status = dcerpc_lsa_OpenPolicy2(lsa_pipe, tmp_ctx, &lsa_open_policy);
+
+ /* This now fails on ncacn_ip_tcp against Win2k3 SP1 */
+ if (NT_STATUS_IS_OK(status)) {
+ /* Look to see if this is ADS (a fault indicates NT4 or Samba 3.0) */
+
+ lsa_query_info2.in.handle = &lsa_p_handle;
+ lsa_query_info2.in.level = LSA_POLICY_INFO_DNS;
+
+ status = dcerpc_lsa_QueryInfoPolicy2(lsa_pipe, tmp_ctx,
+ &lsa_query_info2);
+
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
+ if (!NT_STATUS_IS_OK(status)) {
+ r->out.error_string = talloc_asprintf(r,
+ "lsa_QueryInfoPolicy2 failed: %s",
+ nt_errstr(status));
+ talloc_free(tmp_ctx);
+ return status;
+ }
+ r->out.realm = lsa_query_info2.out.info->dns.dns_domain.string;
+ } else {
+ r->out.realm = NULL;
+ }
+
+ /* Grab the domain SID (regardless of the result of the previous call */
+
+ lsa_query_info.in.handle = &lsa_p_handle;
+ lsa_query_info.in.level = LSA_POLICY_INFO_DOMAIN;
+
+ status = dcerpc_lsa_QueryInfoPolicy(lsa_pipe, tmp_ctx,
+ &lsa_query_info);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ r->out.error_string = talloc_asprintf(r,
+ "lsa_QueryInfoPolicy2 failed: %s",
+ nt_errstr(status));
+ talloc_free(tmp_ctx);
+ return status;
+ }
+
+ r->out.domain_sid = lsa_query_info.out.info->domain.sid;
+ r->out.domain_name = lsa_query_info.out.info->domain.name.string;
+ } else {
+ /* Cause the code further down to try this with just SAMR */
+ r->out.domain_sid = NULL;
+ r->out.domain_name = NULL;
+ r->out.realm = NULL;
+ }
+
+ /* Find the original binding string */
+ final_binding = talloc(tmp_ctx, struct dcerpc_binding);
+ if (!final_binding) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ *final_binding = *lsa_pipe->binding;
+ /* Ensure we keep hold of the member elements */
+ talloc_reference(final_binding, lsa_pipe->binding);
+
+ /* Make binding string for samr, not the other pipe */
+ status = dcerpc_epm_map_binding(tmp_ctx, final_binding,
+ r->in.dcerpc_iface,
+ lsa_pipe->conn->event_ctx);
+ if (!NT_STATUS_IS_OK(status)) {
+ r->out.error_string = talloc_asprintf(r,
+ "Failed to map pipe with endpoint mapper - %s",
+ nt_errstr(status));
+ talloc_free(tmp_ctx);
+ return status;
+ }
+
+ /* Now that we have the info setup a final connection to the pipe they wanted */
+ status = dcerpc_secondary_connection(lsa_pipe, &final_pipe, final_binding);
+ if (!NT_STATUS_IS_OK(status)) {
+ r->out.error_string = talloc_asprintf(r,
+ "secondary connection failed: %s",
+ nt_errstr(status));
+ talloc_free(tmp_ctx);
+ return status;
+ }
+ r->out.dcerpc_pipe = final_pipe;
+
+ talloc_steal(r, r->out.realm);
+ talloc_steal(r, r->out.domain_sid);
+ talloc_steal(r, r->out.domain_name);
+ talloc_steal(r, r->out.dcerpc_pipe);
+
+ /* This should close the LSA pipe, which we don't need now we have the info */
+ talloc_free(tmp_ctx);
+ return NT_STATUS_OK;
+}
+
diff --git a/source4/libnet/libnet_rpc.h b/source4/libnet/libnet_rpc.h
index 5505e69a09d..ce88462485f 100644
--- a/source4/libnet/libnet_rpc.h
+++ b/source4/libnet/libnet_rpc.h
@@ -45,3 +45,22 @@ struct libnet_RpcConnect {
const char *error_string;
} out;
};
+
+struct libnet_RpcConnectDCInfo {
+ enum libnet_RpcConnect_level level;
+
+ struct {
+ const char *name;
+ const char *binding;
+ const struct dcerpc_interface_table *dcerpc_iface;
+ } in;
+ struct {
+ struct dcerpc_pipe *dcerpc_pipe;
+ struct dom_sid *domain_sid;
+ const char *domain_name;
+
+ /* This parameter only present if the remote server is known to be AD */
+ const char *realm;
+ const char *error_string;
+ } out;
+};
diff --git a/source4/libnet/libnet_samdump.c b/source4/libnet/libnet_samdump.c
index e094293916a..8936d6829a7 100644
--- a/source4/libnet/libnet_samdump.c
+++ b/source4/libnet/libnet_samdump.c
@@ -46,7 +46,6 @@ struct samdump_state {
};
static NTSTATUS vampire_samdump_handle_user(TALLOC_CTX *mem_ctx,
- struct creds_CredentialState *creds,
struct netr_DELTA_ENUM *delta)
{
uint32_t rid = delta->delta_id_union.rid;
@@ -72,7 +71,6 @@ static NTSTATUS vampire_samdump_handle_user(TALLOC_CTX *mem_ctx,
static NTSTATUS vampire_samdump_handle_secret(TALLOC_CTX *mem_ctx,
struct samdump_state *samdump_state,
- struct creds_CredentialState *creds,
struct netr_DELTA_ENUM *delta)
{
struct netr_DELTA_SECRET *secret = delta->delta_union.secret;
@@ -90,7 +88,6 @@ static NTSTATUS vampire_samdump_handle_secret(TALLOC_CTX *mem_ctx,
static NTSTATUS vampire_samdump_handle_trusted_domain(TALLOC_CTX *mem_ctx,
struct samdump_state *samdump_state,
- struct creds_CredentialState *creds,
struct netr_DELTA_ENUM *delta)
{
struct netr_DELTA_TRUSTED_DOMAIN *trusted_domain = delta->delta_union.trusted_domain;
@@ -108,7 +105,6 @@ static NTSTATUS vampire_samdump_handle_trusted_domain(TALLOC_CTX *mem_ctx,
static NTSTATUS libnet_samdump_fn(TALLOC_CTX *mem_ctx,
void *private,
- struct creds_CredentialState *creds,
enum netr_SamDatabaseID database,
struct netr_DELTA_ENUM *delta,
char **error_string)
@@ -123,7 +119,6 @@ static NTSTATUS libnet_samdump_fn(TALLOC_CTX *mem_ctx,
/* not interested in builtin users */
if (database == SAM_DATABASE_DOMAIN) {
nt_status = vampire_samdump_handle_user(mem_ctx,
- creds,
delta);
break;
}
@@ -132,7 +127,6 @@ static NTSTATUS libnet_samdump_fn(TALLOC_CTX *mem_ctx,
{
nt_status = vampire_samdump_handle_secret(mem_ctx,
samdump_state,
- creds,
delta);
break;
}
@@ -140,7 +134,6 @@ static NTSTATUS libnet_samdump_fn(TALLOC_CTX *mem_ctx,
{
nt_status = vampire_samdump_handle_trusted_domain(mem_ctx,
samdump_state,
- creds,
delta);
break;
}
@@ -169,11 +162,13 @@ NTSTATUS libnet_SamDump(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct
r2.out.error_string = NULL;
r2.in.binding_string = r->in.binding_string;
+ r2.in.init_fn = NULL;
r2.in.delta_fn = libnet_samdump_fn;
r2.in.fn_ctx = samdump_state;
r2.in.machine_account = r->in.machine_account;
nt_status = libnet_SamSync_netlogon(ctx, samdump_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(samdump_state);
diff --git a/source4/libnet/libnet_samdump_keytab.c b/source4/libnet/libnet_samdump_keytab.c
index f16e0ae383f..de575ec6689 100644
--- a/source4/libnet/libnet_samdump_keytab.c
+++ b/source4/libnet/libnet_samdump_keytab.c
@@ -27,7 +27,6 @@
static NTSTATUS samdump_keytab_handle_user(TALLOC_CTX *mem_ctx,
const char *keytab_name,
- struct creds_CredentialState *creds,
struct netr_DELTA_ENUM *delta)
{
struct netr_DELTA_USER *user = delta->delta_union.user;
@@ -66,7 +65,6 @@ static NTSTATUS samdump_keytab_handle_user(TALLOC_CTX *mem_ctx,
static NTSTATUS libnet_samdump_keytab_fn(TALLOC_CTX *mem_ctx,
void *private,
- struct creds_CredentialState *creds,
enum netr_SamDatabaseID database,
struct netr_DELTA_ENUM *delta,
char **error_string)
@@ -82,7 +80,6 @@ static NTSTATUS libnet_samdump_keytab_fn(TALLOC_CTX *mem_ctx,
if (database == SAM_DATABASE_DOMAIN) {
nt_status = samdump_keytab_handle_user(mem_ctx,
keytab_name,
- creds,
delta);
break;
}
@@ -101,11 +98,13 @@ NTSTATUS libnet_SamDump_keytab(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
r2.out.error_string = NULL;
r2.in.binding_string = r->in.binding_string;
+ r2.in.init_fn = NULL;
r2.in.delta_fn = libnet_samdump_keytab_fn;
r2.in.fn_ctx = discard_const(r->in.keytab_name);
r2.in.machine_account = r->in.machine_account;
nt_status = libnet_SamSync_netlogon(ctx, mem_ctx, &r2);
r->out.error_string = r2.out.error_string;
+ talloc_steal(mem_ctx, r->out.error_string);
if (!NT_STATUS_IS_OK(nt_status)) {
return nt_status;
diff --git a/source4/libnet/libnet_samsync_ldb.c b/source4/libnet/libnet_samsync_ldb.c
index 5587f208ef9..da4e777a153 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);
diff --git a/source4/libnet/libnet_vampire.c b/source4/libnet/libnet_vampire.c
index da8c3b49d11..b9fb37fea63 100644
--- a/source4/libnet/libnet_vampire.c
+++ b/source4/libnet/libnet_vampire.c
@@ -152,7 +152,7 @@ NTSTATUS libnet_SamSync_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx
struct cli_credentials *machine_account;
struct dcerpc_pipe *p;
struct libnet_context *machine_net_ctx;
- struct libnet_RpcConnect *c;
+ struct libnet_RpcConnectDCInfo *c;
const enum netr_SamDatabaseID database_ids[] = {SAM_DATABASE_DOMAIN, SAM_DATABASE_BUILTIN, SAM_DATABASE_PRIVS};
int i;
@@ -187,7 +187,7 @@ NTSTATUS libnet_SamSync_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
}
- c = talloc(samsync_ctx, struct libnet_RpcConnect);
+ c = talloc(samsync_ctx, struct libnet_RpcConnectDCInfo);
if (!c) {
r->out.error_string = NULL;
talloc_free(samsync_ctx);
@@ -217,7 +217,7 @@ NTSTATUS libnet_SamSync_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx
machine_net_ctx->cred = machine_account;
/* connect to the NETLOGON pipe of the PDC */
- nt_status = libnet_RpcConnect(machine_net_ctx, c, c);
+ nt_status = libnet_RpcConnectDCInfo(machine_net_ctx, c);
if (!NT_STATUS_IS_OK(nt_status)) {
if (r->in.binding_string) {
r->out.error_string = talloc_asprintf(mem_ctx,
@@ -258,6 +258,26 @@ NTSTATUS libnet_SamSync_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx
return nt_status;
}
+ /* initialise the callback layer. It may wish to contact the
+ * server with ldap, now we know the name */
+
+ if (r->in.init_fn) {
+ char *error_string;
+ nt_status = r->in.init_fn(samsync_ctx,
+ r->in.fn_ctx,
+ machine_net_ctx,
+ p,
+ c->out.domain_name,
+ c->out.domain_sid,
+ c->out.realm,
+ &error_string);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ r->out.error_string = talloc_steal(mem_ctx, error_string);
+ talloc_free(samsync_ctx);
+ return nt_status;
+ }
+ }
+
/* get NETLOGON credentails */
nt_status = dcerpc_schannel_creds(p->conn->security_state.generic_state, samsync_ctx, &creds);
@@ -285,13 +305,13 @@ NTSTATUS libnet_SamSync_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx
dbsync_nt_status = dcerpc_netr_DatabaseSync(p, loop_ctx, &dbsync);
if (!NT_STATUS_IS_OK(dbsync_nt_status) &&
!NT_STATUS_EQUAL(dbsync_nt_status, STATUS_MORE_ENTRIES)) {
- r->out.error_string = talloc_asprintf(samsync_ctx, "DatabaseSync failed - %s", nt_errstr(nt_status));
+ r->out.error_string = talloc_asprintf(mem_ctx, "DatabaseSync failed - %s", nt_errstr(nt_status));
talloc_free(samsync_ctx);
return nt_status;
}
if (!creds_client_check(creds, &dbsync.out.return_authenticator.cred)) {
- r->out.error_string = talloc_strdup(samsync_ctx, "Credential chaining failed");
+ r->out.error_string = talloc_strdup(mem_ctx, "Credential chaining on incoming DatabaseSync failed");
talloc_free(samsync_ctx);
return NT_STATUS_ACCESS_DENIED;
}
@@ -310,7 +330,7 @@ NTSTATUS libnet_SamSync_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx
&dbsync.out.delta_enum_array->delta_enum[d],
&error_string);
if (!NT_STATUS_IS_OK(nt_status)) {
- r->out.error_string = talloc_steal(samsync_ctx, error_string);
+ r->out.error_string = talloc_steal(mem_ctx, error_string);
talloc_free(samsync_ctx);
return nt_status;
}
@@ -320,12 +340,11 @@ NTSTATUS libnet_SamSync_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx
* write to an ldb */
nt_status = r->in.delta_fn(delta_ctx,
r->in.fn_ctx,
- creds,
dbsync.in.database_id,
&dbsync.out.delta_enum_array->delta_enum[d],
&error_string);
if (!NT_STATUS_IS_OK(nt_status)) {
- r->out.error_string = talloc_steal(samsync_ctx, error_string);
+ r->out.error_string = talloc_steal(mem_ctx, error_string);
talloc_free(samsync_ctx);
return nt_status;
}
@@ -333,7 +352,13 @@ NTSTATUS libnet_SamSync_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx
}
talloc_free(loop_ctx);
} while (NT_STATUS_EQUAL(dbsync_nt_status, STATUS_MORE_ENTRIES));
- nt_status = dbsync_nt_status;
+
+ if (!NT_STATUS_IS_OK(dbsync_nt_status)) {
+ r->out.error_string = talloc_asprintf(mem_ctx, "libnet_SamSync_netlogon failed: unexpected inconsistancy. Should not get error %s here", nt_errstr(nt_status));
+ talloc_free(samsync_ctx);
+ return dbsync_nt_status;
+ }
+ nt_status = NT_STATUS_OK;
}
talloc_free(samsync_ctx);
return nt_status;
diff --git a/source4/libnet/libnet_vampire.h b/source4/libnet/libnet_vampire.h
index 4bbdf2733a9..03a085aa871 100644
--- a/source4/libnet/libnet_vampire.h
+++ b/source4/libnet/libnet_vampire.h
@@ -24,9 +24,16 @@
struct libnet_SamSync {
struct {
const char *binding_string;
+ NTSTATUS (*init_fn)(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);
NTSTATUS (*delta_fn)(TALLOC_CTX *mem_ctx,
void *private,
- struct creds_CredentialState *creds,
enum netr_SamDatabaseID database,
struct netr_DELTA_ENUM *delta,
char **error_string);