libnet_rpc.c
来自「samba最新软件」· C语言 代码 · 共 975 行 · 第 1/2 页
C
975 行
/* Unix SMB/CIFS implementation. Copyright (C) Stefan Metzmacher 2004 Copyright (C) Rafal Szczesniak 2005 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.*/#include "includes.h"#include "libnet/libnet.h"#include "libcli/libcli.h"#include "libcli/composite/composite.h"#include "librpc/rpc/dcerpc.h"#include "librpc/rpc/dcerpc_proto.h"#include "librpc/gen_ndr/ndr_lsa_c.h"#include "librpc/gen_ndr/ndr_samr.h"struct rpc_connect_srv_state { struct libnet_context *ctx; struct libnet_RpcConnect r; const char *binding; /* information about the progress */ void (*monitor_fn)(struct monitor_msg*);};static void continue_pipe_connect(struct composite_context *ctx);/** * Initiates connection to rpc pipe on remote server * * @param ctx initialised libnet context * @param mem_ctx memory context of this call * @param r data structure containing necessary parameters and return values * @return composite context of this call **/static struct composite_context* libnet_RpcConnectSrv_send(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_RpcConnect *r, void (*monitor)(struct monitor_msg*)){ struct composite_context *c; struct rpc_connect_srv_state *s; struct dcerpc_binding *b; struct composite_context *pipe_connect_req; /* composite context allocation and setup */ c = composite_create(ctx, ctx->event_ctx); if (c == NULL) return c; s = talloc_zero(c, struct rpc_connect_srv_state); if (composite_nomem(s, c)) return c; c->private_data = s; s->monitor_fn = monitor; s->ctx = ctx; s->r = *r; ZERO_STRUCT(s->r.out); /* prepare binding string */ switch (r->level) { case LIBNET_RPC_CONNECT_SERVER: s->binding = talloc_asprintf(s, "ncacn_np:%s", r->in.name); break; case LIBNET_RPC_CONNECT_SERVER_ADDRESS: s->binding = talloc_asprintf(s, "ncacn_np:%s", r->in.address); break; case LIBNET_RPC_CONNECT_BINDING: s->binding = talloc_strdup(s, r->in.binding); break; case LIBNET_RPC_CONNECT_DC: case LIBNET_RPC_CONNECT_PDC: /* this should never happen - DC and PDC level has a separate composite function */ case LIBNET_RPC_CONNECT_DC_INFO: /* this should never happen - DC_INFO level has a separate composite function */ composite_error(c, NT_STATUS_INVALID_LEVEL); return c; } /* parse binding string to the structure */ c->status = dcerpc_parse_binding(c, s->binding, &b); if (!NT_STATUS_IS_OK(c->status)) { DEBUG(0, ("Failed to parse dcerpc binding '%s'\n", s->binding)); composite_error(c, c->status); return c; } if (r->level == LIBNET_RPC_CONNECT_SERVER_ADDRESS) { b->target_hostname = talloc_reference(b, r->in.name); if (composite_nomem(b->target_hostname, c)) { return c; } } /* connect to remote dcerpc pipe */ pipe_connect_req = dcerpc_pipe_connect_b_send(c, b, r->in.dcerpc_iface, ctx->cred, c->event_ctx, ctx->lp_ctx); if (composite_nomem(pipe_connect_req, c)) return c; composite_continue(c, pipe_connect_req, continue_pipe_connect, c); return c;}/* Step 2 of RpcConnectSrv - get rpc connection*/static void continue_pipe_connect(struct composite_context *ctx){ struct composite_context *c; struct rpc_connect_srv_state *s; c = talloc_get_type(ctx->async.private_data, struct composite_context); s = talloc_get_type(c->private_data, struct rpc_connect_srv_state); /* receive result of rpc pipe connection */ c->status = dcerpc_pipe_connect_b_recv(ctx, c, &s->r.out.dcerpc_pipe); /* post monitor message */ if (s->monitor_fn) { struct monitor_msg msg; struct msg_net_rpc_connect data; struct dcerpc_binding *binding = s->r.out.dcerpc_pipe->binding; /* prepare monitor message and post it */ data.host = binding->host; data.endpoint = binding->endpoint; data.transport = binding->transport; data.domain_name = binding->target_hostname; msg.type = mon_NetRpcConnect; msg.data = (void*)&data; msg.data_size = sizeof(data); s->monitor_fn(&msg); } composite_done(c); }/** * Receives result of connection to rpc pipe on remote server * * @param c composite context * @param ctx initialised libnet context * @param mem_ctx memory context of this call * @param r data structure containing necessary parameters and return values * @return nt status of rpc connection **/static NTSTATUS libnet_RpcConnectSrv_recv(struct composite_context *c, struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_RpcConnect *r){ NTSTATUS status; struct rpc_connect_srv_state *s = talloc_get_type(c->private_data, struct rpc_connect_srv_state); status = composite_wait(c); if (NT_STATUS_IS_OK(status)) { /* move the returned rpc pipe between memory contexts */ s = talloc_get_type(c->private_data, struct rpc_connect_srv_state); r->out.dcerpc_pipe = talloc_steal(mem_ctx, s->r.out.dcerpc_pipe); /* reference created pipe structure to long-term libnet_context so that it can be used by other api functions even after short-term mem_ctx is freed */ if (r->in.dcerpc_iface == &ndr_table_samr) { ctx->samr.pipe = talloc_reference(ctx, r->out.dcerpc_pipe); } else if (r->in.dcerpc_iface == &ndr_table_lsarpc) { ctx->lsa.pipe = talloc_reference(ctx, r->out.dcerpc_pipe); } r->out.error_string = talloc_strdup(mem_ctx, "Success"); } else { r->out.error_string = talloc_asprintf(mem_ctx, "Error: %s", nt_errstr(status)); } talloc_free(c); return status;}struct rpc_connect_dc_state { struct libnet_context *ctx; struct libnet_RpcConnect r; struct libnet_RpcConnect r2; struct libnet_LookupDCs f; const char *connect_name; /* information about the progress */ void (*monitor_fn)(struct monitor_msg *);};static void continue_lookup_dc(struct composite_context *ctx);static void continue_rpc_connect(struct composite_context *ctx);/** * Initiates connection to rpc pipe on domain pdc * * @param ctx initialised libnet context * @param mem_ctx memory context of this call * @param r data structure containing necessary parameters and return values * @return composite context of this call **/static struct composite_context* libnet_RpcConnectDC_send(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_RpcConnect *r, void (*monitor)(struct monitor_msg *msg)){ struct composite_context *c; struct rpc_connect_dc_state *s; struct composite_context *lookup_dc_req; /* composite context allocation and setup */ c = composite_create(ctx, ctx->event_ctx); if (c == NULL) return c; s = talloc_zero(c, struct rpc_connect_dc_state); if (composite_nomem(s, c)) return c; c->private_data = s; s->monitor_fn = monitor; s->ctx = ctx; s->r = *r; ZERO_STRUCT(s->r.out); switch (r->level) { case LIBNET_RPC_CONNECT_PDC: s->f.in.name_type = NBT_NAME_PDC; break; case LIBNET_RPC_CONNECT_DC: s->f.in.name_type = NBT_NAME_LOGON; break; default: break; } s->f.in.domain_name = r->in.name; s->f.out.num_dcs = 0; s->f.out.dcs = NULL; /* find the domain pdc first */ lookup_dc_req = libnet_LookupDCs_send(ctx, c, &s->f); if (composite_nomem(lookup_dc_req, c)) return c; composite_continue(c, lookup_dc_req, continue_lookup_dc, c); return c;}/* Step 2 of RpcConnectDC: get domain controller name and initiate RpcConnect to it*/static void continue_lookup_dc(struct composite_context *ctx){ struct composite_context *c; struct rpc_connect_dc_state *s; struct composite_context *rpc_connect_req; struct monitor_msg msg; struct msg_net_lookup_dc data; c = talloc_get_type(ctx->async.private_data, struct composite_context); s = talloc_get_type(c->private_data, struct rpc_connect_dc_state); /* receive result of domain controller lookup */ c->status = libnet_LookupDCs_recv(ctx, c, &s->f); if (!composite_is_ok(c)) return; /* decide on preferred address type depending on DC type */ s->connect_name = s->f.out.dcs[0].name; /* post monitor message */ if (s->monitor_fn) { /* prepare a monitor message and post it */ data.domain_name = s->f.in.domain_name; data.hostname = s->f.out.dcs[0].name; data.address = s->f.out.dcs[0].address; msg.type = mon_NetLookupDc; msg.data = &data; msg.data_size = sizeof(data); s->monitor_fn(&msg); } /* ok, pdc has been found so do attempt to rpc connect */ s->r2.level = LIBNET_RPC_CONNECT_SERVER_ADDRESS; /* this will cause yet another name resolution, but at least * we pass the right name down the stack now */ s->r2.in.name = talloc_strdup(s, s->connect_name); s->r2.in.address = talloc_steal(s, s->f.out.dcs[0].address); s->r2.in.dcerpc_iface = s->r.in.dcerpc_iface; /* send rpc connect request to the server */ rpc_connect_req = libnet_RpcConnectSrv_send(s->ctx, c, &s->r2, s->monitor_fn); if (composite_nomem(rpc_connect_req, c)) return; composite_continue(c, rpc_connect_req, continue_rpc_connect, c);}/* Step 3 of RpcConnectDC: get rpc connection to the server*/static void continue_rpc_connect(struct composite_context *ctx){ struct composite_context *c; struct rpc_connect_dc_state *s; c = talloc_get_type(ctx->async.private_data, struct composite_context); s = talloc_get_type(c->private_data, struct rpc_connect_dc_state); c->status = libnet_RpcConnectSrv_recv(ctx, s->ctx, c, &s->r2); /* error string is to be passed anyway */ s->r.out.error_string = s->r2.out.error_string; if (!composite_is_ok(c)) return; s->r.out.dcerpc_pipe = s->r2.out.dcerpc_pipe; /* post monitor message */ if (s->monitor_fn) { struct monitor_msg msg; struct msg_net_rpc_connect data; struct dcerpc_binding *binding = s->r.out.dcerpc_pipe->binding; data.host = binding->host; data.endpoint = binding->endpoint; data.transport = binding->transport; data.domain_name = binding->target_hostname; msg.type = mon_NetRpcConnect; msg.data = (void*)&data; msg.data_size = sizeof(data); s->monitor_fn(&msg); } composite_done(c);}/** * Receives result of connection to rpc pipe on domain pdc * * @param c composite context * @param ctx initialised libnet context * @param mem_ctx memory context of this call * @param r data structure containing necessary parameters and return values * @return nt status of rpc connection **/static NTSTATUS libnet_RpcConnectDC_recv(struct composite_context *c, struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_RpcConnect *r){ NTSTATUS status; struct rpc_connect_dc_state *s = talloc_get_type(c->private_data, struct rpc_connect_dc_state); status = composite_wait(c); if (NT_STATUS_IS_OK(status)) { /* move connected rpc pipe between memory contexts */ r->out.dcerpc_pipe = talloc_steal(mem_ctx, s->r.out.dcerpc_pipe); /* reference created pipe structure to long-term libnet_context so that it can be used by other api functions even after short-term mem_ctx is freed */ if (r->in.dcerpc_iface == &ndr_table_samr) { ctx->samr.pipe = talloc_reference(ctx, r->out.dcerpc_pipe); } else if (r->in.dcerpc_iface == &ndr_table_lsarpc) { ctx->lsa.pipe = talloc_reference(ctx, r->out.dcerpc_pipe); } } else { r->out.error_string = talloc_asprintf(mem_ctx, "Failed to rpc connect: %s", nt_errstr(status)); } talloc_free(c); return status;}struct rpc_connect_dci_state { struct libnet_context *ctx; struct libnet_RpcConnect r; struct libnet_RpcConnect rpc_conn; struct policy_handle lsa_handle; struct lsa_QosInfo qos; struct lsa_ObjectAttribute attr; struct lsa_OpenPolicy2 lsa_open_policy; struct dcerpc_pipe *lsa_pipe; struct lsa_QueryInfoPolicy2 lsa_query_info2; struct lsa_QueryInfoPolicy lsa_query_info; struct dcerpc_binding *final_binding; struct dcerpc_pipe *final_pipe; /* information about the progress */ void (*monitor_fn)(struct monitor_msg*);};static void continue_dci_rpc_connect(struct composite_context *ctx);static void continue_lsa_policy(struct rpc_request *req);static void continue_lsa_query_info(struct rpc_request *req);static void continue_lsa_query_info2(struct rpc_request *req);static void continue_epm_map_binding(struct composite_context *ctx);static void continue_secondary_conn(struct composite_context *ctx);static void continue_epm_map_binding_send(struct composite_context *c);/** * Initiates connection to rpc pipe on remote server or pdc. Received result * contains info on the domain name, domain sid and realm. * * @param ctx initialised libnet context * @param mem_ctx memory context of this call * @param r data structure containing necessary parameters and return values. Must be a talloc context * @return composite context of this call **/static struct composite_context* libnet_RpcConnectDCInfo_send(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_RpcConnect *r, void (*monitor)(struct monitor_msg*)){ struct composite_context *c, *conn_req; struct rpc_connect_dci_state *s; /* composite context allocation and setup */ c = composite_create(ctx, ctx->event_ctx); if (c == NULL) return c; s = talloc_zero(c, struct rpc_connect_dci_state); if (composite_nomem(s, c)) return c; c->private_data = s; s->monitor_fn = monitor; s->ctx = ctx; s->r = *r; ZERO_STRUCT(s->r.out); /* proceed to pure rpc connection if the binding string is provided, otherwise try to connect domain controller */ if (r->in.binding == NULL) { s->rpc_conn.in.name = r->in.name; s->rpc_conn.level = LIBNET_RPC_CONNECT_DC; } else { s->rpc_conn.in.binding = r->in.binding; s->rpc_conn.level = LIBNET_RPC_CONNECT_BINDING;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?