⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dcerpc_sock.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    Unix SMB/CIFS implementation.   dcerpc over standard sockets transport   Copyright (C) Andrew Tridgell 2003   Copyright (C) Jelmer Vernooij 2004   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 "lib/socket/socket.h"#include "lib/stream/packet.h"#include "libcli/composite/composite.h"#include "librpc/rpc/dcerpc.h"#include "librpc/rpc/dcerpc_proto.h"#include "libcli/resolve/resolve.h"#include "param/param.h"/* transport private information used by general socket pipe transports */struct sock_private {	struct fd_event *fde;	struct socket_context *sock;	char *server_name;	struct packet_context *packet;	uint32_t pending_reads;};/*  mark the socket dead*/static void sock_dead(struct dcerpc_connection *p, NTSTATUS status){	struct sock_private *sock = (struct sock_private *)p->transport.private_data;	if (!sock) return;	if (sock->packet) {		packet_recv_disable(sock->packet);		packet_set_fde(sock->packet, NULL);		packet_set_socket(sock->packet, NULL);	}	if (sock->fde) {		talloc_free(sock->fde);		sock->fde = NULL;	}	if (sock->sock) {		talloc_free(sock->sock);		sock->sock = NULL;	}	if (NT_STATUS_EQUAL(NT_STATUS_UNSUCCESSFUL, status)) {		status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;	}	if (NT_STATUS_EQUAL(NT_STATUS_OK, status)) {		status = NT_STATUS_END_OF_FILE;	}	if (p->transport.recv_data) {		p->transport.recv_data(p, NULL, status);	}}/*  handle socket recv errors*/static void sock_error_handler(void *private, NTSTATUS status){	struct dcerpc_connection *p = talloc_get_type(private, 						      struct dcerpc_connection);	sock_dead(p, status);}/*  check if a blob is a complete packet*/static NTSTATUS sock_complete_packet(void *private, DATA_BLOB blob, size_t *size){	if (blob.length < DCERPC_FRAG_LEN_OFFSET+2) {		return STATUS_MORE_ENTRIES;	}	*size = dcerpc_get_frag_length(&blob);	if (*size > blob.length) {		return STATUS_MORE_ENTRIES;	}	return NT_STATUS_OK;}/*  process recv requests*/static NTSTATUS sock_process_recv(void *private, DATA_BLOB blob){	struct dcerpc_connection *p = talloc_get_type(private, 						      struct dcerpc_connection);	struct sock_private *sock = (struct sock_private *)p->transport.private_data;	sock->pending_reads--;	if (sock->pending_reads == 0) {		packet_recv_disable(sock->packet);	}	p->transport.recv_data(p, &blob, NT_STATUS_OK);	return NT_STATUS_OK;}/*  called when a IO is triggered by the events system*/static void sock_io_handler(struct event_context *ev, struct fd_event *fde, 			    uint16_t flags, void *private){	struct dcerpc_connection *p = talloc_get_type(private, 						      struct dcerpc_connection);	struct sock_private *sock = (struct sock_private *)p->transport.private_data;	if (flags & EVENT_FD_WRITE) {		packet_queue_run(sock->packet);		return;	}	if (sock->sock == NULL) {		return;	}	if (flags & EVENT_FD_READ) {		packet_recv(sock->packet);	}}/*    initiate a read request - not needed for dcerpc sockets*/static NTSTATUS sock_send_read(struct dcerpc_connection *p){	struct sock_private *sock = (struct sock_private *)p->transport.private_data;	sock->pending_reads++;	if (sock->pending_reads == 1) {		packet_recv_enable(sock->packet);	}	return NT_STATUS_OK;}/*    send an initial pdu in a multi-pdu sequence*/static NTSTATUS sock_send_request(struct dcerpc_connection *p, DATA_BLOB *data, 				  bool trigger_read){	struct sock_private *sock = (struct sock_private *)p->transport.private_data;	DATA_BLOB blob;	NTSTATUS status;	if (sock->sock == NULL) {		return NT_STATUS_CONNECTION_DISCONNECTED;	}	blob = data_blob_talloc(sock->packet, data->data, data->length);	if (blob.data == NULL) {		return NT_STATUS_NO_MEMORY;	}	status = packet_send(sock->packet, blob);	if (!NT_STATUS_IS_OK(status)) {		return status;	}	if (trigger_read) {		sock_send_read(p);	}	return NT_STATUS_OK;}/*    shutdown sock pipe connection*/static NTSTATUS sock_shutdown_pipe(struct dcerpc_connection *p, NTSTATUS status){	struct sock_private *sock = (struct sock_private *)p->transport.private_data;	if (sock && sock->sock) {		sock_dead(p, status);	}	return status;}/*  return sock server name*/static const char *sock_peer_name(struct dcerpc_connection *p){	struct sock_private *sock = talloc_get_type(p->transport.private_data, struct sock_private);	return sock->server_name;}/*  return remote name we make the actual connection (good for kerberos) */static const char *sock_target_hostname(struct dcerpc_connection *p){	struct sock_private *sock = talloc_get_type(p->transport.private_data, struct sock_private);	return sock->server_name;}struct pipe_open_socket_state {	struct dcerpc_connection *conn;	struct socket_context *socket_ctx;	struct sock_private *sock;	struct socket_address *server;	const char *target_hostname;	enum dcerpc_transport_t transport;};static void continue_socket_connect(struct composite_context *ctx){	struct dcerpc_connection *conn;	struct sock_private *sock;	struct composite_context *c = talloc_get_type(ctx->async.private_data,						      struct composite_context);	struct pipe_open_socket_state *s = talloc_get_type(c->private_data,							   struct pipe_open_socket_state);	/* make it easier to write a function calls */	conn = s->conn;	sock = s->sock;	c->status = socket_connect_recv(ctx);	if (!NT_STATUS_IS_OK(c->status)) {		DEBUG(0, ("Failed to connect host %s on port %d - %s\n", 			  s->server->addr, s->server->port,			  nt_errstr(c->status)));		composite_error(c, c->status);		return;	}	/*	  fill in the transport methods	*/	conn->transport.transport       = s->transport;	conn->transport.private_data    = NULL;	conn->transport.send_request    = sock_send_request;	conn->transport.send_read       = sock_send_read;	conn->transport.recv_data       = NULL;	conn->transport.shutdown_pipe   = sock_shutdown_pipe;	conn->transport.peer_name       = sock_peer_name;	conn->transport.target_hostname = sock_target_hostname;	sock->sock          = s->socket_ctx;	sock->pending_reads = 0;	sock->server_name   = strupper_talloc(sock, s->target_hostname);	sock->fde = event_add_fd(conn->event_ctx, sock->sock, socket_get_fd(sock->sock),				 EVENT_FD_READ, sock_io_handler, conn);		conn->transport.private_data = sock;	sock->packet = packet_init(sock);	if (sock->packet == NULL) {		composite_error(c, NT_STATUS_NO_MEMORY);		talloc_free(sock);		return;	}	packet_set_private(sock->packet, conn);	packet_set_socket(sock->packet, sock->sock);	packet_set_callback(sock->packet, sock_process_recv);	packet_set_full_request(sock->packet, sock_complete_packet);	packet_set_error_handler(sock->packet, sock_error_handler);	packet_set_event_context(sock->packet, conn->event_ctx);	packet_set_fde(sock->packet, sock->fde);	packet_set_serialise(sock->packet);	packet_set_initial_read(sock->packet, 16);	/* ensure we don't get SIGPIPE */	BlockSignals(true, SIGPIPE);	composite_done(c);}static struct composite_context *dcerpc_pipe_open_socket_send(TALLOC_CTX *mem_ctx,						       struct dcerpc_connection *cn,						       struct resolve_context *resolve_context,						       struct socket_address *server,						       const char *target_hostname,						       enum dcerpc_transport_t transport){	struct composite_context *c;	struct pipe_open_socket_state *s;	struct composite_context *conn_req;	c = composite_create(mem_ctx, cn->event_ctx);	if (c == NULL) return NULL;	s = talloc_zero(c, struct pipe_open_socket_state);	if (composite_nomem(s, c)) return c;	c->private_data = s;	s->conn      = cn;	s->transport = transport;	s->server    = talloc_reference(c, server);	if (composite_nomem(s->server, c)) return c;	s->target_hostname = talloc_reference(s, target_hostname);	s->sock = talloc(cn, struct sock_private);	if (composite_nomem(s->sock, c)) return c;	c->status = socket_create(server->family, SOCKET_TYPE_STREAM, &s->socket_ctx, 0);	if (!composite_is_ok(c)) return c;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -