[SCM] Samba Shared Repository - branch master updated - release-4-0-0alpha8-1093-gecec01c

Stefan Metzmacher metze at samba.org
Wed Aug 19 14:15:12 MDT 2009


The branch, master has been updated
       via  ecec01cc8f66a4fcf0f8ab855be0ee85b1df579a (commit)
       via  f00a3bfee7577c9ef82cb03b0580dccf0c7bc463 (commit)
       via  e621b7a52ee597cef9fbcd7b7af337e8749c4dca (commit)
       via  cf6e81f158ca7b76103fc53f5b96ffae00db6aed (commit)
       via  b70ae644edf0f28437aab61c68c755028094f79b (commit)
      from  f1434665048a7c16c702da03c32e6174b4bff5bc (commit)

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


- Log -----------------------------------------------------------------
commit ecec01cc8f66a4fcf0f8ab855be0ee85b1df579a
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Aug 6 12:16:30 2009 +0200

    s3:smbd: implement SMB2 Find (Query Directory)
    
    metze

commit f00a3bfee7577c9ef82cb03b0580dccf0c7bc463
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Aug 6 12:53:05 2009 +0200

    s3:smbd: store a dirptr on the files_struct for SMB2 Query Directory
    
    metze

commit e621b7a52ee597cef9fbcd7b7af337e8749c4dca
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Aug 14 13:23:19 2009 +0200

    s3:smbd: add a generic smbd_dirptr_lanman2_entry() function
    
    This can we used by SMB2, the key difference between
    SMB1 and SMB2 is that with SMB2 entries are aligned
    to 8 bytes and there's no padding at the end of the last entry.
    
    metze

commit cf6e81f158ca7b76103fc53f5b96ffae00db6aed
Author: Stefan Metzmacher <metze at samba.org>
Date:   Sat Aug 15 11:52:37 2009 +0200

    s3:smbd: implement all SMB2 Create contexts except "ExtA"
    
    metze

commit b70ae644edf0f28437aab61c68c755028094f79b
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Aug 19 18:03:43 2009 +0200

    s3:smbd: make smbd_check_open_rights() function non-static for use in SMB2
    
    metze

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

Summary of changes:
 source3/include/smb.h      |    2 +
 source3/smbd/close.c       |    4 +
 source3/smbd/globals.h     |   26 +++++
 source3/smbd/open.c        |   16 ++--
 source3/smbd/smb2_create.c |  225 ++++++++++++++++++++++++++++++++++++++++--
 source3/smbd/smb2_find.c   |  198 ++++++++++++++++++++++++++++++++++++-
 source3/smbd/trans2.c      |  239 +++++++++++++++++++++++++++++++++++---------
 7 files changed, 647 insertions(+), 63 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/include/smb.h b/source3/include/smb.h
index 28bd60a..4cd090b 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -459,6 +459,8 @@ typedef struct files_struct {
 	struct notify_change_buf *notify;
 
 	struct files_struct *base_fsp; /* placeholder for delete on close */
+
+	struct dptr_struct *dptr;
 } files_struct;
 
 #include "ntquotas.h"
diff --git a/source3/smbd/close.c b/source3/smbd/close.c
index 788b0a7..1f2e460 100644
--- a/source3/smbd/close.c
+++ b/source3/smbd/close.c
@@ -753,6 +753,10 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
 			  strerror(errno)));
 	}
 
+	if (fsp->dptr) {
+		dptr_CloseDir(fsp->dptr);
+	}
+
 	/*
 	 * Do the code common to files and directories.
 	 */
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index 4fa85a9..0db61f8 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -234,6 +234,32 @@ bool smbd_dirptr_get_entry(TALLOC_CTX *ctx,
 			   uint32_t *_mode,
 			   long *_prev_offset);
 
+bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
+			       connection_struct *conn,
+			       struct dptr_struct *dirptr,
+			       uint16 flags2,
+			       const char *path_mask,
+			       uint32 dirtype,
+			       int info_level,
+			       int requires_resume_key,
+			       bool dont_descend,
+			       bool ask_sharemode,
+			       uint8_t align,
+			       bool do_pad,
+			       char **ppdata,
+			       char *base_data,
+			       char *end_data,
+			       int space_remaining,
+			       bool *out_of_space,
+			       bool *got_exact_match,
+			       int *_last_entry_off,
+			       struct ea_list *name_list);
+
+NTSTATUS smbd_check_open_rights(struct connection_struct *conn,
+				const struct smb_filename *smb_fname,
+				uint32_t access_mask,
+				uint32_t *access_granted);
+
 void smbd_notify_cancel_by_smbreq(struct smbd_server_connection *sconn,
 				  const struct smb_request *smbreq);
 
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 6398234..0456355 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -64,7 +64,7 @@ NTSTATUS smb1_file_se_access_check(const struct security_descriptor *sd,
  Check if we have open rights.
 ****************************************************************************/
 
-static NTSTATUS check_open_rights(struct connection_struct *conn,
+NTSTATUS smbd_check_open_rights(struct connection_struct *conn,
 				const struct smb_filename *smb_fname,
 				uint32_t access_mask,
 				uint32_t *access_granted)
@@ -90,7 +90,7 @@ static NTSTATUS check_open_rights(struct connection_struct *conn,
 			DACL_SECURITY_INFORMATION),&sd);
 
 	if (!NT_STATUS_IS_OK(status)) {
-		DEBUG(10, ("check_open_rights: Could not get acl "
+		DEBUG(10, ("smbd_check_open_rights: Could not get acl "
 			"on %s: %s\n",
 			smb_fname_str_dbg(smb_fname),
 			nt_errstr(status)));
@@ -105,7 +105,7 @@ static NTSTATUS check_open_rights(struct connection_struct *conn,
 
 	TALLOC_FREE(sd);
 
-	DEBUG(10,("check_open_rights: file %s requesting "
+	DEBUG(10,("smbd_check_open_rights: file %s requesting "
 		"0x%x returning 0x%x (%s)\n",
 		smb_fname_str_dbg(smb_fname),
 		(unsigned int)access_mask,
@@ -477,7 +477,7 @@ static NTSTATUS open_file(files_struct *fsp,
 		if (file_existed) {
 			uint32_t access_granted = 0;
 
-			status = check_open_rights(conn,
+			status = smbd_check_open_rights(conn,
 					smb_fname,
 					access_mask,
 					&access_granted);
@@ -547,7 +547,7 @@ static NTSTATUS open_file(files_struct *fsp,
 							  smb_fname)));
 				} else {
 					DEBUG(10,("open_file: "
-						  "check_open_rights on file "
+						  "smbd_check_open_rights on file "
 						  "%s returned %s\n",
 						  smb_fname_str_dbg(smb_fname),
 						  nt_errstr(status) ));
@@ -2545,8 +2545,8 @@ static NTSTATUS open_directory(connection_struct *conn,
 
 	if (info == FILE_WAS_OPENED) {
 		uint32_t access_granted = 0;
-		status = check_open_rights(conn, smb_dname, access_mask,
-					   &access_granted);
+		status = smbd_check_open_rights(conn, smb_dname, access_mask,
+						&access_granted);
 
 		/* Were we trying to do a directory open
 		 * for delete and didn't get DELETE
@@ -2567,7 +2567,7 @@ static NTSTATUS open_directory(connection_struct *conn,
 		}
 
 		if (!NT_STATUS_IS_OK(status)) {
-			DEBUG(10, ("open_directory: check_open_rights on "
+			DEBUG(10, ("open_directory: smbd_check_open_rights on "
 				"file %s failed with %s\n",
 				smb_fname_str_dbg(smb_dname),
 				nt_errstr(status)));
diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c
index 08aebd6..3090650 100644
--- a/source3/smbd/smb2_create.c
+++ b/source3/smbd/smb2_create.c
@@ -409,16 +409,176 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
 	} else {
 		char *fname;
 		struct smb_filename *smb_fname = NULL;
-
-		/* these are ignored for SMB2 */
-		in_create_options &= ~(0x10);/* NTCREATEX_OPTIONS_SYNC_ALERT */
-		in_create_options &= ~(0x20);/* NTCREATEX_OPTIONS_ASYNC_ALERT */
+		struct smb2_create_blob *exta = NULL;
+		struct ea_list *ea_list = NULL;
+		struct smb2_create_blob *mxac = NULL;
+		NTTIME max_access_time = 0;
+		struct smb2_create_blob *secd = NULL;
+		struct security_descriptor *sec_desc = NULL;
+		struct smb2_create_blob *dhnq = NULL;
+		struct smb2_create_blob *dhnc = NULL;
+		struct smb2_create_blob *alsi = NULL;
+		uint64_t allocation_size = 0;
+		struct smb2_create_blob *twrp = NULL;
+		struct smb2_create_blob *qfid = NULL;
+
+		exta = smb2_create_blob_find(&in_context_blobs,
+					     SMB2_CREATE_TAG_EXTA);
+		mxac = smb2_create_blob_find(&in_context_blobs,
+					     SMB2_CREATE_TAG_MXAC);
+		secd = smb2_create_blob_find(&in_context_blobs,
+					     SMB2_CREATE_TAG_SECD);
+		dhnq = smb2_create_blob_find(&in_context_blobs,
+					     SMB2_CREATE_TAG_DHNQ);
+		dhnc = smb2_create_blob_find(&in_context_blobs,
+					     SMB2_CREATE_TAG_DHNC);
+		alsi = smb2_create_blob_find(&in_context_blobs,
+					     SMB2_CREATE_TAG_ALSI);
+		twrp = smb2_create_blob_find(&in_context_blobs,
+					     SMB2_CREATE_TAG_TWRP);
+		qfid = smb2_create_blob_find(&in_context_blobs,
+					     SMB2_CREATE_TAG_QFID);
 
 		fname = talloc_strdup(state, in_name);
 		if (tevent_req_nomem(fname, req)) {
 			return tevent_req_post(req, ev);
 		}
 
+		if (exta) {
+			if (dhnc) {
+				tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+				return tevent_req_post(req, ev);
+			}
+
+			/* TODO */
+			tevent_req_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
+			return tevent_req_post(req, ev);
+		}
+
+		if (mxac) {
+			if (dhnc) {
+				tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+				return tevent_req_post(req, ev);
+			}
+
+			if (mxac->data.length == 0) {
+				max_access_time = 0;
+			} else if (mxac->data.length == 8) {
+				max_access_time = BVAL(mxac->data.data, 0);
+			} else {
+				tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+				return tevent_req_post(req, ev);
+			}
+		}
+
+		if (secd) {
+			enum ndr_err_code ndr_err;
+
+			if (dhnc) {
+				tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+				return tevent_req_post(req, ev);
+			}
+
+			sec_desc = talloc_zero(state, struct security_descriptor);
+			if (tevent_req_nomem(sec_desc, req)) {
+				return tevent_req_post(req, ev);
+			}
+
+			ndr_err = ndr_pull_struct_blob(&secd->data,
+				sec_desc, NULL, sec_desc,
+				(ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
+			if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+				DEBUG(2,("ndr_pull_security_descriptor failed: %s\n",
+					 ndr_errstr(ndr_err)));
+				tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+				return tevent_req_post(req, ev);
+			}
+		}
+
+		if (dhnq) {
+			if (dhnc) {
+				tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+				return tevent_req_post(req, ev);
+			}
+
+			if (dhnq->data.length != 16) {
+				tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+				return tevent_req_post(req, ev);
+			}
+			/*
+			 * we don't support durable handles yet
+			 * and have to ignore this
+			 */
+		}
+
+		if (dhnc) {
+			if (dhnc->data.length != 16) {
+				tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+				return tevent_req_post(req, ev);
+			}
+			/* we don't support durable handles yet */
+			tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
+			return tevent_req_post(req, ev);
+		}
+
+		if (alsi) {
+			if (dhnc) {
+				tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+				return tevent_req_post(req, ev);
+			}
+
+			if (alsi->data.length != 8) {
+				tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+				return tevent_req_post(req, ev);
+			}
+			allocation_size = BVAL(alsi->data.data, 0);
+		}
+
+		if (twrp) {
+			NTTIME nttime;
+			time_t t;
+			struct tm *tm;
+
+			if (dhnc) {
+				tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+				return tevent_req_post(req, ev);
+			}
+
+			if (twrp->data.length != 8) {
+				tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+				return tevent_req_post(req, ev);
+			}
+
+			nttime = BVAL(twrp->data.data, 0);
+			t = nt_time_to_unix(nttime);
+			tm = gmtime(&t);
+
+			TALLOC_FREE(fname);
+			fname = talloc_asprintf(state,
+					"@GMT-%04u.%02u.%02u-%02u.%02u.%02u\\%s",
+					tm->tm_year + 1900,
+					tm->tm_mon + 1,
+					tm->tm_mday,
+					tm->tm_hour,
+					tm->tm_min,
+					tm->tm_sec,
+					in_name);
+			if (tevent_req_nomem(fname, req)) {
+				return tevent_req_post(req, ev);
+			}
+		}
+
+		if (qfid) {
+			if (qfid->data.length != 0) {
+				tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+				return tevent_req_post(req, ev);
+			}
+		}
+
+		/* these are ignored for SMB2 */
+		in_create_options &= ~(0x10);/* NTCREATEX_OPTIONS_SYNC_ALERT */
+		in_create_options &= ~(0x20);/* NTCREATEX_OPTIONS_ASYNC_ALERT */
+
 		/* convert '\\' into '/' */
 		status = check_path_syntax(fname);
 		if (!NT_STATUS_IS_OK(status)) {
@@ -448,16 +608,65 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
 					     in_create_options,
 					     in_file_attributes,
 					     0, /* oplock_request */
-					     0, /* allocation_size */
-					     NULL, /* security_descriptor */
-					     NULL, /* ea_list */
+					     allocation_size,
+					     sec_desc,
+					     ea_list,
 					     &result,
 					     &info);
 		if (!NT_STATUS_IS_OK(status)) {
 			tevent_req_nterror(req, status);
 			return tevent_req_post(req, ev);
 		}
-		sbuf = smb_fname->st;
+
+		if (mxac) {
+			NTTIME last_write_time;
+
+			unix_timespec_to_nt_time(&last_write_time,
+						 result->fsp_name->st.st_ex_mtime);
+			if (last_write_time != max_access_time) {
+				uint8_t p[8];
+				uint32_t max_access_granted;
+				DATA_BLOB blob = data_blob_const(p, sizeof(p));
+
+				status = smbd_check_open_rights(smbreq->conn,
+							result->fsp_name,
+							SEC_FLAG_MAXIMUM_ALLOWED,
+							&max_access_granted);
+
+				SIVAL(p, 0, NT_STATUS_V(status));
+				SIVAL(p, 4, max_access_granted);
+
+				status = smb2_create_blob_add(state,
+							&out_context_blobs,
+							SMB2_CREATE_TAG_MXAC,
+							blob);
+				if (!NT_STATUS_IS_OK(status)) {
+					tevent_req_nterror(req, status);
+					return tevent_req_post(req, ev);
+				}
+			}
+		}
+
+		if (qfid) {
+			uint8_t p[32];
+			DATA_BLOB blob = data_blob_const(p, sizeof(p));
+
+			ZERO_STRUCT(p);
+
+			/* TODO: maybe use result->file_id */
+			SIVAL(p, 0, result->fsp_name->st.st_ex_ino);/* FileIndexLow */
+			SIVAL(p, 4, result->fsp_name->st.st_ex_dev);/* FileIndexHigh */
+
+			status = smb2_create_blob_add(state, &out_context_blobs,
+						      SMB2_CREATE_TAG_QFID,
+						      blob);
+			if (!NT_STATUS_IS_OK(status)) {
+				tevent_req_nterror(req, status);
+				return tevent_req_post(req, ev);
+			}
+		}
+
+		sbuf = result->fsp_name->st;
 	}
 
 	smb2req->compat_chain_fsp = smbreq->chain_fsp;
diff --git a/source3/smbd/smb2_find.c b/source3/smbd/smb2_find.c
index 40ba320..546aed8 100644
--- a/source3/smbd/smb2_find.c
+++ b/source3/smbd/smb2_find.c
@@ -202,6 +202,20 @@ static struct tevent_req *smbd_smb2_find_send(TALLOC_CTX *mem_ctx,
 	struct smb_request *smbreq;
 	connection_struct *conn = smb2req->tcon->compat_conn;
 	files_struct *fsp;
+	NTSTATUS status;
+	NTSTATUS empty_status;
+	uint32_t info_level;
+	uint32_t max_count;
+	char *pdata;
+	char *base_data;
+	char *end_data;
+	int last_entry_off = 0;
+	uint64_t off = 0;
+	uint32_t num = 0;
+	uint32_t dirtype = aHIDDEN | aSYSTEM | aDIR;
+	const char *directory;
+	bool dont_descend = false;
+	bool ask_sharemode = true;
 
 	req = tevent_req_create(mem_ctx, &state,
 				struct smbd_smb2_find_state);
@@ -233,7 +247,189 @@ static struct tevent_req *smbd_smb2_find_send(TALLOC_CTX *mem_ctx,
 		return tevent_req_post(req, ev);
 	}
 
-	tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
+	if (!fsp->is_directory) {
+		tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
+		return tevent_req_post(req, ev);
+	}
+
+	directory = fsp->fsp_name->base_name;
+
+	if (strcmp(in_file_name, "") == 0) {
+		tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_INVALID);
+		return tevent_req_post(req, ev);
+	}
+	if (strcmp(in_file_name, "\\") == 0) {
+		tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_INVALID);
+		return tevent_req_post(req, ev);
+	}
+	if (strcmp(in_file_name, "/") == 0) {
+		tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_INVALID);
+		return tevent_req_post(req, ev);
+	}
+
+	if (in_output_buffer_length > 0x10000) {
+		tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+		return tevent_req_post(req, ev);
+	}
+
+	switch (in_file_info_class) {
+	case SMB2_FIND_DIRECTORY_INFO:
+		info_level = SMB_FIND_FILE_DIRECTORY_INFO;
+		break;
+
+	case SMB2_FIND_FULL_DIRECTORY_INFO:
+		info_level = SMB_FIND_FILE_FULL_DIRECTORY_INFO;
+		break;
+
+	case SMB2_FIND_BOTH_DIRECTORY_INFO:
+		info_level = SMB_FIND_FILE_BOTH_DIRECTORY_INFO;
+		break;
+
+	case SMB2_FIND_NAME_INFO:
+		info_level = SMB_FIND_FILE_NAMES_INFO;
+		break;
+
+	case SMB2_FIND_ID_BOTH_DIRECTORY_INFO:
+		info_level = SMB_FIND_ID_BOTH_DIRECTORY_INFO;
+		break;
+
+	case SMB2_FIND_ID_FULL_DIRECTORY_INFO:
+		info_level = SMB_FIND_ID_FULL_DIRECTORY_INFO;
+		break;
+
+	default:
+		tevent_req_nterror(req, NT_STATUS_INVALID_INFO_CLASS);
+		return tevent_req_post(req, ev);
+	}
+
+	if (in_flags & SMB2_CONTINUE_FLAG_REOPEN) {
+		if (fsp->dptr) {
+			dptr_CloseDir(fsp->dptr);
+			fsp->dptr = NULL;
+		}
+	}
+
+	if (fsp->dptr == NULL) {
+		bool wcard_has_wild;
+
+		if (!(fsp->access_mask & SEC_DIR_LIST)) {
+			tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
+			return tevent_req_post(req, ev);
+		}
+
+		wcard_has_wild = ms_has_wild(in_file_name);
+
+		status = dptr_create(conn,
+				     directory,
+				     false, /* old_handle */
+				     false, /* expect_close */
+				     0, /* spid */
+				     in_file_name, /* wcard */
+				     wcard_has_wild,
+				     dirtype,
+				     &fsp->dptr);


-- 
Samba Shared Repository


More information about the samba-cvs mailing list