[SCM] Samba Shared Repository - branch master updated - release-4-0-0alpha8-181-gd49a0e5

Stefan Metzmacher metze at samba.org
Thu Jul 2 07:15:08 GMT 2009


The branch, master has been updated
       via  d49a0e5f7d3788c67aa78d4c856fd3922d13fff9 (commit)
       via  b804c30856edc2d57a82ca64e6c98177f3116e49 (commit)
       via  ef96e8c95867a23e664ef25b1a96e5796e51a72b (commit)
       via  8b94eb6cc8b0c63cf0787bd08ad469a72b0331c0 (commit)
       via  d73bc83c1921e2659dba27a0afc0b71a1760a5ca (commit)
       via  f62a331045581ec706949f79d01951270d8d763b (commit)
       via  99c1e4f19af9fd88c0cbb19b754c85d2aec2b99c (commit)
      from  d47bb0a96c8205511e622eacc88de3ec31ddeeab (commit)

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


- Log -----------------------------------------------------------------
commit d49a0e5f7d3788c67aa78d4c856fd3922d13fff9
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Jun 29 22:31:13 2009 +0200

    s3:smbd: add support for SMB2 Notify
    
    metze

commit b804c30856edc2d57a82ca64e6c98177f3116e49
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Jun 30 15:01:00 2009 +0200

    s3:smbd: make change_notify_reply() more generic and hide send_nt_replies() behind a callback
    
    This prepares change notify support for SMB2.
    
    metze

commit ef96e8c95867a23e664ef25b1a96e5796e51a72b
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Jun 29 22:17:17 2009 +0200

    s3:smbd: simplify the notify code a bit and always reply via change_notify_reply() -> send_nt_replies()
    
    metze

commit 8b94eb6cc8b0c63cf0787bd08ad469a72b0331c0
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Jun 29 15:38:48 2009 +0200

    s3:smbd: push nttrans and trans2 responses with no data to the client
    
    For sync replies it's not a problem, as construct_reply() will send
    the response, but for async replies we would not send the reply to the client.
    Currently the notify code works arround this manually, so I assume
    we didn't have a bug here. But the next commits will simplify
    the notify code.
    
    metze

commit d73bc83c1921e2659dba27a0afc0b71a1760a5ca
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Jul 1 12:56:30 2009 +0200

    s3:smbd: restore the 3.0.x bahavior of send_nt_replies()
    
    We should also set the error code, when we return no parameters or data.
    
    metze

commit f62a331045581ec706949f79d01951270d8d763b
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Jun 30 10:17:38 2009 +0200

    s3:smbd: move global notify_changes_by_mid to smbd_server_connection
    
    metze

commit 99c1e4f19af9fd88c0cbb19b754c85d2aec2b99c
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Jun 30 13:25:21 2009 +0200

    s3:smbd: allow the offset to the path being 0 in SMB2 create
    
    metze

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

Summary of changes:
 source3/Makefile.in        |    1 +
 source3/include/proto.h    |   14 ++-
 source3/smbd/globals.c     |    2 -
 source3/smbd/globals.h     |    5 +-
 source3/smbd/notify.c      |   86 ++++++-----
 source3/smbd/nttrans.c     |   30 +++-
 source3/smbd/smb2_create.c |    4 +-
 source3/smbd/smb2_notify.c |  375 ++++++++++++++++++++++++++++++++++++++++++++
 source3/smbd/smb2_server.c |    2 +-
 source3/smbd/trans2.c      |    8 +
 10 files changed, 474 insertions(+), 53 deletions(-)
 create mode 100644 source3/smbd/smb2_notify.c


Changeset truncated at 500 lines:

diff --git a/source3/Makefile.in b/source3/Makefile.in
index 528fb11..11fd285 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -774,6 +774,7 @@ SMBD_OBJ_SRV = smbd/files.o smbd/chgpasswd.o smbd/connection.o \
 	       smbd/smb2_write.o \
 	       smbd/smb2_ioctl.o \
 	       smbd/smb2_keepalive.o \
+	       smbd/smb2_notify.o \
 	       $(MANGLE_OBJ) @VFS_STATIC@
 
 SMBD_OBJ_BASE = $(PARAM_WITHOUT_REG_OBJ) $(SMBD_OBJ_SRV) $(LIBSMB_OBJ) \
diff --git a/source3/include/proto.h b/source3/include/proto.h
index a3ae1dd..2b29011 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -6466,14 +6466,22 @@ void reply_negprot(struct smb_request *req);
 /* The following definitions come from smbd/notify.c  */
 
 void change_notify_reply(connection_struct *conn,
-			 struct smb_request *req, uint32 max_param,
-			 struct notify_change_buf *notify_buf);
+			 struct smb_request *req,
+			 NTSTATUS error_code,
+			 uint32_t max_param,
+			 struct notify_change_buf *notify_buf,
+			 void (*reply_fn)(struct smb_request *req,
+				NTSTATUS error_code,
+				uint8_t *buf, size_t len));
 NTSTATUS change_notify_create(struct files_struct *fsp, uint32 filter,
 			      bool recursive);
 NTSTATUS change_notify_add_request(struct smb_request *req,
 				uint32 max_param,
 				uint32 filter, bool recursive,
-				struct files_struct *fsp);
+				struct files_struct *fsp,
+				void (*reply_fn)(struct smb_request *req,
+					NTSTATUS error_code,
+					uint8_t *buf, size_t len));
 void remove_pending_change_notify_requests_by_mid(uint16 mid);
 void remove_pending_change_notify_requests_by_fid(files_struct *fsp,
 						  NTSTATUS status);
diff --git a/source3/smbd/globals.c b/source3/smbd/globals.c
index 2e1b5c8..15550ed 100644
--- a/source3/smbd/globals.c
+++ b/source3/smbd/globals.c
@@ -134,8 +134,6 @@ int32_t level_II_oplocks_open = 0;
 bool global_client_failed_oplock_break = false;
 struct kernel_oplocks *koplocks = NULL;
 
-struct notify_mid_map *notify_changes_by_mid = NULL;
-
 int am_parent = 1;
 int server_fd = -1;
 struct event_context *smbd_event_ctx = NULL;
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index 5e9da66..75f553d 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -144,8 +144,6 @@ extern int32_t level_II_oplocks_open;
 extern bool global_client_failed_oplock_break;
 extern struct kernel_oplocks *koplocks;
 
-extern struct notify_mid_map *notify_changes_by_mid;
-
 extern int am_parent;
 extern int server_fd;
 extern struct event_context *smbd_event_ctx;
@@ -219,6 +217,7 @@ NTSTATUS smbd_smb2_request_process_read(struct smbd_smb2_request *req);
 NTSTATUS smbd_smb2_request_process_write(struct smbd_smb2_request *req);
 NTSTATUS smbd_smb2_request_process_ioctl(struct smbd_smb2_request *req);
 NTSTATUS smbd_smb2_request_process_keepalive(struct smbd_smb2_request *req);
+NTSTATUS smbd_smb2_request_process_notify(struct smbd_smb2_request *req);
 
 struct smbd_smb2_request {
 	struct smbd_smb2_request *prev, *next;
@@ -376,6 +375,8 @@ struct smbd_server_connection {
 		struct smb_signing_state *signing_state;
 		/* List to store partial SPNEGO auth fragments. */
 		struct pending_auth_data *pd_list;
+
+		struct notify_mid_map *notify_mid_maps;
 	} smb1;
 	struct {
 		struct tevent_context *event_ctx;
diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c
index a242fc3..ded888c 100644
--- a/source3/smbd/notify.c
+++ b/source3/smbd/notify.c
@@ -28,6 +28,9 @@ struct notify_change_request {
 	struct smb_request *req;
 	uint32 filter;
 	uint32 max_param;
+	void (*reply_fn)(struct smb_request *req,
+			 NTSTATUS error_code,
+			 uint8_t *buf, size_t len);
 	struct notify_mid_map *mid_map;
 	void *backend_data;
 };
@@ -64,6 +67,10 @@ static bool notify_marshall_changes(int num_changes,
 	int i;
 	UNISTR uni_name;
 
+	if (num_changes == -1) {
+		return false;
+	}
+
 	uni_name.buffer = NULL;
 
 	for (i=0; i<num_changes; i++) {
@@ -131,37 +138,24 @@ static bool notify_marshall_changes(int num_changes,
  Setup the common parts of the return packet and send it.
 *****************************************************************************/
 
-static void change_notify_reply_packet(connection_struct *conn,
-				       struct smb_request *req,
-				       NTSTATUS error_code)
+void change_notify_reply(connection_struct *conn,
+			 struct smb_request *req,
+			 NTSTATUS error_code,
+			 uint32_t max_param,
+			 struct notify_change_buf *notify_buf,
+			 void (*reply_fn)(struct smb_request *req,
+				NTSTATUS error_code,
+				uint8_t *buf, size_t len))
 {
-	reply_outbuf(req, 18, 0);
+	prs_struct ps;
 
 	if (!NT_STATUS_IS_OK(error_code)) {
-		error_packet_set((char *)req->outbuf, 0, 0, error_code,
-				 __LINE__,__FILE__);
-	}
-
-	show_msg((char *)req->outbuf);
-	if (!srv_send_smb(smbd_server_fd(),
-			  (char *)req->outbuf,
-			  true, req->seqnum+1,
-			  req->encrypted, &req->pcd)) {
-		exit_server_cleanly("change_notify_reply_packet: srv_send_smb "
-				    "failed.");
+		reply_fn(req, error_code, NULL, 0);
+		return;
 	}
-	TALLOC_FREE(req->outbuf);
-}
-
-void change_notify_reply(connection_struct *conn,
-			 struct smb_request *req, uint32 max_param,
-			 struct notify_change_buf *notify_buf)
-{
-	prs_struct ps;
 
-	if (notify_buf->num_changes == -1) {
-		change_notify_reply_packet(conn, req, NT_STATUS_OK);
-		notify_buf->num_changes = 0;
+	if (max_param == 0 || notify_buf == NULL) {
+		reply_fn(req, NT_STATUS_OK, NULL, 0);
 		return;
 	}
 
@@ -173,14 +167,12 @@ void change_notify_reply(connection_struct *conn,
 		 * We exceed what the client is willing to accept. Send
 		 * nothing.
 		 */
-		change_notify_reply_packet(conn, req, NT_STATUS_OK);
-		goto done;
+		prs_mem_free(&ps);
+		prs_init_empty(&ps, NULL, MARSHALL);
 	}
 
-	send_nt_replies(conn, req, NT_STATUS_OK, prs_data_p(&ps),
-			prs_offset(&ps), NULL, 0);
+	reply_fn(req, NT_STATUS_OK, (uint8_t *)prs_data_p(&ps), prs_offset(&ps));
 
- done:
 	prs_mem_free(&ps);
 
 	TALLOC_FREE(notify_buf->changes);
@@ -234,10 +226,14 @@ NTSTATUS change_notify_create(struct files_struct *fsp, uint32 filter,
 NTSTATUS change_notify_add_request(struct smb_request *req,
 				uint32 max_param,
 				uint32 filter, bool recursive,
-				struct files_struct *fsp)
+				struct files_struct *fsp,
+				void (*reply_fn)(struct smb_request *req,
+					NTSTATUS error_code,
+					uint8_t *buf, size_t len))
 {
 	struct notify_change_request *request = NULL;
 	struct notify_mid_map *map = NULL;
+	struct smbd_server_connection *sconn = smbd_server_conn;
 
 	DEBUG(10, ("change_notify_add_request: Adding request for %s: "
 		   "max_param = %d\n", fsp->fsp_name, (int)max_param));
@@ -255,13 +251,14 @@ NTSTATUS change_notify_add_request(struct smb_request *req,
 	request->max_param = max_param;
 	request->filter = filter;
 	request->fsp = fsp;
+	request->reply_fn = reply_fn;
 	request->backend_data = NULL;
 
 	DLIST_ADD_END(fsp->notify->requests, request,
 		      struct notify_change_request *);
 
 	map->mid = request->req->mid;
-	DLIST_ADD(notify_changes_by_mid, map);
+	DLIST_ADD(sconn->smb1.notify_mid_maps, map);
 
 	return NT_STATUS_OK;
 }
@@ -270,6 +267,7 @@ static void change_notify_remove_request(struct notify_change_request *remove_re
 {
 	files_struct *fsp;
 	struct notify_change_request *req;
+	struct smbd_server_connection *sconn = smbd_server_conn;
 
 	/*
 	 * Paranoia checks, the fsp referenced must must have the request in
@@ -290,7 +288,7 @@ static void change_notify_remove_request(struct notify_change_request *remove_re
 	}
 
 	DLIST_REMOVE(fsp->notify->requests, req);
-	DLIST_REMOVE(notify_changes_by_mid, req->mid_map);
+	DLIST_REMOVE(sconn->smb1.notify_mid_maps, req->mid_map);
 	TALLOC_FREE(req);
 }
 
@@ -301,8 +299,9 @@ static void change_notify_remove_request(struct notify_change_request *remove_re
 void remove_pending_change_notify_requests_by_mid(uint16 mid)
 {
 	struct notify_mid_map *map;
+	struct smbd_server_connection *sconn = smbd_server_conn;
 
-	for (map = notify_changes_by_mid; map; map = map->next) {
+	for (map = sconn->smb1.notify_mid_maps; map; map = map->next) {
 		if (map->mid == mid) {
 			break;
 		}
@@ -312,8 +311,8 @@ void remove_pending_change_notify_requests_by_mid(uint16 mid)
 		return;
 	}
 
-	change_notify_reply_packet(map->req->fsp->conn, map->req->req,
-				   NT_STATUS_CANCELLED);
+	change_notify_reply(map->req->fsp->conn, map->req->req,
+			    NT_STATUS_CANCELLED, 0, NULL, map->req->reply_fn);
 	change_notify_remove_request(map->req);
 }
 
@@ -329,8 +328,9 @@ void remove_pending_change_notify_requests_by_fid(files_struct *fsp,
 	}
 
 	while (fsp->notify->requests != NULL) {
-		change_notify_reply_packet(
-			fsp->conn, fsp->notify->requests->req, status);
+		change_notify_reply(fsp->conn, fsp->notify->requests->req,
+				    status, 0, NULL,
+				    fsp->notify->requests->reply_fn);
 		change_notify_remove_request(fsp->notify->requests);
 	}
 }
@@ -402,8 +402,10 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name)
 		if (fsp->notify->requests != NULL) {
 			change_notify_reply(fsp->conn,
 					    fsp->notify->requests->req,
+					    NT_STATUS_OK,
 					    fsp->notify->requests->max_param,
-					    fsp->notify);
+					    fsp->notify,
+					    fsp->notify->requests->reply_fn);
 			change_notify_remove_request(fsp->notify->requests);
 		}
 		return;
@@ -461,8 +463,10 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name)
 
 	change_notify_reply(fsp->conn,
 			    fsp->notify->requests->req,
+			    NT_STATUS_OK,
 			    fsp->notify->requests->max_param,
-			    fsp->notify);
+			    fsp->notify,
+			    fsp->notify->requests->reply_fn);
 
 	change_notify_remove_request(fsp->notify->requests);
 }
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index 04767bf..c65cbf8 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -68,7 +68,20 @@ void send_nt_replies(connection_struct *conn,
 
 	if(params_to_send == 0 && data_to_send == 0) {
 		reply_outbuf(req, 18, 0);
+		if (NT_STATUS_V(nt_error)) {
+			error_packet_set((char *)req->outbuf,
+					 0, 0, nt_error,
+					 __LINE__,__FILE__);
+		}
 		show_msg((char *)req->outbuf);
+		if (!srv_send_smb(smbd_server_fd(),
+				(char *)req->outbuf,
+				true, req->seqnum+1,
+				IS_CONN_ENCRYPTED(conn),
+				&req->pcd)) {
+			exit_server_cleanly("send_nt_replies: srv_send_smb failed.");
+		}
+		TALLOC_FREE(req->outbuf);
 		return;
 	}
 
@@ -1504,6 +1517,13 @@ void reply_ntrename(struct smb_request *req)
  don't allow a directory to be opened.
 ****************************************************************************/
 
+static void smbd_smb1_notify_reply(struct smb_request *req,
+				   NTSTATUS error_code,
+				   uint8_t *buf, size_t len)
+{
+	send_nt_replies(req->conn, req, error_code, (char *)buf, len, NULL, 0);
+}
+
 static void call_nt_transact_notify_change(connection_struct *conn,
 					   struct smb_request *req,
 					   uint16 **ppsetup,
@@ -1579,8 +1599,11 @@ static void call_nt_transact_notify_change(connection_struct *conn,
 		 * here.
 		 */
 
-		change_notify_reply(fsp->conn, req, max_param_count,
-				    fsp->notify);
+		change_notify_reply(fsp->conn, req,
+				    NT_STATUS_OK,
+				    max_param_count,
+				    fsp->notify,
+				    smbd_smb1_notify_reply);
 
 		/*
 		 * change_notify_reply() above has independently sent its
@@ -1596,7 +1619,8 @@ static void call_nt_transact_notify_change(connection_struct *conn,
 	status = change_notify_add_request(req,
 			max_param_count,
 			filter,
-			recursive, fsp);
+			recursive, fsp,
+			smbd_smb1_notify_reply);
 	if (!NT_STATUS_IS_OK(status)) {
 		reply_nterror(req, status);
 	}
diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c
index 578dfa7..2c79077 100644
--- a/source3/smbd/smb2_create.c
+++ b/source3/smbd/smb2_create.c
@@ -88,7 +88,9 @@ NTSTATUS smbd_smb2_request_process_create(struct smbd_smb2_request *req)
 	in_name_offset		= SVAL(inbody, 0x2C);
 	in_name_length		= SVAL(inbody, 0x2E);
 
-	if (in_name_offset != (SMB2_HDR_BODY + (body_size & 0xFFFFFFFE))) {
+	if (in_name_offset == 0 && in_name_length == 0) {
+		/* This is ok */
+	} else if (in_name_offset != (SMB2_HDR_BODY + (body_size & 0xFFFFFFFE))) {
 		return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
 	}
 
diff --git a/source3/smbd/smb2_notify.c b/source3/smbd/smb2_notify.c
new file mode 100644
index 0000000..7ab93ce
--- /dev/null
+++ b/source3/smbd/smb2_notify.c
@@ -0,0 +1,375 @@
+/*
+   Unix SMB/CIFS implementation.
+   Core SMB2 server
+
+   Copyright (C) Stefan Metzmacher 2009
+
+   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 "smbd/globals.h"
+#include "../source4/libcli/smb2/smb2_constants.h"
+
+static struct tevent_req *smbd_smb2_notify_send(TALLOC_CTX *mem_ctx,
+						struct tevent_context *ev,
+						struct smbd_smb2_request *smb2req,
+						uint16_t in_flags,
+						uint32_t in_output_buffer_length,
+						uint64_t in_file_id_volatile,
+						uint64_t in_completion_filter);
+static NTSTATUS smbd_smb2_notify_recv(struct tevent_req *req,
+				      TALLOC_CTX *mem_ctx,
+				      DATA_BLOB *out_output_buffer);
+
+static void smbd_smb2_request_notify_done(struct tevent_req *subreq);
+NTSTATUS smbd_smb2_request_process_notify(struct smbd_smb2_request *req)
+{
+	const uint8_t *inhdr;
+	const uint8_t *inbody;
+	int i = req->current_idx;
+	size_t expected_body_size = 0x20;
+	size_t body_size;
+	uint16_t in_flags;
+	uint32_t in_output_buffer_length;
+	uint64_t in_file_id_persistent;
+	uint64_t in_file_id_volatile;
+	uint64_t in_completion_filter;
+	struct tevent_req *subreq;
+
+	inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
+	if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
+		return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
+	}
+
+	inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
+
+	body_size = SVAL(inbody, 0x00);
+	if (body_size != expected_body_size) {
+		return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
+	}
+
+	in_flags		= SVAL(inbody, 0x02);
+	in_output_buffer_length	= IVAL(inbody, 0x04);
+	in_file_id_persistent	= BVAL(inbody, 0x08);
+	in_file_id_volatile	= BVAL(inbody, 0x10);
+	in_completion_filter	= IVAL(inbody, 0x18);
+
+	/*
+	 * 0x00010000 is what Windows 7 uses,
+	 * Windows 2008 uses 0x00080000
+	 */
+	if (in_output_buffer_length > 0x00010000) {
+		return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
+	}
+
+	if (req->compat_chain_fsp) {
+		/* skip check */
+	} else if (in_file_id_persistent != 0) {
+		return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
+	}
+
+	subreq = smbd_smb2_notify_send(req,
+				       req->conn->smb2.event_ctx,
+				       req,
+				       in_flags,
+				       in_output_buffer_length,
+				       in_file_id_volatile,
+				       in_completion_filter);
+	if (subreq == NULL) {
+		return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
+	}
+	tevent_req_set_callback(subreq, smbd_smb2_request_notify_done, req);
+
+	if (tevent_req_is_in_progress(subreq)) {
+		return smbd_smb2_request_pending_queue(req);
+	}
+
+	return NT_STATUS_OK;
+}
+
+static void smbd_smb2_request_notify_done(struct tevent_req *subreq)
+{
+	struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
+					struct smbd_smb2_request);
+	int i = req->current_idx;
+	uint8_t *outhdr;
+	DATA_BLOB outbody;
+	DATA_BLOB outdyn;
+	uint16_t out_output_buffer_offset;
+	DATA_BLOB out_output_buffer;
+	NTSTATUS status;
+	NTSTATUS error; /* transport error */
+
+	status = smbd_smb2_notify_recv(subreq,
+				       req,
+				       &out_output_buffer);
+	TALLOC_FREE(subreq);
+	if (!NT_STATUS_IS_OK(status)) {
+		error = smbd_smb2_request_error(req, status);
+		if (!NT_STATUS_IS_OK(error)) {
+			smbd_server_connection_terminate(req->conn,
+							 nt_errstr(error));
+			return;
+		}
+		return;
+	}
+
+	out_output_buffer_offset = SMB2_HDR_BODY + 0x08;
+


-- 
Samba Shared Repository


More information about the samba-cvs mailing list