We've already checked fsp must be non-null here.
[kai/samba.git] / source3 / smbd / trans2.c
index b853722eae0947db984bf51cde9b0204b0f441cc..05c180fc5dbc4f2dd3963053b07108a418acbeab 100644 (file)
@@ -1082,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,
@@ -1137,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;
                }
@@ -2269,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);
@@ -2312,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);
@@ -2329,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)) {
@@ -3209,7 +3211,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                                DEBUG(0,("set_user_quota: access_denied "
                                         "service [%s] user [%s]\n",
                                         lp_servicename(SNUM(conn)),
-                                        conn->session_info->unix_name));
+                                        conn->session_info->unix_info->unix_name));
                                return NT_STATUS_ACCESS_DENIED;
                        }
 
@@ -3386,7 +3388,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                            + 4 /* num_sids */
                            + 4 /* SID bytes */
                            + 4 /* pad/reserved */
-                           + (conn->session_info->utok.ngroups * 8)
+                           + (conn->session_info->unix_token->ngroups * 8)
                                /* groups list */
                            + (conn->session_info->security_token->num_sids *
                                    SID_MAX_SIZE)
@@ -3395,9 +3397,9 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                        SIVAL(pdata, 0, flags);
                        SIVAL(pdata, 4, SMB_WHOAMI_MASK);
                        SBIG_UINT(pdata, 8,
-                                 (uint64_t)conn->session_info->utok.uid);
+                                 (uint64_t)conn->session_info->unix_token->uid);
                        SBIG_UINT(pdata, 16,
-                                 (uint64_t)conn->session_info->utok.gid);
+                                 (uint64_t)conn->session_info->unix_token->gid);
 
 
                        if (data_len >= max_data_bytes) {
@@ -3412,7 +3414,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                                break;
                        }
 
-                       SIVAL(pdata, 24, conn->session_info->utok.ngroups);
+                       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
@@ -3434,9 +3436,9 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                        data_len = 40;
 
                        /* GID list */
-                       for (i = 0; i < conn->session_info->utok.ngroups; ++i) {
+                       for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
                                SBIG_UINT(pdata, data_len,
-                                         (uint64_t)conn->session_info->utok.groups[i]);
+                                         (uint64_t)conn->session_info->unix_token->groups[i]);
                                data_len += 8;
                        }
 
@@ -3538,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;
@@ -3578,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:
                        {
@@ -3684,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;
@@ -3703,7 +3706,7 @@ cap_low = 0x%x, cap_high = 0x%x\n",
                                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->session_info->unix_name));
+                                                conn->session_info->unix_info->unix_name));
                                        reply_nterror(req, NT_STATUS_ACCESS_DENIED);
                                        return;
                                }
@@ -4671,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"));
@@ -4681,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",
@@ -5102,6 +5104,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
        } else {
                uint32_t name_hash;
                char *fname = NULL;
+               uint32_t ucf_flags = 0;
 
                /* qpathinfo */
                if (total_params < 7) {
@@ -5113,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],
@@ -5130,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)) {
@@ -5763,7 +5773,7 @@ static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
+       if (!(fsp->access_mask & FILE_WRITE_EA)) {
                return NT_STATUS_ACCESS_DENIED;
        }
 
@@ -5817,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->session_info->utok)) {
+                                conn->session_info->unix_token)) {
                return NT_STATUS_ACCESS_DENIED;
        }
        return NT_STATUS_OK;
@@ -6554,10 +6564,6 @@ static NTSTATUS smb_set_info_standard(connection_struct *conn,
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
-               return NT_STATUS_ACCESS_DENIED;
-       }
-
        /* create time */
        ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
        /* access time */
@@ -6616,16 +6622,16 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
                allocation_size = smb_roundup(conn, allocation_size);
        }
 
-       if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
-               return NT_STATUS_ACCESS_DENIED;
-       }
-
        DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
                  "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
                  (double)allocation_size));
 
        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) {
@@ -6717,10 +6723,6 @@ static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
                  "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
                  (double)size));
 
-       if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
-               return NT_STATUS_ACCESS_DENIED;
-       }
-
        return smb_set_file_size(conn, req,
                                fsp,
                                smb_fname,
@@ -8047,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;
                }