[SCM] Samba Shared Repository - branch master updated

Stefan Metzmacher metze at samba.org
Thu May 27 00:27:58 MDT 2010


The branch, master has been updated
       via  85a3853... s3:rpc_server: make use of the npa_tstream code to connect to named pipes
       via  4afa54f... s3:Makefile.in: add npa_tstream.o to the build of smbd
       via  9a6636a... s3:rpc_server: pass down local and remote tsocket_address to np_open()
       via  56ebbb5... s3:smbd: add PIPE_BUSY handling for SMBtrans calls on named pipes
       via  9a77cb2... s3:rpc_server: add np_read_in_progress() function
       via  8c0be92... s3:rpc_server: make sure we don't send uninitialized memory for the named_pipe_auth handshake
      from  6a14dad... s3-net: fix the build.

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 85a385324958c41ac9c017421b35db1eeabed87c
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Apr 27 15:15:09 2010 +0200

    s3:rpc_server: make use of the npa_tstream code to connect to named pipes
    
    This way we use the newest protocol, which is able to pass
    the local and remote address of the SMB connection.
    
    And we correctly support message mode named pipes
    without the hack that analyzes the content for DCERPC pdus.
    
    metze

commit 4afa54fd53cdef1dd8b8e549d77ab02fdec09df4
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Apr 27 15:08:02 2010 +0200

    s3:Makefile.in: add npa_tstream.o to the build of smbd
    
    metze

commit 9a6636a56e3565202d71ae7049431e3764575b79
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Apr 27 15:12:32 2010 +0200

    s3:rpc_server: pass down local and remote tsocket_address to np_open()
    
    metze

commit 56ebbb53c80a49f2d8dda8a108afc07669af333e
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Apr 28 15:15:23 2010 +0200

    s3:smbd: add PIPE_BUSY handling for SMBtrans calls on named pipes
    
    metze

commit 9a77cb247d00828845df02030e7d174351daf432
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Apr 28 15:05:30 2010 +0200

    s3:rpc_server: add np_read_in_progress() function
    
    metze

commit 8c0be920442778c24e19f8a52d9f8bc385218834
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed May 26 10:43:19 2010 +0200

    s3:rpc_server: make sure we don't send uninitialized memory for the named_pipe_auth handshake
    
    metze

-----------------------------------------------------------------------

Summary of changes:
 source3/Makefile.in               |    4 +-
 source3/include/proto.h           |    5 +-
 source3/rpc_server/srv_pipe_hnd.c |  384 ++++++++++++++++++-------------------
 source3/smbd/ipc.c                |   11 +
 source3/smbd/pipes.c              |    5 +-
 5 files changed, 212 insertions(+), 197 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/Makefile.in b/source3/Makefile.in
index 1651644..72a7315 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -651,12 +651,14 @@ RPC_SPOOLSS_OBJ = rpc_server/srv_spoolss_nt.o \
 RPC_EVENTLOG_OBJ = rpc_server/srv_eventlog_nt.o \
 		   $(LIB_EVENTLOG_OBJ) librpc/gen_ndr/srv_eventlog.o
 
+NPA_TSTREAM_OBJ = ../libcli/named_pipe_auth/npa_tstream.o
+
 RPC_PIPE_OBJ = rpc_server/srv_pipe_hnd.o \
                rpc_server/srv_pipe.o rpc_server/srv_lsa_hnd.o
 
 RPC_ECHO_OBJ = rpc_server/srv_echo_nt.o librpc/gen_ndr/srv_echo.o
 
-RPC_SERVER_OBJ = @RPC_STATIC@ $(RPC_PIPE_OBJ)
+RPC_SERVER_OBJ = @RPC_STATIC@ $(RPC_PIPE_OBJ) $(NPA_TSTREAM_OBJ)
 
 RPC_PARSE_OBJ = $(RPC_PARSE_OBJ2)
 
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 92c757b..6c9790b 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -5205,10 +5205,13 @@ pipes_struct *get_first_internal_pipe(void);
 pipes_struct *get_next_internal_pipe(pipes_struct *p);
 
 bool fsp_is_np(struct files_struct *fsp);
+struct tsocket_address;
 NTSTATUS np_open(TALLOC_CTX *mem_ctx, const char *name,
-		 const char *client_address,
+		 const struct tsocket_address *local_address,
+		 const struct tsocket_address *remote_address,
 		 struct auth_serversupplied_info *server_info,
 		 struct fake_file_handle **phandle);
+bool np_read_in_progress(struct fake_file_handle *handle);
 struct tevent_req *np_write_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
 				 struct fake_file_handle *handle,
 				 const uint8_t *data, size_t len);
diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c
index 075d705..5ba9477 100644
--- a/source3/rpc_server/srv_pipe_hnd.c
+++ b/source3/rpc_server/srv_pipe_hnd.c
@@ -22,6 +22,7 @@
 #include "includes.h"
 #include "../librpc/gen_ndr/srv_spoolss.h"
 #include "librpc/gen_ndr/ndr_named_pipe_auth.h"
+#include "../libcli/named_pipe_auth/npa_tstream.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_RPC_SRV
@@ -956,40 +957,30 @@ bool fsp_is_np(struct files_struct *fsp)
 }
 
 struct np_proxy_state {
+	uint16_t file_type;
+	uint16_t device_state;
+	uint64_t allocation_size;
+	struct tstream_context *npipe;
 	struct tevent_queue *read_queue;
 	struct tevent_queue *write_queue;
-	int fd;
-
-	uint8_t *msg;
-	size_t sent;
 };
 
-static int np_proxy_state_destructor(struct np_proxy_state *state)
-{
-	if (state->fd != -1) {
-		close(state->fd);
-	}
-	return 0;
-}
-
 static struct np_proxy_state *make_external_rpc_pipe_p(TALLOC_CTX *mem_ctx,
-						       const char *pipe_name,
-						       struct auth_serversupplied_info *server_info)
+				const char *pipe_name,
+				const struct tsocket_address *local_address,
+				const struct tsocket_address *remote_address,
+				struct auth_serversupplied_info *server_info)
 {
 	struct np_proxy_state *result;
-	struct sockaddr_un addr;
-	char *socket_path;
+	char *socket_np_dir;
 	const char *socket_dir;
-
-	DATA_BLOB req_blob;
+	struct tevent_context *ev;
+	struct tevent_req *subreq;
 	struct netr_SamInfo3 *info3;
-	struct named_pipe_auth_req req;
-	DATA_BLOB rep_blob;
-	uint8 rep_buf[20];
-	struct named_pipe_auth_rep rep;
-	enum ndr_err_code ndr_err;
 	NTSTATUS status;
-	ssize_t written;
+	bool ok;
+	int ret;
+	int sys_errno;
 
 	result = talloc(mem_ctx, struct np_proxy_state);
 	if (result == NULL) {
@@ -997,15 +988,23 @@ static struct np_proxy_state *make_external_rpc_pipe_p(TALLOC_CTX *mem_ctx,
 		return NULL;
 	}
 
-	result->fd = socket(AF_UNIX, SOCK_STREAM, 0);
-	if (result->fd == -1) {
-		DEBUG(10, ("socket(2) failed: %s\n", strerror(errno)));
+	result->read_queue = tevent_queue_create(result, "np_read");
+	if (result->read_queue == NULL) {
+		DEBUG(0, ("tevent_queue_create failed\n"));
+		goto fail;
+	}
+
+	result->write_queue = tevent_queue_create(result, "np_write");
+	if (result->write_queue == NULL) {
+		DEBUG(0, ("tevent_queue_create failed\n"));
 		goto fail;
 	}
-	talloc_set_destructor(result, np_proxy_state_destructor);
 
-	ZERO_STRUCT(addr);
-	addr.sun_family = AF_UNIX;
+	ev = s3_tevent_context_init(talloc_tos());
+	if (ev == NULL) {
+		DEBUG(0, ("s3_tevent_context_init failed\n"));
+		goto fail;
+	}
 
 	socket_dir = lp_parm_const_string(
 		GLOBAL_SECTION_SNUM, "external_rpc_pipe", "socket_dir",
@@ -1014,26 +1013,13 @@ static struct np_proxy_state *make_external_rpc_pipe_p(TALLOC_CTX *mem_ctx,
 		DEBUG(0, ("externan_rpc_pipe:socket_dir not set\n"));
 		goto fail;
 	}
-
-	socket_path = talloc_asprintf(talloc_tos(), "%s/np/%s",
-				      socket_dir, pipe_name);
-	if (socket_path == NULL) {
+	socket_np_dir = talloc_asprintf(talloc_tos(), "%s/np", socket_dir);
+	if (socket_np_dir == NULL) {
 		DEBUG(0, ("talloc_asprintf failed\n"));
 		goto fail;
 	}
-	strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
-	TALLOC_FREE(socket_path);
-
-	become_root();
-	if (sys_connect(result->fd, (struct sockaddr *)&addr) == -1) {
-		unbecome_root();
-		DEBUG(0, ("connect(%s) failed: %s\n", addr.sun_path,
-			  strerror(errno)));
-		goto fail;
-	}
-	unbecome_root();
 
-	info3 = talloc(talloc_tos(), struct netr_SamInfo3);
+	info3 = talloc_zero(talloc_tos(), struct netr_SamInfo3);
 	if (info3 == NULL) {
 		DEBUG(0, ("talloc failed\n"));
 		goto fail;
@@ -1047,80 +1033,40 @@ static struct np_proxy_state *make_external_rpc_pipe_p(TALLOC_CTX *mem_ctx,
 		goto fail;
 	}
 
-	req.level = 1;
-	req.info.info1 = *info3;
-
-	ndr_err = ndr_push_struct_blob(&req_blob, talloc_tos(), &req,
-		(ndr_push_flags_fn_t)ndr_push_named_pipe_auth_req);
-
-	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-		DEBUG(10, ("ndr_push_named_pipe_auth_req failed: %s\n",
-			   ndr_errstr(ndr_err)));
-		goto fail;
-	}
-
-	DEBUG(10, ("named_pipe_auth_req(client)[%u]\n", (uint32_t)req_blob.length));
-	dump_data(10, req_blob.data, req_blob.length);
-
-	written = write_data(result->fd, (char *)req_blob.data,
-			     req_blob.length);
-	if (written == -1) {
-		DEBUG(3, ("Could not write auth req data to RPC server\n"));
-		goto fail;
-	}
-
-	status = read_data(result->fd, (char *)rep_buf, sizeof(rep_buf));
-	if (!NT_STATUS_IS_OK(status)) {
-		DEBUG(3, ("Could not read auth result\n"));
-		goto fail;
-	}
-
-	rep_blob = data_blob_const(rep_buf, sizeof(rep_buf));
-
-	DEBUG(10,("name_pipe_auth_rep(client)[%u]\n", (uint32_t)rep_blob.length));
-	dump_data(10, rep_blob.data, rep_blob.length);
-
-	ndr_err = ndr_pull_struct_blob(&rep_blob, talloc_tos(), &rep,
-		(ndr_pull_flags_fn_t)ndr_pull_named_pipe_auth_rep);
-
-	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-		DEBUG(0, ("ndr_pull_named_pipe_auth_rep failed: %s\n",
-			  ndr_errstr(ndr_err)));
-		goto fail;
-	}
-
-	if (rep.length != 16) {
-		DEBUG(0, ("req invalid length: %u != 16\n",
-			  rep.length));
-		goto fail;
-	}
-
-	if (strcmp(NAMED_PIPE_AUTH_MAGIC, rep.magic) != 0) {
-		DEBUG(0, ("req invalid magic: %s != %s\n",
-			  rep.magic, NAMED_PIPE_AUTH_MAGIC));
-		goto fail;
-	}
-
-	if (!NT_STATUS_IS_OK(rep.status)) {
-		DEBUG(0, ("req failed: %s\n",
-			  nt_errstr(rep.status)));
+	become_root();
+	subreq = tstream_npa_connect_send(talloc_tos(), ev,
+					  socket_np_dir,
+					  pipe_name,
+					  remote_address, /* client_addr */
+					  NULL, /* client_name */
+					  local_address, /* server_addr */
+					  NULL, /* server_name */
+					  info3,
+					  server_info->user_session_key,
+					  data_blob_null /* delegated_creds */);
+	if (subreq == NULL) {
+		unbecome_root();
+		DEBUG(0, ("tstream_npa_connect_send failed\n"));
 		goto fail;
 	}
-
-	if (rep.level != 1) {
-		DEBUG(0, ("req invalid level: %u != 1\n",
-			  rep.level));
+	ok = tevent_req_poll(subreq, ev);
+	unbecome_root();
+	if (!ok) {
+		DEBUG(0, ("tevent_req_poll failed for tstream_npa_connect: %s\n",
+			  strerror(errno)));
 		goto fail;
-	}
 
-	result->msg = NULL;
-
-	result->read_queue = tevent_queue_create(result, "np_read");
-	if (result->read_queue == NULL) {
-		goto fail;
 	}
-	result->write_queue = tevent_queue_create(result, "np_write");
-	if (result->write_queue == NULL) {
+	ret = tstream_npa_connect_recv(subreq, &sys_errno,
+				       result,
+				       &result->npipe,
+				       &result->file_type,
+				       &result->device_state,
+				       &result->allocation_size);
+	TALLOC_FREE(subreq);
+	if (ret != 0) {
+		DEBUG(0, ("tstream_npa_connect_recv failed: %s\n",
+			  strerror(sys_errno)));
 		goto fail;
 	}
 
@@ -1132,7 +1078,8 @@ static struct np_proxy_state *make_external_rpc_pipe_p(TALLOC_CTX *mem_ctx,
 }
 
 NTSTATUS np_open(TALLOC_CTX *mem_ctx, const char *name,
-		 const char *client_address,
+		 const struct tsocket_address *local_address,
+		 const struct tsocket_address *remote_address,
 		 struct auth_serversupplied_info *server_info,
 		 struct fake_file_handle **phandle)
 {
@@ -1149,19 +1096,35 @@ NTSTATUS np_open(TALLOC_CTX *mem_ctx, const char *name,
 	if ((proxy_list != NULL) && str_list_check_ci(proxy_list, name)) {
 		struct np_proxy_state *p;
 
-		p = make_external_rpc_pipe_p(handle, name, server_info);
+		p = make_external_rpc_pipe_p(handle, name,
+					     local_address,
+					     remote_address,
+					     server_info);
 
 		handle->type = FAKE_FILE_TYPE_NAMED_PIPE_PROXY;
 		handle->private_data = p;
 	} else {
 		struct pipes_struct *p;
 		struct ndr_syntax_id syntax;
+		const char *client_address;
 
 		if (!is_known_pipename(name, &syntax)) {
 			TALLOC_FREE(handle);
 			return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 		}
 
+		if (tsocket_address_is_inet(remote_address, "ip")) {
+			client_address = tsocket_address_inet_addr_string(
+						remote_address,
+						talloc_tos());
+			if (client_address == NULL) {
+				TALLOC_FREE(handle);
+				return NT_STATUS_NO_MEMORY;
+			}
+		} else {
+			client_address = "";
+		}
+
 		p = make_internal_rpc_pipe_p(handle, &syntax, client_address,
 					     server_info);
 
@@ -1179,6 +1142,28 @@ NTSTATUS np_open(TALLOC_CTX *mem_ctx, const char *name,
 	return NT_STATUS_OK;
 }
 
+bool np_read_in_progress(struct fake_file_handle *handle)
+{
+	if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE) {
+		return false;
+	}
+
+	if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
+		struct np_proxy_state *p = talloc_get_type_abort(
+			handle->private_data, struct np_proxy_state);
+		size_t read_count;
+
+		read_count = tevent_queue_length(p->read_queue);
+		if (read_count > 0) {
+			return true;
+		}
+
+		return false;
+	}
+
+	return false;
+}
+
 struct np_write_state {
 	struct event_context *ev;
 	struct np_proxy_state *p;
@@ -1231,8 +1216,10 @@ struct tevent_req *np_write_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
 		state->iov.iov_base = CONST_DISCARD(void *, data);
 		state->iov.iov_len = len;
 
-		subreq = writev_send(state, ev, p->write_queue, p->fd,
-				     false, &state->iov, 1);
+		subreq = tstream_writev_queue_send(state, ev,
+						   p->npipe,
+						   p->write_queue,
+						   &state->iov, 1);
 		if (subreq == NULL) {
 			goto fail;
 		}
@@ -1262,7 +1249,7 @@ static void np_write_done(struct tevent_req *subreq)
 	ssize_t received;
 	int err;
 
-	received = writev_recv(subreq, &err);
+	received = tstream_writev_queue_recv(subreq, &err);
 	if (received < 0) {
 		tevent_req_nterror(req, map_nt_error_from_unix(err));
 		return;
@@ -1284,38 +1271,90 @@ NTSTATUS np_write_recv(struct tevent_req *req, ssize_t *pnwritten)
 	return NT_STATUS_OK;
 }
 
-static ssize_t rpc_frag_more_fn(uint8_t *buf, size_t buflen, void *priv)
+struct np_ipc_readv_next_vector_state {
+	uint8_t *buf;
+	size_t len;
+	off_t ofs;
+	size_t remaining;
+};
+
+static void np_ipc_readv_next_vector_init(struct np_ipc_readv_next_vector_state *s,
+					  uint8_t *buf, size_t len)
+{
+	ZERO_STRUCTP(s);
+
+	s->buf = buf;
+	s->len = MIN(len, UINT16_MAX);
+}
+
+static int np_ipc_readv_next_vector(struct tstream_context *stream,
+				    void *private_data,
+				    TALLOC_CTX *mem_ctx,
+				    struct iovec **_vector,
+				    size_t *count)
 {
-	prs_struct hdr_prs;
-	struct rpc_hdr_info hdr;
-	bool ret;
+	struct np_ipc_readv_next_vector_state *state =
+		(struct np_ipc_readv_next_vector_state *)private_data;
+	struct iovec *vector;
+	ssize_t pending;
+	size_t wanted;
+
+	if (state->ofs == state->len) {
+		*_vector = NULL;
+		*count = 0;
+		return 0;
+	}
+
+	pending = tstream_pending_bytes(stream);
+	if (pending == -1) {
+		return -1;
+	}
 
-	if (buflen > RPC_HEADER_LEN) {
+	if (pending == 0 && state->ofs != 0) {
+		/* return a short read */
+		*_vector = NULL;
+		*count = 0;
 		return 0;
 	}
-	prs_init_empty(&hdr_prs, talloc_tos(), UNMARSHALL);
-	prs_give_memory(&hdr_prs, (char *)buf, RPC_HEADER_LEN, false);
-	ret = smb_io_rpc_hdr("", &hdr, &hdr_prs, 0);
-	prs_mem_free(&hdr_prs);
 
-	if (!ret) {
+	if (pending == 0) {
+		/* we want at least one byte and recheck again */
+		wanted = 1;
+	} else {
+		size_t missing = state->len - state->ofs;
+		if (pending > missing) {
+			/* there's more available */
+			state->remaining = pending - missing;
+			wanted = missing;
+		} else {
+			/* read what we can get and recheck in the next cycle */
+			wanted = pending;
+		}
+	}
+
+	vector = talloc_array(mem_ctx, struct iovec, 1);
+	if (!vector) {
 		return -1;
 	}
 
-	return (hdr.frag_len - RPC_HEADER_LEN);
+	vector[0].iov_base = state->buf + state->ofs;
+	vector[0].iov_len = wanted;
+
+	state->ofs += wanted;
+
+	*_vector = vector;
+	*count = 1;
+	return 0;
 }
 
 struct np_read_state {
-	struct event_context *ev;
 	struct np_proxy_state *p;
-	uint8_t *data;
-	size_t len;
+	struct np_ipc_readv_next_vector_state next_vector;
 
 	size_t nread;
 	bool is_data_outstanding;
 };
 
-static void np_read_trigger(struct tevent_req *req, void *private_data);
 static void np_read_done(struct tevent_req *subreq);
 
 struct tevent_req *np_read_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
@@ -1346,36 +1385,21 @@ struct tevent_req *np_read_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
 	if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
 		struct np_proxy_state *p = talloc_get_type_abort(
 			handle->private_data, struct np_proxy_state);
+		struct tevent_req *subreq;
 
-		if (p->msg != NULL) {
-			size_t thistime;
-
-			thistime = MIN(talloc_get_size(p->msg) - p->sent,
-				       len);
-
-			memcpy(data, p->msg+p->sent, thistime);
-			state->nread = thistime;
-			p->sent += thistime;
-
-			if (p->sent < talloc_get_size(p->msg)) {
-				state->is_data_outstanding = true;
-			} else {
-				state->is_data_outstanding = false;


-- 
Samba Shared Repository


More information about the samba-cvs mailing list