X-Git-Url: http://git.samba.org/?a=blobdiff_plain;f=source3%2Fsmbd%2Ftrans2.c;h=28862d1f4e8d78de92d71543895c192437117071;hb=bd269443e311d96ef495a9db47d1b95eb83bb8f4;hp=93b217558dc13cceb3e1d505b5a2e36bb3f2483a;hpb=c9dca82ed7757f4745edf6ee6048bd94d86c4dbc;p=samba.git diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 93b217558dc..28862d1f4e8 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_MARKER, + XATTR_NTACL_NAME, 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; } @@ -1004,7 +1012,7 @@ static void call_trans2open(connection_struct *conn, pname = ¶ms[28]; if (IS_IPC(conn)) { - reply_doserror(req, ERRSRV, ERRaccess); + reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED); goto out; } @@ -1047,7 +1055,7 @@ static void call_trans2open(connection_struct *conn, &access_mask, &share_mode, &create_disposition, &create_options)) { - reply_doserror(req, ERRDOS, ERRbadaccess); + reply_nterror(req, NT_STATUS_ACCESS_DENIED); goto out; } @@ -1113,7 +1121,7 @@ static void call_trans2open(connection_struct *conn, inode = smb_fname->st.st_ex_ino; if (fattr & aDIR) { close_file(req, fsp, ERROR_CLOSE); - reply_doserror(req, ERRDOS,ERRnoaccess); + reply_nterror(req, NT_STATUS_ACCESS_DENIED); goto out; } @@ -1457,6 +1465,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, @@ -1474,7 +1484,8 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx, char *nameptr; 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 +1501,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 +1516,27 @@ 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; - nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL; + pad = 0; + off = 0; 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 +1572,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 +1616,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 +1641,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,17 +1671,17 @@ 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; + SIVAL(p,0,mode); p += 4; q = p; p += 4; /* q is placeholder for name length. */ { unsigned int ea_size = estimate_ea_size(conn, NULL, @@ -1693,47 +1717,73 @@ 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; + SIVAL(p,0,mode); 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; + 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; + SIVAL(p,0,mode); p += 4; q = p; p += 4; /* q is placeholder for name length. */ { unsigned int ea_size = estimate_ea_size(conn, NULL, @@ -1747,15 +1797,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,24 +1828,37 @@ 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; + SIVAL(p,0,mode); p += 4; q = p; p += 4; /* q is placeholder for name length. */ { unsigned int ea_size = estimate_ea_size(conn, NULL, @@ -1799,25 +1874,38 @@ 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; + SIVAL(p,0,mode); p += 4; q = p; p += 4; /* q is placeholder for name length */ { unsigned int ea_size = estimate_ea_size(conn, NULL, @@ -1857,11 +1945,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 +1975,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 +1993,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 +2021,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 +2033,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 +2115,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 +2136,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. ****************************************************************************/ @@ -2180,7 +2334,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } if (!lp_ea_support(SNUM(conn))) { - reply_doserror(req, ERRDOS, ERReasnotsupported); + reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED); goto out; } @@ -2307,8 +2461,8 @@ 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) { - reply_doserror(req, ERRDOS, ERRnofiles); + if (get_Protocol() < PROTOCOL_NT1) { + reply_force_doserror(req, ERRDOS, ERRnofiles); goto out; } else { reply_botherror(req, NT_STATUS_NO_SUCH_FILE, @@ -2418,23 +2572,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 +2599,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. */ @@ -2491,7 +2649,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } if (!lp_ea_support(SNUM(conn))) { - reply_doserror(req, ERRDOS, ERReasnotsupported); + reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED); return; } @@ -2524,7 +2682,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd /* Check that the dptr is valid */ if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) { - reply_doserror(req, ERRDOS, ERRnofiles); + reply_nterror(req, STATUS_NO_MORE_FILES); return; } @@ -2533,7 +2691,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd /* Get the wildcard mask from the dptr */ if((p = dptr_wcard(sconn, dptr_num))== NULL) { DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num)); - reply_doserror(req, ERRDOS, ERRnofiles); + reply_nterror(req, STATUS_NO_MORE_FILES); return; } @@ -2567,7 +2725,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 +2876,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 +2890,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 +2986,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 +3862,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 +3998,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 +4141,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 +4158,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 +4171,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; } @@ -4031,10 +4184,8 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, } else { mode = dos_mode(conn, smb_fname); } - if (!mode) - mode = FILE_ATTRIBUTE_NORMAL; - nlink = sbuf.st_ex_nlink; + nlink = psbuf->st_ex_nlink; if (nlink && (mode&aDIR)) { nlink = 1; @@ -4054,13 +4205,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 +4256,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 +4288,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 +4375,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 +4416,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 +4511,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 +4543,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 +4676,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 +4700,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 +4716,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 +4741,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 +4789,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 +4826,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 +4835,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); } @@ -5077,8 +5231,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } if (!lp_ea_support(SNUM(conn))) { - reply_doserror(req, ERRDOS, - ERReasnotsupported); + reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED); return; } @@ -5227,12 +5380,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 +5408,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 +5456,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); @@ -5378,7 +5532,8 @@ static NTSTATUS smb_set_file_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname, const SMB_STRUCT_STAT *psbuf, - SMB_OFF_T size) + SMB_OFF_T size, + bool fail_after_createfile) { NTSTATUS status = NT_STATUS_OK; struct smb_filename *smb_fname_tmp = NULL; @@ -5418,7 +5573,7 @@ static NTSTATUS smb_set_file_size(connection_struct *conn, req, /* req */ 0, /* root_dir_fid */ smb_fname_tmp, /* fname */ - FILE_WRITE_ATTRIBUTES, /* access_mask */ + FILE_WRITE_DATA, /* access_mask */ (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */ FILE_SHARE_DELETE), FILE_OPEN, /* create_disposition*/ @@ -5438,6 +5593,12 @@ static NTSTATUS smb_set_file_size(connection_struct *conn, return status; } + /* See RAW-SFILEINFO-END-OF-FILE */ + if (fail_after_createfile) { + close_file(req, new_fsp,NORMAL_CLOSE); + return NT_STATUS_INVALID_LEVEL; + } + if (vfs_set_filelen(new_fsp, size) == -1) { status = map_nt_error_from_unix(errno); close_file(req, new_fsp,NORMAL_CLOSE); @@ -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; @@ -5523,10 +5731,11 @@ static NTSTATUS smb_set_file_disposition_info(connection_struct *conn, (unsigned int)dosmode, (unsigned int)delete_on_close )); - status = can_set_delete_on_close(fsp, delete_on_close, dosmode); - - if (!NT_STATUS_IS_OK(status)) { - return status; + if (delete_on_close) { + status = can_set_delete_on_close(fsp, dosmode); + if (!NT_STATUS_IS_OK(status)) { + return status; + } } /* The set is across all open files on this dev/inode pair. */ @@ -5627,42 +5836,6 @@ static NTSTATUS smb_set_file_unix_link(connection_struct *conn, return NT_STATUS_INVALID_PARAMETER; } - /* !widelinks forces the target path to be within the share. */ - /* This means we can interpret the target as a pathname. */ - if (!lp_widelinks(SNUM(conn))) { - char *rel_name = NULL; - char *last_dirp = NULL; - - if (*link_target == '/') { - /* No absolute paths allowed. */ - return NT_STATUS_ACCESS_DENIED; - } - rel_name = talloc_strdup(ctx,newname); - if (!rel_name) { - return NT_STATUS_NO_MEMORY; - } - last_dirp = strrchr_m(rel_name, '/'); - if (last_dirp) { - last_dirp[1] = '\0'; - } else { - rel_name = talloc_strdup(ctx,"./"); - if (!rel_name) { - return NT_STATUS_NO_MEMORY; - } - } - rel_name = talloc_asprintf_append(rel_name, - "%s", - link_target); - if (!rel_name) { - return NT_STATUS_NO_MEMORY; - } - - status = check_name(conn, rel_name); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - } - DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n", newname, link_target )); @@ -6267,7 +6440,8 @@ static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn, const char *pdata, int total_data, files_struct *fsp, - const struct smb_filename *smb_fname) + const struct smb_filename *smb_fname, + bool fail_after_createfile) { SMB_OFF_T size; @@ -6292,7 +6466,8 @@ static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn, fsp, smb_fname, &smb_fname->st, - size); + size, + fail_after_createfile); } /**************************************************************************** @@ -6578,7 +6753,8 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn, fsp, smb_fname, &sbuf, - size); + size, + false); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -7174,11 +7350,22 @@ NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn, case SMB_FILE_END_OF_FILE_INFORMATION: case SMB_SET_FILE_END_OF_FILE_INFO: { + /* + * XP/Win7 both fail after the createfile with + * SMB_SET_FILE_END_OF_FILE_INFO but not + * SMB_FILE_END_OF_FILE_INFORMATION (pass-through). + * The level is known here, so pass it down + * appropriately. + */ + bool should_fail = + (info_level == SMB_SET_FILE_END_OF_FILE_INFO); + status = smb_set_file_end_of_file_info(conn, req, pdata, total_data, fsp, - smb_fname); + smb_fname, + should_fail); break; } @@ -7211,6 +7398,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, @@ -7431,7 +7627,8 @@ static void call_trans2setfilepathinfo(connection_struct *conn, max_data_bytes); return; } else { - reply_doserror(req, ERRDOS, ERRbadpath); + reply_nterror(req, + NT_STATUS_OBJECT_PATH_NOT_FOUND); return; } } else { @@ -7571,7 +7768,7 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req, TALLOC_CTX *ctx = talloc_tos(); if (!CAN_WRITE(conn)) { - reply_doserror(req, ERRSRV, ERRaccess); + reply_nterror(req, NT_STATUS_ACCESS_DENIED); return; } @@ -7790,7 +7987,7 @@ static void call_trans2getdfsreferral(connection_struct *conn, max_referral_level = SVAL(params,0); if(!lp_host_msdfs()) { - reply_doserror(req, ERRDOS, ERRbadfunc); + reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED); return; } @@ -7832,7 +8029,7 @@ static void call_trans2ioctl(connection_struct *conn, /* check for an invalid fid before proceeding */ if (!fsp) { - reply_doserror(req, ERRDOS, ERRbadfid); + reply_nterror(req, NT_STATUS_INVALID_HANDLE); return; } @@ -7861,7 +8058,7 @@ static void call_trans2ioctl(connection_struct *conn, } DEBUG(2,("Unknown TRANS2_IOCTL\n")); - reply_doserror(req, ERRSRV, ERRerror); + reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED); } /**************************************************************************** @@ -7930,7 +8127,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); } @@ -8087,7 +8284,7 @@ static void handle_trans2(connection_struct *conn, struct smb_request *req, default: /* Error in request */ DEBUG(2,("Unknown request %d in trans2 call\n", state->call)); - reply_doserror(req, ERRSRV,ERRerror); + reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED); } } @@ -8139,7 +8336,7 @@ void reply_trans2(struct smb_request *req) case TRANSACT2_SETFSINFO: break; default: - reply_doserror(req, ERRSRV, ERRaccess); + reply_nterror(req, NT_STATUS_ACCESS_DENIED); END_PROFILE(SMBtrans2); return; }