summaryrefslogtreecommitdiff
path: root/source4/libnet/libnet_rpc.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_rpc.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_rpc.c')
-rw-r--r--source4/libnet/libnet_rpc.c191
1 files changed, 189 insertions, 2 deletions
diff --git a/source4/libnet/libnet_rpc.c b/source4/libnet/libnet_rpc.c
index 1f98e575d1..aba393d7fb 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;
+}
+