s3: Fix shadow copy display on Windows 7
[samba.git] / source / smbd / nttrans.c
index 362823d78a55258b4273be39cf78847c2e9bc649..c392380b5ec7e39adff73fe2a2c8b991c71dc464 100644 (file)
 
 extern int max_send;
 extern enum protocol_types Protocol;
-extern struct current_user current_user;
-
-static const char *known_nt_pipes[] = {
-       "\\LANMAN",
-       "\\srvsvc",
-       "\\samr",
-       "\\wkssvc",
-       "\\NETLOGON",
-       "\\ntlsa",
-       "\\ntsvcs",
-       "\\lsass",
-       "\\lsarpc",
-       "\\winreg",
-       "\\initshutdown",
-       "\\spoolss",
-       "\\netdfs",
-       "\\rpcecho",
-        "\\svcctl",
-       "\\eventlog",
-       "\\unixinfo",
-       NULL
-};
+extern const struct generic_mapping file_generic_mapping;
 
 static char *nttrans_realloc(char **ptr, size_t size)
 {
@@ -113,14 +92,11 @@ void send_nt_replies(connection_struct *conn,
                                    + alignment_offset
                                    + data_alignment_offset);
 
-       /*
-        * useable_space can never be more than max_send minus the
-        * alignment offset.
-        */
-
-       useable_space = MIN(useable_space,
-                               max_send - (alignment_offset+data_alignment_offset));
-
+       if (useable_space < 0) {
+               DEBUG(0, ("send_nt_replies failed sanity useable_space "
+                         "= %d!!!", useable_space));
+               exit_server_cleanly("send_nt_replies: srv_send_smb failed.");
+       }
 
        while (params_to_send || data_to_send) {
 
@@ -128,8 +104,7 @@ void send_nt_replies(connection_struct *conn,
                 * Calculate whether we will totally or partially fill this packet.
                 */
 
-               total_sent_thistime = params_to_send + data_to_send +
-                                       alignment_offset + data_alignment_offset;
+               total_sent_thistime = params_to_send + data_to_send;
 
                /*
                 * We can never send more than useable_space.
@@ -137,7 +112,9 @@ void send_nt_replies(connection_struct *conn,
 
                total_sent_thistime = MIN(total_sent_thistime, useable_space);
 
-               reply_outbuf(req, 18, total_sent_thistime);
+               reply_outbuf(req, 18,
+                            total_sent_thistime + alignment_offset
+                            + data_alignment_offset);
 
                /*
                 * Set total params and data to be sent.
@@ -264,7 +241,7 @@ void send_nt_replies(connection_struct *conn,
                if(params_to_send < 0 || data_to_send < 0) {
                        DEBUG(0,("send_nt_replies failed sanity check pts = %d, dts = %d\n!!!",
                                params_to_send, data_to_send));
-                       return;
+                       exit_server_cleanly("send_nt_replies: internal error");
                }
        }
 }
@@ -292,25 +269,12 @@ static void nt_open_pipe(char *fname, connection_struct *conn,
                         struct smb_request *req, int *ppnum)
 {
        smb_np_struct *p = NULL;
-       int i;
 
        DEBUG(4,("nt_open_pipe: Opening pipe %s.\n", fname));
 
        /* See if it is one we want to handle. */
 
-       if (lp_disable_spoolss() && strequal(fname, "\\spoolss")) {
-               reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
-                               ERRDOS, ERRbadpipe);
-               return;
-       }
-
-       for( i = 0; known_nt_pipes[i]; i++ ) {
-               if( strequal(fname,known_nt_pipes[i])) {
-                       break;
-               }
-       }
-
-       if ( known_nt_pipes[i] == NULL ) {
+       if (!is_known_pipename(fname)) {
                reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
                                ERRDOS, ERRbadpipe);
                return;
@@ -489,6 +453,12 @@ void reply_ntcreate_and_X(struct smb_request *req)
                        (unsigned int)root_dir_fid,
                        fname));
 
+       /*
+        * we need to remove ignored bits when they come directly from the client
+        * because we reuse some of them for internal stuff
+        */
+       create_options &= ~NTCREATEX_OPTIONS_MUST_IGNORE_MASK;
+
        /*
         * If it's an IPC, use the pipe handler.
         */
@@ -757,17 +727,20 @@ static NTSTATUS set_sd(files_struct *fsp, uint8 *data, uint32 sd_len,
                return status;
        }
 
-       if (psd->owner_sid==0) {
+       if (psd->owner_sid == NULL) {
                security_info_sent &= ~OWNER_SECURITY_INFORMATION;
        }
-       if (psd->group_sid==0) {
+       if (psd->group_sid == NULL) {
                security_info_sent &= ~GROUP_SECURITY_INFORMATION;
        }
-       if (psd->sacl==0) {
-               security_info_sent &= ~SACL_SECURITY_INFORMATION;
-       }
-       if (psd->dacl==0) {
-               security_info_sent &= ~DACL_SECURITY_INFORMATION;
+
+       /* Convert all the generic bits. */
+       security_acl_map_generic(psd->dacl, &file_generic_mapping);
+       security_acl_map_generic(psd->sacl, &file_generic_mapping);
+
+       if (DEBUGLEVEL >= 10) {
+               DEBUG(10,("set_sd for file %s\n", fsp->fsp_name ));
+               NDR_PRINT_DEBUG(security_descriptor, psd);
        }
 
        status = SMB_VFS_FSET_NT_ACL(fsp, security_info_sent, psd);
@@ -893,6 +866,12 @@ static void call_nt_transact_create(connection_struct *conn,
        allocation_size |= (((SMB_BIG_UINT)IVAL(params,16)) << 32);
 #endif
 
+       /*
+        * we need to remove ignored bits when they come directly from the client
+        * because we reuse some of them for internal stuff
+        */
+       create_options &= ~NTCREATEX_OPTIONS_MUST_IGNORE_MASK;
+
        /* Ensure the data_len is correct for the sd and ea values given. */
        if ((ea_len + sd_len > data_count)
            || (ea_len > data_count) || (sd_len > data_count)
@@ -1097,7 +1076,7 @@ void reply_ntcancel(struct smb_request *req)
        START_PROFILE(SMBntcancel);
        remove_pending_change_notify_requests_by_mid(req->mid);
        remove_pending_lock_requests_by_mid(req->mid);
-       srv_cancel_sign_response(req->mid);
+       srv_cancel_sign_response(req->mid, true);
 
        DEBUG(3,("reply_ntcancel: cancel called on mid = %d.\n", req->mid));
 
@@ -1284,13 +1263,6 @@ void reply_ntrename(struct smb_request *req)
                return;
        }
 
-       if( is_ntfs_stream_name(oldname)) {
-               /* Can't rename a stream. */
-               reply_nterror(req, NT_STATUS_ACCESS_DENIED);
-               END_PROFILE(SMBntrename);
-               return;
-       }
-
        if (ms_has_wild(oldname)) {
                reply_nterror(req, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
                END_PROFILE(SMBntrename);
@@ -1339,6 +1311,13 @@ void reply_ntrename(struct smb_request *req)
                return;
        }
 
+       /* The new name must begin with a ':' if the old name is a stream. */
+       if (is_ntfs_stream_name(oldname) && (newname[0] != ':')) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               END_PROFILE(SMBntrename);
+               return;
+       }
+
        DEBUG(3,("reply_ntrename : %s -> %s\n",oldname,newname));
 
        switch(rename_type) {
@@ -1520,7 +1499,7 @@ static void call_nt_transact_rename(connection_struct *conn,
        }
 
        fsp = file_fsp(SVAL(params, 0));
-       if (!check_fsp(conn, req, fsp, &current_user)) {
+       if (!check_fsp(conn, req, fsp)) {
                return;
        }
        srvstr_get_path_wcard(ctx, params, req->flags2, &new_name, params+4,
@@ -1612,25 +1591,32 @@ static void call_nt_transact_query_security_desc(connection_struct *conn,
        if (!lp_nt_acl_support(SNUM(conn))) {
                status = get_null_nt_acl(talloc_tos(), &psd);
        } else {
-               if (fsp->fh->fd != -1) {
-                       status = SMB_VFS_FGET_NT_ACL(
-                               fsp, security_info_wanted, &psd);
-               }
-               else {
-                       status = SMB_VFS_GET_NT_ACL(
-                               conn, fsp->fsp_name, security_info_wanted, &psd);
-               }
+               status = SMB_VFS_FGET_NT_ACL(
+                       fsp, security_info_wanted, &psd);
        }
-
        if (!NT_STATUS_IS_OK(status)) {
                reply_nterror(req, status);
                return;
        }
 
+       /* If the SACL/DACL is NULL, but was requested, we mark that it is
+        * present in the reply to match Windows behavior */
+       if (psd->sacl == NULL &&
+           security_info_wanted & SACL_SECURITY_INFORMATION)
+               psd->type |= SEC_DESC_SACL_PRESENT;
+       if (psd->dacl == NULL &&
+           security_info_wanted & DACL_SECURITY_INFORMATION)
+               psd->type |= SEC_DESC_DACL_PRESENT;
+
        sd_size = ndr_size_security_descriptor(psd, 0);
 
        DEBUG(3,("call_nt_transact_query_security_desc: sd_size = %lu.\n",(unsigned long)sd_size));
 
+       if (DEBUGLEVEL >= 10) {
+               DEBUG(10,("call_nt_transact_query_security_desc for file %s\n", fsp->fsp_name ));
+               NDR_PRINT_DEBUG(security_descriptor, psd);
+       }
+
        SIVAL(params,0,(uint32)sd_size);
 
        if (max_data_count < sd_size) {
@@ -1779,7 +1765,7 @@ static void call_nt_transact_ioctl(connection_struct *conn,
 
                DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on FID[0x%04X]\n",fidnum));
 
-               if (!fsp_belongs_conn(conn, req, fsp, &current_user)) {
+               if (!fsp_belongs_conn(conn, req, fsp)) {
                        return;
                }
 
@@ -1834,7 +1820,7 @@ static void call_nt_transact_ioctl(connection_struct *conn,
                uint32 i;
                char *cur_pdata;
 
-               if (!fsp_belongs_conn(conn, req, fsp, &current_user)) {
+               if (!fsp_belongs_conn(conn, req, fsp)) {
                        return;
                }
 
@@ -1918,7 +1904,7 @@ static void call_nt_transact_ioctl(connection_struct *conn,
                }
 
                /* needed_data_count 4 bytes */
-               SIVAL(pdata,8,labels_data_count);
+               SIVAL(pdata, 8, labels_data_count+4);
 
                cur_pdata+=12;
 
@@ -1957,7 +1943,7 @@ static void call_nt_transact_ioctl(connection_struct *conn,
 
                DEBUG(10,("FSCTL_FIND_FILES_BY_SID: called on FID[0x%04X]\n",fidnum));
 
-               if (!fsp_belongs_conn(conn, req, fsp, &current_user)) {
+               if (!fsp_belongs_conn(conn, req, fsp)) {
                        return;
                }
 
@@ -2042,9 +2028,10 @@ static void call_nt_transact_get_user_quota(connection_struct *conn,
        ZERO_STRUCT(qt);
 
        /* access check */
-       if (current_user.ut.uid != 0) {
-               DEBUG(1,("get_user_quota: access_denied service [%s] user [%s]\n",
-                       lp_servicename(SNUM(conn)),conn->user));
+       if (conn->server_info->utok.uid != 0) {
+               DEBUG(1,("get_user_quota: access_denied service [%s] user "
+                        "[%s]\n", lp_servicename(SNUM(conn)),
+                        conn->server_info->unix_name));
                reply_doserror(req, ERRDOS, ERRnoaccess);
                return;
        }
@@ -2061,7 +2048,7 @@ static void call_nt_transact_get_user_quota(connection_struct *conn,
 
        /* maybe we can check the quota_fnum */
        fsp = file_fsp(SVAL(params,0));
-       if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
+       if (!check_fsp_ntquota_handle(conn, req, fsp)) {
                DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
                reply_nterror(req, NT_STATUS_INVALID_HANDLE);
                return;
@@ -2070,7 +2057,7 @@ static void call_nt_transact_get_user_quota(connection_struct *conn,
        /* the NULL pointer checking for fsp->fake_file_handle->pd
         * is done by CHECK_NTQUOTA_HANDLE_OK()
         */
-       qt_handle = (SMB_NTQUOTA_HANDLE *)fsp->fake_file_handle->pd;
+       qt_handle = (SMB_NTQUOTA_HANDLE *)fsp->fake_file_handle->private_data;
 
        level = SVAL(params,2);
 
@@ -2308,9 +2295,10 @@ static void call_nt_transact_set_user_quota(connection_struct *conn,
        ZERO_STRUCT(qt);
 
        /* access check */
-       if (current_user.ut.uid != 0) {
-               DEBUG(1,("set_user_quota: access_denied service [%s] user [%s]\n",
-                       lp_servicename(SNUM(conn)),conn->user));
+       if (conn->server_info->utok.uid != 0) {
+               DEBUG(1,("set_user_quota: access_denied service [%s] user "
+                        "[%s]\n", lp_servicename(SNUM(conn)),
+                        conn->server_info->unix_name));
                reply_doserror(req, ERRDOS, ERRnoaccess);
                return;
        }
@@ -2327,7 +2315,7 @@ static void call_nt_transact_set_user_quota(connection_struct *conn,
 
        /* maybe we can check the quota_fnum */
        fsp = file_fsp(SVAL(params,0));
-       if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
+       if (!check_fsp_ntquota_handle(conn, req, fsp)) {
                DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
                reply_nterror(req, NT_STATUS_INVALID_HANDLE);
                return;
@@ -2837,10 +2825,10 @@ void reply_nttranss(struct smb_request *req)
                        goto bad_param;
                }
 
-               if (ddisp > av_size ||
+               if (doff > av_size ||
                                dcnt > av_size ||
-                               ddisp+dcnt > av_size ||
-                               ddisp+dcnt < ddisp) {
+                               doff+dcnt > av_size ||
+                               doff+dcnt < doff) {
                        goto bad_param;
                }