Now conn is part of smb_request, we don't need it as
[nivanova/samba-autobuild/.git] / source3 / smbd / trans2.c
index 478f60d094c6113557c9bbe092bf571648578693..c3b5f9fa2f02d50ea13f4a96a7393d56d2ba7721 100644 (file)
@@ -27,7 +27,6 @@
 
 extern int max_send;
 extern enum protocol_types Protocol;
-extern int smb_read_error;
 extern uint32 global_client_caps;
 extern struct current_user current_user;
 
@@ -94,7 +93,7 @@ SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, con
  Refuse to allow clients to overwrite our private xattrs.
 ****************************************************************************/
 
-static BOOL samba_private_attr_name(const char *unix_ea_name)
+static bool samba_private_attr_name(const char *unix_ea_name)
 {
        static const char *prohibited_ea_names[] = {
                SAMBA_POSIX_INHERITANCE_EA_NAME,
@@ -115,7 +114,7 @@ static BOOL samba_private_attr_name(const char *unix_ea_name)
  Get one EA value. Fill in a struct ea_struct.
 ****************************************************************************/
 
-static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
+static bool get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
                                const char *fname, char *ea_name, struct ea_struct *pea)
 {
        /* Get the value of this xattr. Max size is 64k. */
@@ -145,7 +144,7 @@ static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_str
                return False;
        }
 
-       DEBUG(10,("get_ea_value: EA %s is of length %u", ea_name, (unsigned int)sizeret));
+       DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
        dump_data(10, (uint8 *)val, sizeret);
 
        pea->flags = 0;
@@ -576,7 +575,8 @@ static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *
   HACK ! Always assumes smb_setup field is zero.
 ****************************************************************************/
 
-void send_trans2_replies(struct smb_request *req,
+void send_trans2_replies(connection_struct *conn,
+                       struct smb_request *req,
                         const char *params,
                         int paramsize,
                         const char *pdata,
@@ -597,7 +597,7 @@ void send_trans2_replies(struct smb_request *req,
        int params_sent_thistime, data_sent_thistime, total_sent_thistime;
        int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
        int data_alignment_offset = 0;
-       BOOL overflow = False;
+       bool overflow = False;
 
        /* Modify the data_to_send and datasize and set the error if
           we're trying to send more than max_data_bytes. We still send
@@ -738,8 +738,10 @@ void send_trans2_replies(struct smb_request *req,
 
                /* Send the packet */
                show_msg((char *)req->outbuf);
-               if (!send_smb(smbd_server_fd(),(char *)req->outbuf))
-                       exit_server_cleanly("send_trans2_replies: send_smb failed.");
+               if (!srv_send_smb(smbd_server_fd(),
+                               (char *)req->outbuf,
+                               IS_CONN_ENCRYPTED(conn)))
+                       exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
 
                TALLOC_FREE(req->outbuf);
 
@@ -774,9 +776,9 @@ static void call_trans2open(connection_struct *conn,
        char *pdata = *ppdata;
        int deny_mode;
        int32 open_attr;
-       BOOL oplock_request;
+       bool oplock_request;
 #if 0
-       BOOL return_additional_info;
+       bool return_additional_info;
        int16 open_sattr;
        time_t open_time;
 #endif
@@ -842,20 +844,6 @@ static void call_trans2open(connection_struct *conn,
                fname, (unsigned int)deny_mode, (unsigned int)open_attr,
                (unsigned int)open_ofun, open_size));
 
-       /* XXXX we need to handle passed times, sattr and flags */
-
-       status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
-       if (!NT_STATUS_IS_OK(status)) {
-               reply_nterror(req, status);
-               return;
-       }
-
-       status = check_name(conn, fname);
-       if (!NT_STATUS_IS_OK(status)) {
-               reply_nterror(req, status);
-               return;
-       }
-
        if (open_ofun == 0) {
                reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
                return;
@@ -900,14 +888,22 @@ static void call_trans2open(connection_struct *conn,
                return;
        }
 
-       status = open_file_ntcreate(conn, req, fname, &sbuf,
-               access_mask,
-               share_mode,
-               create_disposition,
-               create_options,
-               open_attr,
-               oplock_request,
-               &smb_action, &fsp);
+       status = create_file(conn,                      /* conn */
+                            req,                       /* req */
+                            0,                         /* root_dir_fid */
+                            fname,                     /* fname */
+                            access_mask,               /* access_mask */
+                            share_mode,                /* share_access */
+                            create_disposition,        /* create_disposition*/
+                            create_options,            /* create_options */
+                            open_attr,                 /* file_attributes */
+                            oplock_request,            /* oplock_request */
+                            open_size,                 /* allocation_size */
+                            NULL,                      /* sd */
+                            ea_list,                   /* ea_list */
+                            &fsp,                      /* result */
+                            &smb_action,               /* pinfo */
+                            &sbuf);                    /* psbuf */
 
        if (!NT_STATUS_IS_OK(status)) {
                if (open_was_deferred(req->mid)) {
@@ -928,41 +924,6 @@ static void call_trans2open(connection_struct *conn,
                return;
        }
 
-       /* Save the requested allocation size. */
-       /* Allocate space for the file if a size hint is supplied */
-       if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
-               SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
-               if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
-                        fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
-                        if (fsp->is_directory) {
-                                close_file(fsp,ERROR_CLOSE);
-                                /* Can't set allocation size on a directory. */
-                               reply_nterror(req, NT_STATUS_ACCESS_DENIED);
-                               return;
-                        }
-                        if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
-                                close_file(fsp,ERROR_CLOSE);
-                               reply_nterror(req, NT_STATUS_DISK_FULL);
-                               return;
-                        }
-
-                       /* Adjust size here to return the right size in the reply.
-                          Windows does it this way. */
-                       size = fsp->initial_allocation_size;
-                } else {
-                        fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
-                }
-       }
-
-       if (ea_list && smb_action == FILE_WAS_CREATED) {
-               status = set_ea(conn, fsp, fname, ea_list);
-               if (!NT_STATUS_IS_OK(status)) {
-                       close_file(fsp,ERROR_CLOSE);
-                       reply_nterror(req, status);
-                       return;
-               }
-       }
-
        /* Realloc the size of parameters and data we will return */
        *pparams = (char *)SMB_REALLOC(*pparams, 30);
        if(*pparams == NULL ) {
@@ -998,7 +959,7 @@ static void call_trans2open(connection_struct *conn,
        }
 
        /* Send the required number of replies */
-       send_trans2_replies(req, params, 30, *ppdata, 0, max_data_bytes);
+       send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
 }
 
 /*********************************************************
@@ -1008,7 +969,7 @@ static void call_trans2open(connection_struct *conn,
  Case can be significant or not.
 **********************************************************/
 
-static BOOL exact_match(connection_struct *conn,
+static bool exact_match(connection_struct *conn,
                const char *str,
                const char *mask)
 {
@@ -1136,25 +1097,25 @@ static NTSTATUS unix_perms_from_wire( connection_struct *conn,
  Get a level dependent lanman2 dir entry.
 ****************************************************************************/
 
-static BOOL get_lanman2_dir_entry(TALLOC_CTX *ctx,
+static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
                                connection_struct *conn,
                                uint16 flags2,
                                const char *path_mask,
                                uint32 dirtype,
                                int info_level,
                                int requires_resume_key,
-                               BOOL dont_descend,
+                               bool dont_descend,
                                char **ppdata,
                                char *base_data,
                                char *end_data,
                                int space_remaining,
-                               BOOL *out_of_space,
-                               BOOL *got_exact_match,
+                               bool *out_of_space,
+                               bool *got_exact_match,
                                int *last_entry_off,
                                struct ea_list *name_list)
 {
        const char *dname;
-       BOOL found = False;
+       bool found = False;
        SMB_STRUCT_STAT sbuf;
        const char *mask = NULL;
        char *pathreal = NULL;
@@ -1170,10 +1131,10 @@ static BOOL get_lanman2_dir_entry(TALLOC_CTX *ctx,
        time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
        char *nameptr;
        char *last_entry_ptr;
-       BOOL was_8_3;
+       bool was_8_3;
        uint32 nt_extmode; /* Used for NT connections instead of mode */
-       BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
-       BOOL check_mangled_names = lp_manglednames(conn->params);
+       bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
+       bool check_mangled_names = lp_manglednames(conn->params);
        char mangled_name[13]; /* mangled 8.3 name. */
 
        *out_of_space = False;
@@ -1199,8 +1160,8 @@ static BOOL get_lanman2_dir_entry(TALLOC_CTX *ctx,
        }
 
        while (!found) {
-               BOOL got_match;
-               BOOL ms_dfs_link = False;
+               bool got_match;
+               bool ms_dfs_link = False;
 
                /* Needed if we run out of space */
                long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
@@ -1262,7 +1223,7 @@ static BOOL get_lanman2_dir_entry(TALLOC_CTX *ctx,
                }
 
                if (got_match) {
-                       BOOL isdots = (ISDOT(dname) || ISDOTDOT(dname));
+                       bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
 
                        if (dont_descend && !isdots) {
                                continue;
@@ -1372,7 +1333,9 @@ static BOOL get_lanman2_dir_entry(TALLOC_CTX *ctx,
                        SSVAL(p,20,mode);
                        p += 23;
                        nameptr = p;
-                       p += align_string(pdata, p, 0);
+                       if (flags2 & FLAGS2_UNICODE_STRINGS) {
+                               p += ucs2_align(base_data, p, 0);
+                       }
                        len = srvstr_push(base_data, flags2, p,
                                          fname, PTR_DIFF(end_data, p),
                                          STR_TERMINATE);
@@ -1469,7 +1432,7 @@ static BOOL get_lanman2_dir_entry(TALLOC_CTX *ctx,
                        p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
                        nameptr = p;
                        len = srvstr_push(base_data, flags2,
-                                         p + 1, fname, PTR_DIFF(end_data, p),
+                                         p + 1, fname, PTR_DIFF(end_data, p+1),
                                          STR_TERMINATE | STR_NOALIGN);
                        if (flags2 & FLAGS2_UNICODE_STRINGS) {
                                if (len > 2) {
@@ -1554,7 +1517,7 @@ static BOOL get_lanman2_dir_entry(TALLOC_CTX *ctx,
                        SOFF_T(p,0,allocation_size); p += 8;
                        SIVAL(p,0,nt_extmode); p += 4;
                        len = srvstr_push(base_data, flags2,
-                                         p + 4, fname, PTR_DIFF(end_data, p),
+                                         p + 4, fname, PTR_DIFF(end_data, p+4),
                                          STR_TERMINATE_ASCII);
                        SIVAL(p,0,len);
                        p += 4 + len;
@@ -1782,9 +1745,9 @@ static void call_trans2findfirst(connection_struct *conn,
        uint32 dirtype;
        int maxentries;
        uint16 findfirst_flags;
-       BOOL close_after_first;
-       BOOL close_if_end;
-       BOOL requires_resume_key;
+       bool close_after_first;
+       bool close_if_end;
+       bool requires_resume_key;
        int info_level;
        char *directory = NULL;
        const char *mask = NULL;
@@ -1793,11 +1756,11 @@ static void call_trans2findfirst(connection_struct *conn,
        int dptr_num = -1;
        int numentries = 0;
        int i;
-       BOOL finished = False;
-       BOOL dont_descend = False;
-       BOOL out_of_space = False;
+       bool finished = False;
+       bool dont_descend = False;
+       bool out_of_space = False;
        int space_remaining;
-       BOOL mask_contains_wcard = False;
+       bool mask_contains_wcard = False;
        SMB_STRUCT_STAT sbuf;
        struct ea_list *ea_list = NULL;
        NTSTATUS ntstatus = NT_STATUS_OK;
@@ -1984,7 +1947,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
        out_of_space = False;
 
        for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
-               BOOL got_exact_match = False;
+               bool got_exact_match = False;
 
                /* this is a heuristic to avoid seeking the dirptr except when 
                        absolutely necessary. It allows for a filename of about 40 chars */
@@ -2023,7 +1986,13 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                if(got_exact_match)
                        finished = True;
 
-               space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
+               /* Ensure space_remaining never goes -ve. */
+               if (PTR_DIFF(p,pdata) > max_data_bytes) {
+                       space_remaining = 0;
+                       out_of_space = true;
+               } else {
+                       space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
+               }
        }
 
        /* Check if we can close the dirptr */
@@ -2060,7 +2029,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
        SSVAL(params,6,0); /* Never an EA error */
        SSVAL(params,8,last_entry_off);
 
-       send_trans2_replies(req, params, 10, pdata, PTR_DIFF(p,pdata),
+       send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
                            max_data_bytes);
 
        if ((! *directory) && dptr_path(dptr_num)) {
@@ -2113,11 +2082,11 @@ static void call_trans2findnext(connection_struct *conn,
        uint16 info_level;
        uint32 resume_key;
        uint16 findnext_flags;
-       BOOL close_after_request;
-       BOOL close_if_end;
-       BOOL requires_resume_key;
-       BOOL continue_bit;
-       BOOL mask_contains_wcard = False;
+       bool close_after_request;
+       bool close_if_end;
+       bool requires_resume_key;
+       bool continue_bit;
+       bool mask_contains_wcard = False;
        char *resume_name = NULL;
        const char *mask = NULL;
        const char *directory = NULL;
@@ -2125,9 +2094,9 @@ static void call_trans2findnext(connection_struct *conn,
        uint16 dirtype;
        int numentries = 0;
        int i, last_entry_off=0;
-       BOOL finished = False;
-       BOOL dont_descend = False;
-       BOOL out_of_space = False;
+       bool finished = False;
+       bool dont_descend = False;
+       bool out_of_space = False;
        int space_remaining;
        struct ea_list *ea_list = NULL;
        NTSTATUS ntstatus = NT_STATUS_OK;
@@ -2326,7 +2295,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
        } /* end if resume_name && !continue_bit */
 
        for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
-               BOOL got_exact_match = False;
+               bool got_exact_match = False;
 
                /* this is a heuristic to avoid seeking the dirptr except when 
                        absolutely necessary. It allows for a filename of about 40 chars */
@@ -2384,7 +2353,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
        SSVAL(params,4,0); /* Never an EA error */
        SSVAL(params,6,last_entry_off);
 
-       send_trans2_replies(req, params, 8, pdata, PTR_DIFF(p,pdata),
+       send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
                            max_data_bytes);
 
        return;
@@ -2423,6 +2392,27 @@ static void call_trans2qfsinfo(connection_struct *conn,
 
        info_level = SVAL(params,0);
 
+       if (IS_IPC(conn)) {
+               if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
+                       DEBUG(0,("call_trans2qfsinfo: not an allowed "
+                               "info level (0x%x) on IPC$.\n",
+                               (unsigned int)info_level));
+                       reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+                       return;
+               }
+       }
+
+       if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
+               if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
+                       DEBUG(0,("call_trans2qfsinfo: encryption required "
+                               "and info level 0x%x sent.\n",
+                               (unsigned int)info_level));
+                       exit_server_cleanly("encryption required "
+                               "on connection");
+                       return;
+               }
+       }
+
        DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
 
        if(SMB_VFS_STAT(conn,".",&st)!=0) {
@@ -2719,24 +2709,52 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                 */
 
                case SMB_QUERY_CIFS_UNIX_INFO:
+               {
+                       bool large_write = lp_min_receive_file_size() &&
+                                               !srv_is_signing_active();
+                       bool large_read = !srv_is_signing_active();
+                       int encrypt_caps = 0;
+
                        if (!lp_unix_extensions()) {
                                reply_nterror(req, NT_STATUS_INVALID_LEVEL);
                                return;
                        }
+
+                       switch (conn->encrypt_level) {
+                       case 0:
+                               encrypt_caps = 0;
+                               break;
+                       case 1:
+                       case Auto:
+                               encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
+                               break;
+                       case Required:
+                               encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
+                                               CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
+                               large_write = false;
+                               large_read = false;
+                               break;
+                       }
+
                        data_len = 12;
                        SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
                        SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
-                       /* We have POSIX ACLs, pathname and locking capability. */
+
+                       /* We have POSIX ACLs, pathname, encryption, 
+                        * large read/write, and locking capability. */
+
                        SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
                                        CIFS_UNIX_POSIX_ACLS_CAP|
                                        CIFS_UNIX_POSIX_PATHNAMES_CAP|
                                        CIFS_UNIX_FCNTL_LOCKS_CAP|
                                        CIFS_UNIX_EXTATTR_CAP|
                                        CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
-                                       /* Ensure we don't do this on signed or sealed data. */
-                                       (srv_is_signing_active() ? 0 : CIFS_UNIX_LARGE_READ_CAP)
-                                       )));
+                                       encrypt_caps|
+                                       (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
+                                       (large_write ?
+                                       CIFS_UNIX_LARGE_WRITE_CAP : 0))));
                        break;
+               }
 
                case SMB_QUERY_POSIX_FS_INFO:
                {
@@ -2852,8 +2870,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                         */
                        for (i = 0, sid_bytes = 0;
                            i < current_user.nt_user_token->num_sids; ++i) {
-                               sid_bytes +=
-                                   sid_size(&current_user.nt_user_token->user_sids[i]);
+                               sid_bytes += ndr_size_dom_sid(
+                                       &current_user.nt_user_token->user_sids[i], 0);
                        }
 
                        /* SID list byte count */
@@ -2873,8 +2891,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                        /* SID list */
                        for (i = 0;
                            i < current_user.nt_user_token->num_sids; ++i) {
-                               int sid_len =
-                                   sid_size(&current_user.nt_user_token->user_sids[i]);
+                               int sid_len = ndr_size_dom_sid(
+                                       &current_user.nt_user_token->user_sids[i], 0);
 
                                sid_linearize(pdata + data_len, sid_len,
                                    &current_user.nt_user_token->user_sids[i]);
@@ -2901,7 +2919,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
        }
 
 
-       send_trans2_replies(req, params, 0, pdata, data_len,
+       send_trans2_replies(conn, req, params, 0, pdata, data_len,
                            max_data_bytes);
 
        DEBUG( 4, ( "%s info_level = %d\n",
@@ -2936,6 +2954,28 @@ static void call_trans2setfsinfo(connection_struct *conn,
 
        info_level = SVAL(params,2);
 
+       if (IS_IPC(conn)) {
+               if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
+                               info_level != SMB_SET_CIFS_UNIX_INFO) {
+                       DEBUG(0,("call_trans2setfsinfo: not an allowed "
+                               "info level (0x%x) on IPC$.\n",
+                               (unsigned int)info_level));
+                       reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+                       return;
+               }
+       }
+
+       if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
+               if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
+                       DEBUG(0,("call_trans2setfsinfo: encryption required "
+                               "and info level 0x%x sent.\n",
+                               (unsigned int)info_level));
+                       exit_server_cleanly("encryption required "
+                               "on connection");
+                       return;
+               }
+       }
+
        switch(info_level) {
                case SMB_SET_CIFS_UNIX_INFO:
                        {
@@ -2986,6 +3026,7 @@ cap_low = 0x%x, cap_high = 0x%x\n",
                                }
                                break;
                        }
+
                case SMB_REQUEST_TRANSPORT_ENCRYPTION:
                        {
                                NTSTATUS status;
@@ -2994,43 +3035,53 @@ cap_low = 0x%x, cap_high = 0x%x\n",
 
                                if (!lp_unix_extensions()) {
                                        reply_nterror(
-                                               req, NT_STATUS_INVALID_LEVEL);
+                                               req,
+                                               NT_STATUS_INVALID_LEVEL);
                                        return;
                                }
 
-                               DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n"));
+                               if (lp_smb_encrypt(SNUM(conn)) == false) {
+                                       reply_nterror(
+                                               req,
+                                               NT_STATUS_NOT_SUPPORTED);
+                                       return;
+                               }
+
+                               DEBUG( 4,("call_trans2setfsinfo: "
+                                       "request transport encrption.\n"));
 
                                status = srv_request_encryption_setup(conn,
-                                                                       (unsigned char **)ppdata,
-                                                                       &data_len,
-                                                                       (unsigned char **)pparams,
-                                                                       &param_len
-                                                                       );
-
-                               if (!NT_STATUS_IS_OK(status)) {
-                                       /*
-                                        * TODO: Check
-                                        * MORE_PROCESSING_REQUIRED, this used
-                                        * to have special handling here.
-                                        */
+                                                               (unsigned char **)ppdata,
+                                                               &data_len,
+                                                               (unsigned char **)pparams,
+                                                               &param_len);
+
+                               if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
+                                               !NT_STATUS_IS_OK(status)) {
                                        reply_nterror(req, status);
                                        return;
                                }
 
-                               send_trans2_replies(req,
-                                                   *pparams, param_len,
-                                                   *ppdata, data_len,
-                                                   max_data_bytes);
+                               send_trans2_replies(conn, req,
+                                               *pparams,
+                                               param_len,
+                                               *ppdata,
+                                               data_len,
+                                               max_data_bytes);
 
                                if (NT_STATUS_IS_OK(status)) {
-                                       /* Server-side transport encryption is now *on*. */
+                                       /* Server-side transport
+                                        * encryption is now *on*. */
                                        status = srv_encryption_start(conn);
                                        if (!NT_STATUS_IS_OK(status)) {
-                                               exit_server_cleanly("Failure in setting up encrypted transport");
+                                               exit_server_cleanly(
+                                                       "Failure in setting "
+                                                       "up encrypted transport");
                                        }
                                }
                                return;
                        }
+
                case SMB_FS_QUOTA_INFORMATION:
                        {
                                files_struct *fsp = NULL;
@@ -3157,7 +3208,7 @@ static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_a
  Utility function to marshall a POSIX acl into wire format.
 ****************************************************************************/
 
-static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
+static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
 {
        int entry_id = SMB_ACL_FIRST_ENTRY;
        SMB_ACL_ENTRY_T entry;
@@ -3312,7 +3363,7 @@ static char *store_file_unix_basic(connection_struct *conn,
  *
  * XXX: this really should be behind the VFS interface. To do this, we would
  * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
- * Each VFS module could then implement it's own mapping as appropriate for the
+ * Each VFS module could then implement its own mapping as appropriate for the
  * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
  */
 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
@@ -3356,7 +3407,7 @@ static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
 #endif /* HAVE_STAT_ST_FLAGS */
 }
 
-static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
+static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
                                const uint32 smb_fflags,
                                const uint32 smb_fmask,
                                int *stat_fflags)
@@ -3487,7 +3538,7 @@ static void call_trans2qpipeinfo(connection_struct *conn,
                        return;
        }
 
-       send_trans2_replies(req, params, param_size, *ppdata, data_size,
+       send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
                            max_data_bytes);
 
        return;
@@ -3522,7 +3573,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
        char *base_name;
        char *p;
        SMB_OFF_T pos = 0;
-       BOOL delete_pending = False;
+       bool delete_pending = False;
        int len;
        time_t create_time, mtime, atime;
        struct timespec create_time_ts, mtime_ts, atime_ts;
@@ -4209,7 +4260,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 
                case SMB_QUERY_FILE_UNIX_LINK:
                        {
-                               char *buffer = TALLOC_SIZE(ctx, 1024);
+                               char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
 
                                if (!buffer) {
                                        reply_nterror(req, NT_STATUS_NO_MEMORY);
@@ -4228,7 +4279,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                                return;
 #endif
                                len = SMB_VFS_READLINK(conn,fullpathname,
-                                               buffer, 1023);
+                                               buffer, PATH_MAX);
                                if (len == -1) {
                                        reply_unixerror(req, ERRDOS,
                                                        ERRnoaccess);
@@ -4419,7 +4470,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                        return;
        }
 
-       send_trans2_replies(req, params, param_size, *ppdata, data_size,
+       send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
                            max_data_bytes);
 
        return;
@@ -4507,13 +4558,13 @@ static NTSTATUS smb_set_file_time(connection_struct *conn,
                                files_struct *fsp,
                                const char *fname,
                                const SMB_STRUCT_STAT *psbuf,
-                               struct timespec ts[2])
+                               struct timespec ts[2],
+                               bool setting_write_time)
 {
        uint32 action =
                FILE_NOTIFY_CHANGE_LAST_ACCESS
                |FILE_NOTIFY_CHANGE_LAST_WRITE;
 
-       
        if (!VALID_STAT(*psbuf)) {
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
        }
@@ -4529,6 +4580,11 @@ static NTSTATUS smb_set_file_time(connection_struct *conn,
                action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
        }
 
+       if (!setting_write_time) {
+               /* ts[1] comes from change time, not write time. */
+               action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
+       }
+
        DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
        DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
 
@@ -4568,9 +4624,8 @@ static NTSTATUS smb_set_file_time(connection_struct *conn,
        if(file_ntimes(conn, fname, ts)!=0) {
                return map_nt_error_from_unix(errno);
        }
-       if (action != 0) {
-               notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
-       }
+       notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
+
        return NT_STATUS_OK;
 }
 
@@ -4603,7 +4658,7 @@ static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
                DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
                                        fname, (unsigned int)dosmode ));
 
-               if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
+               if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
                        DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
                                                fname, strerror(errno)));
                        return map_nt_error_from_unix(errno);
@@ -4731,7 +4786,7 @@ static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
                                SMB_STRUCT_STAT *psbuf)
 {
        NTSTATUS status = NT_STATUS_OK;
-       BOOL delete_on_close;
+       bool delete_on_close;
        uint32 dosmode = 0;
 
        if (total_data < 1) {
@@ -4948,12 +5003,12 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
                                            files_struct *fsp,
                                            const char *fname)
 {
-       BOOL overwrite;
+       bool overwrite;
        uint32 root_fid;
        uint32 len;
        char *newname = NULL;
        char *base_name = NULL;
-       BOOL dest_has_wcard = False;
+       bool dest_has_wcard = False;
        NTSTATUS status = NT_STATUS_OK;
        char *p;
        TALLOC_CTX *ctx = talloc_tos();
@@ -5066,8 +5121,8 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn,
        uint16 posix_acl_version;
        uint16 num_file_acls;
        uint16 num_def_acls;
-       BOOL valid_file_acls = True;
-       BOOL valid_def_acls = True;
+       bool valid_file_acls = True;
+       bool valid_def_acls = True;
 
        if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
                return NT_STATUS_INVALID_PARAMETER;
@@ -5119,8 +5174,7 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn,
 ****************************************************************************/
 
 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
-                               const uint8 *inbuf,
-                               int length,
+                               const struct smb_request *req,
                                const char *pdata,
                                int total_data,
                                files_struct *fsp)
@@ -5128,8 +5182,9 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn,
        SMB_BIG_UINT count;
        SMB_BIG_UINT offset;
        uint32 lock_pid;
-       BOOL blocking_lock = False;
+       bool blocking_lock = False;
        enum brl_type lock_type;
+
        NTSTATUS status = NT_STATUS_OK;
 
        if (fsp == NULL || fsp->fh->fd == -1) {
@@ -5217,7 +5272,7 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn,
                         * onto the blocking lock queue.
                         */
                        if(push_blocking_lock_request(br_lck,
-                                               (char *)inbuf, length,
+                                               req,
                                                fsp,
                                                -1, /* infinite timeout. */
                                                0,
@@ -5266,7 +5321,8 @@ static NTSTATUS smb_set_info_standard(connection_struct *conn,
                                fsp,
                                fname,
                                psbuf,
-                               ts);
+                               ts,
+                               true);
 }
 
 /****************************************************************************
@@ -5286,6 +5342,7 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
        uint32 dosmode = 0;
        struct timespec ts[2];
        NTSTATUS status = NT_STATUS_OK;
+       bool setting_write_time = true;
 
        if (total_data < 36) {
                return NT_STATUS_INVALID_PARAMETER;
@@ -5318,7 +5375,12 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
 
        /* Prefer a defined time to an undefined one. */
        if (null_timespec(ts[1])) {
-               ts[1] = null_timespec(write_time) ? changed_time : write_time;
+               if (null_timespec(write_time)) {
+                       ts[1] = changed_time;
+                       setting_write_time = false;
+               } else {
+                       ts[1] = write_time;
+               }
        }
 
        DEBUG(10,("smb_set_file_basic_info: file %s\n",
@@ -5328,7 +5390,8 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
                                fsp,
                                fname,
                                psbuf,
-                               ts);
+                               ts,
+                               setting_write_time);
 }
 
 /****************************************************************************
@@ -5389,7 +5452,8 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
                         * This is equivalent to a write. Ensure it's seen immediately
                         * if there are no pending writes.
                         */
-                       set_filetime(fsp->conn, fsp->fsp_name, timespec_current());
+                       set_filetime(fsp->conn, fsp->fsp_name,
+                                       timespec_current());
                }
                return NT_STATUS_OK;
        }
@@ -5569,7 +5633,7 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
        uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
        gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
        NTSTATUS status = NT_STATUS_OK;
-       BOOL delete_on_fail = False;
+       bool delete_on_fail = False;
        enum perm_type ptype;
 
        if (total_data < 100) {
@@ -5722,7 +5786,8 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
                                fsp,
                                fname,
                                psbuf,
-                               ts);
+                               ts,
+                               true);
 }
 
 /****************************************************************************
@@ -5894,7 +5959,7 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
                                SMB_STRUCT_STAT *psbuf,
                                int *pdata_return_size)
 {
-       BOOL extended_oplock_granted = False;
+       bool extended_oplock_granted = False;
        char *pdata = *ppdata;
        uint32 flags = 0;
        uint32 wire_open_mode = 0;
@@ -6265,7 +6330,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
                                DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
 
                                SSVAL(params,0,0);
-                               send_trans2_replies(req, params, 2,
+                               send_trans2_replies(conn, req, params, 2,
                                                    *ppdata, 0,
                                                    max_data_bytes);
                                return;
@@ -6555,8 +6620,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
                                reply_nterror(req, NT_STATUS_INVALID_LEVEL);
                                return;
                        }
-                       status = smb_set_posix_lock(conn, req->inbuf,
-                                                   smb_len(req->inbuf) + 4,
+                       status = smb_set_posix_lock(conn, req,
                                                    pdata, total_data, fsp);
                        break;
                }
@@ -6624,7 +6688,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
        }
 
        SSVAL(params,0,0);
-       send_trans2_replies(req, params, 2, *ppdata, data_return_size,
+       send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
                            max_data_bytes);
   
        return;
@@ -6716,7 +6780,7 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
                return;
        }
 
-       status = create_directory(conn, directory);
+       status = create_directory(conn, req, directory);
 
        if (!NT_STATUS_IS_OK(status)) {
                reply_nterror(req, status);
@@ -6742,7 +6806,7 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
 
        SSVAL(params,0,0);
 
-       send_trans2_replies(req, params, 2, *ppdata, 0, max_data_bytes);
+       send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
   
        return;
 }
@@ -6796,7 +6860,7 @@ static void call_trans2findnotifyfirst(connection_struct *conn,
        if(fnf_handle == 0)
                fnf_handle = 257;
 
-       send_trans2_replies(req, params, 6, *ppdata, 0, max_data_bytes);
+       send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
   
        return;
 }
@@ -6827,7 +6891,7 @@ static void call_trans2findnotifynext(connection_struct *conn,
        SSVAL(params,0,0); /* No changes */
        SSVAL(params,2,0); /* No EA errors */
 
-       send_trans2_replies(req, params, 4, *ppdata, 0, max_data_bytes);
+       send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
   
        return;
 }
@@ -6877,7 +6941,7 @@ static void call_trans2getdfsreferral(connection_struct *conn,
 
        SSVAL(req->inbuf, smb_flg2,
              SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
-       send_trans2_replies(req,0,0,*ppdata,reply_size, max_data_bytes);
+       send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
 
        return;
 }
@@ -6924,7 +6988,7 @@ static void call_trans2ioctl(connection_struct *conn,
                srvstr_push(pdata, req->flags2, pdata+18,
                            lp_servicename(SNUM(conn)), 13,
                            STR_ASCII|STR_TERMINATE); /* Service name */
-               send_trans2_replies(req, *pparams, 0, *ppdata, 32,
+               send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
                                    max_data_bytes);
                return;
        }
@@ -6937,7 +7001,7 @@ static void call_trans2ioctl(connection_struct *conn,
  Reply to a SMBfindclose (stop trans2 directory search).
 ****************************************************************************/
 
-void reply_findclose(connection_struct *conn, struct smb_request *req)
+void reply_findclose(struct smb_request *req)
 {
        int dptr_num;
 
@@ -6967,7 +7031,7 @@ void reply_findclose(connection_struct *conn, struct smb_request *req)
  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
 ****************************************************************************/
 
-void reply_findnclose(connection_struct *conn, struct smb_request *req)
+void reply_findnclose(struct smb_request *req)
 {
        int dptr_num;
 
@@ -7003,6 +7067,17 @@ static void handle_trans2(connection_struct *conn, struct smb_request *req,
                SSVAL(req->inbuf,smb_flg2,req->flags2);
        }
 
+       if (conn->encrypt_level == Required && !req->encrypted) {
+               if (state->call != TRANSACT2_QFSINFO &&
+                               state->call != TRANSACT2_SETFSINFO) {
+                       DEBUG(0,("handle_trans2: encryption required "
+                               "with call 0x%x\n",
+                               (unsigned int)state->call));
+                       reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+                       return;
+               }
+       }
+
        /* Now we must call the relevant TRANS2 function */
        switch(state->call)  {
        case TRANSACT2_OPEN:
@@ -7150,8 +7225,9 @@ static void handle_trans2(connection_struct *conn, struct smb_request *req,
  Reply to a SMBtrans2.
  ****************************************************************************/
 
-void reply_trans2(connection_struct *conn, struct smb_request *req)
+void reply_trans2(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        unsigned int dsoff;
        unsigned int dscnt;
        unsigned int psoff;
@@ -7185,12 +7261,20 @@ void reply_trans2(connection_struct *conn, struct smb_request *req)
                return;
        }
 
-       if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
-            && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
-            && (tran_call != TRANSACT2_QFILEINFO)) {
-               reply_doserror(req, ERRSRV, ERRaccess);
-               END_PROFILE(SMBtrans2);
-               return;
+       if (IS_IPC(conn)) {
+               switch (tran_call) {
+               /* List the allowed trans2 calls on IPC$ */
+               case TRANSACT2_OPEN:
+               case TRANSACT2_GET_DFS_REFERRAL:
+               case TRANSACT2_QFILEINFO:
+               case TRANSACT2_QFSINFO:
+               case TRANSACT2_SETFSINFO:
+                       break;
+               default:
+                       reply_doserror(req, ERRSRV, ERRaccess);
+                       END_PROFILE(SMBtrans2);
+                       return;
+               }
        }
 
        if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
@@ -7331,8 +7415,9 @@ void reply_trans2(connection_struct *conn, struct smb_request *req)
  Reply to a SMBtranss2
  ****************************************************************************/
 
-void reply_transs2(connection_struct *conn, struct smb_request *req)
+void reply_transs2(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
        struct trans_state *state;
        int size;