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

📄 dcerpc.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 3 页
字号:
	talloc_free(req);	return status;}/*  perform a full request/response pair on a dcerpc pipe*/NTSTATUS dcerpc_request(struct dcerpc_pipe *p, 			struct GUID *object,			uint16_t opnum,			bool async,			TALLOC_CTX *mem_ctx,			DATA_BLOB *stub_data_in,			DATA_BLOB *stub_data_out){	struct rpc_request *req;	req = dcerpc_request_send(p, object, opnum, async, stub_data_in);	if (req == NULL) {		return NT_STATUS_NO_MEMORY;	}	return dcerpc_request_recv(req, mem_ctx, stub_data_out);}/*  this is a paranoid NDR validator. For every packet we push onto the wire  we pull it back again, then push it again. Then we compare the raw NDR data  for that to the NDR we initially generated. If they don't match then we know  we must have a bug in either the pull or push side of our code*/static NTSTATUS dcerpc_ndr_validate_in(struct dcerpc_connection *c, 				       TALLOC_CTX *mem_ctx,				       DATA_BLOB blob,				       size_t struct_size,				       ndr_push_flags_fn_t ndr_push,				       ndr_pull_flags_fn_t ndr_pull){	void *st;	struct ndr_pull *pull;	struct ndr_push *push;	DATA_BLOB blob2;	enum ndr_err_code ndr_err;	st = talloc_size(mem_ctx, struct_size);	if (!st) {		return NT_STATUS_NO_MEMORY;	}	pull = ndr_pull_init_flags(c, &blob, mem_ctx);	if (!pull) {		return NT_STATUS_NO_MEMORY;	}	pull->flags |= LIBNDR_FLAG_REF_ALLOC;	ndr_err = ndr_pull(pull, NDR_IN, st);	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {		NTSTATUS status = ndr_map_error2ntstatus(ndr_err);		ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,					 "failed input validation pull - %s",					 nt_errstr(status));		return ndr_map_error2ntstatus(ndr_err);	}	push = ndr_push_init_ctx(mem_ctx, c->iconv_convenience);	if (!push) {		return NT_STATUS_NO_MEMORY;	}		ndr_err = ndr_push(push, NDR_IN, st);	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {		NTSTATUS status = ndr_map_error2ntstatus(ndr_err);		ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,					 "failed input validation push - %s",					 nt_errstr(status));		return ndr_map_error2ntstatus(ndr_err);	}	blob2 = ndr_push_blob(push);	if (data_blob_cmp(&blob, &blob2) != 0) {		DEBUG(3,("original:\n"));		dump_data(3, blob.data, blob.length);		DEBUG(3,("secondary:\n"));		dump_data(3, blob2.data, blob2.length);		ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,					 "failed input validation blobs doesn't match");		return ndr_map_error2ntstatus(ndr_err);	}	return NT_STATUS_OK;}/*  this is a paranoid NDR input validator. For every packet we pull  from the wire we push it back again then pull and push it  again. Then we compare the raw NDR data for that to the NDR we  initially generated. If they don't match then we know we must have a  bug in either the pull or push side of our code*/static NTSTATUS dcerpc_ndr_validate_out(struct dcerpc_connection *c,					struct ndr_pull *pull_in,					void *struct_ptr,					size_t struct_size,					ndr_push_flags_fn_t ndr_push,					ndr_pull_flags_fn_t ndr_pull,					ndr_print_function_t ndr_print){	void *st;	struct ndr_pull *pull;	struct ndr_push *push;	DATA_BLOB blob, blob2;	TALLOC_CTX *mem_ctx = pull_in;	char *s1, *s2;	enum ndr_err_code ndr_err;	st = talloc_size(mem_ctx, struct_size);	if (!st) {		return NT_STATUS_NO_MEMORY;	}	memcpy(st, struct_ptr, struct_size);	push = ndr_push_init_ctx(mem_ctx, c->iconv_convenience);	if (!push) {		return NT_STATUS_NO_MEMORY;	}		ndr_err = ndr_push(push, NDR_OUT, struct_ptr);	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {		NTSTATUS status = ndr_map_error2ntstatus(ndr_err);		ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,					 "failed output validation push - %s",					 nt_errstr(status));		return ndr_map_error2ntstatus(ndr_err);	}	blob = ndr_push_blob(push);	pull = ndr_pull_init_flags(c, &blob, mem_ctx);	if (!pull) {		return NT_STATUS_NO_MEMORY;	}	pull->flags |= LIBNDR_FLAG_REF_ALLOC;	ndr_err = ndr_pull(pull, NDR_OUT, st);	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {		NTSTATUS status = ndr_map_error2ntstatus(ndr_err);		ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,					 "failed output validation pull - %s",					 nt_errstr(status));		return ndr_map_error2ntstatus(ndr_err);	}	push = ndr_push_init_ctx(mem_ctx, c->iconv_convenience);	if (!push) {		return NT_STATUS_NO_MEMORY;	}		ndr_err = ndr_push(push, NDR_OUT, st);	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {		NTSTATUS status = ndr_map_error2ntstatus(ndr_err);		ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,					 "failed output validation push2 - %s",					 nt_errstr(status));		return ndr_map_error2ntstatus(ndr_err);	}	blob2 = ndr_push_blob(push);	if (data_blob_cmp(&blob, &blob2) != 0) {		DEBUG(3,("original:\n"));		dump_data(3, blob.data, blob.length);		DEBUG(3,("secondary:\n"));		dump_data(3, blob2.data, blob2.length);		ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,					 "failed output validation blobs doesn't match");		return ndr_map_error2ntstatus(ndr_err);	}	/* this checks the printed forms of the two structures, which effectively	   tests all of the value() attributes */	s1 = ndr_print_function_string(mem_ctx, ndr_print, "VALIDATE", 				       NDR_OUT, struct_ptr);	s2 = ndr_print_function_string(mem_ctx, ndr_print, "VALIDATE", 				       NDR_OUT, st);	if (strcmp(s1, s2) != 0) {#if 1		DEBUG(3,("VALIDATE ERROR:\nWIRE:\n%s\n GEN:\n%s\n", s1, s2));#else		/* this is sometimes useful */		printf("VALIDATE ERROR\n");		file_save("wire.dat", s1, strlen(s1));		file_save("gen.dat", s2, strlen(s2));		system("diff -u wire.dat gen.dat");#endif		ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,					 "failed output validation strings doesn't match");		return ndr_map_error2ntstatus(ndr_err);	}	return NT_STATUS_OK;}/** send a rpc request given a dcerpc_call structure  */struct rpc_request *dcerpc_ndr_request_send(struct dcerpc_pipe *p,						const struct GUID *object,						const struct ndr_interface_table *table,						uint32_t opnum, 						TALLOC_CTX *mem_ctx, 						void *r){	const struct ndr_interface_call *call;	struct ndr_push *push;	NTSTATUS status;	DATA_BLOB request;	struct rpc_request *req;	enum ndr_err_code ndr_err;	call = &table->calls[opnum];	/* setup for a ndr_push_* call */	push = ndr_push_init_ctx(mem_ctx, p->conn->iconv_convenience);	if (!push) {		return NULL;	}	if (p->conn->flags & DCERPC_PUSH_BIGENDIAN) {		push->flags |= LIBNDR_FLAG_BIGENDIAN;	}	/* push the structure into a blob */	ndr_err = call->ndr_push(push, NDR_IN, r);	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {		status = ndr_map_error2ntstatus(ndr_err);		DEBUG(2,("Unable to ndr_push structure in dcerpc_ndr_request_send - %s\n",			 nt_errstr(status)));		talloc_free(push);		return NULL;	}	/* retrieve the blob */	request = ndr_push_blob(push);	if (p->conn->flags & DCERPC_DEBUG_VALIDATE_IN) {		status = dcerpc_ndr_validate_in(p->conn, push, request, call->struct_size, 						call->ndr_push, call->ndr_pull);		if (!NT_STATUS_IS_OK(status)) {			DEBUG(2,("Validation failed in dcerpc_ndr_request_send - %s\n",				 nt_errstr(status)));			talloc_free(push);			return NULL;		}	}	DEBUG(10,("rpc request data:\n"));	dump_data(10, request.data, request.length);	/* make the actual dcerpc request */	req = dcerpc_request_send(p, object, opnum, table->calls[opnum].async,				  &request);	if (req != NULL) {		req->ndr.table = table;		req->ndr.opnum = opnum;		req->ndr.struct_ptr = r;		req->ndr.mem_ctx = mem_ctx;	}	talloc_free(push);	return req;}/*  receive the answer from a dcerpc_ndr_request_send()*/_PUBLIC_ NTSTATUS dcerpc_ndr_request_recv(struct rpc_request *req){	struct dcerpc_pipe *p = req->p;	NTSTATUS status;	DATA_BLOB response;	struct ndr_pull *pull;	uint_t flags;	TALLOC_CTX *mem_ctx = req->ndr.mem_ctx;	void *r = req->ndr.struct_ptr;	uint32_t opnum = req->ndr.opnum;	const struct ndr_interface_table *table = req->ndr.table;	const struct ndr_interface_call *call = &table->calls[opnum];	enum ndr_err_code ndr_err;	/* make sure the recv code doesn't free the request, as we	   need to grab the flags element before it is freed */	if (talloc_reference(p, req) == NULL) {		return NT_STATUS_NO_MEMORY;	}	status = dcerpc_request_recv(req, mem_ctx, &response);	if (!NT_STATUS_IS_OK(status)) {		talloc_unlink(p, req);		return status;	}	flags = req->flags;	/* prepare for ndr_pull_* */	pull = ndr_pull_init_flags(p->conn, &response, mem_ctx);	if (!pull) {		talloc_unlink(p, req);		return NT_STATUS_NO_MEMORY;	}	if (pull->data) {		pull->data = talloc_steal(pull, pull->data);	}	talloc_unlink(p, req);	if (flags & DCERPC_PULL_BIGENDIAN) {		pull->flags |= LIBNDR_FLAG_BIGENDIAN;	}	DEBUG(10,("rpc reply data:\n"));	dump_data(10, pull->data, pull->data_size);	/* pull the structure from the blob */	ndr_err = call->ndr_pull(pull, NDR_OUT, r);	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {		status = ndr_map_error2ntstatus(ndr_err);		dcerpc_log_packet(table, opnum, NDR_OUT, 				  &response);		return status;	}	if (p->conn->flags & DCERPC_DEBUG_VALIDATE_OUT) {		status = dcerpc_ndr_validate_out(p->conn, pull, r, call->struct_size, 						 call->ndr_push, call->ndr_pull, 						 call->ndr_print);		if (!NT_STATUS_IS_OK(status)) {			dcerpc_log_packet(table, opnum, NDR_OUT, 				  &response);			return status;		}	}	if (pull->offset != pull->data_size) {		DEBUG(0,("Warning! ignoring %d unread bytes in rpc packet!\n", 			 pull->data_size - pull->offset));		/* we used to return NT_STATUS_INFO_LENGTH_MISMATCH here,		   but it turns out that early versions of NT		   (specifically NT3.1) add junk onto the end of rpc		   packets, so if we want to interoperate at all with		   those versions then we need to ignore this error */	}	/* TODO: make pull context independent from the output mem_ctx and free the pull context */	return NT_STATUS_OK;}/*  a useful helper function for synchronous rpc requests   this can be used when you have ndr push/pull functions in the  standard format*/_PUBLIC_ NTSTATUS dcerpc_ndr_request(struct dcerpc_pipe *p,			    const struct GUID *object,			    const struct ndr_interface_table *table,			    uint32_t opnum, 			    TALLOC_CTX *mem_ctx, 			    void *r){	struct rpc_request *req;	req = dcerpc_ndr_request_send(p, object, table, opnum, mem_ctx, r);	if (req == NULL) {		return NT_STATUS_NO_MEMORY;	}	return dcerpc_ndr_request_recv(req);}/*  a useful function for retrieving the server name we connected to*/_PUBLIC_ const char *dcerpc_server_name(struct dcerpc_pipe *p){	if (!p->conn->transport.target_hostname) {		if (!p->conn->transport.peer_name) {			return "";		}		return p->conn->transport.peer_name(p->conn);	}	return p->conn->transport.target_hostname(p->conn);}/*  get the dcerpc auth_level for a open connection*/uint32_t dcerpc_auth_level(struct dcerpc_connection *c) {	uint8_t auth_level;	if (c->flags & DCERPC_SEAL) {		auth_level = DCERPC_AUTH_LEVEL_PRIVACY;	} else if (c->flags & DCERPC_SIGN) {		auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;	} else if (c->flags & DCERPC_CONNECT) {		auth_level = DCERPC_AUTH_LEVEL_CONNECT;	} else {		auth_level = DCERPC_AUTH_LEVEL_NONE;	}	return auth_level;}/*  Receive an alter reply from the transport*/static void dcerpc_alter_recv_handler(struct rpc_request *req,				      DATA_BLOB *raw_packet, struct ncacn_packet *pkt){	struct composite_context *c;	struct dcerpc_pipe *recv_pipe;	c = talloc_get_type(req->async.private_data, struct composite_context);	recv_pipe = talloc_get_type(c->private_data, struct dcerpc_pipe);	if (pkt->ptype == DCERPC_PKT_ALTER_RESP &&	    pkt->u.alter_resp.num_results == 1 &&	    pkt->u.alter_resp.ctx_list[0].result != 0) {		DEBUG(2,("dcerpc: alter_resp failed - reason %d\n", 			 pkt->u.alter_resp.ctx_list[0].reason));		composite_error(c, dcerpc_map_reason(pkt->u.alter_resp.ctx_list[0].reason));		return;	}	if (pkt->ptype != DCERPC_PKT_ALTER_RESP ||	    pkt->u.alter_resp.num_results == 0 ||	    pkt->u.alter_resp.ctx_list[0].result != 0) {		composite_error(c, NT_STATUS_NET_WRITE_FAULT);		return;	}	/* the alter_resp might contain a reply set of credentials */	if (recv_pipe->conn->security_state.auth_info &&	    pkt->u.alter_resp.auth_info.length) {		enum ndr_err_code ndr_err;		ndr_err = ndr_pull_struct_blob(			&pkt->u.alter_resp.auth_info, recv_pipe,			NULL,			recv_pipe->conn->security_state.auth_info,			(ndr_pull_flags_fn_t)ndr_pull_dcerpc_auth);		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {			c->status = ndr_map_error2ntstatus(ndr_err);			if (!composite_is_ok(c)) return;		}	}	composite_done(c);}/*    send a dcerpc alter_context request*/struct composite_context *dcerpc_alter_context_send(struct dcerpc_pipe *p, 						    TALLOC_CTX *mem_ctx,						    const struct ndr_syntax_id *syntax,						    const struct ndr_syntax_id *transfer_syntax){	struct composite_context *c;	struct ncacn_packet pkt;	DATA_BLOB blob;	struct rpc_request *req;	c = composite_create(mem_ctx, p->conn->event_ctx);	if (c == NULL) return NULL;	c->private_data = p;	p->syntax = *syntax;	p->transfer_syntax = *transfer_syntax;	init_ncacn_hdr(p->conn, &pkt);	pkt.ptype = DCERPC_PKT_ALTER;	pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;	pkt.call_id = p->conn->call_id;	pkt.auth_length = 0;	if (p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) {		pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;	}	pkt.u.alter.max_xmit_frag = 5840;	pkt.u.alter.max_recv_frag = 5840;	pkt.u.alter.assoc_group_id = p->binding->assoc_group_id;	pkt.u.alter.num_contexts = 1;	pkt.u.alter.ctx_list = talloc_array(c, struct dcerpc_ctx_list, 1);	if (composite_nomem(pkt.u.alter.ctx_list, c)) return c;	pkt.u.alter.ctx_list[0].context_id = p->context_id;	pkt.u.alter.ctx_list[0].num_transfer_syntaxes = 1;	pkt.u.alter.ctx_list[0].abstract_syntax = p->syntax;	pkt.u.alter.ctx_list[0].transfer_syntaxes = &p->transfer_syntax;	pkt.u.alter.auth_info = data_blob(NULL, 0);	/* construct the NDR form of the packet */	c->status = ncacn_push_auth(&blob, mem_ctx, p->conn->iconv_convenience, &pkt,				    p->conn->security_state.auth_info);	if (!composite_is_ok(c)) return c;	p->conn->transport.recv_data = dcerpc_recv_data;	/*	 * we allocate a dcerpc_request so we can be in the same	 * request queue as normal requests	 */	req = talloc_zero(c, struct rpc_request);	if (composite_nomem(req, c)) return c;	req->state = RPC_REQUEST_PENDING;	req->call_id = pkt.call_id;	req->async.private_data = c;	req->async.callback = dcerpc_composite_fail;	req->p = p;	req->recv_handler = dcerpc_alter_recv_handler;	DLIST_ADD_END(p->conn->pending, req, struct rpc_request *);	talloc_set_destructor(req, dcerpc_req_dequeue);	c->status = p->conn->transport.send_request(p->conn, &blob, true);	if (!composite_is_ok(c)) return c;	event_add_timed(c->event_ctx, req,			timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),			dcerpc_timeout_handler, req);	return c;}NTSTATUS dcerpc_alter_context_recv(struct composite_context *ctx){	NTSTATUS result = composite_wait(ctx);	talloc_free(ctx);	return result;}/*    send a dcerpc alter_context request*/_PUBLIC_ NTSTATUS dcerpc_alter_context(struct dcerpc_pipe *p, 			      TALLOC_CTX *mem_ctx,			      const struct ndr_syntax_id *syntax,			      const struct ndr_syntax_id *transfer_syntax){	struct composite_context *creq;	creq = dcerpc_alter_context_send(p, mem_ctx, syntax, transfer_syntax);	return dcerpc_alter_context_recv(creq);}

⌨️ 快捷键说明

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