summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/smbd/trans2.c925
1 files changed, 482 insertions, 443 deletions
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 9273339b71..780d7d606c 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -1446,88 +1446,41 @@ static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
return true;
}
-static bool get_lanman2_dir_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,
- 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)
+static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
+ connection_struct *conn,
+ uint16_t flags2,
+ uint32_t info_level,
+ struct ea_list *name_list,
+ bool check_mangled_names,
+ bool requires_resume_key,
+ uint32_t mode,
+ const char *fname,
+ const struct smb_filename *smb_fname,
+ uint64_t space_remaining,
+ char *base_data,
+ char **ppdata,
+ char *end_data,
+ bool *out_of_space,
+ uint64_t *last_entry_off)
{
- const char *mask = NULL;
char *p, *q, *pdata = *ppdata;
- uint32 reskey=0;
- long prev_dirpos=0;
- uint32 mode=0;
- SMB_OFF_T file_size = 0;
+ uint32_t reskey=0;
+ uint64_t file_size = 0;
uint64_t allocation_size = 0;
- uint32 len;
+ uint32_t len;
struct timespec mdate_ts, adate_ts, create_date_ts;
time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
char *nameptr;
char *last_entry_ptr;
bool was_8_3;
- uint32 nt_extmode; /* Used for NT connections instead of mode */
- char *fname = NULL;
- struct smb_filename *smb_fname = NULL;
- struct smbd_dirptr_lanman2_state state;
- bool ok;
+ uint32_t nt_extmode; /* Used for NT connections instead of mode */
- ZERO_STRUCT(state);
- state.conn = conn;
- state.info_level = info_level;
- state.check_mangled_names = lp_manglednames(conn->params);
- state.has_wild = dptr_has_wild(dirptr);
- state.got_exact_match = false;
-
- *out_of_space = False;
- *got_exact_match = False;
+ *out_of_space = false;
ZERO_STRUCT(mdate_ts);
ZERO_STRUCT(adate_ts);
ZERO_STRUCT(create_date_ts);
- p = strrchr_m(path_mask,'/');
- if(p != NULL) {
- if(p[1] == '\0') {
- mask = "*.*";
- } else {
- mask = p+1;
- }
- } else {
- mask = path_mask;
- }
-
- ok = smbd_dirptr_get_entry(ctx,
- dirptr,
- mask,
- dirtype,
- dont_descend,
- ask_sharemode,
- smbd_dirptr_lanman2_match_fn,
- smbd_dirptr_lanman2_mode_fn,
- &state,
- &fname,
- &smb_fname,
- &mode,
- &prev_dirpos);
- if (!ok) {
- return false;
- }
-
- *got_exact_match = state.got_exact_match;
-
if (!(mode & aDIR)) {
file_size = get_file_size_stat(&smb_fname->st);
}
@@ -1553,418 +1506,405 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
switch (info_level) {
- case SMB_FIND_INFO_STANDARD:
- DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
- if(requires_resume_key) {
- SIVAL(p,0,reskey);
- p += 4;
- }
- srv_put_dos_date2(p,0,create_date);
- srv_put_dos_date2(p,4,adate);
- srv_put_dos_date2(p,8,mdate);
- SIVAL(p,12,(uint32)file_size);
- SIVAL(p,16,(uint32)allocation_size);
- SSVAL(p,20,mode);
- p += 23;
- nameptr = p;
- if (flags2 & FLAGS2_UNICODE_STRINGS) {
- p += ucs2_align(base_data, p, 0);
- }
- len = srvstr_push(base_data, flags2, p,
- fname, PTR_DIFF(end_data, p),
- STR_TERMINATE);
- if (flags2 & FLAGS2_UNICODE_STRINGS) {
- if (len > 2) {
- SCVAL(nameptr, -1, len - 2);
- } else {
- SCVAL(nameptr, -1, 0);
- }
+ case SMB_FIND_INFO_STANDARD:
+ DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
+ if(requires_resume_key) {
+ SIVAL(p,0,reskey);
+ p += 4;
+ }
+ srv_put_dos_date2(p,0,create_date);
+ srv_put_dos_date2(p,4,adate);
+ srv_put_dos_date2(p,8,mdate);
+ SIVAL(p,12,(uint32)file_size);
+ SIVAL(p,16,(uint32)allocation_size);
+ SSVAL(p,20,mode);
+ p += 23;
+ nameptr = p;
+ if (flags2 & FLAGS2_UNICODE_STRINGS) {
+ p += ucs2_align(base_data, p, 0);
+ }
+ len = srvstr_push(base_data, flags2, p,
+ fname, PTR_DIFF(end_data, p),
+ STR_TERMINATE);
+ if (flags2 & FLAGS2_UNICODE_STRINGS) {
+ if (len > 2) {
+ SCVAL(nameptr, -1, len - 2);
} else {
- if (len > 1) {
- SCVAL(nameptr, -1, len - 1);
- } else {
- SCVAL(nameptr, -1, 0);
- }
- }
- p += len;
- break;
-
- case SMB_FIND_EA_SIZE:
- DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
- if(requires_resume_key) {
- SIVAL(p,0,reskey);
- p += 4;
- }
- srv_put_dos_date2(p,0,create_date);
- srv_put_dos_date2(p,4,adate);
- srv_put_dos_date2(p,8,mdate);
- SIVAL(p,12,(uint32)file_size);
- SIVAL(p,16,(uint32)allocation_size);
- SSVAL(p,20,mode);
- {
- unsigned int ea_size = estimate_ea_size(conn, NULL,
- smb_fname->base_name);
- SIVAL(p,22,ea_size); /* Extended attributes */
+ SCVAL(nameptr, -1, 0);
}
- p += 27;
- nameptr = p - 1;
- len = srvstr_push(base_data, flags2,
- p, fname, PTR_DIFF(end_data, p),
- STR_TERMINATE | STR_NOALIGN);
- if (flags2 & FLAGS2_UNICODE_STRINGS) {
- if (len > 2) {
- len -= 2;
- } else {
- len = 0;
- }
+ } else {
+ if (len > 1) {
+ SCVAL(nameptr, -1, len - 1);
} else {
- if (len > 1) {
- len -= 1;
- } else {
- len = 0;
- }
+ SCVAL(nameptr, -1, 0);
}
- SCVAL(nameptr,0,len);
- p += len;
- SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
- break;
+ }
+ p += len;
+ break;
- case SMB_FIND_EA_LIST:
+ case SMB_FIND_EA_SIZE:
+ DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
+ if (requires_resume_key) {
+ SIVAL(p,0,reskey);
+ p += 4;
+ }
+ srv_put_dos_date2(p,0,create_date);
+ srv_put_dos_date2(p,4,adate);
+ srv_put_dos_date2(p,8,mdate);
+ SIVAL(p,12,(uint32)file_size);
+ SIVAL(p,16,(uint32)allocation_size);
+ SSVAL(p,20,mode);
{
- struct ea_list *file_list = NULL;
- size_t ea_len = 0;
-
- DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
- if (!name_list) {
- TALLOC_FREE(fname);
- TALLOC_FREE(smb_fname);
- return False;
- }
- if(requires_resume_key) {
- SIVAL(p,0,reskey);
- p += 4;
- }
- srv_put_dos_date2(p,0,create_date);
- srv_put_dos_date2(p,4,adate);
- srv_put_dos_date2(p,8,mdate);
- SIVAL(p,12,(uint32)file_size);
- SIVAL(p,16,(uint32)allocation_size);
- SSVAL(p,20,mode);
- p += 22; /* p now points to the EA area. */
-
- file_list = get_ea_list_from_file(ctx, conn, NULL,
- smb_fname->base_name,
- &ea_len);
- name_list = ea_list_union(name_list, file_list, &ea_len);
-
- /* We need to determine if this entry will fit in the space available. */
- /* Max string size is 255 bytes. */
- if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
- TALLOC_FREE(fname);
- TALLOC_FREE(smb_fname);
- /* Move the dirptr back to prev_dirpos */
- dptr_SeekDir(dirptr, prev_dirpos);
- *out_of_space = True;
- DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
- return False; /* Not finished - just out of space */
+ unsigned int ea_size = estimate_ea_size(conn, NULL,
+ smb_fname->base_name);
+ SIVAL(p,22,ea_size); /* Extended attributes */
+ }
+ p += 27;
+ nameptr = p - 1;
+ len = srvstr_push(base_data, flags2,
+ p, fname, PTR_DIFF(end_data, p),
+ STR_TERMINATE | STR_NOALIGN);
+ if (flags2 & FLAGS2_UNICODE_STRINGS) {
+ if (len > 2) {
+ len -= 2;
+ } else {
+ len = 0;
}
-
- /* Push the ea_data followed by the name. */
- p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
- nameptr = p;
- len = srvstr_push(base_data, flags2,
- p + 1, fname, PTR_DIFF(end_data, p+1),
- STR_TERMINATE | STR_NOALIGN);
- if (flags2 & FLAGS2_UNICODE_STRINGS) {
- if (len > 2) {
- len -= 2;
- } else {
- len = 0;
- }
+ } else {
+ if (len > 1) {
+ len -= 1;
} else {
- if (len > 1) {
- len -= 1;
- } else {
- len = 0;
- }
+ len = 0;
}
- SCVAL(nameptr,0,len);
- p += len + 1;
- SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
- break;
}
+ SCVAL(nameptr,0,len);
+ p += len;
+ SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
+ break;
- case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
- DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
- was_8_3 = mangle_is_8_3(fname, True, conn->params);
+ case SMB_FIND_EA_LIST:
+ {
+ struct ea_list *file_list = NULL;
+ size_t ea_len = 0;
+
+ DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
+ if (!name_list) {
+ return false;
+ }
+ if (requires_resume_key) {
+ SIVAL(p,0,reskey);
p += 4;
- SIVAL(p,0,reskey); p += 4;
- put_long_date_timespec(p,create_date_ts); p += 8;
- put_long_date_timespec(p,adate_ts); p += 8;
- put_long_date_timespec(p,mdate_ts); p += 8;
- put_long_date_timespec(p,mdate_ts); p += 8;
- SOFF_T(p,0,file_size); p += 8;
- SOFF_T(p,0,allocation_size); p += 8;
- SIVAL(p,0,nt_extmode); p += 4;
- q = p; p += 4; /* q is placeholder for name length. */
- {
- unsigned int ea_size = estimate_ea_size(conn, NULL,
- smb_fname->base_name);
- SIVAL(p,0,ea_size); /* Extended attributes */
- p += 4;
+ }
+ srv_put_dos_date2(p,0,create_date);
+ srv_put_dos_date2(p,4,adate);
+ srv_put_dos_date2(p,8,mdate);
+ SIVAL(p,12,(uint32)file_size);
+ SIVAL(p,16,(uint32)allocation_size);
+ SSVAL(p,20,mode);
+ p += 22; /* p now points to the EA area. */
+
+ file_list = get_ea_list_from_file(ctx, conn, NULL,
+ smb_fname->base_name,
+ &ea_len);
+ name_list = ea_list_union(name_list, file_list, &ea_len);
+
+ /* We need to determine if this entry will fit in the space available. */
+ /* Max string size is 255 bytes. */
+ if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
+ *out_of_space = true;
+ DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
+ return False; /* Not finished - just out of space */
+ }
+
+ /* Push the ea_data followed by the name. */
+ p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
+ nameptr = p;
+ len = srvstr_push(base_data, flags2,
+ p + 1, fname, PTR_DIFF(end_data, p+1),
+ STR_TERMINATE | STR_NOALIGN);
+ if (flags2 & FLAGS2_UNICODE_STRINGS) {
+ if (len > 2) {
+ len -= 2;
+ } else {
+ len = 0;
}
- /* Clear the short name buffer. This is
- * IMPORTANT as not doing so will trigger
- * a Win2k client bug. JRA.
- */
- if (!was_8_3 && state.check_mangled_names) {
- char mangled_name[13]; /* mangled 8.3 name. */
- if (!name_to_8_3(fname,mangled_name,True,
- conn->params)) {
- /* Error - mangle failed ! */
- memset(mangled_name,'\0',12);
- }
- mangled_name[12] = 0;
- len = srvstr_push(base_data, flags2,
- p+2, mangled_name, 24,
- STR_UPPER|STR_UNICODE);
- if (len < 24) {
- memset(p + 2 + len,'\0',24 - len);
- }
- SSVAL(p, 0, len);
+ } else {
+ if (len > 1) {
+ len -= 1;
} else {
- memset(p,'\0',26);
+ len = 0;
}
- p += 2 + 24;
- len = srvstr_push(base_data, flags2, p,
- fname, PTR_DIFF(end_data, p),
- STR_TERMINATE_ASCII);
- SIVAL(q,0,len);
- p += len;
- SIVAL(p,0,0); /* Ensure any padding is null. */
- len = PTR_DIFF(p, pdata);
- len = (len + 3) & ~3;
- SIVAL(pdata,0,len);
- p = pdata + len;
- break;
+ }
+ SCVAL(nameptr,0,len);
+ p += len + 1;
+ SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
+ break;
+ }
- case SMB_FIND_FILE_DIRECTORY_INFO:
- DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
+ case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
+ DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
+ was_8_3 = mangle_is_8_3(fname, True, conn->params);
+ p += 4;
+ SIVAL(p,0,reskey); p += 4;
+ put_long_date_timespec(p,create_date_ts); p += 8;
+ put_long_date_timespec(p,adate_ts); p += 8;
+ put_long_date_timespec(p,mdate_ts); p += 8;
+ put_long_date_timespec(p,mdate_ts); p += 8;
+ SOFF_T(p,0,file_size); p += 8;
+ SOFF_T(p,0,allocation_size); p += 8;
+ SIVAL(p,0,nt_extmode); p += 4;
+ q = p; p += 4; /* q is placeholder for name length. */
+ {
+ unsigned int ea_size = estimate_ea_size(conn, NULL,
+ smb_fname->base_name);
+ SIVAL(p,0,ea_size); /* Extended attributes */
p += 4;
- SIVAL(p,0,reskey); p += 4;
- put_long_date_timespec(p,create_date_ts); p += 8;
- put_long_date_timespec(p,adate_ts); p += 8;
- put_long_date_timespec(p,mdate_ts); p += 8;
- put_long_date_timespec(p,mdate_ts); p += 8;
- SOFF_T(p,0,file_size); p += 8;
- SOFF_T(p,0,allocation_size); p += 8;
- SIVAL(p,0,nt_extmode); p += 4;
+ }
+ /* Clear the short name buffer. This is
+ * IMPORTANT as not doing so will trigger
+ * a Win2k client bug. JRA.
+ */
+ if (!was_8_3 && check_mangled_names) {
+ char mangled_name[13]; /* mangled 8.3 name. */
+ if (!name_to_8_3(fname,mangled_name,True,
+ conn->params)) {
+ /* Error - mangle failed ! */
+ memset(mangled_name,'\0',12);
+ }
+ mangled_name[12] = 0;
len = srvstr_push(base_data, flags2,
- p + 4, fname, PTR_DIFF(end_data, p+4),
- STR_TERMINATE_ASCII);
- SIVAL(p,0,len);
- p += 4 + len;
- SIVAL(p,0,0); /* Ensure any padding is null. */
- len = PTR_DIFF(p, pdata);
- len = (len + 3) & ~3;
- SIVAL(pdata,0,len);
- p = pdata + len;
- break;
-
- case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
- DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
- p += 4;
- SIVAL(p,0,reskey); p += 4;
- put_long_date_timespec(p,create_date_ts); p += 8;
- put_long_date_timespec(p,adate_ts); p += 8;
- put_long_date_timespec(p,mdate_ts); p += 8;
- put_long_date_timespec(p,mdate_ts); p += 8;
- SOFF_T(p,0,file_size); p += 8;
- SOFF_T(p,0,allocation_size); p += 8;
- SIVAL(p,0,nt_extmode); p += 4;
- q = p; p += 4; /* q is placeholder for name length. */
- {
- unsigned int ea_size = estimate_ea_size(conn, NULL,
- smb_fname->base_name);
- SIVAL(p,0,ea_size); /* Extended attributes */
- p +=4;
+ p+2, mangled_name, 24,
+ STR_UPPER|STR_UNICODE);
+ if (len < 24) {
+ memset(p + 2 + len,'\0',24 - len);
}
- len = srvstr_push(base_data, flags2, p,
- fname, PTR_DIFF(end_data, p),
- STR_TERMINATE_ASCII);
- SIVAL(q, 0, len);
- p += len;
+ SSVAL(p, 0, len);
+ } else {
+ memset(p,'\0',26);
+ }
+ p += 2 + 24;
+ len = srvstr_push(base_data, flags2, p,
+ fname, PTR_DIFF(end_data, p),
+ STR_TERMINATE_ASCII);
+ SIVAL(q,0,len);
+ p += len;
+ SIVAL(p,0,0); /* Ensure any padding is null. */
+ len = PTR_DIFF(p, pdata);
+ len = (len + 3) & ~3;
+ SIVAL(pdata,0,len);
+ p = pdata + len;
+ break;
- SIVAL(p,0,0); /* Ensure any padding is null. */
- len = PTR_DIFF(p, pdata);
- len = (len + 3) & ~3;
- SIVAL(pdata,0,len);
- p = pdata + len;
- break;
+ case SMB_FIND_FILE_DIRECTORY_INFO:
+ DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
+ p += 4;
+ SIVAL(p,0,reskey); p += 4;
+ put_long_date_timespec(p,create_date_ts); p += 8;
+ put_long_date_timespec(p,adate_ts); p += 8;
+ put_long_date_timespec(p,mdate_ts); p += 8;
+ put_long_date_timespec(p,mdate_ts); p += 8;
+ SOFF_T(p,0,file_size); p += 8;
+ SOFF_T(p,0,allocation_size); p += 8;
+ SIVAL(p,0,nt_extmode); p += 4;
+ len = srvstr_push(base_data, flags2,
+ p + 4, fname, PTR_DIFF(end_data, p+4),
+ STR_TERMINATE_ASCII);
+ SIVAL(p,0,len);
+ p += 4 + len;
+ SIVAL(p,0,0); /* Ensure any padding is null. */
+ len = PTR_DIFF(p, pdata);
+ len = (len + 3) & ~3;
+ SIVAL(pdata,0,len);
+ p = pdata + len;
+ break;
- case SMB_FIND_FILE_NAMES_INFO:
- DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
- p += 4;
- SIVAL(p,0,reskey); p += 4;
- p += 4;
- /* this must *not* be null terminated or w2k gets in a loop trying to set an
- acl on a dir (tridge) */
- len = srvstr_push(base_data, flags2, p,
- fname, PTR_DIFF(end_data, p),
- STR_TERMINATE_ASCII);
- SIVAL(p, -4, len);
- p += len;
- SIVAL(p,0,0); /* Ensure any padding is null. */
- len = PTR_DIFF(p, pdata);
- len = (len + 3) & ~3;
- SIVAL(pdata,0,len);
- p = pdata + len;
- break;
+ case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
+ DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
+ p += 4;
+ SIVAL(p,0,reskey); p += 4;
+ put_long_date_timespec(p,create_date_ts); p += 8;
+ put_long_date_timespec(p,adate_ts); p += 8;
+ put_long_date_timespec(p,mdate_ts); p += 8;
+ put_long_date_timespec(p,mdate_ts); p += 8;
+ SOFF_T(p,0,file_size); p += 8;
+ SOFF_T(p,0,allocation_size); p += 8;
+ SIVAL(p,0,nt_extmode); p += 4;
+ q = p; p += 4; /* q is placeholder for name length. */
+ {
+ unsigned int ea_size = estimate_ea_size(conn, NULL,
+ smb_fname->base_name);
+ SIVAL(p,0,ea_size); /* Extended attributes */
+ p +=4;
+ }
+ len = srvstr_push(base_data, flags2, p,
+ fname, PTR_DIFF(end_data, p),
+ STR_TERMINATE_ASCII);
+ SIVAL(q, 0, len);
+ p += len;
+
+ SIVAL(p,0,0); /* Ensure any padding is null. */
+ len = PTR_DIFF(p, pdata);
+ len = (len + 3) & ~3;
+ SIVAL(pdata,0,len);
+ p = pdata + len;
+ break;
- case SMB_FIND_ID_FULL_DIRECTORY_INFO:
- DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
- p += 4;
- SIVAL(p,0,reskey); p += 4;
- put_long_date_timespec(p,create_date_ts); p += 8;
- put_long_date_timespec(p,adate_ts); p += 8;
- put_long_date_timespec(p,mdate_ts); p += 8;
- put_long_date_timespec(p,mdate_ts); p += 8;
- SOFF_T(p,0,file_size); p += 8;
- SOFF_T(p,0,allocation_size); p += 8;
- SIVAL(p,0,nt_extmode); p += 4;
- q = p; p += 4; /* q is placeholder for name length. */
- {
- unsigned int ea_size = estimate_ea_size(conn, NULL,
- smb_fname->base_name);
- SIVAL(p,0,ea_size); /* Extended attributes */
- p +=4;
- }
- SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
- SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
- SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
- len = srvstr_push(base_data, flags2, p,
- fname, PTR_DIFF(end_data, p),
- STR_TERMINATE_ASCII);
- SIVAL(q, 0, len);
- p += len;
- SIVAL(p,0,0); /* Ensure any padding is null. */
- len = PTR_DIFF(p, pdata);
- len = (len + 3) & ~3;
- SIVAL(pdata,0,len);
- p = pdata + len;
- break;
+ case SMB_FIND_FILE_NAMES_INFO:
+ DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
+ p += 4;
+ SIVAL(p,0,reskey); p += 4;
+ p += 4;
+ /* this must *not* be null terminated or w2k gets in a loop trying to set an
+ acl on a dir (tridge) */
+ len = srvstr_push(base_data, flags2, p,
+ fname, PTR_DIFF(end_data, p),
+ STR_TERMINATE_ASCII);
+ SIVAL(p, -4, len);
+ p += len;
+ SIVAL(p,0,0); /* Ensure any padding is null. */
+ len = PTR_DIFF(p, pdata);
+ len = (len + 3) & ~3;
+ SIVAL(pdata,0,len);
+ p = pdata + len;
+ break;
- case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
- DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
- was_8_3 = mangle_is_8_3(fname, True, conn->params);
- p += 4;
- SIVAL(p,0,reskey); p += 4;
- put_long_date_timespec(p,create_date_ts); p += 8;
- put_long_date_timespec(p,adate_ts); p += 8;
- put_long_date_timespec(p,mdate_ts); p += 8;
- put_long_date_timespec(p,mdate_ts); p += 8;
- SOFF_T(p,0,file_size); p += 8;
- SOFF_T(p,0,allocation_size); p += 8;
- SIVAL(p,0,nt_extmode); p += 4;
- q = p; p += 4; /* q is placeholder for name length */
- {
- unsigned int ea_size = estimate_ea_size(conn, NULL,
- smb_fname->base_name);
- SIVAL(p,0,ea_size); /* Extended attributes */
- p +=4;
+ case SMB_FIND_ID_FULL_DIRECTORY_INFO:
+ DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
+ p += 4;
+ SIVAL(p,0,reskey); p += 4;
+ put_long_date_timespec(p,create_date_ts); p += 8;
+ put_long_date_timespec(p,adate_ts); p += 8;
+ put_long_date_timespec(p,mdate_ts); p += 8;
+ put_long_date_timespec(p,mdate_ts); p += 8;
+ SOFF_T(p,0,file_size); p += 8;
+ SOFF_T(p,0,allocation_size); p += 8;
+ SIVAL(p,0,nt_extmode); p += 4;
+ q = p; p += 4; /* q is placeholder for name length. */
+ {
+ unsigned int ea_size = estimate_ea_size(conn, NULL,
+ smb_fname->base_name);
+ SIVAL(p,0,ea_size); /* Extended attributes */
+ p +=4;
+ }
+ SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
+ SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
+ SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
+ len = srvstr_push(base_data, flags2, p,
+ fname, PTR_DIFF(end_data, p),
+ STR_TERMINATE_ASCII);
+ SIVAL(q, 0, len);
+ p += len;
+ SIVAL(p,0,0); /* Ensure any padding is null. */
+ len = PTR_DIFF(p, pdata);
+ len = (len + 3) & ~3;
+ SIVAL(pdata,0,len);
+ p = pdata + len;
+ break;
+
+ case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
+ DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
+ was_8_3 = mangle_is_8_3(fname, True, conn->params);
+ p += 4;
+ SIVAL(p,0,reskey); p += 4;
+ put_long_date_timespec(p,create_date_ts); p += 8;
+ put_long_date_timespec(p,adate_ts); p += 8;
+ put_long_date_timespec(p,mdate_ts); p += 8;
+ put_long_date_timespec(p,mdate_ts); p += 8;
+ SOFF_T(p,0,file_size); p += 8;
+ SOFF_T(p,0,allocation_size); p += 8;
+ SIVAL(p,0,nt_extmode); p += 4;
+ q = p; p += 4; /* q is placeholder for name length */
+ {
+ unsigned int ea_size = estimate_ea_size(conn, NULL,
+ smb_fname->base_name);
+ SIVAL(p,0,ea_size); /* Extended attributes */
+ p +=4;
+ }
+ /* Clear the short name buffer. This is
+ * IMPORTANT as not doing so will trigger
+ * a Win2k client bug. JRA.
+ */
+ if (!was_8_3 && check_mangled_names) {
+ char mangled_name[13]; /* mangled 8.3 name. */
+ if (!name_to_8_3(fname,mangled_name,True,
+ conn->params)) {
+ /* Error - mangle failed ! */
+ memset(mangled_name,'\0',12);
}
- /* Clear the short name buffer. This is
- * IMPORTANT as not doing so will trigger
- * a Win2k client bug. JRA.
- */
- if (!was_8_3 && state.check_mangled_names) {
- char mangled_name[13]; /* mangled 8.3 name. */
- if (!name_to_8_3(fname,mangled_name,True,
- conn->params)) {
- /* Error - mangle failed ! */
- memset(mangled_name,'\0',12);
- }
- mangled_name[12] = 0;
- len = srvstr_push(base_data, flags2,
- p+2, mangled_name, 24,
- STR_UPPER|STR_UNICODE);
- SSVAL(p, 0, len);
- if (len < 24) {
- memset(p + 2 + len,'\0',24 - len);
- }
- SSVAL(p, 0, len);
- } else {
- memset(p,'\0',26);
+ mangled_name[12] = 0;
+ len = srvstr_push(base_data, flags2,
+ p+2, mangled_name, 24,
+ STR_UPPER|STR_UNICODE);
+ SSVAL(p, 0, len);
+ if (len < 24) {
+ memset(p + 2 + len,'\0',24 - len);
}
- p += 26;
- SSVAL(p,0,0); p += 2; /* Reserved ? */
- SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
- SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
- len = srvstr_push(base_data, flags2, p,
- fname, PTR_DIFF(end_data, p),
- STR_TERMINATE_ASCII);
- SIVAL(q,0,len);
- p += len;
- SIVAL(p,0,0); /* Ensure any padding is null. */
- len = PTR_DIFF(p, pdata);
- len = (len + 3) & ~3;
- SIVAL(pdata,0,len);
- p = pdata + len;
- break;
+ SSVAL(p, 0, len);
+ } else {
+ memset(p,'\0',26);
+ }
+ p += 26;
+ SSVAL(p,0,0); p += 2; /* Reserved ? */
+ SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
+ SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
+ len = srvstr_push(base_data, flags2, p,
+ fname, PTR_DIFF(end_data, p),
+ STR_TERMINATE_ASCII);
+ SIVAL(q,0,len);
+ p += len;
+ SIVAL(p,0,0); /* Ensure any padding is null. */
+ len = PTR_DIFF(p, pdata);
+ len = (len + 3) & ~3;
+ SIVAL(pdata,0,len);
+ p = pdata + len;
+ break;
- /* CIFS UNIX Extension. */
+ /* CIFS UNIX Extension. */
- case SMB_FIND_FILE_UNIX:
- case SMB_FIND_FILE_UNIX_INFO2:
- p+= 4;
- SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
+ case SMB_FIND_FILE_UNIX:
+ case SMB_FIND_FILE_UNIX_INFO2:
+ p+= 4;
+ SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
- /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
+ /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
- if (info_level == SMB_FIND_FILE_UNIX) {
- DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
- p = store_file_unix_basic(conn, p,
- NULL, &smb_fname->st);
- len = srvstr_push(base_data, flags2, p,
- fname, PTR_DIFF(end_data, p),
- STR_TERMINATE);
- } else {
- DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
- p = store_file_unix_basic_info2(conn, p,
- NULL, &smb_fname->st);
- nameptr = p;
- p += 4;
- len = srvstr_push(base_data, flags2, p, fname,
- PTR_DIFF(end_data, p), 0);
- SIVAL(nameptr, 0, len);
- }
+ if (info_level == SMB_FIND_FILE_UNIX) {
+ DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
+ p = store_file_unix_basic(conn, p,
+ NULL, &smb_fname->st);
+ len = srvstr_push(base_data, flags2, p,
+ fname, PTR_DIFF(end_data, p),
+ STR_TERMINATE);
+ } else {
+ DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
+ p = store_file_unix_basic_info2(conn, p,
+ NULL, &smb_fname->st);
+ nameptr = p;
+ p += 4;
+ len = srvstr_push(base_data, flags2, p, fname,
+ PTR_DIFF(end_data, p), 0);
+ SIVAL(nameptr, 0, len);
+ }
- p += len;
- SIVAL(p,0,0); /* Ensure any padding is null. */
+ p += len;
+ SIVAL(p,0,0); /* Ensure any padding is null. */
- len = PTR_DIFF(p, pdata);
- len = (len + 3) & ~3;
- SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
- p = pdata + len;
- /* End of SMB_QUERY_FILE_UNIX_BASIC */
+ len = PTR_DIFF(p, pdata);
+ len = (len + 3) & ~3;
+ SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
+ p = pdata + len;
+ /* End of SMB_QUERY_FILE_UNIX_BASIC */
- break;
+ break;
- default:
- TALLOC_FREE(fname);
- TALLOC_FREE(smb_fname);
- return false;
+ default:
+ return false;
}
- TALLOC_FREE(fname);
- TALLOC_FREE(smb_fname);
-
if (PTR_DIFF(p,pdata) > space_remaining) {
- /* Move the dirptr back to prev_dirpos */
- dptr_SeekDir(dirptr, prev_dirpos);
- *out_of_space = True;
+ *out_of_space = true;
DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
- return False; /* Not finished - just out of space */
+ return false; /* Not finished - just out of space */
}
/* Setup the last entry pointer, as an offset from base_data */
@@ -1975,6 +1915,105 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
return true;
}
+static bool get_lanman2_dir_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,
+ 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)
+{
+ const char *p;
+ const char *mask = NULL;
+ long prev_dirpos = 0;
+ uint32_t mode = 0;
+ char *fname = NULL;
+ struct smb_filename *smb_fname = NULL;
+ struct smbd_dirptr_lanman2_state state;
+ bool ok;
+ uint64_t last_entry_off = 0;
+
+ ZERO_STRUCT(state);
+ state.conn = conn;
+ state.info_level = info_level;
+ state.check_mangled_names = lp_manglednames(conn->params);
+ state.has_wild = dptr_has_wild(dirptr);
+ state.got_exact_match = false;
+
+ *out_of_space = false;
+ *got_exact_match = false;
+
+ p = strrchr_m(path_mask,'/');
+ if(p != NULL) {
+ if(p[1] == '\0') {
+ mask = "*.*";
+ } else {
+ mask = p+1;
+ }
+ } else {
+ mask = path_mask;
+ }
+
+ ok = smbd_dirptr_get_entry(ctx,
+ dirptr,
+ mask,
+ dirtype,
+ dont_descend,
+ ask_sharemode,
+ smbd_dirptr_lanman2_match_fn,
+ smbd_dirptr_lanman2_mode_fn,
+ &state,
+ &fname,
+ &smb_fname,
+ &mode,
+ &prev_dirpos);
+ if (!ok) {
+ return false;
+ }
+
+ *got_exact_match = state.got_exact_match;
+
+ ok = smbd_marshall_dir_entry(ctx,
+ conn,
+ flags2,
+ info_level,
+ name_list,
+ state.check_mangled_names,
+ requires_resume_key,
+ mode,
+ fname,
+ smb_fname,
+ space_remaining,
+ base_data,
+ ppdata,
+ end_data,
+ out_of_space,
+ &last_entry_off);
+ TALLOC_FREE(fname);
+ TALLOC_FREE(smb_fname);
+ if (*out_of_space) {
+ dptr_SeekDir(dirptr, prev_dirpos);
+ return false;
+ }
+ if (!ok) {
+ return false;
+ }
+
+ *_last_entry_off = last_entry_off;
+ return true;
+}
+
/****************************************************************************
Reply to a TRANS2_FINDFIRST.
****************************************************************************/