We've already checked fsp must be non-null here.
[mat/samba.git] / source3 / smbd / trans2.c
index b81eb837befa3c29b5010d48f1964370a4017cc7..05c180fc5dbc4f2dd3963053b07108a418acbeab 100644 (file)
 */
 
 #include "includes.h"
+#include "system/filesys.h"
 #include "version.h"
+#include "smbd/smbd.h"
 #include "smbd/globals.h"
 #include "../libcli/auth/libcli_auth.h"
 #include "../librpc/gen_ndr/xattr.h"
 #include "../librpc/gen_ndr/ndr_security.h"
+#include "libcli/security/security.h"
+#include "trans2.h"
+#include "auth.h"
+#include "smbprofile.h"
+#include "rpc_server/srv_pipe_hnd.h"
 
 #define DIR_ENTRY_SAFETY_MARGIN 4096
 
@@ -100,7 +107,7 @@ static bool samba_private_attr_name(const char *unix_ea_name)
                if (strequal( prohibited_ea_names[i], unix_ea_name))
                        return true;
        }
-       if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
+       if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
                        strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
                return true;
        }
@@ -122,7 +129,7 @@ NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
 
  again:
 
-       val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
+       val = talloc_realloc(mem_ctx, val, char, attr_size);
        if (!val) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -185,7 +192,7 @@ NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
         * TALLOC the result early to get the talloc hierarchy right.
         */
 
-       names = TALLOC_ARRAY(mem_ctx, char *, 1);
+       names = talloc_array(mem_ctx, char *, 1);
        if (names == NULL) {
                DEBUG(0, ("talloc failed\n"));
                return NT_STATUS_NO_MEMORY;
@@ -193,7 +200,7 @@ NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
 
        while (ea_namelist_size <= 65536) {
 
-               ea_namelist = TALLOC_REALLOC_ARRAY(
+               ea_namelist = talloc_realloc(
                        names, ea_namelist, char, ea_namelist_size);
                if (ea_namelist == NULL) {
                        DEBUG(0, ("talloc failed\n"));
@@ -252,7 +259,7 @@ NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
                num_names += 1;
        }
 
-       tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
+       tmp = talloc_realloc(mem_ctx, names, char *, num_names);
        if (tmp == NULL) {
                DEBUG(0, ("talloc failed\n"));
                TALLOC_FREE(names);
@@ -309,7 +316,7 @@ static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_str
                    || samba_private_attr_name(names[i]))
                        continue;
 
-               listp = TALLOC_P(mem_ctx, struct ea_list);
+               listp = talloc(mem_ctx, struct ea_list);
                if (listp == NULL) {
                        return NULL;
                }
@@ -381,7 +388,7 @@ static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned in
                SCVAL(p,0,ea_list->ea.flags);
                SCVAL(p,1,dos_namelen);
                SSVAL(p,2,ea_list->ea.value.length);
-               fstrcpy(p+4, dos_ea_name);
+               strlcpy(p+4, dos_ea_name, dos_namelen+1);
                memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
 
                total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
@@ -445,7 +452,7 @@ static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
                SCVAL(p, 0x04, ea_list->ea.flags);
                SCVAL(p, 0x05, dos_namelen);
                SSVAL(p, 0x06, ea_list->ea.value.length);
-               fstrcpy((char *)(p+0x08), dos_ea_name);
+               strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
                memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
 
                total_data_size -= this_size;
@@ -484,7 +491,7 @@ static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, con
                if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
                        DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
                                &unix_ea_name[5], ea_list->ea.name));
-                       safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
+                       strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
                        break;
                }
        }
@@ -503,6 +510,10 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
                return NT_STATUS_EAS_NOT_SUPPORTED;
        }
 
+       if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
        /* For now setting EAs on streams isn't supported. */
        fname = smb_fname->base_name;
 
@@ -579,7 +590,7 @@ static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, siz
        size_t converted_size, offset = 0;
 
        while (offset + 2 < data_size) {
-               struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
+               struct ea_list *eal = talloc_zero(ctx, struct ea_list);
                unsigned int namelen = CVAL(pdata,offset);
 
                offset++; /* Go past the namelen byte. */
@@ -617,7 +628,7 @@ static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, siz
 
 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
 {
-       struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
+       struct ea_list *eal = talloc_zero(ctx, struct ea_list);
        uint16 val_len;
        unsigned int namelen;
        size_t converted_size;
@@ -800,7 +811,7 @@ void send_trans2_replies(connection_struct *conn,
        if(params_to_send == 0 && data_to_send == 0) {
                reply_outbuf(req, 10, 0);
                show_msg((char *)req->outbuf);
-               if (!srv_send_smb(smbd_server_fd(),
+               if (!srv_send_smb(sconn,
                                (char *)req->outbuf,
                                true, req->seqnum+1,
                                IS_CONN_ENCRYPTED(conn),
@@ -939,7 +950,7 @@ void send_trans2_replies(connection_struct *conn,
 
                /* Send the packet */
                show_msg((char *)req->outbuf);
-               if (!srv_send_smb(smbd_server_fd(),
+               if (!srv_send_smb(sconn,
                                (char *)req->outbuf,
                                true, req->seqnum+1,
                                IS_CONN_ENCRYPTED(conn),
@@ -1071,7 +1082,8 @@ static void call_trans2open(connection_struct *conn,
                goto out;
        }
 
-       if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
+       if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
+                                        open_ofun,
                                         &access_mask, &share_mode,
                                         &create_disposition,
                                         &create_options,
@@ -1126,7 +1138,7 @@ static void call_trans2open(connection_struct *conn,
                &smb_action);                           /* psbuf */
 
        if (!NT_STATUS_IS_OK(status)) {
-               if (open_was_deferred(req->mid)) {
+               if (open_was_deferred(req->sconn, req->mid)) {
                        /* We have re-scheduled this call. */
                        goto out;
                }
@@ -1138,7 +1150,7 @@ static void call_trans2open(connection_struct *conn,
        fattr = dos_mode(conn, smb_fname);
        mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
        inode = smb_fname->st.st_ex_ino;
-       if (fattr & aDIR) {
+       if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
                close_file(req, fsp, ERROR_CLOSE);
                reply_nterror(req, NT_STATUS_ACCESS_DENIED);
                goto out;
@@ -1208,7 +1220,7 @@ static bool exact_match(bool has_wild,
        if (case_sensitive) {
                return strcmp(str,mask)==0;
        } else {
-               return StrCaseCmp(str,mask) == 0;
+               return strcasecmp_m(str,mask) == 0;
        }
 }
 
@@ -1514,7 +1526,7 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
        ZERO_STRUCT(create_date_ts);
        ZERO_STRUCT(cdate_ts);
 
-       if (!(mode & aDIR)) {
+       if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
                file_size = get_file_size_stat(&smb_fname->st);
        }
        allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
@@ -2258,6 +2270,7 @@ static void call_trans2findfirst(connection_struct *conn,
        TALLOC_CTX *ctx = talloc_tos();
        struct dptr_struct *dirptr = NULL;
        struct smbd_server_connection *sconn = req->sconn;
+       uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
 
        if (total_params < 13) {
                reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
@@ -2301,6 +2314,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
                                reply_nterror(req, NT_STATUS_INVALID_LEVEL);
                                goto out;
                        }
+                       ucf_flags |= UCF_UNIX_NAME_LOOKUP;
                        break;
                default:
                        reply_nterror(req, NT_STATUS_INVALID_LEVEL);
@@ -2318,8 +2332,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
        ntstatus = filename_convert(ctx, conn,
                                    req->flags2 & FLAGS2_DFS_PATHNAMES,
                                    directory,
-                                   (UCF_SAVE_LCOMP |
-                                       UCF_ALWAYS_ALLOW_WCARD_LCOMP),
+                                   ucf_flags,
                                    &mask_contains_wcard,
                                    &smb_dname);
        if (!NT_STATUS_IS_OK(ntstatus)) {
@@ -2347,13 +2360,17 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
                        }
                        mask_contains_wcard = True;
                }
-               directory = talloc_strdup(talloc_tos(), "./");
+       } else {
+               *p = 0;
+       }
+
+       if (p == NULL || p == directory) {
+               /* Ensure we don't have a directory name of "". */
+               directory = talloc_strdup(talloc_tos(), ".");
                if (!directory) {
                        reply_nterror(req, NT_STATUS_NO_MEMORY);
                        goto out;
                }
-       } else {
-               *p = 0;
        }
 
        DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
@@ -2408,6 +2425,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                needed as lanman2 assumes these are being saved between calls */
 
        ntstatus = dptr_create(conn,
+                               NULL, /* fsp */
                                directory,
                                False,
                                True,
@@ -2891,8 +2909,8 @@ static void samba_extended_info_version(struct smb_extended_info *extended_info)
        extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
 #endif
        extended_info->samba_gitcommitdate = 0;
-#ifdef SAMBA_VERSION_GIT_COMMIT_TIME
-       unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
+#ifdef SAMBA_VERSION_COMMIT_TIME
+       unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
 #endif
 
        memset(extended_info->samba_version_string, 0,
@@ -3189,11 +3207,11 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                        fsp.fnum = -1;
 
                        /* access check */
-                       if (conn->server_info->utok.uid != sec_initial_uid()) {
+                       if (get_current_uid(conn) != 0) {
                                DEBUG(0,("set_user_quota: access_denied "
                                         "service [%s] user [%s]\n",
                                         lp_servicename(SNUM(conn)),
-                                        conn->server_info->unix_name));
+                                        conn->session_info->unix_info->unix_name));
                                return NT_STATUS_ACCESS_DENIED;
                        }
 
@@ -3346,7 +3364,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                         * in our list of SIDs.
                         */
                        if (nt_token_check_sid(&global_sid_Builtin_Guests,
-                                              conn->server_info->ptok)) {
+                                              conn->session_info->security_token)) {
                                flags |= SMB_WHOAMI_GUEST;
                        }
 
@@ -3354,7 +3372,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                         * is in our list of SIDs.
                         */
                        if (nt_token_check_sid(&global_sid_Authenticated_Users,
-                                              conn->server_info->ptok)) {
+                                              conn->session_info->security_token)) {
                                flags &= ~SMB_WHOAMI_GUEST;
                        }
 
@@ -3370,18 +3388,18 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                            + 4 /* num_sids */
                            + 4 /* SID bytes */
                            + 4 /* pad/reserved */
-                           + (conn->server_info->utok.ngroups * 8)
+                           + (conn->session_info->unix_token->ngroups * 8)
                                /* groups list */
-                           + (conn->server_info->ptok->num_sids *
+                           + (conn->session_info->security_token->num_sids *
                                    SID_MAX_SIZE)
                                /* SID list */;
 
                        SIVAL(pdata, 0, flags);
                        SIVAL(pdata, 4, SMB_WHOAMI_MASK);
                        SBIG_UINT(pdata, 8,
-                                 (uint64_t)conn->server_info->utok.uid);
+                                 (uint64_t)conn->session_info->unix_token->uid);
                        SBIG_UINT(pdata, 16,
-                                 (uint64_t)conn->server_info->utok.gid);
+                                 (uint64_t)conn->session_info->unix_token->gid);
 
 
                        if (data_len >= max_data_bytes) {
@@ -3396,17 +3414,17 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                                break;
                        }
 
-                       SIVAL(pdata, 24, conn->server_info->utok.ngroups);
-                       SIVAL(pdata, 28, conn->server_info->ptok->num_sids);
+                       SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
+                       SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
 
                        /* We walk the SID list twice, but this call is fairly
                         * infrequent, and I don't expect that it's performance
                         * sensitive -- jpeach
                         */
                        for (i = 0, sid_bytes = 0;
-                            i < conn->server_info->ptok->num_sids; ++i) {
+                            i < conn->session_info->security_token->num_sids; ++i) {
                                sid_bytes += ndr_size_dom_sid(
-                                       &conn->server_info->ptok->user_sids[i],
+                                       &conn->session_info->security_token->sids[i],
                                        0);
                        }
 
@@ -3418,21 +3436,21 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                        data_len = 40;
 
                        /* GID list */
-                       for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
+                       for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
                                SBIG_UINT(pdata, data_len,
-                                         (uint64_t)conn->server_info->utok.groups[i]);
+                                         (uint64_t)conn->session_info->unix_token->groups[i]);
                                data_len += 8;
                        }
 
                        /* SID list */
                        for (i = 0;
-                           i < conn->server_info->ptok->num_sids; ++i) {
+                           i < conn->session_info->security_token->num_sids; ++i) {
                                int sid_len = ndr_size_dom_sid(
-                                       &conn->server_info->ptok->user_sids[i],
+                                       &conn->session_info->security_token->sids[i],
                                        0);
 
                                sid_linearize(pdata + data_len, sid_len,
-                                   &conn->server_info->ptok->user_sids[i]);
+                                   &conn->session_info->security_token->sids[i]);
                                data_len += sid_len;
                        }
 
@@ -3522,6 +3540,7 @@ static void call_trans2setfsinfo(connection_struct *conn,
                                 char **ppdata, int total_data,
                                 unsigned int max_data_bytes)
 {
+       struct smbd_server_connection *sconn = req->sconn;
        char *pdata = *ppdata;
        char *params = *pparams;
        uint16 info_level;
@@ -3562,54 +3581,52 @@ static void call_trans2setfsinfo(connection_struct *conn,
 
        switch(info_level) {
                case SMB_SET_CIFS_UNIX_INFO:
-                       {
-                               uint16 client_unix_major;
-                               uint16 client_unix_minor;
-                               uint32 client_unix_cap_low;
-                               uint32 client_unix_cap_high;
-
-                               if (!lp_unix_extensions()) {
-                                       reply_nterror(req,
-                                                     NT_STATUS_INVALID_LEVEL);
-                                       return;
-                               }
+                       if (!lp_unix_extensions()) {
+                               reply_nterror(req,
+                                             NT_STATUS_INVALID_LEVEL);
+                               return;
+                       }
 
-                               /* There should be 12 bytes of capabilities set. */
-                               if (total_data < 8) {
-                                       reply_nterror(
-                                               req,
-                                               NT_STATUS_INVALID_PARAMETER);
-                                       return;
-                               }
-                               client_unix_major = SVAL(pdata,0);
-                               client_unix_minor = SVAL(pdata,2);
-                               client_unix_cap_low = IVAL(pdata,4);
-                               client_unix_cap_high = IVAL(pdata,8);
-                               /* Just print these values for now. */
-                               DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
-cap_low = 0x%x, cap_high = 0x%x\n",
-                                       (unsigned int)client_unix_major,
-                                       (unsigned int)client_unix_minor,
-                                       (unsigned int)client_unix_cap_low,
-                                       (unsigned int)client_unix_cap_high ));
-
-                               /* Here is where we must switch to posix pathname processing... */
-                               if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
-                                       lp_set_posix_pathnames();
-                                       mangle_change_to_posix();
-                               }
+                       /* There should be 12 bytes of capabilities set. */
+                       if (total_data < 8) {
+                               reply_nterror(
+                                       req,
+                                       NT_STATUS_INVALID_PARAMETER);
+                               return;
+                       }
+                       sconn->smb1.unix_info.client_major = SVAL(pdata,0);
+                       sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
+                       sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
+                       sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
+                       /* Just print these values for now. */
+                       DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
+                                  "major = %u, minor = %u cap_low = 0x%x, "
+                                  "cap_high = 0x%xn",
+                                  (unsigned int)sconn->
+                                  smb1.unix_info.client_major,
+                                  (unsigned int)sconn->
+                                  smb1.unix_info.client_minor,
+                                  (unsigned int)sconn->
+                                  smb1.unix_info.client_cap_low,
+                                  (unsigned int)sconn->
+                                  smb1.unix_info.client_cap_high));
+
+                       /* Here is where we must switch to posix pathname processing... */
+                       if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
+                               lp_set_posix_pathnames();
+                               mangle_change_to_posix();
+                       }
 
-                               if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
-                                   !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
-                                       /* Client that knows how to do posix locks,
-                                        * but not posix open/mkdir operations. Set a
-                                        * default type for read/write checks. */
+                       if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
+                           !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
+                               /* Client that knows how to do posix locks,
+                                * but not posix open/mkdir operations. Set a
+                                * default type for read/write checks. */
 
-                                       lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
+                               lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
 
-                               }
-                               break;
                        }
+                       break;
 
                case SMB_REQUEST_TRANSPORT_ENCRYPTION:
                        {
@@ -3668,9 +3685,11 @@ cap_low = 0x%x, cap_high = 0x%x\n",
                                         * encryption is now *on*. */
                                        status = srv_encryption_start(conn);
                                        if (!NT_STATUS_IS_OK(status)) {
-                                               exit_server_cleanly(
-                                                       "Failure in setting "
-                                                       "up encrypted transport");
+                                               char *reason = talloc_asprintf(talloc_tos(),
+                                                                              "Failure in setting "
+                                                                              "up encrypted transport: %s",
+                                                                              nt_errstr(status));
+                                               exit_server_cleanly(reason);
                                        }
                                }
                                return;
@@ -3684,11 +3703,10 @@ cap_low = 0x%x, cap_high = 0x%x\n",
                                ZERO_STRUCT(quotas);
 
                                /* access check */
-                               if ((conn->server_info->utok.uid != sec_initial_uid())
-                                   ||!CAN_WRITE(conn)) {
+                               if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
                                        DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
                                                 lp_servicename(SNUM(conn)),
-                                                conn->server_info->unix_name));
+                                                conn->session_info->unix_info->unix_name));
                                        reply_nterror(req, NT_STATUS_ACCESS_DENIED);
                                        return;
                                }
@@ -3719,36 +3737,10 @@ cap_low = 0x%x, cap_high = 0x%x\n",
                                /* unknown_1 24 NULL bytes in pdata*/
 
                                /* the soft quotas 8 bytes (uint64_t)*/
-                               quotas.softlim = (uint64_t)IVAL(pdata,24);
-#ifdef LARGE_SMB_OFF_T
-                               quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
-#else /* LARGE_SMB_OFF_T */
-                               if ((IVAL(pdata,28) != 0)&&
-                                       ((quotas.softlim != 0xFFFFFFFF)||
-                                       (IVAL(pdata,28)!=0xFFFFFFFF))) {
-                                       /* more than 32 bits? */
-                                       reply_nterror(
-                                               req,
-                                               NT_STATUS_INVALID_PARAMETER);
-                                       return;
-                               }
-#endif /* LARGE_SMB_OFF_T */
+                               quotas.softlim = BVAL(pdata,24);
 
                                /* the hard quotas 8 bytes (uint64_t)*/
-                               quotas.hardlim = (uint64_t)IVAL(pdata,32);
-#ifdef LARGE_SMB_OFF_T
-                               quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
-#else /* LARGE_SMB_OFF_T */
-                               if ((IVAL(pdata,36) != 0)&&
-                                       ((quotas.hardlim != 0xFFFFFFFF)||
-                                       (IVAL(pdata,36)!=0xFFFFFFFF))) {
-                                       /* more than 32 bits? */
-                                       reply_nterror(
-                                               req,
-                                               NT_STATUS_INVALID_PARAMETER);
-                                       return;
-                               }
-#endif /* LARGE_SMB_OFF_T */
+                               quotas.hardlim = BVAL(pdata,32);
 
                                /* quota_flags 2 bytes **/
                                quotas.qflags = SVAL(pdata,40);
@@ -4239,7 +4231,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
        mode = dos_mode(conn, smb_fname);
        nlink = psbuf->st_ex_nlink;
 
-       if (nlink && (mode&aDIR)) {
+       if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
                nlink = 1;
        }
 
@@ -4314,13 +4306,13 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                /* Do we have this path open ? */
                files_struct *fsp1;
                struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
-               fsp1 = file_find_di_first(fileid);
+               fsp1 = file_find_di_first(conn->sconn, fileid);
                if (fsp1 && fsp1->initial_allocation_size) {
                        allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
                }
        }
 
-       if (!(mode & aDIR)) {
+       if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
                file_size = get_file_size_stat(psbuf);
        }
 
@@ -4490,7 +4482,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                        SOFF_T(pdata,8,file_size);
                        SIVAL(pdata,16,nlink);
                        SCVAL(pdata,20,delete_pending?1:0);
-                       SCVAL(pdata,21,(mode&aDIR)?1:0);
+                       SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
                        SSVAL(pdata,22,0); /* Padding. */
                        break;
 
@@ -4573,7 +4565,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                        SOFF_T(pdata,8,file_size);
                        SIVAL(pdata,16,nlink);
                        SCVAL(pdata,20,delete_pending);
-                       SCVAL(pdata,21,(mode&aDIR)?1:0);
+                       SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
                        SSVAL(pdata,22,0);
                        pdata += 24;
                        SIVAL(pdata,0,ea_size);
@@ -4604,7 +4596,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                        SBVAL(pdata,    0x30, file_size);
                        SIVAL(pdata,    0x38, nlink);
                        SCVAL(pdata,    0x3C, delete_pending);
-                       SCVAL(pdata,    0x3D, (mode&aDIR)?1:0);
+                       SCVAL(pdata,    0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
                        SSVAL(pdata,    0x3E, 0); /* padding */
                        SBVAL(pdata,    0x40, file_index);
                        SIVAL(pdata,    0x48, ea_size);
@@ -4682,8 +4674,8 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                 */
                case SMB_QUERY_FILE_STREAM_INFO:
                case SMB_FILE_STREAM_INFORMATION: {
-                       unsigned int num_streams;
-                       struct stream_struct *streams;
+                       unsigned int num_streams = 0;
+                       struct stream_struct *streams = NULL;
 
                        DEBUG(10,("smbd_do_qfilepathinfo: "
                                  "SMB_FILE_STREAM_INFORMATION\n"));
@@ -4692,9 +4684,8 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                                return NT_STATUS_INVALID_PARAMETER;
                        }
 
-                       status = SMB_VFS_STREAMINFO(
-                               conn, fsp, smb_fname->base_name, talloc_tos(),
-                               &num_streams, &streams);
+                       status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
+                                               talloc_tos(), &num_streams, &streams);
 
                        if (!NT_STATUS_IS_OK(status)) {
                                DEBUG(10, ("could not get stream info: %s\n",
@@ -4754,14 +4745,9 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                        pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
                        data_size = PTR_DIFF(pdata,(*ppdata));
 
-                       {
-                               int i;
-                               DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
-
-                               for (i=0; i<100; i++)
-                                       DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
-                               DEBUG(4,("\n"));
-                       }
+                       DEBUG(4,("smbd_do_qfilepathinfo: "
+                                "SMB_QUERY_FILE_UNIX_BASIC\n"));
+                       dump_data(4, (uint8_t *)(*ppdata), data_size);
 
                        break;
 
@@ -4784,7 +4770,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                case SMB_QUERY_FILE_UNIX_LINK:
                        {
                                int len;
-                               char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
+                               char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
 
                                if (!buffer) {
                                        return NT_STATUS_NO_MEMORY;
@@ -4823,7 +4809,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                                uint16 num_file_acls = 0;
                                uint16 num_def_acls = 0;
 
-                               if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
+                               if (fsp && fsp->fh->fd != -1) {
                                        file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
                                } else {
                                        file_acl =
@@ -4916,7 +4902,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                        enum brl_type lock_type;
 
                        /* We need an open file with a real fd for this. */
-                       if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
+                       if (!fsp || fsp->fh->fd == -1) {
                                return NT_STATUS_INVALID_LEVEL;
                        }
 
@@ -5069,7 +5055,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
 
                        /* We know this name is ok, it's already passed the checks. */
 
-               } else if(fsp->is_directory || fsp->fh->fd == -1) {
+               } else if(fsp->fh->fd == -1) {
                        /*
                         * This is actually a QFILEINFO on a directory
                         * handle (returned from an NT SMB). NT5.0 seems
@@ -5099,15 +5085,11 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
                        }
 
                        fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
-                       get_file_infos(fileid, &delete_pending, &write_time_ts);
+                       get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
                } else {
                        /*
                         * Original code - this is an open file.
                         */
-                       if (!check_fsp(conn, req, fsp)) {
-                               return;
-                       }
-
                        if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
                                DEBUG(3, ("fstat of fnum %d failed (%s)\n",
                                          fsp->fnum, strerror(errno)));
@@ -5116,11 +5098,13 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
                                return;
                        }
                        fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
-                       get_file_infos(fileid, &delete_pending, &write_time_ts);
+                       get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
                }
 
        } else {
+               uint32_t name_hash;
                char *fname = NULL;
+               uint32_t ucf_flags = 0;
 
                /* qpathinfo */
                if (total_params < 7) {
@@ -5132,9 +5116,16 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
 
                DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
 
-               if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
-                       reply_nterror(req, NT_STATUS_INVALID_LEVEL);
-                       return;
+               if (INFO_LEVEL_IS_UNIX(info_level)) {
+                       if (!lp_unix_extensions()) {
+                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                               return;
+                       }
+                       if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
+                                       info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
+                                       info_level == SMB_QUERY_FILE_UNIX_LINK) {
+                               ucf_flags |= UCF_UNIX_NAME_LOOKUP;
+                       }
                }
 
                srvstr_get_path(req, params, req->flags2, &fname, &params[6],
@@ -5149,7 +5140,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
                                        conn,
                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
                                        fname,
-                                       0,
+                                       ucf_flags,
                                        NULL,
                                        &smb_fname);
                if (!NT_STATUS_IS_OK(status)) {
@@ -5206,10 +5197,19 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
                                }
                        }
 
+                       status = file_name_hash(conn,
+                                       smb_fname_str_dbg(smb_fname_base),
+                                       &name_hash);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               TALLOC_FREE(smb_fname_base);
+                               reply_nterror(req, status);
+                               return;
+                       }
+
                        fileid = vfs_file_id_from_sbuf(conn,
                                                       &smb_fname_base->st);
                        TALLOC_FREE(smb_fname_base);
-                       get_file_infos(fileid, &delete_pending, NULL);
+                       get_file_infos(fileid, name_hash, &delete_pending, NULL);
                        if (delete_pending) {
                                reply_nterror(req, NT_STATUS_DELETE_PENDING);
                                return;
@@ -5240,8 +5240,16 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
                        }
                }
 
+               status = file_name_hash(conn,
+                               smb_fname_str_dbg(smb_fname),
+                               &name_hash);
+               if (!NT_STATUS_IS_OK(status)) {
+                       reply_nterror(req, status);
+                       return;
+               }
+
                fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
-               get_file_infos(fileid, &delete_pending, &write_time_ts);
+               get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
                if (delete_pending) {
                        reply_nterror(req, NT_STATUS_DELETE_PENDING);
                        return;
@@ -5303,7 +5311,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                        }
 
                        /* Copy the lock range data. */
-                       lock_data = (char *)TALLOC_MEMDUP(
+                       lock_data = (char *)talloc_memdup(
                                req, pdata, total_data);
                        if (!lock_data) {
                                reply_nterror(req, NT_STATUS_NO_MEMORY);
@@ -5450,6 +5458,10 @@ NTSTATUS smb_set_file_time(connection_struct *conn,
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
        }
 
+       if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
        /* get some defaults (no modifications) if any info is zero or -1. */
        if (null_timespec(ft->create_time)) {
                action &= ~FILE_NOTIFY_CHANGE_CREATION;
@@ -5553,9 +5565,9 @@ static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
 
        if (dosmode) {
                if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
-                       dosmode |= aDIR;
+                       dosmode |= FILE_ATTRIBUTE_DIRECTORY;
                } else {
-                       dosmode &= ~aDIR;
+                       dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
                }
        }
 
@@ -5603,6 +5615,10 @@ static NTSTATUS smb_set_file_size(connection_struct *conn,
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
        }
 
+       if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
        DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
 
        if (size == get_file_size_stat(psbuf)) {
@@ -5709,6 +5725,11 @@ static NTSTATUS smb_info_set_ea(connection_struct *conn,
        if (!ea_list) {
                return NT_STATUS_INVALID_PARAMETER;
        }
+
+       if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
        status = set_ea(conn, fsp, smb_fname, ea_list);
 
        return status;
@@ -5751,6 +5772,11 @@ static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
        if (!ea_list) {
                return NT_STATUS_INVALID_PARAMETER;
        }
+
+       if (!(fsp->access_mask & FILE_WRITE_EA)) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
        status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
 
        DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
@@ -5801,7 +5827,7 @@ static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
 
        /* The set is across all open files on this dev/inode pair. */
        if (!set_delete_on_close(fsp, delete_on_close,
-                                &conn->server_info->utok)) {
+                                conn->session_info->unix_token)) {
                return NT_STATUS_ACCESS_DENIED;
        }
        return NT_STATUS_OK;
@@ -5996,7 +6022,7 @@ static NTSTATUS smb2_file_rename_information(connection_struct *conn,
                                conn,
                                req->flags2 & FLAGS2_DFS_PATHNAMES,
                                newname,
-                               0,
+                               UCF_SAVE_LCOMP,
                                NULL,
                                &smb_fname_dst);
        if (!NT_STATUS_IS_OK(status)) {
@@ -6034,8 +6060,9 @@ static NTSTATUS smb2_file_rename_information(connection_struct *conn,
                  "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
                  fsp->fnum, fsp_str_dbg(fsp),
                  smb_fname_str_dbg(smb_fname_dst)));
-       status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
-                                     overwrite);
+       status = rename_internals_fsp(conn, fsp, smb_fname_dst,
+                               (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
+                               overwrite);
 
  out:
        TALLOC_FREE(smb_fname_dst);
@@ -6085,7 +6112,7 @@ static NTSTATUS smb_file_link_information(connection_struct *conn,
                                conn,
                                req->flags2 & FLAGS2_DFS_PATHNAMES,
                                newname,
-                               0,
+                               UCF_SAVE_LCOMP,
                                NULL,
                                &smb_fname_dst);
        if (!NT_STATUS_IS_OK(status)) {
@@ -6220,7 +6247,7 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
                if (p) {
                        p[1] = '\0';
                } else {
-                       base_name = talloc_strdup(ctx, "./");
+                       base_name = talloc_strdup(ctx, "");
                        if (!base_name) {
                                return NT_STATUS_NO_MEMORY;
                        }
@@ -6489,6 +6516,10 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
                return NT_STATUS_INVALID_PARAMETER;
        }
 
+       if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
        /* Set the attributes */
        dosmode = IVAL(pdata,32);
        status = smb_set_file_dosmode(conn, smb_fname, dosmode);
@@ -6597,6 +6628,10 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
 
        if (fsp && fsp->fh->fd != -1) {
                /* Open file handle. */
+               if (!(fsp->access_mask & FILE_WRITE_DATA)) {
+                       return NT_STATUS_ACCESS_DENIED;
+               }
+
                /* Only change if needed. */
                if (allocation_size != get_file_size_stat(&smb_fname->st)) {
                        if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
@@ -6804,6 +6839,7 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
        files_struct *all_fsps = NULL;
        bool modify_mtime = true;
        struct file_id id;
+       struct smb_filename *smb_fname_tmp = NULL;
        SMB_STRUCT_STAT sbuf;
 
        ZERO_STRUCT(ft);
@@ -6856,7 +6892,6 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
        sbuf = smb_fname->st;
 
        if (!VALID_STAT(sbuf)) {
-               struct smb_filename *smb_fname_tmp = NULL;
                /*
                 * The only valid use of this is to create character and block
                 * devices, and named pipes. This is deprecated (IMHO) and 
@@ -6885,7 +6920,7 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
                }
 
                sbuf = smb_fname_tmp->st;
-               TALLOC_FREE(smb_fname_tmp);
+               smb_fname = smb_fname_tmp;
 
                /* Ensure we don't try and change anything else. */
                raw_unixmode = SMB_MODE_NO_CHANGE;
@@ -6992,7 +7027,7 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
        }
 
        id = vfs_file_id_from_sbuf(conn, &sbuf);
-       for(all_fsps = file_find_di_first(id); all_fsps;
+       for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
                        all_fsps = file_find_di_next(all_fsps)) {
                /*
                 * We're setting the time explicitly for UNIX.
@@ -7194,6 +7229,9 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
  Open/Create a file with POSIX semantics.
 ****************************************************************************/
 
+#define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
+#define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
+
 static NTSTATUS smb_posix_open(connection_struct *conn,
                               struct smb_request *req,
                                char **ppdata,
@@ -7209,7 +7247,7 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
        uint32 mod_unixmode = 0;
        uint32 create_disp = 0;
        uint32 access_mask = 0;
-       uint32 create_options = 0;
+       uint32 create_options = FILE_NON_DIRECTORY_FILE;
        NTSTATUS status = NT_STATUS_OK;
        mode_t unixmode = (mode_t)0;
        files_struct *fsp = NULL;
@@ -7239,13 +7277,14 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
 
        switch (wire_open_mode & SMB_ACCMODE) {
                case SMB_O_RDONLY:
-                       access_mask = FILE_READ_DATA;
+                       access_mask = SMB_O_RDONLY_MAPPING;
                        break;
                case SMB_O_WRONLY:
-                       access_mask = FILE_WRITE_DATA;
+                       access_mask = SMB_O_WRONLY_MAPPING;
                        break;
                case SMB_O_RDWR:
-                       access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
+                       access_mask = (SMB_O_RDONLY_MAPPING|
+                                       SMB_O_WRONLY_MAPPING);
                        break;
                default:
                        DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
@@ -7255,18 +7294,55 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
 
        wire_open_mode &= ~SMB_ACCMODE;
 
-       if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
-               create_disp = FILE_CREATE;
-       } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
-               create_disp = FILE_OVERWRITE_IF;
-       } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
-               create_disp = FILE_OPEN_IF;
-       } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
-               create_disp = FILE_OPEN;
-       } else {
-               DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
-                       (unsigned int)wire_open_mode ));
-               return NT_STATUS_INVALID_PARAMETER;
+       /* First take care of O_CREAT|O_EXCL interactions. */
+       switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
+               case (SMB_O_CREAT | SMB_O_EXCL):
+                       /* File exists fail. File not exist create. */
+                       create_disp = FILE_CREATE;
+                       break;
+               case SMB_O_CREAT:
+                       /* File exists open. File not exist create. */
+                       create_disp = FILE_OPEN_IF;
+                       break;
+               case 0:
+                       /* File exists open. File not exist fail. */
+                       create_disp = FILE_OPEN;
+                       break;
+               case SMB_O_EXCL:
+                       /* O_EXCL on its own without O_CREAT is undefined. */
+               default:
+                       DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
+                               (unsigned int)wire_open_mode ));
+                       return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       /* Next factor in the effects of O_TRUNC. */
+       wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
+
+       if (wire_open_mode & SMB_O_TRUNC) {
+               switch (create_disp) {
+                       case FILE_CREATE:
+                               /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
+                               /* Leave create_disp alone as
+                                  (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
+                               */
+                               /* File exists fail. File not exist create. */
+                               break;
+                       case FILE_OPEN_IF:
+                               /* SMB_O_CREAT | SMB_O_TRUNC */
+                               /* File exists overwrite. File not exist create. */
+                               create_disp = FILE_OVERWRITE_IF;
+                               break;
+                       case FILE_OPEN:
+                               /* SMB_O_TRUNC */
+                               /* File exists overwrite. File not exist fail. */
+                               create_disp = FILE_OVERWRITE;
+                               break;
+                       default:
+                               /* Cannot get here. */
+                               smb_panic("smb_posix_open: logic error");
+                               return NT_STATUS_INVALID_PARAMETER;
+               }
        }
 
        raw_unixmode = IVAL(pdata,8);
@@ -7293,6 +7369,15 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
                mod_unixmode |= FILE_FLAG_NO_BUFFERING;
        }
 
+       if ((wire_open_mode & SMB_O_DIRECTORY) ||
+                       VALID_STAT_OF_DIR(smb_fname->st)) {
+               if (access_mask != SMB_O_RDONLY_MAPPING) {
+                       return NT_STATUS_FILE_IS_A_DIRECTORY;
+               }
+               create_options &= ~FILE_NON_DIRECTORY_FILE;
+               create_options |= FILE_DIRECTORY_FILE;
+       }
+
        DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
                smb_fname_str_dbg(smb_fname),
                (unsigned int)wire_open_mode,
@@ -7307,7 +7392,7 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
                (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
                    FILE_SHARE_DELETE),
                create_disp,                            /* create_disposition*/
-               FILE_NON_DIRECTORY_FILE,                /* create_options */
+               create_options,                         /* create_options */
                mod_unixmode,                           /* file_attributes */
                oplock_request,                         /* oplock_request */
                0,                                      /* allocation_size */
@@ -7829,7 +7914,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
                        return;
                }
 
-               if(fsp->is_directory || fsp->fh->fd == -1) {
+               if(fsp->fh->fd == -1) {
                        /*
                         * This is actually a SETFILEINFO on a directory
                         * handle (returned from an NT SMB). NT5.0 seems
@@ -7881,10 +7966,6 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
                        /*
                         * Original code - this is an open file.
                         */
-                       if (!check_fsp(conn, req, fsp)) {
-                               return;
-                       }
-
                        if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
                                DEBUG(3,("call_trans2setfilepathinfo: fstat "
                                         "of fnum %d failed (%s)\n", fsp->fnum,
@@ -7968,7 +8049,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
                                         ppdata, total_data,
                                         &data_return_size);
        if (!NT_STATUS_IS_OK(status)) {
-               if (open_was_deferred(req->mid)) {
+               if (open_was_deferred(req->sconn, req->mid)) {
                        /* We have re-scheduled this call. */
                        return;
                }
@@ -8249,7 +8330,7 @@ static void call_trans2getdfsreferral(connection_struct *conn,
                return;
        }
 
-       SSVAL(req->inbuf, smb_flg2,
+       SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
              SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
        send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
 
@@ -8298,7 +8379,7 @@ static void call_trans2ioctl(connection_struct *conn,
                        SSVAL(pdata, 0, 0);
                }
                srvstr_push(pdata, req->flags2, pdata + 2,
-                           global_myname(), 15,
+                           lp_netbios_name(), 15,
                            STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
                srvstr_push(pdata, req->flags2, pdata+18,
                            lp_servicename(SNUM(conn)), 13,
@@ -8380,7 +8461,7 @@ static void handle_trans2(connection_struct *conn, struct smb_request *req,
 {
        if (get_Protocol() >= PROTOCOL_NT1) {
                req->flags2 |= 0x40; /* IS_LONG_NAME */
-               SSVAL(req->inbuf,smb_flg2,req->flags2);
+               SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
        }
 
        if (conn->encrypt_level == Required && !req->encrypted) {
@@ -8593,7 +8674,7 @@ void reply_trans2(struct smb_request *req)
                }
        }
 
-       if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
+       if ((state = talloc(conn, struct trans_state)) == NULL) {
                DEBUG(0, ("talloc failed\n"));
                reply_nterror(req, NT_STATUS_NO_MEMORY);
                END_PROFILE(SMBtrans2);
@@ -8739,7 +8820,7 @@ void reply_transs2(struct smb_request *req)
 
        START_PROFILE(SMBtranss2);
 
-       show_msg((char *)req->inbuf);
+       show_msg((const char *)req->inbuf);
 
        if (req->wct < 8) {
                reply_nterror(req, NT_STATUS_INVALID_PARAMETER);