X-Git-Url: http://git.samba.org/samba.git/?a=blobdiff_plain;f=source3%2Fsmbd%2Ftrans2.c;h=8226b6c4280c9fd3b2ef0eb6590dbcef2aef6b6c;hb=0f8e2a6ebb716588e741c2cdd8e9918262fdd4c6;hp=93b217558dc13cceb3e1d505b5a2e36bb3f2483a;hpb=c9dca82ed7757f4745edf6ee6048bd94d86c4dbc;p=ira%2Fwip.git diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 93b217558dc..8226b6c4280 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -28,8 +28,6 @@ #include "smbd/globals.h" #include "../libcli/auth/libcli_auth.h" -extern enum protocol_types Protocol; - #define DIR_ENTRY_SAFETY_MARGIN 4096 static char *store_file_unix_basic(connection_struct *conn, @@ -72,6 +70,8 @@ static bool samba_private_attr_name(const char *unix_ea_name) static const char * const prohibited_ea_names[] = { SAMBA_POSIX_INHERITANCE_EA_NAME, SAMBA_XATTR_DOS_ATTRIB, + SAMBA_XATTR_DOSTIMESTAMPS, + SAMBA_XATTR_MARKER, NULL }; @@ -155,7 +155,9 @@ NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, ssize_t sizeret = -1; if (!lp_ea_support(SNUM(conn))) { - *pnames = NULL; + if (pnames) { + *pnames = NULL; + } *pnum_names = 0; return NT_STATUS_OK; } @@ -206,7 +208,9 @@ NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, if (sizeret == 0) { TALLOC_FREE(names); - *pnames = NULL; + if (pnames) { + *pnames = NULL; + } *pnum_names = 0; return NT_STATUS_OK; } @@ -243,7 +247,11 @@ NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, names[num_names++] = p; } - *pnames = names; + if (pnames) { + *pnames = names; + } else { + TALLOC_FREE(names); + } *pnum_names = num_names; return NT_STATUS_OK; } @@ -1360,7 +1368,7 @@ static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx, fname, mask); state->got_exact_match = got_match; if (!got_match) { - got_match = mask_match(fname, mask, + got_match = mask_match(fname, mask, get_Protocol(), state->conn->case_sensitive); } @@ -1385,6 +1393,7 @@ static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx, state->got_exact_match = got_match; if (!got_match) { got_match = mask_match(mangled_name, mask, + get_Protocol(), state->conn->case_sensitive); } } @@ -1457,6 +1466,8 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx, const char *fname, const struct smb_filename *smb_fname, uint64_t space_remaining, + uint8_t align, + bool do_pad, char *base_data, char **ppdata, char *end_data, @@ -1475,6 +1486,8 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx, char *last_entry_ptr; bool was_8_3; uint32_t nt_extmode; /* Used for NT connections instead of mode */ + off_t off; + off_t pad = 0; *out_of_space = false; @@ -1490,8 +1503,8 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx, mdate_ts = smb_fname->st.st_ex_mtime; adate_ts = smb_fname->st.st_ex_atime; - create_date_ts = get_create_timespec(NULL, smb_fname); - cdate_ts = get_change_timespec(NULL, smb_fname); + create_date_ts = get_create_timespec(conn, NULL, smb_fname); + cdate_ts = get_change_timespec(conn, NULL, smb_fname); if (lp_dos_filetime_resolution(SNUM(conn))) { dos_filetime_timespec(&create_date_ts); @@ -1505,14 +1518,29 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx, adate = convert_timespec_to_time_t(adate_ts); c_date = convert_timespec_to_time_t(cdate_ts); + /* align the record */ + off = PTR_DIFF(pdata, base_data); + pad = (off + (align-1)) & ~(align-1); + pad -= off; + off += pad; + /* initialize padding to 0 */ + if (pad) { + memset(pdata, 0, pad); + } + space_remaining -= pad; + + pdata += pad; p = pdata; last_entry_ptr = p; + pad = 0; + off = 0; + 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")); + DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n")); if(requires_resume_key) { SIVAL(p,0,reskey); p += 4; @@ -1548,7 +1576,7 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx, break; case SMB_FIND_EA_SIZE: - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n")); + DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n")); if (requires_resume_key) { SIVAL(p,0,reskey); p += 4; @@ -1592,7 +1620,7 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx, struct ea_list *file_list = NULL; size_t ea_len = 0; - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n")); + DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n")); if (!name_list) { return false; } @@ -1617,7 +1645,7 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx, /* 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")); + DEBUG(9,("smbd_marshall_dir_entry: out of space\n")); return False; /* Not finished - just out of space */ } @@ -1647,14 +1675,14 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx, } case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n")); + DEBUG(10,("smbd_marshall_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,cdate_ts); p += 8; + put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8; + put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8; + put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8; + put_long_date_timespec(conn->ts_res,p,cdate_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; @@ -1693,21 +1721,34 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx, 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; + pad = (len + (align-1)) & ~(align-1); + /* + * offset to the next entry, the caller + * will overwrite it for the last entry + * that's why we always include the padding + */ + SIVAL(pdata,0,pad); + /* + * set padding to zero + */ + if (do_pad) { + memset(p, 0, pad - len); + p = pdata + pad; + } else { + p = pdata + len; + } break; case SMB_FIND_FILE_DIRECTORY_INFO: - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n")); + DEBUG(10,("smbd_marshall_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,cdate_ts); p += 8; + put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8; + put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8; + put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8; + put_long_date_timespec(conn->ts_res,p,cdate_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; @@ -1716,21 +1757,34 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx, 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; + pad = (len + (align-1)) & ~(align-1); + /* + * offset to the next entry, the caller + * will overwrite it for the last entry + * that's why we always include the padding + */ + SIVAL(pdata,0,pad); + /* + * set padding to zero + */ + if (do_pad) { + memset(p, 0, pad - len); + p = pdata + pad; + } else { + p = pdata + len; + } break; case SMB_FIND_FILE_FULL_DIRECTORY_INFO: - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n")); + DEBUG(10,("smbd_marshall_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,cdate_ts); p += 8; + put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8; + put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8; + put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8; + put_long_date_timespec(conn->ts_res,p,cdate_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; @@ -1747,15 +1801,27 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx, 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; + pad = (len + (align-1)) & ~(align-1); + /* + * offset to the next entry, the caller + * will overwrite it for the last entry + * that's why we always include the padding + */ + SIVAL(pdata,0,pad); + /* + * set padding to zero + */ + if (do_pad) { + memset(p, 0, pad - len); + p = pdata + pad; + } else { + p = pdata + len; + } break; case SMB_FIND_FILE_NAMES_INFO: - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n")); + DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n")); p += 4; SIVAL(p,0,reskey); p += 4; p += 4; @@ -1766,21 +1832,34 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx, 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; + pad = (len + (align-1)) & ~(align-1); + /* + * offset to the next entry, the caller + * will overwrite it for the last entry + * that's why we always include the padding + */ + SIVAL(pdata,0,pad); + /* + * set padding to zero + */ + if (do_pad) { + memset(p, 0, pad - len); + p = pdata + pad; + } else { + p = pdata + len; + } break; case SMB_FIND_ID_FULL_DIRECTORY_INFO: - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n")); + DEBUG(10,("smbd_marshall_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,cdate_ts); p += 8; + put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8; + put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8; + put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8; + put_long_date_timespec(conn->ts_res,p,cdate_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; @@ -1799,22 +1878,35 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx, 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; + pad = (len + (align-1)) & ~(align-1); + /* + * offset to the next entry, the caller + * will overwrite it for the last entry + * that's why we always include the padding + */ + SIVAL(pdata,0,pad); + /* + * set padding to zero + */ + if (do_pad) { + memset(p, 0, pad - len); + p = pdata + pad; + } else { + p = pdata + len; + } break; case SMB_FIND_ID_BOTH_DIRECTORY_INFO: - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n")); + DEBUG(10,("smbd_marshall_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,cdate_ts); p += 8; + put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8; + put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8; + put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8; + put_long_date_timespec(conn->ts_res,p,cdate_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; @@ -1857,11 +1949,24 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx, 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; + pad = (len + (align-1)) & ~(align-1); + /* + * offset to the next entry, the caller + * will overwrite it for the last entry + * that's why we always include the padding + */ + SIVAL(pdata,0,pad); + /* + * set padding to zero + */ + if (do_pad) { + memset(p, 0, pad - len); + p = pdata + pad; + } else { + p = pdata + len; + } break; /* CIFS UNIX Extension. */ @@ -1874,14 +1979,14 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx, /* 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")); + DEBUG(10,("smbd_marshall_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")); + DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n")); p = store_file_unix_basic_info2(conn, p, NULL, &smb_fname->st); nameptr = p; @@ -1892,12 +1997,24 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx, } 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; + pad = (len + (align-1)) & ~(align-1); + /* + * offset to the next entry, the caller + * will overwrite it for the last entry + * that's why we always include the padding + */ + SIVAL(pdata,0,pad); + /* + * set padding to zero + */ + if (do_pad) { + memset(p, 0, pad - len); + p = pdata + pad; + } else { + p = pdata + len; + } /* End of SMB_QUERY_FILE_UNIX_BASIC */ break; @@ -1908,7 +2025,7 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx, if (PTR_DIFF(p,pdata) > space_remaining) { *out_of_space = true; - DEBUG(9,("get_lanman2_dir_entry: out of space\n")); + DEBUG(9,("smbd_marshall_dir_entry: out of space\n")); return false; /* Not finished - just out of space */ } @@ -1920,24 +2037,26 @@ static bool smbd_marshall_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) +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) { const char *p; const char *mask = NULL; @@ -2000,6 +2119,8 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, fname, smb_fname, space_remaining, + align, + do_pad, base_data, ppdata, end_data, @@ -2019,6 +2140,43 @@ 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, + bool 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) +{ + uint8_t align = 4; + const bool do_pad = true; + + if (info_level >= 1 && info_level <= 3) { + /* No alignment on earlier info levels. */ + align = 1; + } + + return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2, + path_mask, dirtype, info_level, + requires_resume_key, dont_descend, ask_sharemode, + align, do_pad, + ppdata, base_data, end_data, + space_remaining, + out_of_space, got_exact_match, + last_entry_off, name_list); +} + /**************************************************************************** Reply to a TRANS2_FINDFIRST. ****************************************************************************/ @@ -2307,7 +2465,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd if(numentries == 0) { dptr_close(sconn, &dptr_num); - if (Protocol < PROTOCOL_NT1) { + if (get_Protocol() < PROTOCOL_NT1) { reply_doserror(req, ERRDOS, ERRnofiles); goto out; } else { @@ -2418,23 +2576,26 @@ static void call_trans2findnext(connection_struct *conn, requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME); continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE); - srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name, + if (!continue_bit) { + /* We only need resume_name if continue_bit is zero. */ + srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name, params+12, total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard); - if (!NT_STATUS_IS_OK(ntstatus)) { - /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to - complain (it thinks we're asking for the directory above the shared - path or an invalid name). Catch this as the resume name is only compared, never used in - a file access. JRA. */ - srvstr_pull_talloc(ctx, params, req->flags2, + if (!NT_STATUS_IS_OK(ntstatus)) { + /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to + complain (it thinks we're asking for the directory above the shared + path or an invalid name). Catch this as the resume name is only compared, never used in + a file access. JRA. */ + srvstr_pull_talloc(ctx, params, req->flags2, &resume_name, params+12, total_params - 12, STR_TERMINATE); - if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) { - reply_nterror(req, ntstatus); - return; + if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) { + reply_nterror(req, ntstatus); + return; + } } } @@ -2442,7 +2603,8 @@ static void call_trans2findnext(connection_struct *conn, close_after_request=%d, close_if_end = %d requires_resume_key = %d \ resume_key = %d resume name = %s continue=%d level = %d\n", dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, - requires_resume_key, resume_key, resume_name, continue_bit, info_level)); + requires_resume_key, resume_key, + resume_name ? resume_name : "(NULL)", continue_bit, info_level)); if (!maxentries) { /* W2K3 seems to treat zero as 1. */ @@ -2567,7 +2729,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd * depend on the last file name instead. */ - if(*resume_name && !continue_bit) { + if(!continue_bit && resume_name && *resume_name) { SMB_STRUCT_STAT st; long current_pos = 0; @@ -2718,9 +2880,8 @@ NTSTATUS smbd_do_qfsinfo(connection_struct *conn, int snum = SNUM(conn); char *fstype = lp_fstype(SNUM(conn)); uint32 additional_flags = 0; - struct smb_filename *smb_fname_dot = NULL; + struct smb_filename smb_fname_dot; SMB_STRUCT_STAT st; - NTSTATUS status; if (IS_IPC(conn)) { if (info_level != SMB_QUERY_CIFS_UNIX_INFO) { @@ -2733,20 +2894,15 @@ NTSTATUS smbd_do_qfsinfo(connection_struct *conn, DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level)); - status = create_synthetic_smb_fname(talloc_tos(), ".", NULL, NULL, - &smb_fname_dot); - if (!NT_STATUS_IS_OK(status)) { - return status; - } + ZERO_STRUCT(smb_fname_dot); + smb_fname_dot.base_name = discard_const_p(char, "."); - if(SMB_VFS_STAT(conn, smb_fname_dot) != 0) { + if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) { DEBUG(2,("stat of . failed (%s)\n", strerror(errno))); - TALLOC_FREE(smb_fname_dot); return map_nt_error_from_unix(errno); } - st = smb_fname_dot->st; - TALLOC_FREE(smb_fname_dot); + st = smb_fname_dot.st; *ppdata = (char *)SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); @@ -2834,6 +2990,9 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u /* Capabilities are filled in at connection time through STATVFS call */ additional_flags |= conn->fs_capabilities; + additional_flags |= lp_parm_int(conn->params->service, + "share", "fake_fscaps", + 0); SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH| FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK| @@ -3707,9 +3866,9 @@ static char *store_file_unix_basic(connection_struct *conn, SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */ pdata += 8; - put_long_date_timespec(pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */ - put_long_date_timespec(pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */ - put_long_date_timespec(pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */ + put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */ + put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */ + put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */ pdata += 24; SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */ @@ -3843,7 +4002,7 @@ static char *store_file_unix_basic_info2(connection_struct *conn, pdata = store_file_unix_basic(conn, pdata, fsp, psbuf); /* Create (birth) time 64 bit */ - put_long_date_timespec(pdata, psbuf->st_ex_btime); + put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime); pdata += 8; map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask); @@ -3986,7 +4145,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, TALLOC_CTX *mem_ctx, uint16_t info_level, files_struct *fsp, - const struct smb_filename *smb_fname, + struct smb_filename *smb_fname, bool delete_pending, struct timespec write_time_ts, bool ms_dfs_link, @@ -4003,7 +4162,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, unsigned int data_size; struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts; time_t create_time, mtime, atime, c_time; - SMB_STRUCT_STAT sbuf; + SMB_STRUCT_STAT *psbuf = &smb_fname->st; char *p; char *base_name; char *dos_fname; @@ -4016,8 +4175,6 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, uint64_t file_index = 0; uint32_t access_mask = 0; - sbuf = smb_fname->st; - if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) { return NT_STATUS_INVALID_LEVEL; } @@ -4034,7 +4191,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, if (!mode) mode = FILE_ATTRIBUTE_NORMAL; - nlink = sbuf.st_ex_nlink; + nlink = psbuf->st_ex_nlink; if (nlink && (mode&aDIR)) { nlink = 1; @@ -4054,13 +4211,13 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, dend = dstart + data_size - 1; if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) { - update_stat_ex_mtime(&sbuf, write_time_ts); + update_stat_ex_mtime(psbuf, write_time_ts); } - create_time_ts = get_create_timespec(fsp, smb_fname); - mtime_ts = sbuf.st_ex_mtime; - atime_ts = sbuf.st_ex_atime; - ctime_ts = get_change_timespec(fsp, smb_fname); + create_time_ts = get_create_timespec(conn, fsp, smb_fname); + mtime_ts = psbuf->st_ex_mtime; + atime_ts = psbuf->st_ex_atime; + ctime_ts = get_change_timespec(conn, fsp, smb_fname); if (lp_dos_filetime_resolution(SNUM(conn))) { dos_filetime_timespec(&create_time_ts); @@ -4105,20 +4262,20 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, string_replace(dos_fname, '/', '\\'); } - allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &sbuf); + allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf); if (!fsp) { /* Do we have this path open ? */ files_struct *fsp1; - struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf); + struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf); fsp1 = file_find_di_first(fileid); if (fsp1 && fsp1->initial_allocation_size) { - allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf); + allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf); } } if (!(mode & aDIR)) { - file_size = get_file_size_stat(&sbuf); + file_size = get_file_size_stat(psbuf); } if (fsp) { @@ -4137,8 +4294,8 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, I think this causes us to fail the IFSKIT BasicFileInformationTest. -tpot */ - file_index = ((sbuf.st_ex_ino) & UINT32_MAX); /* FileIndexLow */ - file_index |= ((uint64_t)((sbuf.st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */ + file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */ + file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */ switch (info_level) { case SMB_INFO_STANDARD: @@ -4224,6 +4381,9 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/ { + /* This is FileFullEaInformation - 0xF which maps to + * 1015 (decimal) in smbd_do_setfilepathinfo. */ + /* We have data_size bytes to put EA's into. */ size_t total_ea_len = 0; struct ea_list *ea_file_list = NULL; @@ -4262,10 +4422,10 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, data_size = 40; SIVAL(pdata,36,0); } - put_long_date_timespec(pdata,create_time_ts); - put_long_date_timespec(pdata+8,atime_ts); - put_long_date_timespec(pdata+16,mtime_ts); /* write time */ - put_long_date_timespec(pdata+24,ctime_ts); /* change time */ + put_long_date_timespec(conn->ts_res,pdata,create_time_ts); + put_long_date_timespec(conn->ts_res,pdata+8,atime_ts); + put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */ + put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */ SIVAL(pdata,32,mode); DEBUG(5,("SMB_QFBI - ")); @@ -4357,10 +4517,10 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, unsigned int ea_size = estimate_ea_size(conn, fsp, smb_fname->base_name); DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n")); - put_long_date_timespec(pdata,create_time_ts); - put_long_date_timespec(pdata+8,atime_ts); - put_long_date_timespec(pdata+16,mtime_ts); /* write time */ - put_long_date_timespec(pdata+24,ctime_ts); /* change time */ + put_long_date_timespec(conn->ts_res,pdata,create_time_ts); + put_long_date_timespec(conn->ts_res,pdata+8,atime_ts); + put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */ + put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */ SIVAL(pdata,32,mode); SIVAL(pdata,36,0); /* padding. */ pdata += 40; @@ -4389,10 +4549,10 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, unsigned int ea_size = estimate_ea_size(conn, fsp, smb_fname->base_name); DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n")); - put_long_date_timespec(pdata+0x00,create_time_ts); - put_long_date_timespec(pdata+0x08,atime_ts); - put_long_date_timespec(pdata+0x10,mtime_ts); /* write time */ - put_long_date_timespec(pdata+0x18,ctime_ts); /* change time */ + put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts); + put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts); + put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */ + put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */ SIVAL(pdata, 0x20, mode); SIVAL(pdata, 0x24, 0); /* padding. */ SBVAL(pdata, 0x28, allocation_size); @@ -4522,10 +4682,10 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, case SMB_FILE_NETWORK_OPEN_INFORMATION: DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n")); - put_long_date_timespec(pdata,create_time_ts); - put_long_date_timespec(pdata+8,atime_ts); - put_long_date_timespec(pdata+16,mtime_ts); /* write time */ - put_long_date_timespec(pdata+24,ctime_ts); /* change time */ + put_long_date_timespec(conn->ts_res,pdata,create_time_ts); + put_long_date_timespec(conn->ts_res,pdata+8,atime_ts); + put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */ + put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */ SOFF_T(pdata,32,allocation_size); SOFF_T(pdata,40,file_size); SIVAL(pdata,48,mode); @@ -4546,7 +4706,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, case SMB_QUERY_FILE_UNIX_BASIC: - pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf); + pdata = store_file_unix_basic(conn, pdata, fsp, psbuf); data_size = PTR_DIFF(pdata,(*ppdata)); { @@ -4562,7 +4722,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, case SMB_QUERY_FILE_UNIX_INFO2: - pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf); + pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf); data_size = PTR_DIFF(pdata,(*ppdata)); { @@ -4587,7 +4747,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n")); #ifdef S_ISLNK - if(!S_ISLNK(sbuf.st_ex_mode)) { + if(!S_ISLNK(psbuf->st_ex_mode)) { return NT_STATUS_DOS(ERRSRV, ERRbadlink); } #else @@ -4635,7 +4795,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, return NT_STATUS_NOT_IMPLEMENTED; } - if (S_ISDIR(sbuf.st_ex_mode)) { + if (S_ISDIR(psbuf->st_ex_mode)) { if (fsp && fsp->is_directory) { def_acl = SMB_VFS_SYS_ACL_GET_FILE( @@ -4672,7 +4832,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, SSVAL(pdata,0,SMB_POSIX_ACL_VERSION); SSVAL(pdata,2,num_file_acls); SSVAL(pdata,4,num_def_acls); - if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) { + if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) { if (file_acl) { SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl); } @@ -4681,7 +4841,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, } return NT_STATUS_INTERNAL_ERROR; } - if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) { + if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) { if (file_acl) { SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl); } @@ -5227,12 +5387,11 @@ NTSTATUS smb_set_file_time(connection_struct *conn, struct smb_file_time *ft, bool setting_write_time) { - struct smb_filename *smb_fname_base = NULL; + struct smb_filename smb_fname_base; uint32 action = FILE_NOTIFY_CHANGE_LAST_ACCESS |FILE_NOTIFY_CHANGE_LAST_WRITE |FILE_NOTIFY_CHANGE_CREATION; - NTSTATUS status; if (!VALID_STAT(smb_fname->st)) { return NT_STATUS_OBJECT_NAME_NOT_FOUND; @@ -5256,6 +5415,14 @@ NTSTATUS smb_set_file_time(connection_struct *conn, action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE; } + /* Ensure the resolution is the correct for + * what we can store on this filesystem. */ + + round_timespec(conn->ts_res, &ft->create_time); + round_timespec(conn->ts_res, &ft->ctime); + round_timespec(conn->ts_res, &ft->atime); + round_timespec(conn->ts_res, &ft->mtime); + DEBUG(5,("smb_set_filetime: actime: %s\n ", time_to_asc(convert_timespec_to_time_t(ft->atime)))); DEBUG(5,("smb_set_filetime: modtime: %s\n ", @@ -5296,18 +5463,12 @@ NTSTATUS smb_set_file_time(connection_struct *conn, DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n")); /* Always call ntimes on the base, even if a stream was passed in. */ - status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name, - NULL, &smb_fname->st, - &smb_fname_base); - if (!NT_STATUS_IS_OK(status)) { - return status; - } + smb_fname_base = *smb_fname; + smb_fname_base.stream_name = NULL; - if(file_ntimes(conn, smb_fname_base, ft)!=0) { - TALLOC_FREE(smb_fname_base); + if(file_ntimes(conn, &smb_fname_base, ft)!=0) { return map_nt_error_from_unix(errno); } - TALLOC_FREE(smb_fname_base); notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, smb_fname->base_name); @@ -5492,6 +5653,53 @@ static NTSTATUS smb_info_set_ea(connection_struct *conn, return status; } +/**************************************************************************** + Deal with SMB_FILE_FULL_EA_INFORMATION set. +****************************************************************************/ + +static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn, + const char *pdata, + int total_data, + files_struct *fsp) +{ + struct ea_list *ea_list = NULL; + NTSTATUS status; + + if (!fsp) { + return NT_STATUS_INVALID_HANDLE; + } + + if (!lp_ea_support(SNUM(conn))) { + DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but " + "EA's not supported.\n", + (unsigned int)total_data)); + return NT_STATUS_EAS_NOT_SUPPORTED; + } + + if (total_data < 10) { + DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u " + "too small.\n", + (unsigned int)total_data)); + return NT_STATUS_INVALID_PARAMETER; + } + + ea_list = read_nttrans_ea_list(talloc_tos(), + pdata, + total_data); + + if (!ea_list) { + return NT_STATUS_INVALID_PARAMETER; + } + status = set_ea(conn, fsp, fsp->fsp_name, ea_list); + + DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n", + smb_fname_str_dbg(fsp->fsp_name), + nt_errstr(status) )); + + return status; +} + + /**************************************************************************** Deal with SMB_SET_FILE_DISPOSITION_INFO. ****************************************************************************/ @@ -5500,7 +5708,7 @@ static NTSTATUS smb_set_file_disposition_info(connection_struct *conn, const char *pdata, int total_data, files_struct *fsp, - const struct smb_filename *smb_fname) + struct smb_filename *smb_fname) { NTSTATUS status = NT_STATUS_OK; bool delete_on_close; @@ -7211,6 +7419,15 @@ NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn, break; } + case SMB_FILE_FULL_EA_INFORMATION: + { + status = smb_set_file_full_ea_info(conn, + pdata, + total_data, + fsp); + break; + } + /* From tridge Samba4 : * MODE_INFORMATION in setfileinfo (I have no * idea what "mode information" on a file is - it takes a value of 0, @@ -7930,7 +8147,7 @@ void reply_findnclose(struct smb_request *req) static void handle_trans2(connection_struct *conn, struct smb_request *req, struct trans_state *state) { - if (Protocol >= PROTOCOL_NT1) { + if (get_Protocol() >= PROTOCOL_NT1) { req->flags2 |= 0x40; /* IS_LONG_NAME */ SSVAL(req->inbuf,smb_flg2,req->flags2); }