📄 dcerpc_util.c
字号:
/* Unix SMB/CIFS implementation. dcerpc utility functions Copyright (C) Andrew Tridgell 2003 Copyright (C) Jelmer Vernooij 2004 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005 Copyright (C) Rafal Szczesniak 2006 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 "lib/events/events.h"#include "libcli/composite/composite.h"#include "librpc/gen_ndr/ndr_epmapper_c.h"#include "librpc/gen_ndr/ndr_dcerpc.h"#include "librpc/gen_ndr/ndr_misc.h"#include "librpc/rpc/dcerpc_proto.h"#include "auth/credentials/credentials.h"#include "param/param.h"/* find a dcerpc call on an interface by name*/const struct ndr_interface_call *dcerpc_iface_find_call(const struct ndr_interface_table *iface, const char *name){ int i; for (i=0;i<iface->num_calls;i++) { if (strcmp(iface->calls[i].name, name) == 0) { return &iface->calls[i]; } } return NULL;}/* push a ncacn_packet into a blob, potentially with auth info*/NTSTATUS ncacn_push_auth(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, struct smb_iconv_convenience *iconv_convenience, struct ncacn_packet *pkt, struct dcerpc_auth *auth_info){ struct ndr_push *ndr; enum ndr_err_code ndr_err; ndr = ndr_push_init_ctx(mem_ctx, iconv_convenience); if (!ndr) { return NT_STATUS_NO_MEMORY; } if (!(pkt->drep[0] & DCERPC_DREP_LE)) { ndr->flags |= LIBNDR_FLAG_BIGENDIAN; } if (pkt->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) { ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT; } if (auth_info) { pkt->auth_length = auth_info->credentials.length; } else { pkt->auth_length = 0; } ndr_err = ndr_push_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return ndr_map_error2ntstatus(ndr_err); } if (auth_info) { ndr_err = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, auth_info); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return ndr_map_error2ntstatus(ndr_err); } } *blob = ndr_push_blob(ndr); /* fill in the frag length */ dcerpc_set_frag_length(blob, blob->length); return NT_STATUS_OK;}struct epm_map_binding_state { struct dcerpc_binding *binding; const struct ndr_interface_table *table; struct dcerpc_pipe *pipe; struct policy_handle handle; struct GUID guid; struct epm_twr_t twr; struct epm_twr_t *twr_r; struct epm_Map r;};static void continue_epm_recv_binding(struct composite_context *ctx);static void continue_epm_map(struct rpc_request *req);/* Stage 2 of epm_map_binding: Receive connected rpc pipe and send endpoint mapping rpc request*/static void continue_epm_recv_binding(struct composite_context *ctx){ struct rpc_request *map_req; struct composite_context *c = talloc_get_type(ctx->async.private_data, struct composite_context); struct epm_map_binding_state *s = talloc_get_type(c->private_data, struct epm_map_binding_state); /* receive result of rpc pipe connect request */ c->status = dcerpc_pipe_connect_b_recv(ctx, c, &s->pipe); if (!composite_is_ok(c)) return; s->pipe->conn->flags |= DCERPC_NDR_REF_ALLOC; /* prepare requested binding parameters */ s->binding->object = s->table->syntax_id; c->status = dcerpc_binding_build_tower(s->pipe, s->binding, &s->twr.tower); if (!composite_is_ok(c)) return; /* with some nice pretty paper around it of course */ s->r.in.object = &s->guid; s->r.in.map_tower = &s->twr; s->r.in.entry_handle = &s->handle; s->r.in.max_towers = 1; s->r.out.entry_handle = &s->handle; /* send request for an endpoint mapping - a rpc request on connected pipe */ map_req = dcerpc_epm_Map_send(s->pipe, c, &s->r); if (composite_nomem(map_req, c)) return; composite_continue_rpc(c, map_req, continue_epm_map, c);}/* Stage 3 of epm_map_binding: Receive endpoint mapping and provide binding details*/static void continue_epm_map(struct rpc_request *req){ struct composite_context *c = talloc_get_type(req->async.private_data, struct composite_context); struct epm_map_binding_state *s = talloc_get_type(c->private_data, struct epm_map_binding_state); /* receive result of a rpc request */ c->status = dcerpc_ndr_request_recv(req); if (!composite_is_ok(c)) return; /* check the details */ if (s->r.out.result != 0 || *s->r.out.num_towers != 1) { composite_error(c, NT_STATUS_PORT_UNREACHABLE); return; } s->twr_r = s->r.out.towers[0].twr; if (s->twr_r == NULL) { composite_error(c, NT_STATUS_PORT_UNREACHABLE); return; } if (s->twr_r->tower.num_floors != s->twr.tower.num_floors || s->twr_r->tower.floors[3].lhs.protocol != s->twr.tower.floors[3].lhs.protocol) { composite_error(c, NT_STATUS_PORT_UNREACHABLE); return; } /* get received endpoint */ s->binding->endpoint = talloc_reference(s->binding, dcerpc_floor_get_rhs_data(c, &s->twr_r->tower.floors[3])); if (composite_nomem(s->binding->endpoint, c)) return; composite_done(c);}/* Request for endpoint mapping of dcerpc binding - try to request for endpoint unless there is default one.*/struct composite_context *dcerpc_epm_map_binding_send(TALLOC_CTX *mem_ctx, struct dcerpc_binding *binding, const struct ndr_interface_table *table, struct event_context *ev, struct loadparm_context *lp_ctx){ struct composite_context *c; struct epm_map_binding_state *s; struct composite_context *pipe_connect_req; struct cli_credentials *anon_creds; NTSTATUS status; struct dcerpc_binding *epmapper_binding; int i; if (ev == NULL) { return NULL; } /* composite context allocation and setup */ c = composite_create(mem_ctx, ev); if (c == NULL) { return NULL; } s = talloc_zero(c, struct epm_map_binding_state); if (composite_nomem(s, c)) return c; c->private_data = s; s->binding = binding; s->table = table; /* anonymous credentials for rpc connection used to get endpoint mapping */ anon_creds = cli_credentials_init(mem_ctx); cli_credentials_set_anonymous(anon_creds); /* First, check if there is a default endpoint specified in the IDL */ if (table != NULL) { struct dcerpc_binding *default_binding; /* Find one of the default pipes for this interface */ for (i = 0; i < table->endpoints->count; i++) { status = dcerpc_parse_binding(mem_ctx, table->endpoints->names[i], &default_binding); if (NT_STATUS_IS_OK(status)) { if (binding->transport == NCA_UNKNOWN) binding->transport = default_binding->transport; if (default_binding->transport == binding->transport && default_binding->endpoint) { binding->endpoint = talloc_reference(binding, default_binding->endpoint); talloc_free(default_binding); composite_done(c); return c; } else { talloc_free(default_binding); } } } } epmapper_binding = talloc_zero(c, struct dcerpc_binding); if (composite_nomem(epmapper_binding, c)) return c; /* basic endpoint mapping data */ epmapper_binding->transport = binding->transport; epmapper_binding->host = talloc_reference(epmapper_binding, binding->host); epmapper_binding->target_hostname = epmapper_binding->host; epmapper_binding->options = NULL; epmapper_binding->flags = 0; epmapper_binding->assoc_group_id = 0; epmapper_binding->endpoint = NULL; /* initiate rpc pipe connection */ pipe_connect_req = dcerpc_pipe_connect_b_send(c, epmapper_binding, &ndr_table_epmapper, anon_creds, c->event_ctx, lp_ctx); if (composite_nomem(pipe_connect_req, c)) return c; composite_continue(c, pipe_connect_req, continue_epm_recv_binding, c); return c;}/* Receive result of endpoint mapping request */NTSTATUS dcerpc_epm_map_binding_recv(struct composite_context *c){ NTSTATUS status = composite_wait(c); talloc_free(c); return status;}/* Get endpoint mapping for rpc connection*/_PUBLIC_ NTSTATUS dcerpc_epm_map_binding(TALLOC_CTX *mem_ctx, struct dcerpc_binding *binding, const struct ndr_interface_table *table, struct event_context *ev, struct loadparm_context *lp_ctx){ struct composite_context *c; c = dcerpc_epm_map_binding_send(mem_ctx, binding, table, ev, lp_ctx); return dcerpc_epm_map_binding_recv(c);}struct pipe_auth_state { struct dcerpc_pipe *pipe; struct dcerpc_binding *binding; const struct ndr_interface_table *table; struct loadparm_context *lp_ctx; struct cli_credentials *credentials;};static void continue_auth_schannel(struct composite_context *ctx);static void continue_auth(struct composite_context *ctx);static void continue_auth_none(struct composite_context *ctx);static void continue_ntlmssp_connection(struct composite_context *ctx);static void continue_spnego_after_wrong_pass(struct composite_context *ctx);/* Stage 2 of pipe_auth: Receive result of schannel bind request*/static void continue_auth_schannel(struct composite_context *ctx){ struct composite_context *c = talloc_get_type(ctx->async.private_data, struct composite_context); c->status = dcerpc_bind_auth_schannel_recv(ctx); if (!composite_is_ok(c)) return; composite_done(c);}/* Stage 2 of pipe_auth: Receive result of authenticated bind request*/static void continue_auth(struct composite_context *ctx){ struct composite_context *c = talloc_get_type(ctx->async.private_data, struct composite_context); c->status = dcerpc_bind_auth_recv(ctx); if (!composite_is_ok(c)) return; composite_done(c);}/* Stage 2 of pipe_auth: Receive result of authenticated bind request, but handle fallbacks: SPNEGO -> NTLMSSP*/static void continue_auth_auto(struct composite_context *ctx){ struct composite_context *c = talloc_get_type(ctx->async.private_data,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -