[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